summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-18 05:12:10 +0000
committerChris Lattner <sabre@nondot.org>2005-09-18 05:12:10 +0000
commit27cb9dbd35eb1fd70df5548b5ab47205241dcaad (patch)
tree5fb9bf31657256da2c19018aa3bfc3d2f691e6e8 /llvm/lib
parent1813aabcf2c3e53e1b75f399c1f0f56387666314 (diff)
downloadbcm5719-llvm-27cb9dbd35eb1fd70df5548b5ab47205241dcaad.tar.gz
bcm5719-llvm-27cb9dbd35eb1fd70df5548b5ab47205241dcaad.zip
implement shift.ll:test25. This compiles:
struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus3 (unsigned int x) { b.k += x; } to: _plus3: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r3, 0(r2) rlwinm r4, r3, 0, 0, 14 add r4, r4, r3 rlwimi r4, r3, 0, 15, 31 stw r4, 0(r2) blr instead of: _plus3: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) srwi r5, r4, 17 add r3, r5, r3 slwi r3, r3, 17 rlwimi r3, r4, 0, 15, 31 stw r3, 0(r2) blr llvm-svn: 23381
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp56
1 files changed, 53 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index 2a03bc1461d..2d7adf4ea8d 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -3355,9 +3355,58 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
}
}
- // 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 (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
+ if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0)) {
+ // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
+ switch (Op0BO->getOpcode()) {
+ 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 (ShiftInst *XS = dyn_cast<ShiftInst>(Op0BO->getOperand(1)))
+ if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI &&
+ XS->getOpcode() == Instruction::Shr) {
+ break;
+ Instruction *YS = new ShiftInst(Instruction::Shl,
+ Op0BO->getOperand(0), CUI,
+ Op0BO->getName());
+ InsertNewInstBefore(YS, I); // (Y << C)
+ Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS,
+ XS->getOperand(0),
+ XS->getName());
+ InsertNewInstBefore(X, I); // (X + (Y << C))
+ Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
+ C2 = ConstantExpr::getShl(C2, CUI);
+ std::cerr << "FOLD1: " << *Op0BO;
+ return BinaryOperator::createAnd(X, C2);
+ }
+ // Fall through.
+ case Instruction::Sub:
+ // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C)
+ if (ShiftInst *XS = dyn_cast<ShiftInst>(Op0BO->getOperand(0)))
+ if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI &&
+ XS->getOpcode() == Instruction::Shr) {
+ Instruction *YS = new ShiftInst(Instruction::Shl,
+ Op0BO->getOperand(0), CUI,
+ Op0BO->getName());
+ InsertNewInstBefore(YS, I); // (Y << C)
+ Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS,
+ XS->getOperand(0),
+ XS->getName());
+ InsertNewInstBefore(X, I); // (X + (Y << C))
+ Constant *C2 = ConstantInt::getAllOnesValue(X->getType());
+ C2 = ConstantExpr::getShl(C2, CUI);
+ std::cerr << "FOLD2: " << *Op0BO;
+ return BinaryOperator::createAnd(X, C2);
+ }
+ break;
+ }
+
+
+ // 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?
@@ -3400,6 +3449,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
NewRHS);
}
}
+ }
}
// If this is a shift of a shift, see if we can fold the two together...
OpenPOWER on IntegriCloud