Tweak my last commit to be less conservative about uses.

We still save an instruction when just the "and" part is replaced.
Also change the code to match comments more closely.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147753 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer
2012-01-08 21:12:51 +00:00
parent 79aa048d21
commit d4242d8ab1
2 changed files with 35 additions and 37 deletions

View File

@@ -745,18 +745,17 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
} }
// (X & C) == 0 & X > -1 -> (X & (C | SignBit)) == 0 // (X & C) == 0 & X > -1 -> (X & (C | SignBit)) == 0
if (LHS->hasOneUse() && RHS->hasOneUse() && if ((LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero() &&
((LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero() && RHSCC == ICmpInst::ICMP_SGT && RHSCst->isAllOnesValue()) ||
RHSCC == ICmpInst::ICMP_SGT && RHSCst->isAllOnesValue()) || (RHSCC == ICmpInst::ICMP_EQ && RHSCst->isZero() &&
(RHSCC == ICmpInst::ICMP_EQ && RHSCst->isZero() && LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue())) {
LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()))) { ICmpInst *I = LHSCC == ICmpInst::ICMP_EQ ? LHS : RHS;
BinaryOperator *BO = Value *X; ConstantInt *C;
dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_EQ ? Val : Val2); if (I->hasOneUse() &&
ConstantInt *AndCst; match(I->getOperand(0), m_OneUse(m_And(m_Value(X), m_ConstantInt(C))))){
if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) { APInt New = C->getValue() | APInt::getSignBit(C->getBitWidth());
APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth()); return Builder->CreateICmpEQ(Builder->CreateAnd(X, Builder->getInt(New)),
BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New)); I->getOperand(1));
return BO == Val ? LHS : RHS;
} }
} }
@@ -1458,19 +1457,18 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
} }
} }
// (X & C) != 0 & X < 0 -> (X & (C | SignBit)) != 0 // (X & C) != 0 | X < 0 -> (X & (C | SignBit)) != 0
if (LHS->hasOneUse() && RHS->hasOneUse() && if ((LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero() &&
((LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero() && RHSCC == ICmpInst::ICMP_SLT && RHSCst->isZero()) ||
RHSCC == ICmpInst::ICMP_SLT && RHSCst->isZero()) || (RHSCC == ICmpInst::ICMP_NE && RHSCst->isZero() &&
(RHSCC == ICmpInst::ICMP_NE && RHSCst->isZero() && LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero())) {
LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()))) { ICmpInst *I = LHSCC == ICmpInst::ICMP_NE ? LHS : RHS;
BinaryOperator *BO = Value *X; ConstantInt *C;
dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_NE ? Val : Val2); if (I->hasOneUse() &&
ConstantInt *AndCst; match(I->getOperand(0), m_OneUse(m_And(m_Value(X), m_ConstantInt(C))))){
if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) { APInt New = C->getValue() | APInt::getSignBit(C->getBitWidth());
APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth()); return Builder->CreateICmpNE(Builder->CreateAnd(X, Builder->getInt(New)),
BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New)); I->getOperand(1));
return BO == Val ? LHS : RHS;
} }
} }

View File

@@ -86,9 +86,9 @@ define void @test5(i32 %a) nounwind {
br i1 %or.cond, label %if.then, label %if.end br i1 %or.cond, label %if.then, label %if.end
; CHECK: @test5 ; CHECK: @test5
; CHECK-NEXT: %and = and i32 %a, -2013265920 ; CHECK-NEXT: %1 = and i32 %a, -2013265920
; CHECK-NEXT: %1 = icmp eq i32 %and, 0 ; CHECK-NEXT: %2 = icmp eq i32 %1, 0
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end ; CHECK-NEXT: br i1 %2, label %if.then, label %if.end
if.then: if.then:
tail call void @foo() nounwind tail call void @foo() nounwind
@@ -106,9 +106,9 @@ define void @test6(i32 %a) nounwind {
br i1 %or.cond, label %if.then, label %if.end br i1 %or.cond, label %if.then, label %if.end
; CHECK: @test6 ; CHECK: @test6
; CHECK-NEXT: %and = and i32 %a, -2013265920 ; CHECK-NEXT: %1 = and i32 %a, -2013265920
; CHECK-NEXT: %1 = icmp eq i32 %and, 0 ; CHECK-NEXT: %2 = icmp eq i32 %1, 0
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end ; CHECK-NEXT: br i1 %2, label %if.then, label %if.end
if.then: if.then:
tail call void @foo() nounwind tail call void @foo() nounwind
@@ -126,9 +126,9 @@ define void @test7(i32 %a) nounwind {
br i1 %or.cond, label %if.then, label %if.end br i1 %or.cond, label %if.then, label %if.end
; CHECK: @test7 ; CHECK: @test7
; CHECK-NEXT: %and = and i32 %a, -2013265920 ; CHECK-NEXT: %1 = and i32 %a, -2013265920
; CHECK-NEXT: %1 = icmp eq i32 %and, 0 ; CHECK-NEXT: %2 = icmp eq i32 %1, 0
; CHECK-NEXT: br i1 %1, label %if.end, label %if.the ; CHECK-NEXT: br i1 %2, label %if.end, label %if.the
if.then: if.then:
tail call void @foo() nounwind tail call void @foo() nounwind
@@ -146,9 +146,9 @@ define void @test8(i32 %a) nounwind {
br i1 %or.cond, label %if.then, label %if.end br i1 %or.cond, label %if.then, label %if.end
; CHECK: @test8 ; CHECK: @test8
; CHECK-NEXT: %and = and i32 %a, -2013265920 ; CHECK-NEXT: %1 = and i32 %a, -2013265920
; CHECK-NEXT: %1 = icmp eq i32 %and, 0 ; CHECK-NEXT: %2 = icmp eq i32 %1, 0
; CHECK-NEXT: br i1 %1, label %if.end, label %if.the ; CHECK-NEXT: br i1 %2, label %if.end, label %if.the
if.then: if.then:
tail call void @foo() nounwind tail call void @foo() nounwind