aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar/InstructionCombining.cpp')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp77
1 files changed, 61 insertions, 16 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 15b0bbcdfc..8975322b6f 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -15,8 +15,8 @@
// 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. Logical operators with constant operands are always grouped so that
-// 'or's are performed first, then 'and's, then 'xor's.
+// 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
// N. This list is incomplete
@@ -879,6 +879,7 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
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
@@ -886,17 +887,68 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
Op0 == Constant::getNullValue(Op0->getType()))
return ReplaceInstUsesWith(I, Op0);
+ // 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);
+
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()));
+ // 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 (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))
if (ConstantUInt *ShiftAmt1C =
dyn_cast<ConstantUInt>(Op0SI->getOperand(1))) {
unsigned ShiftAmt1 = ShiftAmt1C->getValue();
@@ -912,13 +964,13 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
// 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() || I.getOpcode() == Instruction::Shl) {
+ if (I.getType()->isUnsigned() || isLeftShift) {
// 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
+ 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),
@@ -937,21 +989,14 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
}
}
}
- }
// 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))
+ if (isLeftShift && CUI->equalsInt(1))
// Convert 'shl int %X, 1' to 'add int %X, %X'
return BinaryOperator::create(Instruction::Add, Op0, Op0, I.getName());
}
- // shr int -1, X = -1 (for any arithmetic shift rights of ~0)
- if (I.getOpcode() == Instruction::Shr)
- if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(Op0))
- if (CSI->isAllOnesValue())
- return ReplaceInstUsesWith(I, CSI);
-
return 0;
}