diff options
author | Evan Cheng <evan.cheng@apple.com> | 2010-01-08 23:41:50 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2010-01-08 23:41:50 +0000 |
commit | 306b4cafc1fd8c075c422825c49bdd14a5f851d7 (patch) | |
tree | 1cb54fea8d9cfa1c3f980f10efb17457dd569800 /test | |
parent | d003c5b3d750706cdc0bfa34ebf85b95a7a42abe (diff) |
Fix a critical bug in 64-bit atomic operation lowering for 32-bit. The results of the cmpxchg8b instructions are being thrown away when it branches back to the top of the checking loop. This means the loop always compares against the old value and this can result in a dead lock.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93028 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/CodeGen/X86/2010-01-08-Atomic64Bug.ll | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll b/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll new file mode 100644 index 0000000000..172e1c73d5 --- /dev/null +++ b/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s +; rdar://r7512579 + +; PHI defs in the atomic loop should be used by the add / adc +; instructions. They should not be dead. + +define void @t(i64* nocapture %p) nounwind ssp { +entry: +; CHECK: t: +; CHECK: movl $1 +; CHECK: movl (%ebp), %eax +; CHECK: movl 4(%ebp), %edx +; CHECK: LBB1_1: +; CHECK-NOT: movl $1 +; CHECK-NOT: movl $0 +; CHECK: addl +; CHECK: adcl +; CHECK: lock +; CHECK: cmpxchg8b +; CHECK: jne + tail call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) ; <i64> [#uses=0] + tail call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + ret void +} + +declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind + +declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind |