From 98066413ca49bc8bcca445bbd5bd3620c5ae49fc Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 6 Nov 2014 23:23:30 +0000 Subject: [PATCH] InstCombine: Rely on cmpxchg's return code when it's strong Comparing the result of a cmpxchg instruction can be replaced with an extractvalue of the cmpxchg success indicator. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221498 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineCompares.cpp | 16 ++++++++++++++++ test/Transforms/InstCombine/icmp.ll | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index f7eb16cbb96..399f1c31755 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3418,6 +3418,22 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } } + // The 'cmpxchg' instruction returns an aggregate containing the old value and + // an i1 which indicates whether or not we successfully did the swap. + // + // Replace comparisons between the old value and the expected value with the + // indicator that 'cmpxchg' returns. + // + // N.B. This transform is only valid when the 'cmpxchg' is not permitted to + // spuriously fail. In those cases, the old value may equal the expected + // value but it is possible for the swap to not occur. + if (I.getPredicate() == ICmpInst::ICMP_EQ) + if (auto *EVI = dyn_cast(Op0)) + if (auto *ACXI = dyn_cast(EVI->getAggregateOperand())) + if (EVI->getIndices()[0] == 0 && ACXI->getCompareOperand() == Op1 && + !ACXI->isWeak()) + return ExtractValueInst::Create(ACXI, 1); + { Value *X; ConstantInt *Cst; // icmp X+Cst, X diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 8c65d9cefc8..279d86d4051 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1511,3 +1511,14 @@ define i1 @icmp_sle_zero_add_nsw(i32 %a) { %cmp = icmp sle i32 %add, 0 ret i1 %cmp } + +; CHECK-LABEL: @icmp_cmpxchg_strong +; CHECK-NEXT: %[[xchg:.*]] = cmpxchg i32* %sc, i32 %old_val, i32 %new_val seq_cst seq_cst +; CHECK-NEXT: %[[icmp:.*]] = extractvalue { i32, i1 } %[[xchg]], 1 +; CHECK-NEXT: ret i1 %[[icmp]] +define zeroext i1 @icmp_cmpxchg_strong(i32* %sc, i32 %old_val, i32 %new_val) { + %xchg = cmpxchg i32* %sc, i32 %old_val, i32 %new_val seq_cst seq_cst + %xtrc = extractvalue { i32, i1 } %xchg, 0 + %icmp = icmp eq i32 %xtrc, %old_val + ret i1 %icmp +} -- 2.11.0