aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-18 06:30:59 +0000
committerChris Lattner <sabre@nondot.org>2005-09-18 06:30:59 +0000
commit150f12af7f2e84888787b8aac3561853cf6a9e5a (patch)
treee3355e12a9842da78ff7e4e524390c8ca8b5cfb5
parent0b7c0bf249ba0e2ace87276b184fd3a1dbfc02a9 (diff)
downloadexternal_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.cpp101
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;
}