diff options
author | Tim Northover <tnorthover@apple.com> | 2014-06-13 17:29:39 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2014-06-13 17:29:39 +0000 |
commit | eee7a7a8362afddab3fd9bf10b7023da7e7c42e5 (patch) | |
tree | 16aab5a93b11f7b57f646d7246bf04e5966c3041 /test | |
parent | f317d86f8f754e414c1ca52bb3fdc346f990c6cc (diff) | |
download | llvm-eee7a7a8362afddab3fd9bf10b7023da7e7c42e5.tar.gz llvm-eee7a7a8362afddab3fd9bf10b7023da7e7c42e5.tar.bz2 llvm-eee7a7a8362afddab3fd9bf10b7023da7e7c42e5.tar.xz |
X86: lower ATOMIC_CMP_SWAP_WITH_SUCCESS directly
Lowering this new node allows us to fold the almost universal
comparison for success before it's even formed. Instead we can create
a copy from EFLAGS and an X86ISD::SETCC operation since all "cmpxchg"
instructions set the zero-flag to the correct value.
rdar://problem/13201607
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210923 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r-- | test/CodeGen/X86/cmpxchg-i1.ll | 87 | ||||
-rw-r--r-- | test/CodeGen/X86/cmpxchg-i128-i1.ll | 83 |
2 files changed, 170 insertions, 0 deletions
diff --git a/test/CodeGen/X86/cmpxchg-i1.ll b/test/CodeGen/X86/cmpxchg-i1.ll new file mode 100644 index 0000000000..a21ab593b0 --- /dev/null +++ b/test/CodeGen/X86/cmpxchg-i1.ll @@ -0,0 +1,87 @@ +; RUN: llc -mtriple=x86_64 -o - %s | FileCheck %s + +define i1 @try_cmpxchg(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: try_cmpxchg: +; CHECK: cmpxchgl +; CHECK-NOT: cmp +; CHECK: sete %al +; CHECK: retq + %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst + %success = extractvalue { i32, i1 } %pair, 1 + ret i1 %success +} + +define void @cmpxchg_flow(i64* %addr, i64 %desired, i64 %new) { +; CHECK-LABEL: cmpxchg_flow: +; CHECK: cmpxchgq +; CHECK-NOT: cmp +; CHECK-NOT: set +; CHECK: {{jne|jeq}} + %pair = cmpxchg i64* %addr, i64 %desired, i64 %new seq_cst seq_cst + %success = extractvalue { i64, i1 } %pair, 1 + br i1 %success, label %true, label %false + +true: + call void @foo() + ret void + +false: + call void @bar() + ret void +} + +define i64 @cmpxchg_sext(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: cmpxchg_sext: +; CHECK-DAG: cmpxchgl +; CHECK-NOT: cmpl +; CHECK: sete %al +; CHECK: retq + %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst + %success = extractvalue { i32, i1 } %pair, 1 + %mask = sext i1 %success to i64 + ret i64 %mask +} + +define i32 @cmpxchg_zext(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: cmpxchg_zext: +; CHECK: cmpxchgl +; CHECK-NOT: cmp +; CHECK: sete [[BYTE:%[a-z0-9]+]] +; CHECK: movzbl [[BYTE]], %eax + %pair = cmpxchg i32* %addr, i32 %desired, i32 %new seq_cst seq_cst + %success = extractvalue { i32, i1 } %pair, 1 + %mask = zext i1 %success to i32 + ret i32 %mask +} + + +define i32 @cmpxchg_use_eflags_and_val(i32* %addr, i32 %offset) { +; CHECK-LABEL: cmpxchg_use_eflags_and_val: +; CHECK: movl (%rdi), %e[[OLDVAL:[a-z0-9]+]] + +; CHECK: [[LOOPBB:.?LBB[0-9]+_[0-9]+]]: +; CHECK: leal (%r[[OLDVAL]],%rsi), [[NEW:%[a-z0-9]+]] +; CHECK: cmpxchgl [[NEW]], (%rdi) +; CHECK-NOT: cmpl +; CHECK: jne [[LOOPBB]] + + ; Result already in %eax +; CHECK: retq +entry: + %init = load atomic i32* %addr seq_cst, align 4 + br label %loop + +loop: + %old = phi i32 [%init, %entry], [%oldval, %loop] + %new = add i32 %old, %offset + %pair = cmpxchg i32* %addr, i32 %old, i32 %new seq_cst seq_cst + %oldval = extractvalue { i32, i1 } %pair, 0 + %success = extractvalue { i32, i1 } %pair, 1 + br i1 %success, label %done, label %loop + +done: + ret i32 %oldval +} + +declare void @foo() +declare void @bar() diff --git a/test/CodeGen/X86/cmpxchg-i128-i1.ll b/test/CodeGen/X86/cmpxchg-i128-i1.ll new file mode 100644 index 0000000000..4dd30013ec --- /dev/null +++ b/test/CodeGen/X86/cmpxchg-i128-i1.ll @@ -0,0 +1,83 @@ +; RUN: llc -mcpu=core-avx2 -mtriple=x86_64 -o - %s | FileCheck %s + +define i1 @try_cmpxchg(i128* %addr, i128 %desired, i128 %new) { +; CHECK-LABEL: try_cmpxchg: +; CHECK: cmpxchg16b +; CHECK-NOT: cmp +; CHECK: sete %al +; CHECK: retq + %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst + %success = extractvalue { i128, i1 } %pair, 1 + ret i1 %success +} + +define void @cmpxchg_flow(i128* %addr, i128 %desired, i128 %new) { +; CHECK-LABEL: cmpxchg_flow: +; CHECK: cmpxchg16b +; CHECK-NOT: cmp +; CHECK-NOT: set +; CHECK: {{jne|jeq}} + %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst + %success = extractvalue { i128, i1 } %pair, 1 + br i1 %success, label %true, label %false + +true: + call void @foo() + ret void + +false: + call void @bar() + ret void +} + +; Can't use the flags here because cmpxchg16b only sets ZF. +define i1 @cmpxchg_arithcmp(i128* %addr, i128 %desired, i128 %new) { +; CHECK-LABEL: cmpxchg_arithcmp: +; CHECK: cmpxchg16b +; CHECK: cmpq +; CHECK: retq + %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst + %oldval = extractvalue { i128, i1 } %pair, 0 + %success = icmp sge i128 %oldval, %desired + ret i1 %success +} + +define i128 @cmpxchg_zext(i128* %addr, i128 %desired, i128 %new) { +; CHECK-LABEL: cmpxchg_zext: +; CHECK: cmpxchg16b +; CHECK-NOT: cmpq +; CHECK: sete [[BYTE:%[a-z0-9]+]] +; CHECK: movzbl [[BYTE]], %eax + %pair = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst + %success = extractvalue { i128, i1 } %pair, 1 + %mask = zext i1 %success to i128 + ret i128 %mask +} + + +define i128 @cmpxchg_use_eflags_and_val(i128* %addr, i128 %offset) { +; CHECK-LABEL: cmpxchg_use_eflags_and_val: + +; CHECK: cmpxchg16b +; CHECK-NOT: cmpq +; CHECK: jne +entry: + %init = load atomic i128* %addr seq_cst, align 16 + br label %loop + +loop: + %old = phi i128 [%init, %entry], [%oldval, %loop] + %new = add i128 %old, %offset + + %pair = cmpxchg i128* %addr, i128 %old, i128 %new seq_cst seq_cst + %oldval = extractvalue { i128, i1 } %pair, 0 + %success = extractvalue { i128, i1 } %pair, 1 + + br i1 %success, label %done, label %loop + +done: + ret i128 %old +} + +declare void @foo() +declare void @bar() |