mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
Implement a pretty general logical shift propagation
framework, which is good at ripping through bitfield operations. This generalize a bunch of the existing xforms that instcombine does, such as (x << c) >> c -> and to handle intermediate logical nodes. This is useful for ripping up the "promote to large integer" code produced by SRoA. llvm-svn: 112304
This commit is contained in:
parent
d107dd5cd2
commit
80632e5fd9
@ -566,8 +566,7 @@ Instruction *InstCombiner::transformZExtICmp(ICmpInst *ICI, Instruction &CI,
|
||||
|
||||
if (CI.getType() == In->getType())
|
||||
return ReplaceInstUsesWith(CI, In);
|
||||
else
|
||||
return CastInst::CreateIntegerCast(In, CI.getType(), false/*ZExt*/);
|
||||
return CastInst::CreateIntegerCast(In, CI.getType(), false/*ZExt*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,10 +56,236 @@ Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// CanEvaluateShifted - See if we can compute the specified value, but shifted
|
||||
/// logically to the left or right by some number of bits. This should return
|
||||
/// true if the expression can be computed for the same cost as the current
|
||||
/// expression tree. This is used to eliminate extraneous shifting from things
|
||||
/// like:
|
||||
/// %C = shl i128 %A, 64
|
||||
/// %D = shl i128 %B, 96
|
||||
/// %E = or i128 %C, %D
|
||||
/// %F = lshr i128 %E, 64
|
||||
/// where the client will ask if E can be computed shifted right by 64-bits. If
|
||||
/// this succeeds, the GetShiftedValue function will be called to produce the
|
||||
/// value.
|
||||
static bool CanEvaluateShifted(Value *V, unsigned NumBits, bool isLeftShift,
|
||||
InstCombiner &IC) {
|
||||
// We can always evaluate constants shifted.
|
||||
if (isa<Constant>(V))
|
||||
return true;
|
||||
|
||||
Instruction *I = dyn_cast<Instruction>(V);
|
||||
if (!I) return false;
|
||||
|
||||
// If this is the opposite shift, we can directly reuse the input of the shift
|
||||
// if the needed bits are already zero in the input. This allows us to reuse
|
||||
// the value which means that we don't care if the shift has multiple uses.
|
||||
// TODO: Handle opposite shift by exact value.
|
||||
ConstantInt *CI;
|
||||
if ((isLeftShift && match(I, m_LShr(m_Value(), m_ConstantInt(CI)))) ||
|
||||
(!isLeftShift && match(I, m_Shl(m_Value(), m_ConstantInt(CI))))) {
|
||||
if (CI->getZExtValue() == NumBits) {
|
||||
// TODO: Check that the input bits are already zero with MaskedValueIsZero
|
||||
#if 0
|
||||
// If this is a truncate of a logical shr, we can truncate it to a smaller
|
||||
// lshr iff we know that the bits we would otherwise be shifting in are
|
||||
// already zeros.
|
||||
uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits();
|
||||
uint32_t BitWidth = Ty->getScalarSizeInBits();
|
||||
if (MaskedValueIsZero(I->getOperand(0),
|
||||
APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth)) &&
|
||||
CI->getLimitedValue(BitWidth) < BitWidth) {
|
||||
return CanEvaluateTruncated(I->getOperand(0), Ty);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// We can't mutate something that has multiple uses: doing so would
|
||||
// require duplicating the instruction in general, which isn't profitable.
|
||||
if (!I->hasOneUse()) return false;
|
||||
|
||||
switch (I->getOpcode()) {
|
||||
default: return false;
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
// Bitwise operators can all arbitrarily be arbitrarily evaluated shifted.
|
||||
return CanEvaluateShifted(I->getOperand(0), NumBits, isLeftShift, IC) &&
|
||||
CanEvaluateShifted(I->getOperand(1), NumBits, isLeftShift, IC);
|
||||
|
||||
case Instruction::Shl:
|
||||
// We can often fold the shift into shifts-by-a-constant.
|
||||
CI = dyn_cast<ConstantInt>(I->getOperand(1));
|
||||
if (CI == 0) return false;
|
||||
|
||||
// We can always fold shl(c1)+shl(c2) -> shl(c1+c2).
|
||||
if (isLeftShift) return true;
|
||||
|
||||
// We can always turn shl(c)+shr(c) -> and(c2).
|
||||
if (CI->getValue() == NumBits) return true;
|
||||
// We can always turn shl(c1)+shr(c2) -> shl(c3)+and(c4), but it isn't
|
||||
// profitable unless we know the and'd out bits are already zero.
|
||||
return false;
|
||||
case Instruction::LShr:
|
||||
// We can often fold the shift into shifts-by-a-constant.
|
||||
CI = dyn_cast<ConstantInt>(I->getOperand(1));
|
||||
if (CI == 0) return false;
|
||||
|
||||
// We can always fold lshr(c1)+lshr(c2) -> lshr(c1+c2).
|
||||
if (!isLeftShift) return true;
|
||||
|
||||
// We can always turn lshr(c)+shl(c) -> and(c2).
|
||||
if (CI->getValue() == NumBits) return true;
|
||||
|
||||
// We can always turn lshr(c1)+shl(c2) -> lshr(c3)+and(c4), but it isn't
|
||||
// profitable unless we know the and'd out bits are already zero.
|
||||
return false;
|
||||
|
||||
case Instruction::Select: {
|
||||
SelectInst *SI = cast<SelectInst>(I);
|
||||
return CanEvaluateShifted(SI->getTrueValue(), NumBits, isLeftShift, IC) &&
|
||||
CanEvaluateShifted(SI->getFalseValue(), NumBits, isLeftShift, IC);
|
||||
}
|
||||
case Instruction::PHI: {
|
||||
// We can change a phi if we can change all operands. Note that we never
|
||||
// get into trouble with cyclic PHIs here because we only consider
|
||||
// instructions with a single use.
|
||||
PHINode *PN = cast<PHINode>(I);
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
||||
if (!CanEvaluateShifted(PN->getIncomingValue(i), NumBits, isLeftShift,IC))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// GetShiftedValue - When CanEvaluateShifted returned true for an expression,
|
||||
/// this value inserts the new computation that produces the shifted value.
|
||||
static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
|
||||
InstCombiner &IC) {
|
||||
// We can always evaluate constants shifted.
|
||||
if (Constant *C = dyn_cast<Constant>(V)) {
|
||||
if (isLeftShift)
|
||||
V = IC.Builder->CreateShl(C, NumBits);
|
||||
else
|
||||
V = IC.Builder->CreateLShr(C, NumBits);
|
||||
// If we got a constantexpr back, try to simplify it with TD info.
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||
V = ConstantFoldConstantExpression(CE, IC.getTargetData());
|
||||
return V;
|
||||
}
|
||||
|
||||
Instruction *I = cast<Instruction>(V);
|
||||
IC.Worklist.Add(I);
|
||||
|
||||
switch (I->getOpcode()) {
|
||||
default: assert(0 && "Inconsistency with CanEvaluateShifted");
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
// Bitwise operators can all arbitrarily be arbitrarily evaluated shifted.
|
||||
I->setOperand(0, GetShiftedValue(I->getOperand(0), NumBits,isLeftShift,IC));
|
||||
I->setOperand(1, GetShiftedValue(I->getOperand(1), NumBits,isLeftShift,IC));
|
||||
return I;
|
||||
|
||||
case Instruction::Shl: {
|
||||
unsigned TypeWidth = I->getType()->getScalarSizeInBits();
|
||||
|
||||
// We only accept shifts-by-a-constant in CanEvaluateShifted.
|
||||
ConstantInt *CI = cast<ConstantInt>(I->getOperand(1));
|
||||
|
||||
// We can always fold shl(c1)+shl(c2) -> shl(c1+c2).
|
||||
if (isLeftShift) {
|
||||
// If this is oversized composite shift, then unsigned shifts get 0.
|
||||
unsigned NewShAmt = NumBits+CI->getZExtValue();
|
||||
if (NewShAmt >= TypeWidth)
|
||||
return Constant::getNullValue(I->getType());
|
||||
|
||||
I->setOperand(1, ConstantInt::get(I->getType(), NewShAmt));
|
||||
return I;
|
||||
}
|
||||
|
||||
// We turn shl(c)+lshr(c) -> and(c2) if the input doesn't already have
|
||||
// zeros.
|
||||
assert(CI->getValue() == NumBits);
|
||||
|
||||
APInt Mask(APInt::getLowBitsSet(TypeWidth, TypeWidth - NumBits));
|
||||
V = IC.Builder->CreateAnd(I->getOperand(0),
|
||||
ConstantInt::get(I->getContext(), Mask));
|
||||
if (Instruction *VI = dyn_cast<Instruction>(V)) {
|
||||
VI->moveBefore(I);
|
||||
VI->takeName(I);
|
||||
}
|
||||
return V;
|
||||
}
|
||||
case Instruction::LShr: {
|
||||
unsigned TypeWidth = I->getType()->getScalarSizeInBits();
|
||||
// We only accept shifts-by-a-constant in CanEvaluateShifted.
|
||||
ConstantInt *CI = cast<ConstantInt>(I->getOperand(1));
|
||||
|
||||
// We can always fold lshr(c1)+lshr(c2) -> lshr(c1+c2).
|
||||
if (!isLeftShift) {
|
||||
// If this is oversized composite shift, then unsigned shifts get 0.
|
||||
unsigned NewShAmt = NumBits+CI->getZExtValue();
|
||||
if (NewShAmt >= TypeWidth)
|
||||
return Constant::getNullValue(I->getType());
|
||||
|
||||
I->setOperand(1, ConstantInt::get(I->getType(), NewShAmt));
|
||||
return I;
|
||||
}
|
||||
|
||||
// We turn lshr(c)+shl(c) -> and(c2) if the input doesn't already have
|
||||
// zeros.
|
||||
assert(CI->getValue() == NumBits);
|
||||
|
||||
APInt Mask(APInt::getHighBitsSet(TypeWidth, TypeWidth - NumBits));
|
||||
V = IC.Builder->CreateAnd(I->getOperand(0),
|
||||
ConstantInt::get(I->getContext(), Mask));
|
||||
if (Instruction *VI = dyn_cast<Instruction>(V)) {
|
||||
VI->moveBefore(I);
|
||||
VI->takeName(I);
|
||||
}
|
||||
return V;
|
||||
}
|
||||
|
||||
case Instruction::Select:
|
||||
I->setOperand(1, GetShiftedValue(I->getOperand(1), NumBits,isLeftShift,IC));
|
||||
I->setOperand(2, GetShiftedValue(I->getOperand(2), NumBits,isLeftShift,IC));
|
||||
return I;
|
||||
case Instruction::PHI: {
|
||||
// We can change a phi if we can change all operands. Note that we never
|
||||
// get into trouble with cyclic PHIs here because we only consider
|
||||
// instructions with a single use.
|
||||
PHINode *PN = cast<PHINode>(I);
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
||||
PN->setIncomingValue(i, GetShiftedValue(PN->getIncomingValue(i),
|
||||
NumBits, isLeftShift, IC));
|
||||
return PN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
||||
BinaryOperator &I) {
|
||||
bool isLeftShift = I.getOpcode() == Instruction::Shl;
|
||||
|
||||
|
||||
// See if we can propagate this shift into the input, this covers the trivial
|
||||
// cast of lshr(shl(x,c1),c2) as well as other more complex cases.
|
||||
if (I.getOpcode() != Instruction::AShr &&
|
||||
CanEvaluateShifted(Op0, Op1->getZExtValue(), isLeftShift, *this)) {
|
||||
DEBUG(dbgs() << "ICE: GetShiftedValue propagatin shift through expression"
|
||||
" to eliminate shift:\n IN: " << *Op0 << "\nSH: " << I << "\n");
|
||||
|
||||
return ReplaceInstUsesWith(I,
|
||||
GetShiftedValue(Op0, Op1->getZExtValue(), isLeftShift, *this));
|
||||
}
|
||||
|
||||
|
||||
// See if we can simplify any instructions used by the instruction whose sole
|
||||
// purpose is to compute bits we don't care about.
|
||||
uint32_t TypeBits = Op0->getType()->getScalarSizeInBits();
|
||||
|
@ -130,8 +130,8 @@ define i8 @test13(i8 %A) {
|
||||
;; D = ((B | 1234) << 4) === ((B << 4)|(1234 << 4)
|
||||
define i32 @test14(i32 %A) {
|
||||
; CHECK: @test14
|
||||
; CHECK-NEXT: or i32 %A, 19744
|
||||
; CHECK-NEXT: and i32
|
||||
; CHECK-NEXT: %B = and i32 %A, -19760
|
||||
; CHECK-NEXT: or i32 %B, 19744
|
||||
; CHECK-NEXT: ret i32
|
||||
%B = lshr i32 %A, 4 ; <i32> [#uses=1]
|
||||
%C = or i32 %B, 1234 ; <i32> [#uses=1]
|
||||
@ -350,8 +350,8 @@ entry:
|
||||
%tmp10 = lshr i32 %tmp917, 31
|
||||
ret i32 %tmp10
|
||||
; CHECK: @test29
|
||||
; CHECK: %tmp101 = lshr i64 %d18, 63
|
||||
; CHECK: %tmp10 = trunc i64 %tmp101 to i32
|
||||
; CHECK: %tmp916 = lshr i64 %d18, 63
|
||||
; CHECK: %tmp10 = trunc i64 %tmp916 to i32
|
||||
}
|
||||
|
||||
|
||||
@ -412,3 +412,16 @@ define i1 @test35(i32 %X) {
|
||||
; CHECK: ret i1 %tmp2
|
||||
}
|
||||
|
||||
define i128 @test36(i128 %A, i128 %B) {
|
||||
entry:
|
||||
%tmp27 = shl i128 %A, 64
|
||||
%tmp23 = shl i128 %B, 64
|
||||
%ins = or i128 %tmp23, %tmp27
|
||||
%tmp45 = lshr i128 %ins, 64
|
||||
ret i128 %tmp45
|
||||
|
||||
; CHECK: %tmp231 = or i128 %B, %A
|
||||
; CHECK: %ins = and i128 %tmp231, 18446744073709551615
|
||||
; CHECK: ret i128 %ins
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user