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 | 150f12af7f2e84888787b8aac3561853cf6a9e5a (patch) | |
tree | e3355e12a9842da78ff7e4e524390c8ca8b5cfb5 | |
parent | 0b7c0bf249ba0e2ace87276b184fd3a1dbfc02a9 (diff) | |
download | external_llvm-150f12af7f2e84888787b8aac3561853cf6a9e5a.zip external_llvm-150f12af7f2e84888787b8aac3561853cf6a9e5a.tar.gz external_llvm-150f12af7f2e84888787b8aac3561853cf6a9e5a.tar.bz2 |
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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23385 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 101 |
1 files changed, 70 insertions, 31 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 5468a56..cd02410 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/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; } |