diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2014-07-14 16:28:13 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2014-07-14 16:28:13 +0000 |
commit | b51d464f1ea70eba6f04bdfe8b6d1103fe865cc8 (patch) | |
tree | 7f59411ea4c8a42ab143ed4f2123111b818199d9 | |
parent | 271ac58eb3f106f97b991b50f0aa4f977a9fb713 (diff) | |
download | bcm5719-llvm-b51d464f1ea70eba6f04bdfe8b6d1103fe865cc8.tar.gz bcm5719-llvm-b51d464f1ea70eba6f04bdfe8b6d1103fe865cc8.zip |
X86: correct 64-bit atomics on 32-bit
We would emit a libcall for a 64-bit atomic on x86 after SVN r212119. This was
due to the misuse of hasCmpxchg16 to indicate if cmpxchg8b was supported on a
32-bit target. They were added at different times and would result in the
border condition being mishandled.
This fixes the border case to emit the cmpxchg8b instruction for 64-bit atomic
operations on x86 at the cost of restoring a long-standing bug in the codegen.
We emit a cmpxchg8b on all x86 targets even where the CPU does not support this
instruction (pre-Pentium CPUs). Although this bug should be fixed, this was
present prior to SVN r212119 and this change, so this is not really introducing
a regression.
llvm-svn: 212956
-rw-r--r-- | llvm/lib/Target/X86/X86AtomicExpandPass.cpp | 20 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/atomic-ops-ancient-64.ll | 1 |
2 files changed, 9 insertions, 12 deletions
diff --git a/llvm/lib/Target/X86/X86AtomicExpandPass.cpp b/llvm/lib/Target/X86/X86AtomicExpandPass.cpp index 61eefbbf75b..3dcadb16760 100644 --- a/llvm/lib/Target/X86/X86AtomicExpandPass.cpp +++ b/llvm/lib/Target/X86/X86AtomicExpandPass.cpp @@ -98,25 +98,21 @@ bool X86AtomicExpandPass::runOnFunction(Function &F) { return MadeChange; } -/// Returns true if operations on the given type will need to use either -/// cmpxchg8b or cmpxchg16b. This occurs if the type is 1 step up from the -/// native width, and the instructions are available (otherwise we leave them -/// alone to become __sync_fetch_and_... calls). +/// Returns true if the operand type is 1 step up from the native width, and +/// the corresponding cmpxchg8b or cmpxchg16b instruction is available +/// (otherwise we leave them alone to become __sync_fetch_and_... calls). bool X86AtomicExpandPass::needsCmpXchgNb(llvm::Type *MemType) { const X86Subtarget &Subtarget = TM->getSubtarget<X86Subtarget>(); - if (!Subtarget.hasCmpxchg16b()) - return false; - - unsigned CmpXchgNbWidth = Subtarget.is64Bit() ? 128 : 64; - unsigned OpWidth = MemType->getPrimitiveSizeInBits(); - if (OpWidth == CmpXchgNbWidth) - return true; + + if (OpWidth == 64) + return !Subtarget.is64Bit(); // FIXME this should be Subtarget.hasCmpxchg8b + if (OpWidth == 128) + return Subtarget.hasCmpxchg16b(); return false; } - bool X86AtomicExpandPass::shouldExpandAtomicRMW(AtomicRMWInst *AI) { const X86Subtarget &Subtarget = TM->getSubtarget<X86Subtarget>(); unsigned NativeWidth = Subtarget.is64Bit() ? 64 : 32; diff --git a/llvm/test/CodeGen/X86/atomic-ops-ancient-64.ll b/llvm/test/CodeGen/X86/atomic-ops-ancient-64.ll index 18749b90287..508d83b0ffe 100644 --- a/llvm/test/CodeGen/X86/atomic-ops-ancient-64.ll +++ b/llvm/test/CodeGen/X86/atomic-ops-ancient-64.ll @@ -1,4 +1,5 @@ ; RUN: llc -mtriple=i386-linux-gnu %s -o - | FileCheck %s +; XFAIL: * define i64 @test_add(i64* %addr, i64 %inc) { ; CHECK-LABEL: test_add: |