diff options
| author | Chris Lattner <sabre@nondot.org> | 2005-09-18 06:30:59 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2005-09-18 06:30:59 +0000 |
| commit | 797dee77053e4bbf0b95ae02ab725b279cf817ef (patch) | |
| tree | 907280b0f7a80507b57bed54ec2eaa1ec299f455 /llvm/lib/Transforms | |
| parent | 01f56c68e947157ab3aa6a3bfde7ebde73d18821 (diff) | |
| download | bcm5719-llvm-797dee77053e4bbf0b95ae02ab725b279cf817ef.tar.gz bcm5719-llvm-797dee77053e4bbf0b95ae02ab725b279cf817ef.zip | |
Compile
struct S { unsigned int i : 6, j : 11, k : 15; } b;
void plus2 (unsigned int x) {
b.j += x;
}
to:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
and %ECX, 131008
mov %EDX, DWORD PTR [%ESP + 4]
shl %EDX, 6
add %EDX, %ECX
and %EDX, 131008
and %EAX, -131009
or %EDX, %EAX
mov DWORD PTR [b], %EDX
ret
instead of:
plus2:
mov %EAX, DWORD PTR [b]
mov %ECX, %EAX
shr %ECX, 6
and %ECX, 2047
add %ECX, DWORD PTR [%ESP + 4]
shl %ECX, 6
and %ECX, 131008
and %EAX, -131009
or %ECX, %EAX
mov DWORD PTR [b], %ECX
ret
llvm-svn: 23385
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/InstructionCombining.cpp | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 5468a5665b0..cd02410705d 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3364,6 +3364,8 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { if (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0)) { // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + Value *V1, *V2, *V3; + ConstantInt *CC; switch (Op0BO->getOpcode()) { default: break; case Instruction::Add: @@ -3372,39 +3374,76 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { 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) { - 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); - return BinaryOperator::createAnd(X, C2); - } - // Fall through. + if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && + match(Op0BO->getOperand(1), + m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == CUI) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + V1, + Op0BO->getOperand(1)->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + return BinaryOperator::createAnd(X, C2); + } + + // Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C)) + if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && + match(Op0BO->getOperand(1), + m_And(m_Shr(m_Value(V1), m_Value(V2)), + m_ConstantInt(CC))) && V2 == CUI && + cast<BinaryOperator>(Op0BO->getOperand(1))->getOperand(0)->hasOneUse()) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *XM = + BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, CUI), + V1->getName()+".mask"); + InsertNewInstBefore(XM, I); // X & (CC << C) + + return BinaryOperator::create(Op0BO->getOpcode(), YS, XM); + } + + // 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(1), 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); - return BinaryOperator::createAnd(X, C2); - } + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), + m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == CUI) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(1), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + V1, + Op0BO->getOperand(0)->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + return BinaryOperator::createAnd(X, C2); + } + + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), + m_And(m_Shr(m_Value(V1), m_Value(V2)), + m_ConstantInt(CC))) && V2 == CUI && + cast<BinaryOperator>(Op0BO->getOperand(0))->getOperand(0)->hasOneUse()) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(1), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *XM = + BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, CUI), + V1->getName()+".mask"); + InsertNewInstBefore(XM, I); // X & (CC << C) + + return BinaryOperator::create(Op0BO->getOpcode(), YS, XM); + } + break; } |

