Fix a random missed optimization by making InstCombine more aggressive when determining which bits are demanded by

a comparison against a constant.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123203 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2011-01-11 00:36:45 +00:00
parent 93c70426f5
commit da1c122da5
3 changed files with 57 additions and 17 deletions

View File

@ -1627,21 +1627,6 @@ int bar() { return foo("abcd"); }
//===---------------------------------------------------------------------===//
InstCombine should use SimplifyDemandedBits to remove the or instruction:
define i1 @test(i8 %x, i8 %y) {
%A = or i8 %x, 1
%B = icmp ugt i8 %A, 3
ret i1 %B
}
Currently instcombine calls SimplifyDemandedBits with either all bits or just
the sign bit, if the comparison is obviously a sign test. In this case, we only
need all but the bottom two bits from %A, and if we gave that mask to SDB it
would delete the or instruction for us.
//===---------------------------------------------------------------------===//
functionattrs doesn't know much about memcpy/memset. This function should be
marked readnone rather than readonly, since it only twiddles local memory, but
functionattrs doesn't handle memset/memcpy/memmove aggressively:

View File

@ -1693,6 +1693,45 @@ static Instruction *ProcessUAddIdiom(Instruction &I, Value *OrigAddV,
return ExtractValueInst::Create(Call, 1, "uadd.overflow");
}
// DemandedBitsLHSMask - When performing a comparison against a constant,
// it is possible that not all the bits in the LHS are demanded. This helper
// method computes the mask that IS demanded.
static APInt DemandedBitsLHSMask(ICmpInst &I,
unsigned BitWidth, bool isSignCheck) {
if (isSignCheck)
return APInt::getSignBit(BitWidth);
ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1));
if (!CI) return APInt::getAllOnesValue(BitWidth);
APInt RHS = CI->getValue();
APInt Mask(BitWidth, 0);
switch (I.getPredicate()) {
// For a UGT comparison, we don't care about any bits that
// correspond to the trailing ones of the comparand. The value of these
// bits doesn't impact the outcome of the comparison, because any value
// greater than the RHS must differ in a bit higher than these due to carry.
case ICmpInst::ICMP_UGT: {
unsigned trailingOnes = RHS.countTrailingOnes();
APInt lowBitsSet = APInt::getLowBitsSet(BitWidth, trailingOnes);
return ~lowBitsSet;
}
// Similarly, for a ULT comparison, we don't care about the trailing zeros.
// Any value less than the RHS must differ in a higher bit because of carries.
case ICmpInst::ICMP_ULT: {
unsigned trailingZeros = RHS.countTrailingZeros();
APInt lowBitsSet = APInt::getLowBitsSet(BitWidth, trailingZeros);
return ~lowBitsSet;
}
default:
return APInt::getAllOnesValue(BitWidth);
}
return Mask;
}
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
bool Changed = false;
@ -1830,8 +1869,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
APInt Op1KnownZero(BitWidth, 0), Op1KnownOne(BitWidth, 0);
if (SimplifyDemandedBits(I.getOperandUse(0),
isSignBit ? APInt::getSignBit(BitWidth)
: APInt::getAllOnesValue(BitWidth),
DemandedBitsLHSMask(I, BitWidth, isSignBit),
Op0KnownZero, Op0KnownOne, 0))
return &I;
if (SimplifyDemandedBits(I.getOperandUse(1),

View File

@ -192,3 +192,20 @@ define i1 @test20(i32 %x) nounwind {
; CHECK-NEXT: %cmp = icmp eq i32 %x, 3
}
define i1 @test21(i8 %x, i8 %y) {
; CHECK: @test21
; CHECK-NOT: or i8
; CHECK: icmp ugt
%A = or i8 %x, 1
%B = icmp ugt i8 %A, 3
ret i1 %B
}
define i1 @test22(i8 %x, i8 %y) {
; CHECK: @test22
; CHECK-NOT: or i8
; CHECK: icmp ult
%A = or i8 %x, 1
%B = icmp ult i8 %A, 4
ret i1 %B
}