mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-09 13:21:30 +00:00
Fix a random missed optimization by making InstCombine more aggressive when determining which bits are demanded by
a comparison against a constant. llvm-svn: 123203
This commit is contained in:
parent
5a4d64216f
commit
4479341626
@ -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:
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user