InstCombine: Teach icmp merging about the equivalence of bit tests and UGE/ULT with a power of 2.

This happens in bitfield code. While there reorganize the existing code
a bit.

llvm-svn: 201176
This commit is contained in:
Benjamin Kramer 2014-02-11 21:09:03 +00:00
parent 86c318f496
commit 94fc18d040
2 changed files with 76 additions and 23 deletions

View File

@ -503,31 +503,46 @@ static unsigned conjugateICmpMask(unsigned Mask) {
/// decomposition fails. /// decomposition fails.
static bool decomposeBitTestICmp(const ICmpInst *I, ICmpInst::Predicate &Pred, static bool decomposeBitTestICmp(const ICmpInst *I, ICmpInst::Predicate &Pred,
Value *&X, Value *&Y, Value *&Z) { Value *&X, Value *&Y, Value *&Z) {
// X < 0 is equivalent to (X & SignBit) != 0. ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1));
if (I->getPredicate() == ICmpInst::ICMP_SLT) if (!C)
if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1))) return false;
if (C->isZero()) {
X = I->getOperand(0);
Y = ConstantInt::get(I->getContext(),
APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_NE;
Z = C;
return true;
}
// X > -1 is equivalent to (X & SignBit) == 0. switch (I->getPredicate()) {
if (I->getPredicate() == ICmpInst::ICMP_SGT) default:
if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1))) return false;
if (C->isAllOnesValue()) { case ICmpInst::ICMP_SLT:
X = I->getOperand(0); // X < 0 is equivalent to (X & SignBit) != 0.
Y = ConstantInt::get(I->getContext(), if (!C->isZero())
APInt::getSignBit(C->getBitWidth())); return false;
Pred = ICmpInst::ICMP_EQ; Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
Z = ConstantInt::getNullValue(C->getType()); Pred = ICmpInst::ICMP_NE;
return true; break;
} case ICmpInst::ICMP_SGT:
// X > -1 is equivalent to (X & SignBit) == 0.
if (!C->isAllOnesValue())
return false;
Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_EQ;
break;
case ICmpInst::ICMP_ULT:
// X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
if (!C->getValue().isPowerOf2())
return false;
Y = ConstantInt::get(I->getContext(), -C->getValue());
Pred = ICmpInst::ICMP_EQ;
break;
case ICmpInst::ICMP_UGT:
// X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
if (!(C->getValue() + 1).isPowerOf2())
return false;
Y = ConstantInt::get(I->getContext(), ~C->getValue());
Pred = ICmpInst::ICMP_NE;
break;
}
return false; X = I->getOperand(0);
Z = ConstantInt::getNullValue(C->getType());
return true;
} }
/// foldLogOpOfMaskedICmpsHelper: /// foldLogOpOfMaskedICmpsHelper:

View File

@ -177,3 +177,41 @@ if.then:
if.end: if.end:
ret void ret void
} }
define void @test10(i32 %a) nounwind {
%1 = and i32 %a, 2
%2 = icmp eq i32 %1, 0
%3 = icmp ult i32 %a, 4
%or.cond = and i1 %2, %3
br i1 %or.cond, label %if.then, label %if.end
; CHECK-LABEL: @test10(
; CHECK-NEXT: %1 = icmp ult i32 %a, 2
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
if.then:
tail call void @foo() nounwind
ret void
if.end:
ret void
}
define void @test11(i32 %a) nounwind {
%1 = and i32 %a, 2
%2 = icmp ne i32 %1, 0
%3 = icmp ugt i32 %a, 3
%or.cond = or i1 %2, %3
br i1 %or.cond, label %if.then, label %if.end
; CHECK-LABEL: @test11(
; CHECK-NEXT: %1 = icmp ugt i32 %a, 1
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
if.then:
tail call void @foo() nounwind
ret void
if.end:
ret void
}