//
// This is a simple worklist driven algorithm.
//
+// This pass guarantees that the following cannonicalizations are performed on
+// the program:
+// 1. If a binary operator has a constant operand, it is moved to the RHS
+// 2. Bitwise operators with constant operands are always grouped so that
+// shifts are performed first, then or's, then and's, then xor's.
+// 3. SetCC instructions are converted from <,>,<=,>= to ==,!= if possible
+// 4. All SetCC instructions on boolean values are replaced with logical ops
+// 5. add X, X is represented as (X*2) => (X << 1)
+// 6. Multiplies with a power-of-two constant argument are transformed into
+// shifts.
+// N. This list is incomplete
+//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar.h"
return &I;
}
+ /// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
+ /// InsertBefore instruction. This is specialized a bit to avoid inserting
+ /// casts that are known to not do anything...
+ ///
+ Value *InsertOperandCastBefore(Value *V, const Type *DestTy,
+ Instruction *InsertBefore);
+
// SimplifyCommutative - This performs a few simplifications for commutative
// operators...
bool SimplifyCommutative(BinaryOperator &I);
// dyn_castMaskingAnd - If this value is an And instruction masking a value with
// a constant, return the constant being anded with.
//
-static inline Constant *dyn_castMaskingAnd(Value *V) {
+template<class ValueType>
+static inline Constant *dyn_castMaskingAnd(ValueType *V) {
if (Instruction *I = dyn_cast<Instruction>(V))
if (I->getOpcode() == Instruction::And)
return dyn_cast<Constant>(I->getOperand(1));
if (RHS == Constant::getNullValue(I.getType()))
return ReplaceInstUsesWith(I, LHS);
+ // Convert 'add X, X' to 'shl X, 1'
+ if (LHS == RHS && I.getType()->isInteger())
+ return new ShiftInst(Instruction::Shl, LHS,
+ ConstantInt::get(Type::UByteTy, 1));
+
// -A + B --> B - A
if (Value *V = dyn_castNegVal(LHS))
return BinaryOperator::create(Instruction::Sub, RHS, V);
return Changed ? &I : 0;
}
+// isSignBit - Return true if the value represented by the constant only has the
+// highest order bit set.
+static bool isSignBit(ConstantInt *CI) {
+ unsigned NumBits = CI->getType()->getPrimitiveSize()*8;
+ return (CI->getRawValue() & ~(-1LL << NumBits)) == (1ULL << (NumBits-1));
+}
+
+static unsigned getTypeSizeInBits(const Type *Ty) {
+ return Ty == Type::BoolTy ? 1 : Ty->getPrimitiveSize()*8;
+}
+
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// Simplify mul instructions with a constant RHS...
if (Constant *Op1 = dyn_cast<Constant>(I.getOperand(1))) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
+
+ // ((X << C1)*C2) == (X * (C2 << C1))
+ if (ShiftInst *SI = dyn_cast<ShiftInst>(Op0))
+ if (SI->getOpcode() == Instruction::Shl)
+ if (Constant *ShOp = dyn_cast<Constant>(SI->getOperand(1)))
+ return BinaryOperator::create(Instruction::Mul, SI->getOperand(0),
+ *CI << *ShOp);
+
const Type *Ty = CI->getType();
- int64_t Val = Ty->isSigned() ? cast<ConstantSInt>(CI)->getValue() :
- (int64_t)cast<ConstantUInt>(CI)->getValue();
+ int64_t Val = (int64_t)cast<ConstantInt>(CI)->getRawValue();
switch (Val) {
case -1: // X * -1 -> -X
return BinaryOperator::createNeg(Op0, I.getName());
return ReplaceInstUsesWith(I, Op1); // Eliminate 'mul double %X, 0'
case 1:
return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul int %X, 1'
- case 2: // Convert 'mul int %X, 2' to 'add int %X, %X'
- return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
}
if (uint64_t C = Log2(Val)) // Replace X*(2^C) with X << C
return ReplaceInstUsesWith(I, Op1);
// and X, -1 == X
- if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1))
+ if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
if (RHS->isAllOnesValue())
return ReplaceInstUsesWith(I, Op0);
+ if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
+ Value *X = Op0I->getOperand(0);
+ if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
+ if (Op0I->getOpcode() == Instruction::Xor) {
+ if ((*RHS & *Op0CI)->isNullValue()) {
+ // (X ^ C1) & C2 --> (X & C2) iff (C1&C2) == 0
+ return BinaryOperator::create(Instruction::And, X, RHS);
+ } else if (isOnlyUse(Op0)) {
+ // (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
+ std::string Op0Name = Op0I->getName(); Op0I->setName("");
+ Instruction *And = BinaryOperator::create(Instruction::And,
+ X, RHS, Op0Name);
+ InsertNewInstBefore(And, I);
+ return BinaryOperator::create(Instruction::Xor, And, *RHS & *Op0CI);
+ }
+ } else if (Op0I->getOpcode() == Instruction::Or) {
+ // (X | C1) & C2 --> X & C2 iff C1 & C1 == 0
+ if ((*RHS & *Op0CI)->isNullValue())
+ return BinaryOperator::create(Instruction::And, X, RHS);
+
+ Constant *Together = *RHS & *Op0CI;
+ if (Together == RHS) // (X | C) & C --> C
+ return ReplaceInstUsesWith(I, RHS);
+
+ if (isOnlyUse(Op0)) {
+ if (Together != Op0CI) {
+ // (X | C1) & C2 --> (X | (C1&C2)) & C2
+ std::string Op0Name = Op0I->getName(); Op0I->setName("");
+ Instruction *Or = BinaryOperator::create(Instruction::Or, X,
+ Together, Op0Name);
+ InsertNewInstBefore(Or, I);
+ return BinaryOperator::create(Instruction::And, Or, RHS);
+ }
+ }
+ }
+ }
+ }
+
Value *Op0NotVal = dyn_castNotVal(Op0);
Value *Op1NotVal = dyn_castNotVal(Op1);
// (~A & ~B) == (~(A | B)) - Demorgan's Law
if (Op0NotVal && Op1NotVal && isOnlyUse(Op0) && isOnlyUse(Op1)) {
Instruction *Or = BinaryOperator::create(Instruction::Or, Op0NotVal,
- Op1NotVal,I.getName()+".demorgan",
- &I);
- WorkList.push_back(Or);
+ Op1NotVal,I.getName()+".demorgan");
+ InsertNewInstBefore(Or, I);
return BinaryOperator::createNot(Or);
}
return ReplaceInstUsesWith(I, Op0);
// or X, -1 == -1
- if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1))
+ if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
if (RHS->isAllOnesValue())
return ReplaceInstUsesWith(I, Op1);
+ if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
+ // (X & C1) | C2 --> (X | C2) & (C1|C2)
+ if (Op0I->getOpcode() == Instruction::And && isOnlyUse(Op0))
+ if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
+ std::string Op0Name = Op0I->getName(); Op0I->setName("");
+ Instruction *Or = BinaryOperator::create(Instruction::Or,
+ Op0I->getOperand(0), RHS,
+ Op0Name);
+ InsertNewInstBefore(Or, I);
+ return BinaryOperator::create(Instruction::And, Or, *RHS | *Op0CI);
+ }
+
+ // (X ^ C1) | C2 --> (X | C2) ^ (C1&~C2)
+ if (Op0I->getOpcode() == Instruction::Xor && isOnlyUse(Op0))
+ if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
+ std::string Op0Name = Op0I->getName(); Op0I->setName("");
+ Instruction *Or = BinaryOperator::create(Instruction::Or,
+ Op0I->getOperand(0), RHS,
+ Op0Name);
+ InsertNewInstBefore(Or, I);
+ return BinaryOperator::create(Instruction::Xor, Or, *Op0CI & *~*RHS);
+ }
+ }
+ }
+
+ // (A & C1)|(A & C2) == A & (C1|C2)
+ if (Instruction *LHS = dyn_cast<BinaryOperator>(Op0))
+ if (Instruction *RHS = dyn_cast<BinaryOperator>(Op1))
+ if (LHS->getOperand(0) == RHS->getOperand(0))
+ if (Constant *C0 = dyn_castMaskingAnd(LHS))
+ if (Constant *C1 = dyn_castMaskingAnd(RHS))
+ return BinaryOperator::create(Instruction::And, LHS->getOperand(0),
+ *C0 | *C1);
+
Value *Op0NotVal = dyn_castNotVal(Op0);
Value *Op1NotVal = dyn_castNotVal(Op1);
if (Op0 == Op1)
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
- if (ConstantIntegral *Op1C = dyn_cast<ConstantIntegral>(Op1)) {
+ if (ConstantIntegral *RHS = dyn_cast<ConstantIntegral>(Op1)) {
// xor X, 0 == X
- if (Op1C->isNullValue())
+ if (RHS->isNullValue())
return ReplaceInstUsesWith(I, Op0);
- // Is this a "NOT" instruction?
- if (Op1C->isAllOnesValue()) {
- // xor (xor X, -1), -1 = not (not X) = X
- if (Value *X = dyn_castNotVal(Op0))
- return ReplaceInstUsesWith(I, X);
-
+ if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
// xor (setcc A, B), true = not (setcc A, B) = setncc A, B
- if (SetCondInst *SCI = dyn_cast<SetCondInst>(Op0))
- if (SCI->use_size() == 1)
+ if (SetCondInst *SCI = dyn_cast<SetCondInst>(Op0I))
+ if (RHS == ConstantBool::True && SCI->use_size() == 1)
return new SetCondInst(SCI->getInverseCondition(),
SCI->getOperand(0), SCI->getOperand(1));
+
+ if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
+ if (Op0I->getOpcode() == Instruction::And) {
+ // (X & C1) ^ C2 --> (X & C1) | C2 iff (C1&C2) == 0
+ if ((*RHS & *Op0CI)->isNullValue())
+ return BinaryOperator::create(Instruction::Or, Op0, RHS);
+ } else if (Op0I->getOpcode() == Instruction::Or) {
+ // (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2
+ if ((*RHS & *Op0CI) == RHS)
+ return BinaryOperator::create(Instruction::And, Op0, ~*RHS);
+ }
}
}
if (Op0 == Op1)
return ReplaceInstUsesWith(I, ConstantBool::get(isTrueWhenEqual(I)));
- // setcc <global*>, 0 - Global value addresses are never null!
- if (isa<GlobalValue>(Op0) && isa<ConstantPointerNull>(Op1))
+ // setcc <global/alloca*>, 0 - Global/Stack value addresses are never null!
+ if (isa<ConstantPointerNull>(Op1) &&
+ (isa<GlobalValue>(Op0) || isa<AllocaInst>(Op0)))
return ReplaceInstUsesWith(I, ConstantBool::get(!isTrueWhenEqual(I)));
+
// setcc's with boolean values can always be turned into bitwise operations
if (Ty == Type::BoolTy) {
// If this is <, >, or !=, we can change this into a simple xor instruction
// integers at the end of their ranges...
//
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- if (CI->isNullValue()) {
- if (I.getOpcode() == Instruction::SetNE)
- return new CastInst(Op0, Type::BoolTy, I.getName());
- else if (I.getOpcode() == Instruction::SetEQ) {
- // seteq X, 0 -> not (cast X to bool)
- Instruction *Val = new CastInst(Op0, Type::BoolTy, I.getName()+".not");
- InsertNewInstBefore(Val, I);
- return BinaryOperator::createNot(Val, I.getName());
+ // Simplify seteq and setne instructions...
+ if (I.getOpcode() == Instruction::SetEQ ||
+ I.getOpcode() == Instruction::SetNE) {
+ bool isSetNE = I.getOpcode() == Instruction::SetNE;
+
+ // If the first operand is (and|or|xor) with a constant, and the second
+ // operand is a constant, simplify a bit.
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Op0)) {
+ switch (BO->getOpcode()) {
+ case Instruction::Add:
+ if (CI->isNullValue()) {
+ // Replace ((add A, B) != 0) with (A != -B) if A or B is
+ // efficiently invertible, or if the add has just this one use.
+ Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
+ if (Value *NegVal = dyn_castNegVal(BOp1))
+ return new SetCondInst(I.getOpcode(), BOp0, NegVal);
+ else if (Value *NegVal = dyn_castNegVal(BOp0))
+ return new SetCondInst(I.getOpcode(), NegVal, BOp1);
+ else if (BO->use_size() == 1) {
+ Instruction *Neg = BinaryOperator::createNeg(BOp1, BO->getName());
+ BO->setName("");
+ InsertNewInstBefore(Neg, I);
+ return new SetCondInst(I.getOpcode(), BOp0, Neg);
+ }
+ }
+ break;
+ case Instruction::Xor:
+ // For the xor case, we can xor two constants together, eliminating
+ // the explicit xor.
+ if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1)))
+ return BinaryOperator::create(I.getOpcode(), BO->getOperand(0),
+ *CI ^ *BOC);
+
+ // FALLTHROUGH
+ case Instruction::Sub:
+ // Replace (([sub|xor] A, B) != 0) with (A != B)
+ if (CI->isNullValue())
+ return new SetCondInst(I.getOpcode(), BO->getOperand(0),
+ BO->getOperand(1));
+ break;
+
+ case Instruction::Or:
+ // If bits are being or'd in that are not present in the constant we
+ // are comparing against, then the comparison could never succeed!
+ if (Constant *BOC = dyn_cast<Constant>(BO->getOperand(1)))
+ if (!(*BOC & *~*CI)->isNullValue())
+ return ReplaceInstUsesWith(I, ConstantBool::get(isSetNE));
+ break;
+
+ case Instruction::And:
+ if (ConstantInt *BOC = dyn_cast<ConstantInt>(BO->getOperand(1))) {
+ // If bits are being compared against that are and'd out, then the
+ // comparison can never succeed!
+ if (!(*CI & *~*BOC)->isNullValue())
+ return ReplaceInstUsesWith(I, ConstantBool::get(isSetNE));
+
+ // Replace (and X, (1 << size(X)-1) != 0) with x < 0, converting X
+ // to be a signed value as appropriate.
+ if (isSignBit(BOC)) {
+ Value *X = BO->getOperand(0);
+ // If 'X' is not signed, insert a cast now...
+ if (!BOC->getType()->isSigned()) {
+ const Type *DestTy;
+ switch (BOC->getType()->getPrimitiveID()) {
+ case Type::UByteTyID: DestTy = Type::SByteTy; break;
+ case Type::UShortTyID: DestTy = Type::ShortTy; break;
+ case Type::UIntTyID: DestTy = Type::IntTy; break;
+ case Type::ULongTyID: DestTy = Type::LongTy; break;
+ default: assert(0 && "Invalid unsigned integer type!"); abort();
+ }
+ CastInst *NewCI = new CastInst(X,DestTy,X->getName()+".signed");
+ InsertNewInstBefore(NewCI, I);
+ X = NewCI;
+ }
+ return new SetCondInst(isSetNE ? Instruction::SetLT :
+ Instruction::SetGE, X,
+ Constant::getNullValue(X->getType()));
+ }
+ }
+ default: break;
+ }
}
}
Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
assert(I.getOperand(1)->getType() == Type::UByteTy);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ bool isLeftShift = I.getOpcode() == Instruction::Shl;
// shl X, 0 == X and shr X, 0 == X
// shl 0, X == 0 and shr 0, X == 0
Op0 == Constant::getNullValue(Op0->getType()))
return ReplaceInstUsesWith(I, Op0);
- // If this is a shift of a shift, see if we can fold the two together...
- if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0)) {
- if (isa<Constant>(Op1) && isa<Constant>(Op0SI->getOperand(1))) {
- ConstantUInt *ShiftAmt1C = cast<ConstantUInt>(Op0SI->getOperand(1));
- unsigned ShiftAmt1 = ShiftAmt1C->getValue();
- unsigned ShiftAmt2 = cast<ConstantUInt>(Op1)->getValue();
-
- // Check for (A << c1) << c2 and (A >> c1) >> c2
- if (I.getOpcode() == Op0SI->getOpcode()) {
- unsigned Amt = ShiftAmt1+ShiftAmt2; // Fold into one big shift...
- return new ShiftInst(I.getOpcode(), Op0SI->getOperand(0),
- ConstantUInt::get(Type::UByteTy, Amt));
- }
-
- if (I.getType()->isUnsigned()) { // Check for (A << c1) >> c2 or visaversa
- // Calculate bitmask for what gets shifted off the edge...
- Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
- if (I.getOpcode() == Instruction::Shr)
- C = ConstantExpr::getShift(Instruction::Shr, C, ShiftAmt1C);
- else
- C = ConstantExpr::getShift(Instruction::Shl, C, ShiftAmt1C);
-
- Instruction *Mask =
- BinaryOperator::create(Instruction::And, Op0SI->getOperand(0),
- C, Op0SI->getOperand(0)->getName()+".mask",&I);
- WorkList.push_back(Mask);
-
- // Figure out what flavor of shift we should use...
- if (ShiftAmt1 == ShiftAmt2)
- return ReplaceInstUsesWith(I, Mask); // (A << c) >> c === A & c2
- else if (ShiftAmt1 < ShiftAmt2) {
- return new ShiftInst(I.getOpcode(), Mask,
- ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
- } else {
- return new ShiftInst(Op0SI->getOpcode(), Mask,
- ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
- }
- }
- }
- }
+ // shr int -1, X = -1 (for any arithmetic shift rights of ~0)
+ if (!isLeftShift)
+ if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
+ if (CSI->isAllOnesValue())
+ return ReplaceInstUsesWith(I, CSI);
- // shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr of
- // a signed value.
- //
if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(Op1)) {
+ // shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr
+ // of a signed value.
+ //
unsigned TypeBits = Op0->getType()->getPrimitiveSize()*8;
if (CUI->getValue() >= TypeBits &&
- (!Op0->getType()->isSigned() || I.getOpcode() == Instruction::Shl))
+ (!Op0->getType()->isSigned() || isLeftShift))
return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType()));
- // Check to see if we are shifting left by 1. If so, turn it into an add
- // instruction.
- if (I.getOpcode() == Instruction::Shl && CUI->equalsInt(1))
- // Convert 'shl int %X, 1' to 'add int %X, %X'
- return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
+ // ((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::create(Instruction::Mul, BO->getOperand(0),
+ *BOOp << *CUI);
+
+
+ // 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 (Op0->use_size() == 1)
+ if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
+ 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()) {
+ default: isValid = false; break; // Do not perform transform!
+ case Instruction::Or:
+ case Instruction::Xor:
+ highBitSet = false;
+ break;
+ case Instruction::And:
+ highBitSet = true;
+ break;
+ }
+
+ // 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 && !isLeftShift && !I.getType()->isUnsigned()) {
+ uint64_t Val = Op0C->getRawValue();
+ isValid = ((Val & (1 << (TypeBits-1))) != 0) == highBitSet;
+ }
+
+ if (isValid) {
+ Constant *NewRHS =
+ ConstantFoldShiftInstruction(I.getOpcode(), Op0C, CUI);
+
+ Instruction *NewShift =
+ new ShiftInst(I.getOpcode(), Op0BO->getOperand(0), CUI,
+ Op0BO->getName());
+ Op0BO->setName("");
+ InsertNewInstBefore(NewShift, I);
+
+ return BinaryOperator::create(Op0BO->getOpcode(), NewShift,
+ NewRHS);
+ }
+ }
+ // If this is a shift of a shift, see if we can fold the two together...
+ if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
+ if (ConstantUInt *ShiftAmt1C =
+ dyn_cast<ConstantUInt>(Op0SI->getOperand(1))) {
+ unsigned ShiftAmt1 = ShiftAmt1C->getValue();
+ unsigned ShiftAmt2 = CUI->getValue();
+
+ // Check for (A << c1) << c2 and (A >> c1) >> c2
+ if (I.getOpcode() == Op0SI->getOpcode()) {
+ unsigned Amt = ShiftAmt1+ShiftAmt2; // Fold into one big shift...
+ return new ShiftInst(I.getOpcode(), Op0SI->getOperand(0),
+ ConstantUInt::get(Type::UByteTy, Amt));
+ }
+
+ // Check for (A << c1) >> c2 or visaversa. If we are dealing with
+ // signed types, we can only support the (A >> c1) << c2 configuration,
+ // because it can not turn an arbitrary bit of A into a sign bit.
+ if (I.getType()->isUnsigned() || isLeftShift) {
+ // Calculate bitmask for what gets shifted off the edge...
+ Constant *C = ConstantIntegral::getAllOnesValue(I.getType());
+ if (isLeftShift)
+ C = ConstantExpr::getShift(Instruction::Shl, C, ShiftAmt1C);
+ else
+ C = ConstantExpr::getShift(Instruction::Shr, C, ShiftAmt1C);
+
+ Instruction *Mask =
+ BinaryOperator::create(Instruction::And, Op0SI->getOperand(0),
+ C, Op0SI->getOperand(0)->getName()+".mask");
+ InsertNewInstBefore(Mask, I);
+
+ // Figure out what flavor of shift we should use...
+ if (ShiftAmt1 == ShiftAmt2)
+ return ReplaceInstUsesWith(I, Mask); // (A << c) >> c === A & c2
+ else if (ShiftAmt1 < ShiftAmt2) {
+ return new ShiftInst(I.getOpcode(), Mask,
+ ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1));
+ } else {
+ return new ShiftInst(Op0SI->getOpcode(), Mask,
+ ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2));
+ }
+ }
+ }
}
- // shr int -1, X = -1 (for any arithmetic shift rights of ~0)
- if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
- if (I.getOpcode() == Instruction::Shr && CSI->isAllOnesValue())
- return ReplaceInstUsesWith(I, CSI);
-
return 0;
}
// isEliminableCastOfCast - Return true if it is valid to eliminate the CI
// instruction.
//
-static inline bool isEliminableCastOfCast(const CastInst &CI,
- const CastInst *CSrc) {
- assert(CI.getOperand(0) == CSrc);
- const Type *SrcTy = CSrc->getOperand(0)->getType();
- const Type *MidTy = CSrc->getType();
- const Type *DstTy = CI.getType();
+static inline bool isEliminableCastOfCast(const Type *SrcTy, const Type *MidTy,
+ const Type *DstTy) {
// It is legal to eliminate the instruction if casting A->B->A if the sizes
// are identical and the bits don't get reinterpreted (for example
return false;
}
+static bool ValueRequiresCast(const Value *V, const Type *Ty) {
+ if (V->getType() == Ty || isa<Constant>(V)) return false;
+ if (const CastInst *CI = dyn_cast<CastInst>(V))
+ if (isEliminableCastOfCast(CI->getOperand(0)->getType(), CI->getType(), Ty))
+ return false;
+ return true;
+}
+
+/// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
+/// InsertBefore instruction. This is specialized a bit to avoid inserting
+/// casts that are known to not do anything...
+///
+Value *InstCombiner::InsertOperandCastBefore(Value *V, const Type *DestTy,
+ Instruction *InsertBefore) {
+ if (V->getType() == DestTy) return V;
+ if (Constant *C = dyn_cast<Constant>(V))
+ return ConstantExpr::getCast(C, DestTy);
+
+ CastInst *CI = new CastInst(V, DestTy, V->getName());
+ InsertNewInstBefore(CI, *InsertBefore);
+ return CI;
+}
// CastInst simplification
//
// one!
//
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) {
- if (isEliminableCastOfCast(CI, CSrc)) {
+ if (isEliminableCastOfCast(CSrc->getOperand(0)->getType(),
+ CSrc->getType(), CI.getType())) {
// This instruction now refers directly to the cast's src operand. This
// has a good chance of making CSrc dead.
CI.setOperand(0, CSrc->getOperand(0));
}
}
- // If this is a cast to bool (which is effectively a "!=0" test), then we can
- // perform a few optimizations...
- //
- if (CI.getType() == Type::BoolTy) {
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Src)) {
- Value *Op0 = BO->getOperand(0), *Op1 = BO->getOperand(1);
-
- // Replace (cast (sub A, B) to bool) with (setne A, B)
- if (BO->getOpcode() == Instruction::Sub)
- return new SetCondInst(Instruction::SetNE, Op0, Op1);
-
- // Replace (cast (add A, B) to bool) with (setne A, -B) if B is
- // efficiently invertible, or if the add has just this one use.
- if (BO->getOpcode() == Instruction::Add)
- if (Value *NegVal = dyn_castNegVal(Op1))
- return new SetCondInst(Instruction::SetNE, Op0, NegVal);
- else if (Value *NegVal = dyn_castNegVal(Op0))
- return new SetCondInst(Instruction::SetNE, NegVal, Op1);
- else if (BO->use_size() == 1) {
- Instruction *Neg = BinaryOperator::createNeg(Op1, BO->getName());
- BO->setName("");
- InsertNewInstBefore(Neg, CI);
- return new SetCondInst(Instruction::SetNE, Op0, Neg);
+ // If the source value is an instruction with only this use, we can attempt to
+ // propagate the cast into the instruction. Also, only handle integral types
+ // for now.
+ if (Instruction *SrcI = dyn_cast<Instruction>(Src))
+ if (SrcI->use_size() == 1 && Src->getType()->isIntegral() &&
+ CI.getType()->isInteger()) { // Don't mess with casts to bool here
+ const Type *DestTy = CI.getType();
+ unsigned SrcBitSize = getTypeSizeInBits(Src->getType());
+ unsigned DestBitSize = getTypeSizeInBits(DestTy);
+
+ Value *Op0 = SrcI->getNumOperands() > 0 ? SrcI->getOperand(0) : 0;
+ Value *Op1 = SrcI->getNumOperands() > 1 ? SrcI->getOperand(1) : 0;
+
+ switch (SrcI->getOpcode()) {
+ case Instruction::Add:
+ case Instruction::Mul:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
+ // If we are discarding information, or just changing the sign, rewrite.
+ if (DestBitSize <= SrcBitSize && DestBitSize != 1) {
+ // Don't insert two casts if they cannot be eliminated. We allow two
+ // casts to be inserted if the sizes are the same. This could only be
+ // converting signedness, which is a noop.
+ if (DestBitSize == SrcBitSize || !ValueRequiresCast(Op1, DestTy) ||
+ !ValueRequiresCast(Op0, DestTy)) {
+ Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
+ Value *Op1c = InsertOperandCastBefore(Op1, DestTy, SrcI);
+ return BinaryOperator::create(cast<BinaryOperator>(SrcI)
+ ->getOpcode(), Op0c, Op1c);
+ }
+ }
+ break;
+ case Instruction::Shl:
+ // Allow changing the sign of the source operand. Do not allow changing
+ // the size of the shift, UNLESS the shift amount is a constant. We
+ // mush not change variable sized shifts to a smaller size, because it
+ // is undefined to shift more bits out than exist in the value.
+ if (DestBitSize == SrcBitSize ||
+ (DestBitSize < SrcBitSize && isa<Constant>(Op1))) {
+ Value *Op0c = InsertOperandCastBefore(Op0, DestTy, SrcI);
+ return new ShiftInst(Instruction::Shl, Op0c, Op1);
}
+ break;
+ }
}
- }
-
+
return 0;
}
// Instcombine load (constant global) into the value loaded...
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Op))
- if (GV->isConstant())
+ if (GV->isConstant() && !GV->isExternal())
return ReplaceInstUsesWith(LI, GV->getInitializer());
// Instcombine load (constantexpr_GEP global, 0, ...) into the value loaded...
if (CE->getOpcode() == Instruction::GetElementPtr)
if (ConstantPointerRef *G=dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getValue()))
- if (GV->isConstant())
+ if (GV->isConstant() && !GV->isExternal())
if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE))
return ReplaceInstUsesWith(LI, V);
return 0;