https://github.com/MalaySanghi updated https://github.com/llvm/llvm-project/pull/93774
>From 38359132ea0b3b56900ba48827c86a93c017223a Mon Sep 17 00:00:00 2001 From: Malay Sanghi <malay.san...@intel.com> Date: Wed, 29 May 2024 22:40:47 -0700 Subject: [PATCH 1/2] Add support for _outp{|w|d} --- clang/lib/Headers/intrin.h | 20 +++++ clang/test/CodeGen/X86/ms-x86-intrinsics.c | 85 ++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 5ceb986a1f652..21a3f030216e6 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -329,6 +329,26 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst, static __inline__ void __DEFAULT_FN_ATTRS __halt(void) { __asm__ volatile("hlt"); } + +static __inline__ int __DEFAULT_FN_ATTRS _outp(unsigned short port, int data) { + __asm__ volatile("outb %b0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +static __inline__ unsigned short __DEFAULT_FN_ATTRS +_outpw(unsigned short port, unsigned short data) { + __asm__ volatile("outw %w0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +static __inline__ unsigned long __DEFAULT_FN_ATTRS _outpd(unsigned short port, + unsigned long data) { + __asm__ volatile("outl %k0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +#define outp(port, data) _outp(port, data) +#define outpw(R, D) _outpw(port, data) #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..e990ccd3449ac 100644 --- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c +++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c @@ -63,6 +63,91 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) { // CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]] // CHECK: ret i64 [[RES]] +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outp( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3:[0-9]+]], !srcloc [[META4:![0-9]+]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outp( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5:[0-9]+]], !srcloc [[META3:![0-9]+]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +int test_outp(unsigned short port, int data) { + return _outp(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5:![0-9]+]] +// CHECK-I386-NEXT: ret i16 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4:![0-9]+]] +// CHECK-X64-NEXT: ret i16 [[DATA]] +// +unsigned short test_outpw(unsigned short port, unsigned short data) { + return _outpw(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outpd( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META6:![0-9]+]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outpd( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META5:![0-9]+]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +unsigned long test_outpd(unsigned short port, unsigned long data) { + return _outpd(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outp2( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META4]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outp2( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META3]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +int test_outp2(unsigned short port, int data) { + return outp(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw2( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5]] +// CHECK-I386-NEXT: ret i16 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw2( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4]] +// CHECK-X64-NEXT: ret i16 [[DATA]] +// +unsigned short test_outpw2(unsigned short port, unsigned short data) { + return outpw(port, data); +} + #if defined(__x86_64__) char test__readgsbyte(unsigned long Offset) { >From a5704660eebde130d17b0a72b0a757d9627aaf21 Mon Sep 17 00:00:00 2001 From: Malay Sanghi <malay.san...@intel.com> Date: Thu, 30 May 2024 00:01:45 -0700 Subject: [PATCH 2/2] remove memory constraint and fix definition. --- clang/lib/Headers/intrin.h | 10 +++++----- clang/test/CodeGen/X86/ms-x86-intrinsics.c | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 21a3f030216e6..1d56952f06cef 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -331,24 +331,24 @@ static __inline__ void __DEFAULT_FN_ATTRS __halt(void) { } static __inline__ int __DEFAULT_FN_ATTRS _outp(unsigned short port, int data) { - __asm__ volatile("outb %b0, %w1" : : "a"(data), "Nd"(port) : "memory"); + __asm__ volatile("outb %b0, %w1" : : "a"(data), "Nd"(port)); return data; } static __inline__ unsigned short __DEFAULT_FN_ATTRS _outpw(unsigned short port, unsigned short data) { - __asm__ volatile("outw %w0, %w1" : : "a"(data), "Nd"(port) : "memory"); + __asm__ volatile("outw %w0, %w1" : : "a"(data), "Nd"(port)); return data; } static __inline__ unsigned long __DEFAULT_FN_ATTRS _outpd(unsigned short port, unsigned long data) { - __asm__ volatile("outl %k0, %w1" : : "a"(data), "Nd"(port) : "memory"); + __asm__ volatile("outl %k0, %w1" : : "a"(data), "Nd"(port)); return data; } -#define outp(port, data) _outp(port, data) -#define outpw(R, D) _outpw(port, data) +#define outp(port, data) _outp((port), (data)) +#define outpw(port, data) _outpw((port), (data)) #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 e990ccd3449ac..423fbc8477d0a 100644 --- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c +++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c @@ -67,13 +67,13 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) { // CHECK-I386-LABEL: define dso_local noundef i32 @test_outp( // CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { // CHECK-I386-NEXT: [[ENTRY:.*:]] -// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3:[0-9]+]], !srcloc [[META4:![0-9]+]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3:[0-9]+]], !srcloc [[META4:![0-9]+]] // CHECK-I386-NEXT: ret i32 [[DATA]] // // CHECK-X64-LABEL: define dso_local noundef i32 @test_outp( // CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // CHECK-X64-NEXT: [[ENTRY:.*:]] -// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5:[0-9]+]], !srcloc [[META3:![0-9]+]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5:[0-9]+]], !srcloc [[META3:![0-9]+]] // CHECK-X64-NEXT: ret i32 [[DATA]] // int test_outp(unsigned short port, int data) { @@ -84,13 +84,13 @@ int test_outp(unsigned short port, int data) { // CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw( // CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-I386-NEXT: [[ENTRY:.*:]] -// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5:![0-9]+]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5:![0-9]+]] // CHECK-I386-NEXT: ret i16 [[DATA]] // // CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw( // CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-X64-NEXT: [[ENTRY:.*:]] -// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4:![0-9]+]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4:![0-9]+]] // CHECK-X64-NEXT: ret i16 [[DATA]] // unsigned short test_outpw(unsigned short port, unsigned short data) { @@ -101,13 +101,13 @@ unsigned short test_outpw(unsigned short port, unsigned short data) { // CHECK-I386-LABEL: define dso_local noundef i32 @test_outpd( // CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-I386-NEXT: [[ENTRY:.*:]] -// CHECK-I386-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META6:![0-9]+]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META6:![0-9]+]] // CHECK-I386-NEXT: ret i32 [[DATA]] // // CHECK-X64-LABEL: define dso_local noundef i32 @test_outpd( // CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-X64-NEXT: [[ENTRY:.*:]] -// CHECK-X64-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META5:![0-9]+]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META5:![0-9]+]] // CHECK-X64-NEXT: ret i32 [[DATA]] // unsigned long test_outpd(unsigned short port, unsigned long data) { @@ -118,13 +118,13 @@ unsigned long test_outpd(unsigned short port, unsigned long data) { // CHECK-I386-LABEL: define dso_local noundef i32 @test_outp2( // CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-I386-NEXT: [[ENTRY:.*:]] -// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META4]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META4]] // CHECK-I386-NEXT: ret i32 [[DATA]] // // CHECK-X64-LABEL: define dso_local noundef i32 @test_outp2( // CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-X64-NEXT: [[ENTRY:.*:]] -// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META3]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META3]] // CHECK-X64-NEXT: ret i32 [[DATA]] // int test_outp2(unsigned short port, int data) { @@ -135,13 +135,13 @@ int test_outp2(unsigned short port, int data) { // CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw2( // CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { // CHECK-I386-NEXT: [[ENTRY:.*:]] -// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5]] // CHECK-I386-NEXT: ret i16 [[DATA]] // // CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw2( // CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-X64-NEXT: [[ENTRY:.*:]] -// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4]] // CHECK-X64-NEXT: ret i16 [[DATA]] // unsigned short test_outpw2(unsigned short port, unsigned short data) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits