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.
static bool decomposeBitTestICmp(const ICmpInst *I, ICmpInst::Predicate &Pred,
Value *&X, Value *&Y, Value *&Z) {
// X < 0 is equivalent to (X & SignBit) != 0.
if (I->getPredicate() == ICmpInst::ICMP_SLT)
if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1)))
if (C->isZero()) {
X = I->getOperand(0);
Y = ConstantInt::get(I->getContext(),
APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_NE;
Z = C;
return true;
}
ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1));
if (!C)
return false;
// X > -1 is equivalent to (X & SignBit) == 0.
if (I->getPredicate() == ICmpInst::ICMP_SGT)
if (ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1)))
if (C->isAllOnesValue()) {
X = I->getOperand(0);
Y = ConstantInt::get(I->getContext(),
APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_EQ;
Z = ConstantInt::getNullValue(C->getType());
return true;
}
switch (I->getPredicate()) {
default:
return false;
case ICmpInst::ICMP_SLT:
// X < 0 is equivalent to (X & SignBit) != 0.
if (!C->isZero())
return false;
Y = ConstantInt::get(I->getContext(), APInt::getSignBit(C->getBitWidth()));
Pred = ICmpInst::ICMP_NE;
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:

View File

@ -177,3 +177,41 @@ if.then:
if.end:
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
}