From 114efe0dc88f9e2a78d2e50c7e5e55329dc59477 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 18 Jun 2014 20:51:10 +0000 Subject: [PATCH] CodeGen: improve ms instrincics support Add support for _InterlockedCompareExchangePointer, _InterlockExchangePointer, _InterlockExchange. These are available as a compiler intrinsic on ARM and x86. These are used directly by the Windows SDK headers without use of the intrin header. llvm-svn: 211216 --- clang/include/clang/Basic/Builtins.def | 3 +++ clang/lib/CodeGen/CGBuiltin.cpp | 29 ++++++++++++++++++++++++ clang/lib/Headers/Intrin.h | 23 +------------------ clang/test/CodeGen/ms-intrinsics.c | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 22 deletions(-) create mode 100644 clang/test/CodeGen/ms-intrinsics.c diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 4c356f1..a7a7f42 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -683,9 +683,12 @@ LANGBUILTIN(__noop, "v.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES) // C99 library functions // C99 stdlib.h diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c9a10a5..d9d1fd1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1516,6 +1516,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, E->getArg(0), true); case Builtin::BI__noop: return RValue::get(nullptr); + case Builtin::BI_InterlockedExchange: + case Builtin::BI_InterlockedExchangePointer: + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); + case Builtin::BI_InterlockedCompareExchangePointer: { + llvm::Type *RTy; + llvm::IntegerType *IntType = + IntegerType::get(getLLVMContext(), + getContext().getTypeSize(E->getType())); + llvm::Type *IntPtrType = IntType->getPointerTo(); + + llvm::Value *Destination = + Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), IntPtrType); + + llvm::Value *Exchange = EmitScalarExpr(E->getArg(1)); + RTy = Exchange->getType(); + Exchange = Builder.CreatePtrToInt(Exchange, IntType); + + llvm::Value *Comparand = + Builder.CreatePtrToInt(EmitScalarExpr(E->getArg(2)), IntType); + + auto Result = Builder.CreateAtomicCmpXchg(Destination, Comparand, Exchange, + SequentiallyConsistent, + SequentiallyConsistent); + Result->setVolatile(true); + + return RValue::get(Builder.CreateIntToPtr(Builder.CreateExtractValue(Result, + 0), + RTy)); + } case Builtin::BI_InterlockedCompareExchange: { AtomicCmpXchgInst *CXI = Builder.CreateAtomicCmpXchg( EmitScalarExpr(E->getArg(0)), diff --git a/clang/lib/Headers/Intrin.h b/clang/lib/Headers/Intrin.h index ff6d278..37c0eb9 100644 --- a/clang/lib/Headers/Intrin.h +++ b/clang/lib/Headers/Intrin.h @@ -223,8 +223,7 @@ static __inline__ long __cdecl _InterlockedDecrement(long volatile *_Addend); static __inline__ short _InterlockedDecrement16(short volatile *_Addend); -static __inline__ -long __cdecl _InterlockedExchange(long volatile *_Target, long _Value); +long _InterlockedExchange(long volatile *_Target, long _Value); static __inline__ short _InterlockedExchange16(short volatile *_Target, short _Value); static __inline__ @@ -411,7 +410,6 @@ __int64 _InterlockedCompareExchange64_HLERelease(__int64 volatile *, __int64, __int64); __int64 _InterlockedCompareExchange64_np(__int64 volatile *_Destination, __int64 _Exchange, __int64 _Comparand); -static __inline__ void *_InterlockedCompareExchangePointer(void *volatile *_Destination, void *_Exchange, void *_Comparand); void *_InterlockedCompareExchangePointer_np(void *volatile *_Destination, @@ -422,7 +420,6 @@ static __inline__ __int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value); static __inline__ __int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value); -static __inline__ void *_InterlockedExchangePointer(void *volatile *_Target, void *_Value); static __inline__ __int64 _InterlockedIncrement64(__int64 volatile *_Addend); @@ -785,22 +782,12 @@ _InterlockedExchange16(short volatile *_Target, short _Value) { __atomic_exchange(_Target, &_Value, &_Value, 0); return _Value; } -static __inline__ long __attribute__((__always_inline__, __nodebug__)) -_InterlockedExchange(long volatile *_Target, long _Value) { - __atomic_exchange(_Target, &_Value, &_Value, 0); - return _Value; -} #ifdef __x86_64__ static __inline__ __int64 __attribute__((__always_inline__, __nodebug__)) _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value) { __atomic_exchange(_Target, &_Value, &_Value, 0); return _Value; } -static __inline__ void *__attribute__((__always_inline__, __nodebug__)) -_InterlockedExchangePointer(void *volatile *_Target, void *_Value) { - __atomic_exchange(_Target, &_Value, &_Value, 0); - return _Value; -} #endif /*----------------------------------------------------------------------------*\ |* Interlocked Compare Exchange @@ -817,14 +804,6 @@ _InterlockedCompareExchange16(short volatile *_Destination, __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0); return _Comparand; } -#ifdef __x86_64__ -static __inline__ void *__attribute__((__always_inline__, __nodebug__)) -_InterlockedCompareExchangePointer(void *volatile *_Destination, - void *_Exchange, void *_Comparand) { - __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0, 0, 0); - return _Comparand; -} -#endif static __inline__ __int64 __attribute__((__always_inline__, __nodebug__)) _InterlockedCompareExchange64(__int64 volatile *_Destination, __int64 _Exchange, __int64 _Comparand) { diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c new file mode 100644 index 0000000..e37a481 --- /dev/null +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple i686--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple thumbv7--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s + +void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) { + return _InterlockedExchangePointer(Target, Value); +} + +// CHECK: define{{.*}}i8* @test_InterlockedExchangePointer(i8** %Target, i8* %Value){{.*}}{ +// CHECK: entry: +// CHECK: %0 = bitcast i8** %Target to i32* +// CHECK: %1 = ptrtoint i8* %Value to i32 +// CHECK: %2 = atomicrmw xchg i32* %0, i32 %1 seq_cst +// CHECK: %3 = inttoptr i32 %2 to i8* +// CHECK: ret i8* %3 +// CHECK: } + +void *test_InterlockedCompareExchangePointer(void * volatile *Destination, + void *Exchange, void *Comparand) { + return _InterlockedCompareExchangePointer(Destination, Exchange, Comparand); +} + +// CHECK: define{{.*}}i8* @test_InterlockedCompareExchangePointer(i8** %Destination, i8* %Exchange, i8* %Comparand){{.*}}{ +// CHECK: entry: +// CHECK: %0 = bitcast i8** %Destination to i32* +// CHECK: %1 = ptrtoint i8* %Exchange to i32 +// CHECK: %2 = ptrtoint i8* %Comparand to i32 +// CHECK: %3 = cmpxchg volatile i32* %0, i32 %2, i32 %1 seq_cst seq_cst +// CHECK: %4 = extractvalue { i32, i1 } %3, 0 +// CHECK: %5 = inttoptr i32 %4 to i8* +// CHECK: ret i8* %5 +// CHECK: } + +long test_InterlockedExchange(long *Target, long Value) { + return _InterlockedExchange(Target, Value); +} + +// CHECK: define{{.*}}i32 @test_InterlockedExchange(i32* %Target, i32 %Value){{.*}}{ +// CHECK: entry: +// CHECK: %0 = atomicrmw xchg i32* %Target, i32 %Value seq_cst +// CHECK: ret i32 %0 +// CHECK: } -- 2.7.4