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:
parent
86c318f496
commit
94fc18d040
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue