2010-01-05 15:44:46 +08:00
|
|
|
//===- InstCombineShifts.cpp ----------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the visitShl, visitLShr, and visitAShr functions.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "InstCombine.h"
|
2010-01-24 02:49:30 +08:00
|
|
|
#include "llvm/IntrinsicInst.h"
|
2010-01-05 15:44:46 +08:00
|
|
|
#include "llvm/Support/PatternMatch.h"
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace PatternMatch;
|
|
|
|
|
|
|
|
Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
|
|
|
|
assert(I.getOperand(1)->getType() == I.getOperand(0)->getType());
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
|
|
|
|
// shl X, 0 == X and shr X, 0 == X
|
|
|
|
// shl 0, X == 0 and shr 0, X == 0
|
|
|
|
if (Op1 == Constant::getNullValue(Op1->getType()) ||
|
|
|
|
Op0 == Constant::getNullValue(Op0->getType()))
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
|
|
|
|
if (isa<UndefValue>(Op0)) {
|
|
|
|
if (I.getOpcode() == Instruction::AShr) // undef >>s X -> undef
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
else // undef << X -> 0, undef >>u X -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
}
|
|
|
|
if (isa<UndefValue>(Op1)) {
|
|
|
|
if (I.getOpcode() == Instruction::AShr) // X >>s undef -> X
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
else // X << undef, X >>u undef -> 0
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if we can fold away this shift.
|
|
|
|
if (SimplifyDemandedInstructionBits(I))
|
|
|
|
return &I;
|
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (isa<Constant>(Op0))
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
|
|
|
return R;
|
|
|
|
|
|
|
|
if (ConstantInt *CUI = dyn_cast<ConstantInt>(Op1))
|
|
|
|
if (Instruction *Res = FoldShiftByConstant(Op0, CUI, I))
|
|
|
|
return Res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-08-28 06:24:38 +08:00
|
|
|
/// 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);
|
|
|
|
|
2010-08-28 06:53:44 +08:00
|
|
|
case Instruction::Shl: {
|
2010-08-28 06:24:38 +08:00
|
|
|
// 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;
|
2010-08-28 06:53:44 +08:00
|
|
|
|
|
|
|
unsigned TypeWidth = I->getType()->getScalarSizeInBits();
|
|
|
|
|
|
|
|
// We can turn shl(c1)+shr(c2) -> shl(c3)+and(c4), but it isn't
|
2010-08-28 06:24:38 +08:00
|
|
|
// profitable unless we know the and'd out bits are already zero.
|
2010-08-28 06:53:44 +08:00
|
|
|
if (CI->getZExtValue() > NumBits) {
|
|
|
|
unsigned HighBits = CI->getZExtValue() - NumBits;
|
|
|
|
if (MaskedValueIsZero(I->getOperand(0),
|
|
|
|
APInt::getHighBitsSet(TypeWidth, HighBits)))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-28 06:24:38 +08:00
|
|
|
return false;
|
2010-08-28 06:53:44 +08:00
|
|
|
}
|
|
|
|
case Instruction::LShr: {
|
2010-08-28 06:24:38 +08:00
|
|
|
// 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;
|
|
|
|
|
2010-08-28 06:53:44 +08:00
|
|
|
unsigned TypeWidth = I->getType()->getScalarSizeInBits();
|
|
|
|
|
2010-08-28 06:24:38 +08:00
|
|
|
// 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.
|
2010-08-28 06:53:44 +08:00
|
|
|
if (CI->getZExtValue() > NumBits) {
|
|
|
|
unsigned LowBits = CI->getZExtValue() - NumBits;
|
|
|
|
if (MaskedValueIsZero(I->getOperand(0),
|
|
|
|
APInt::getLowBitsSet(TypeWidth, LowBits)))
|
|
|
|
return true;
|
|
|
|
}
|
2010-08-28 06:24:38 +08:00
|
|
|
|
2010-08-28 06:53:44 +08:00
|
|
|
return false;
|
|
|
|
}
|
2010-08-28 06:24:38 +08:00
|
|
|
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.
|
2010-08-28 06:53:44 +08:00
|
|
|
if (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;
|
2010-08-28 06:24:38 +08:00
|
|
|
}
|
2010-08-28 06:53:44 +08:00
|
|
|
|
|
|
|
// We turn shl(c1)+shr(c2) -> shl(c3)+and(c4), but only when we know that
|
|
|
|
// the and won't be needed.
|
|
|
|
assert(CI->getZExtValue() > NumBits);
|
|
|
|
I->setOperand(1, ConstantInt::get(I->getType(),
|
|
|
|
CI->getZExtValue() - NumBits));
|
|
|
|
return I;
|
2010-08-28 06:24:38 +08:00
|
|
|
}
|
|
|
|
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.
|
2010-08-28 06:53:44 +08:00
|
|
|
if (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;
|
2010-08-28 06:24:38 +08:00
|
|
|
}
|
2010-08-28 06:53:44 +08:00
|
|
|
|
|
|
|
// We turn lshr(c1)+shl(c2) -> lshr(c3)+and(c4), but only when we know that
|
|
|
|
// the and won't be needed.
|
|
|
|
assert(CI->getZExtValue() > NumBits);
|
|
|
|
I->setOperand(1, ConstantInt::get(I->getType(),
|
|
|
|
CI->getZExtValue() - NumBits));
|
|
|
|
return I;
|
2010-08-28 06:24:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-01-05 15:44:46 +08:00
|
|
|
Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
|
|
|
BinaryOperator &I) {
|
|
|
|
bool isLeftShift = I.getOpcode() == Instruction::Shl;
|
2010-08-28 05:04:34 +08:00
|
|
|
|
2010-08-28 06:24:38 +08:00
|
|
|
|
|
|
|
// 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)) {
|
optimize bitcasts from large integers to vector into vector
element insertion from the pieces that feed into the vector.
This handles a pattern that occurs frequently due to code
generated for the x86-64 abi. We now compile something like
this:
struct S { float A, B, C, D; };
struct S g;
struct S bar() {
struct S A = g;
++A.A;
++A.C;
return A;
}
into all nice vector operations:
_bar: ## @bar
## BB#0: ## %entry
movq _g@GOTPCREL(%rip), %rax
movss LCPI1_0(%rip), %xmm1
movss (%rax), %xmm0
addss %xmm1, %xmm0
pshufd $16, %xmm0, %xmm0
movss 4(%rax), %xmm2
movss 12(%rax), %xmm3
pshufd $16, %xmm2, %xmm2
unpcklps %xmm2, %xmm0
addss 8(%rax), %xmm1
pshufd $16, %xmm1, %xmm1
pshufd $16, %xmm3, %xmm2
unpcklps %xmm2, %xmm1
ret
instead of icky integer operations:
_bar: ## @bar
movq _g@GOTPCREL(%rip), %rax
movss LCPI1_0(%rip), %xmm1
movss (%rax), %xmm0
addss %xmm1, %xmm0
movd %xmm0, %ecx
movl 4(%rax), %edx
movl 12(%rax), %esi
shlq $32, %rdx
addq %rcx, %rdx
movd %rdx, %xmm0
addss 8(%rax), %xmm1
movd %xmm1, %eax
shlq $32, %rsi
addq %rax, %rsi
movd %rsi, %xmm1
ret
This resolves rdar://8360454
llvm-svn: 112343
2010-08-28 09:20:38 +08:00
|
|
|
DEBUG(dbgs() << "ICE: GetShiftedValue propagating shift through expression"
|
|
|
|
" to eliminate shift:\n IN: " << *Op0 << "\n SH: " << I <<"\n");
|
2010-08-28 06:24:38 +08:00
|
|
|
|
|
|
|
return ReplaceInstUsesWith(I,
|
|
|
|
GetShiftedValue(Op0, Op1->getZExtValue(), isLeftShift, *this));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-05 15:44:46 +08:00
|
|
|
// 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();
|
|
|
|
|
|
|
|
// shl i32 X, 32 = 0 and srl i8 Y, 9 = 0, ... just don't eliminate
|
|
|
|
// a signed shift.
|
|
|
|
//
|
|
|
|
if (Op1->uge(TypeBits)) {
|
|
|
|
if (I.getOpcode() != Instruction::AShr)
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
|
2010-01-24 02:49:30 +08:00
|
|
|
// ashr i32 X, 32 --> ashr i32 X, 31
|
|
|
|
I.setOperand(1, ConstantInt::get(I.getType(), TypeBits-1));
|
|
|
|
return &I;
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// ((X*C1) << C2) == (X * (C1 << C2))
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0))
|
|
|
|
if (BO->getOpcode() == Instruction::Mul && isLeftShift)
|
|
|
|
if (Constant *BOOp = dyn_cast<Constant>(BO->getOperand(1)))
|
|
|
|
return BinaryOperator::CreateMul(BO->getOperand(0),
|
|
|
|
ConstantExpr::getShl(BOOp, Op1));
|
|
|
|
|
|
|
|
// Try to fold constant and into select arguments.
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
|
|
|
return R;
|
|
|
|
if (isa<PHINode>(Op0))
|
|
|
|
if (Instruction *NV = FoldOpIntoPhi(I))
|
|
|
|
return NV;
|
|
|
|
|
|
|
|
// Fold shift2(trunc(shift1(x,c1)), c2) -> trunc(shift2(shift1(x,c1),c2))
|
|
|
|
if (TruncInst *TI = dyn_cast<TruncInst>(Op0)) {
|
|
|
|
Instruction *TrOp = dyn_cast<Instruction>(TI->getOperand(0));
|
|
|
|
// If 'shift2' is an ashr, we would have to get the sign bit into a funny
|
|
|
|
// place. Don't try to do this transformation in this case. Also, we
|
|
|
|
// require that the input operand is a shift-by-constant so that we have
|
|
|
|
// confidence that the shifts will get folded together. We could do this
|
|
|
|
// xform in more cases, but it is unlikely to be profitable.
|
|
|
|
if (TrOp && I.isLogicalShift() && TrOp->isShift() &&
|
|
|
|
isa<ConstantInt>(TrOp->getOperand(1))) {
|
|
|
|
// Okay, we'll do this xform. Make the shift of shift.
|
|
|
|
Constant *ShAmt = ConstantExpr::getZExt(Op1, TrOp->getType());
|
|
|
|
// (shift2 (shift1 & 0x00FF), c2)
|
|
|
|
Value *NSh = Builder->CreateBinOp(I.getOpcode(), TrOp, ShAmt,I.getName());
|
|
|
|
|
|
|
|
// For logical shifts, the truncation has the effect of making the high
|
|
|
|
// part of the register be zeros. Emulate this by inserting an AND to
|
|
|
|
// clear the top bits as needed. This 'and' will usually be zapped by
|
|
|
|
// other xforms later if dead.
|
|
|
|
unsigned SrcSize = TrOp->getType()->getScalarSizeInBits();
|
|
|
|
unsigned DstSize = TI->getType()->getScalarSizeInBits();
|
|
|
|
APInt MaskV(APInt::getLowBitsSet(SrcSize, DstSize));
|
|
|
|
|
|
|
|
// The mask we constructed says what the trunc would do if occurring
|
|
|
|
// between the shifts. We want to know the effect *after* the second
|
|
|
|
// shift. We know that it is a logical shift by a constant, so adjust the
|
|
|
|
// mask as appropriate.
|
|
|
|
if (I.getOpcode() == Instruction::Shl)
|
|
|
|
MaskV <<= Op1->getZExtValue();
|
|
|
|
else {
|
|
|
|
assert(I.getOpcode() == Instruction::LShr && "Unknown logical shift");
|
|
|
|
MaskV = MaskV.lshr(Op1->getZExtValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
// shift1 & 0x00FF
|
|
|
|
Value *And = Builder->CreateAnd(NSh,
|
|
|
|
ConstantInt::get(I.getContext(), MaskV),
|
|
|
|
TI->getName());
|
|
|
|
|
|
|
|
// Return the value truncated to the interesting size.
|
|
|
|
return new TruncInst(And, I.getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Op0->hasOneUse()) {
|
|
|
|
if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0)) {
|
|
|
|
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
|
|
|
|
Value *V1, *V2;
|
|
|
|
ConstantInt *CC;
|
|
|
|
switch (Op0BO->getOpcode()) {
|
2010-01-10 14:59:55 +08:00
|
|
|
default: break;
|
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor: {
|
|
|
|
// These operators commute.
|
|
|
|
// Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C)
|
|
|
|
if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(1), m_Shr(m_Value(V1),
|
|
|
|
m_Specific(Op1)))) {
|
|
|
|
Value *YS = // (Y << C)
|
|
|
|
Builder->CreateShl(Op0BO->getOperand(0), Op1, Op0BO->getName());
|
|
|
|
// (X + (Y << C))
|
|
|
|
Value *X = Builder->CreateBinOp(Op0BO->getOpcode(), YS, V1,
|
|
|
|
Op0BO->getOperand(1)->getName());
|
|
|
|
uint32_t Op1Val = Op1->getLimitedValue(TypeBits);
|
|
|
|
return BinaryOperator::CreateAnd(X, ConstantInt::get(I.getContext(),
|
|
|
|
APInt::getHighBitsSet(TypeBits, TypeBits-Op1Val)));
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
2010-01-10 14:59:55 +08:00
|
|
|
|
|
|
|
// Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C))
|
|
|
|
Value *Op0BOOp1 = Op0BO->getOperand(1);
|
|
|
|
if (isLeftShift && Op0BOOp1->hasOneUse() &&
|
|
|
|
match(Op0BOOp1,
|
|
|
|
m_And(m_Shr(m_Value(V1), m_Specific(Op1)),
|
|
|
|
m_ConstantInt(CC))) &&
|
|
|
|
cast<BinaryOperator>(Op0BOOp1)->getOperand(0)->hasOneUse()) {
|
|
|
|
Value *YS = // (Y << C)
|
|
|
|
Builder->CreateShl(Op0BO->getOperand(0), Op1,
|
|
|
|
Op0BO->getName());
|
|
|
|
// X & (CC << C)
|
|
|
|
Value *XM = Builder->CreateAnd(V1, ConstantExpr::getShl(CC, Op1),
|
|
|
|
V1->getName()+".mask");
|
|
|
|
return BinaryOperator::Create(Op0BO->getOpcode(), YS, XM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FALL THROUGH.
|
|
|
|
case Instruction::Sub: {
|
|
|
|
// Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
|
|
|
|
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(0), m_Shr(m_Value(V1),
|
|
|
|
m_Specific(Op1)))) {
|
|
|
|
Value *YS = // (Y << C)
|
|
|
|
Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
|
|
|
|
// (X + (Y << C))
|
|
|
|
Value *X = Builder->CreateBinOp(Op0BO->getOpcode(), V1, YS,
|
|
|
|
Op0BO->getOperand(0)->getName());
|
|
|
|
uint32_t Op1Val = Op1->getLimitedValue(TypeBits);
|
|
|
|
return BinaryOperator::CreateAnd(X, ConstantInt::get(I.getContext(),
|
|
|
|
APInt::getHighBitsSet(TypeBits, TypeBits-Op1Val)));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn (((X >> C)&CC) + Y) << C -> (X + (Y << C)) & (CC << C)
|
|
|
|
if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
|
|
|
|
match(Op0BO->getOperand(0),
|
|
|
|
m_And(m_Shr(m_Value(V1), m_Value(V2)),
|
|
|
|
m_ConstantInt(CC))) && V2 == Op1 &&
|
|
|
|
cast<BinaryOperator>(Op0BO->getOperand(0))
|
|
|
|
->getOperand(0)->hasOneUse()) {
|
|
|
|
Value *YS = // (Y << C)
|
|
|
|
Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->getName());
|
|
|
|
// X & (CC << C)
|
|
|
|
Value *XM = Builder->CreateAnd(V1, ConstantExpr::getShl(CC, Op1),
|
|
|
|
V1->getName()+".mask");
|
2010-01-05 15:44:46 +08:00
|
|
|
|
2010-01-10 14:59:55 +08:00
|
|
|
return BinaryOperator::Create(Op0BO->getOpcode(), XM, YS);
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
2010-01-10 14:59:55 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// If the operand is an bitwise operator with a constant RHS, and the
|
|
|
|
// shift is the only use, we can pull it out of the shift.
|
|
|
|
if (ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
|
|
|
|
bool isValid = true; // Valid only for And, Or, Xor
|
|
|
|
bool highBitSet = false; // Transform if high bit of constant set?
|
|
|
|
|
|
|
|
switch (Op0BO->getOpcode()) {
|
2010-01-10 14:59:55 +08:00
|
|
|
default: isValid = false; break; // Do not perform transform!
|
|
|
|
case Instruction::Add:
|
|
|
|
isValid = isLeftShift;
|
|
|
|
break;
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
highBitSet = false;
|
|
|
|
break;
|
|
|
|
case Instruction::And:
|
|
|
|
highBitSet = true;
|
|
|
|
break;
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a signed shift right, and the high bit is modified
|
|
|
|
// by the logical operation, do not perform the transformation.
|
|
|
|
// The highBitSet boolean indicates the value of the high bit of
|
|
|
|
// the constant which would cause it to be modified for this
|
|
|
|
// operation.
|
|
|
|
//
|
|
|
|
if (isValid && I.getOpcode() == Instruction::AShr)
|
|
|
|
isValid = Op0C->getValue()[TypeBits-1] == highBitSet;
|
|
|
|
|
|
|
|
if (isValid) {
|
|
|
|
Constant *NewRHS = ConstantExpr::get(I.getOpcode(), Op0C, Op1);
|
|
|
|
|
|
|
|
Value *NewShift =
|
|
|
|
Builder->CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), Op1);
|
|
|
|
NewShift->takeName(Op0BO);
|
|
|
|
|
|
|
|
return BinaryOperator::Create(Op0BO->getOpcode(), NewShift,
|
|
|
|
NewRHS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find out if this is a shift of a shift by a constant.
|
|
|
|
BinaryOperator *ShiftOp = dyn_cast<BinaryOperator>(Op0);
|
|
|
|
if (ShiftOp && !ShiftOp->isShift())
|
|
|
|
ShiftOp = 0;
|
|
|
|
|
|
|
|
if (ShiftOp && isa<ConstantInt>(ShiftOp->getOperand(1))) {
|
|
|
|
ConstantInt *ShiftAmt1C = cast<ConstantInt>(ShiftOp->getOperand(1));
|
|
|
|
uint32_t ShiftAmt1 = ShiftAmt1C->getLimitedValue(TypeBits);
|
|
|
|
uint32_t ShiftAmt2 = Op1->getLimitedValue(TypeBits);
|
|
|
|
assert(ShiftAmt2 != 0 && "Should have been simplified earlier");
|
|
|
|
if (ShiftAmt1 == 0) return 0; // Will be simplified in the future.
|
|
|
|
Value *X = ShiftOp->getOperand(0);
|
|
|
|
|
|
|
|
uint32_t AmtSum = ShiftAmt1+ShiftAmt2; // Fold into one big shift.
|
|
|
|
|
|
|
|
const IntegerType *Ty = cast<IntegerType>(I.getType());
|
|
|
|
|
|
|
|
// Check for (X << c1) << c2 and (X >> c1) >> c2
|
|
|
|
if (I.getOpcode() == ShiftOp->getOpcode()) {
|
|
|
|
// If this is oversized composite shift, then unsigned shifts get 0, ashr
|
|
|
|
// saturates.
|
|
|
|
if (AmtSum >= TypeBits) {
|
|
|
|
if (I.getOpcode() != Instruction::AShr)
|
|
|
|
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
|
|
|
AmtSum = TypeBits-1; // Saturate to 31 for i32 ashr.
|
|
|
|
}
|
|
|
|
|
|
|
|
return BinaryOperator::Create(I.getOpcode(), X,
|
|
|
|
ConstantInt::get(Ty, AmtSum));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ShiftAmt1 == ShiftAmt2) {
|
|
|
|
// If we have ((X >>? C) << C), turn this into X & (-1 << C).
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::Shl &&
|
|
|
|
ShiftOp->getOpcode() != Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt1));
|
|
|
|
return BinaryOperator::CreateAnd(X,
|
|
|
|
ConstantInt::get(I.getContext(),Mask));
|
|
|
|
}
|
|
|
|
// If we have ((X << C) >>u C), turn this into X & (-1 >>u C).
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::LShr &&
|
|
|
|
ShiftOp->getOpcode() == Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt1));
|
|
|
|
return BinaryOperator::CreateAnd(X,
|
|
|
|
ConstantInt::get(I.getContext(), Mask));
|
|
|
|
}
|
|
|
|
} else if (ShiftAmt1 < ShiftAmt2) {
|
|
|
|
uint32_t ShiftDiff = ShiftAmt2-ShiftAmt1;
|
|
|
|
|
|
|
|
// (X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2)
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::Shl &&
|
|
|
|
ShiftOp->getOpcode() != Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
assert(ShiftOp->getOpcode() == Instruction::LShr ||
|
|
|
|
ShiftOp->getOpcode() == Instruction::AShr);
|
|
|
|
Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff));
|
|
|
|
|
|
|
|
APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
|
|
|
return BinaryOperator::CreateAnd(Shift,
|
|
|
|
ConstantInt::get(I.getContext(),Mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
// (X << C1) >>u C2 --> X >>u (C2-C1) & (-1 >> C2)
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::LShr &&
|
|
|
|
ShiftOp->getOpcode() == Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
assert(ShiftOp->getOpcode() == Instruction::Shl);
|
|
|
|
Value *Shift = Builder->CreateLShr(X, ConstantInt::get(Ty, ShiftDiff));
|
|
|
|
|
|
|
|
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
|
|
|
return BinaryOperator::CreateAnd(Shift,
|
|
|
|
ConstantInt::get(I.getContext(),Mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can't handle (X << C1) >>s C2, it shifts arbitrary bits in.
|
|
|
|
} else {
|
|
|
|
assert(ShiftAmt2 < ShiftAmt1);
|
|
|
|
uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2;
|
|
|
|
|
|
|
|
// (X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2)
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::Shl &&
|
|
|
|
ShiftOp->getOpcode() != Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
Value *Shift = Builder->CreateBinOp(ShiftOp->getOpcode(), X,
|
|
|
|
ConstantInt::get(Ty, ShiftDiff));
|
|
|
|
|
|
|
|
APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
|
|
|
return BinaryOperator::CreateAnd(Shift,
|
|
|
|
ConstantInt::get(I.getContext(),Mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
// (X << C1) >>u C2 --> X << (C1-C2) & (-1 >> C2)
|
2010-08-28 05:04:34 +08:00
|
|
|
if (I.getOpcode() == Instruction::LShr &&
|
|
|
|
ShiftOp->getOpcode() == Instruction::Shl) {
|
2010-01-05 15:44:46 +08:00
|
|
|
Value *Shift = Builder->CreateShl(X, ConstantInt::get(Ty, ShiftDiff));
|
|
|
|
|
|
|
|
APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2));
|
|
|
|
return BinaryOperator::CreateAnd(Shift,
|
|
|
|
ConstantInt::get(I.getContext(),Mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
// We can't handle (X << C1) >>a C2, it shifts arbitrary bits in.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *InstCombiner::visitShl(BinaryOperator &I) {
|
|
|
|
return commonShiftTransforms(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
2010-01-24 02:49:30 +08:00
|
|
|
if (Instruction *R = commonShiftTransforms(I))
|
|
|
|
return R;
|
|
|
|
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
|
|
|
|
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1))
|
|
|
|
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
|
2010-01-24 07:31:46 +08:00
|
|
|
unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
|
2010-01-24 02:49:30 +08:00
|
|
|
// ctlz.i32(x)>>5 --> zext(x == 0)
|
|
|
|
// cttz.i32(x)>>5 --> zext(x == 0)
|
|
|
|
// ctpop.i32(x)>>5 --> zext(x == -1)
|
|
|
|
if ((II->getIntrinsicID() == Intrinsic::ctlz ||
|
|
|
|
II->getIntrinsicID() == Intrinsic::cttz ||
|
|
|
|
II->getIntrinsicID() == Intrinsic::ctpop) &&
|
2010-01-24 07:31:46 +08:00
|
|
|
isPowerOf2_32(BitWidth) && Log2_32(BitWidth) == Op1C->getZExtValue()){
|
2010-01-24 02:49:30 +08:00
|
|
|
bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
|
2010-01-24 07:31:46 +08:00
|
|
|
Constant *RHS = ConstantInt::getSigned(Op0->getType(), isCtPop ? -1:0);
|
2010-06-24 08:44:01 +08:00
|
|
|
Value *Cmp = Builder->CreateICmpEQ(II->getArgOperand(0), RHS);
|
2010-01-24 02:49:30 +08:00
|
|
|
return new ZExtInst(Cmp, II->getType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2010-01-05 15:44:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
|
|
|
if (Instruction *R = commonShiftTransforms(I))
|
|
|
|
return R;
|
|
|
|
|
2010-01-09 03:04:21 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2010-01-05 15:44:46 +08:00
|
|
|
|
2010-01-09 03:04:21 +08:00
|
|
|
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0)) {
|
|
|
|
// ashr int -1, X = -1 (for any arithmetic shift rights of ~0)
|
2010-01-05 15:44:46 +08:00
|
|
|
if (CSI->isAllOnesValue())
|
|
|
|
return ReplaceInstUsesWith(I, CSI);
|
2010-01-09 03:04:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
|
|
|
|
// If the input is a SHL by the same constant (ashr (shl X, C), C), then we
|
2010-01-19 06:19:16 +08:00
|
|
|
// have a sign-extend idiom.
|
2010-01-09 03:04:21 +08:00
|
|
|
Value *X;
|
2010-01-19 06:19:16 +08:00
|
|
|
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1)))) {
|
|
|
|
// If the input value is known to already be sign extended enough, delete
|
|
|
|
// the extension.
|
|
|
|
if (ComputeNumSignBits(X) > Op1C->getZExtValue())
|
|
|
|
return ReplaceInstUsesWith(I, X);
|
|
|
|
|
|
|
|
// If the input is an extension from the shifted amount value, e.g.
|
|
|
|
// %x = zext i8 %A to i32
|
|
|
|
// %y = shl i32 %x, 24
|
|
|
|
// %z = ashr %y, 24
|
|
|
|
// then turn this into "z = sext i8 A to i32".
|
|
|
|
if (ZExtInst *ZI = dyn_cast<ZExtInst>(X)) {
|
|
|
|
uint32_t SrcBits = ZI->getOperand(0)->getType()->getScalarSizeInBits();
|
|
|
|
uint32_t DestBits = ZI->getType()->getScalarSizeInBits();
|
|
|
|
if (Op1C->getZExtValue() == DestBits-SrcBits)
|
|
|
|
return new SExtInst(ZI->getOperand(0), ZI->getType());
|
|
|
|
}
|
|
|
|
}
|
2010-01-09 03:04:21 +08:00
|
|
|
}
|
2010-01-05 15:44:46 +08:00
|
|
|
|
|
|
|
// See if we can turn a signed shr into an unsigned shr.
|
|
|
|
if (MaskedValueIsZero(Op0,
|
|
|
|
APInt::getSignBit(I.getType()->getScalarSizeInBits())))
|
2010-01-09 03:04:21 +08:00
|
|
|
return BinaryOperator::CreateLShr(Op0, Op1);
|
2010-01-05 15:44:46 +08:00
|
|
|
|
|
|
|
// Arithmetic shifting an all-sign-bit value is a no-op.
|
|
|
|
unsigned NumSignBits = ComputeNumSignBits(Op0);
|
|
|
|
if (NumSignBits == Op0->getType()->getScalarSizeInBits())
|
|
|
|
return ReplaceInstUsesWith(I, Op0);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|