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.

llvm-svn: 221498
This commit is contained in:
David Majnemer 2014-11-06 23:23:30 +00:00
parent 89cb407729
commit c1eca5ad7c
2 changed files with 27 additions and 0 deletions

View File

@ -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<ExtractValueInst>(Op0))
if (auto *ACXI = dyn_cast<AtomicCmpXchgInst>(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

View File

@ -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
}