-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[X86] Add support for MS inp functions. #93804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
support _inp, _inpw, _inpd, inp, inpw. These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.
@llvm/pr-subscribers-backend-x86 Author: Malay Sanghi (MalaySanghi) Changessupport _inp, _inpw, _inpd, inp, inpw. Full diff: https://github.com/llvm/llvm-project/pull/93804.diff 2 Files Affected:
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 5ceb986a1f652..67a062d2166b0 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -329,6 +329,28 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
__asm__ volatile("hlt");
}
+
+static inline int _inp(unsigned short port) {
+ int ret;
+ __asm__ volatile("inb %b1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+static inline unsigned short _inpw(unsigned short port) {
+ unsigned short ret;
+ __asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+static inline unsigned long _inpd(unsigned short port) {
+ unsigned long ret;
+ __asm__ volatile("inb %k1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+#define inp(port) _inp((port))
+#define inpw(port) _inpw((port))
+
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
index aa557c8e19a83..c51f2d53ca771 100644
--- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c
+++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
@@ -63,6 +63,82 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
// CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
// CHECK: ret i64 [[RES]]
+
+int test_inp(unsigned short port) {
+ return _inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+unsigned short test_inpw(unsigned short port) {
+ return _inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i16 [[TMP0]]
+
+unsigned long test_inpd(unsigned short port) {
+ return _inpd(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inpd(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inpd(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+int test_inp2(unsigned short port) {
+ return inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+unsigned short test_inpw2(unsigned short port) {
+ return inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i16 [[TMP0]]
+
#if defined(__x86_64__)
char test__readgsbyte(unsigned long Offset) {
|
@llvm/pr-subscribers-clang Author: Malay Sanghi (MalaySanghi) Changessupport _inp, _inpw, _inpd, inp, inpw. Full diff: https://github.com/llvm/llvm-project/pull/93804.diff 2 Files Affected:
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 5ceb986a1f652..67a062d2166b0 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -329,6 +329,28 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
__asm__ volatile("hlt");
}
+
+static inline int _inp(unsigned short port) {
+ int ret;
+ __asm__ volatile("inb %b1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+static inline unsigned short _inpw(unsigned short port) {
+ unsigned short ret;
+ __asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+static inline unsigned long _inpd(unsigned short port) {
+ unsigned long ret;
+ __asm__ volatile("inb %k1, %b0" : "=a"(ret) : "Nd"(port));
+ return ret;
+}
+
+#define inp(port) _inp((port))
+#define inpw(port) _inpw((port))
+
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
index aa557c8e19a83..c51f2d53ca771 100644
--- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c
+++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
@@ -63,6 +63,82 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
// CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
// CHECK: ret i64 [[RES]]
+
+int test_inp(unsigned short port) {
+ return _inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+unsigned short test_inpw(unsigned short port) {
+ return _inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i16 [[TMP0]]
+
+unsigned long test_inpd(unsigned short port) {
+ return _inpd(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inpd(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inpd(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+int test_inp2(unsigned short port) {
+ return inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i32 [[TMP0]]
+
+unsigned short test_inpw2(unsigned short port) {
+ return inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT: entry:
+// CHECK-I386-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT: ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT: entry:
+// CHECK-X64-NEXT: [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT: ret i16 [[TMP0]]
+
#if defined(__x86_64__)
char test__readgsbyte(unsigned long Offset) {
|
This could probably have been a part of #93774 . If that's preferred, I'll add this change as a new commit to that PR. |
tag @phoebewang @FreddyLeaf @RKSimon for review |
// CHECK-I386-LABEL: define dso_local i32 @test_inp( | ||
// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These can be put in one line now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I had tried that. A variable (PORT in this case) is not allowed in CHECK-LABEL
} | ||
// CHECK-LABEL: i32 @test_inpd(i16 noundef | ||
// CHECK-SAME: [[PORT:%.*]]) | ||
// CHECK: [[TMP0:%.*]] = tail call i32 asm sideeffect "inl ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be ={eax}
for 32-bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In llvm-IR this remain ax.
There were other issues which I fixed. I had only tested the outp end-end and modelled this after the outp intrinsic. I've tested this end-end now.
_ind(port)
becomes
%0 = tail call i32 asm sideeffect "inl ${1:w}, ${0:k}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 %port) #3, !srcloc !6
and eventually
inl %dx, %eax
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add this to ReleaseNotes?
This reverts commit 089dfee.
support _inp, _inpw, _inpd.
These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.