diff options
| author | Chris Lattner <sabre@nondot.org> | 2005-09-18 05:12:10 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2005-09-18 05:12:10 +0000 |
| commit | 27cb9dbd35eb1fd70df5548b5ab47205241dcaad (patch) | |
| tree | 5fb9bf31657256da2c19018aa3bfc3d2f691e6e8 /llvm/lib/Transforms | |
| parent | 1813aabcf2c3e53e1b75f399c1f0f56387666314 (diff) | |
| download | bcm5719-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/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/InstructionCombining.cpp | 56 |
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... |

