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
This commit is contained in:
Chris Lattner 2005-09-18 06:30:59 +00:00
parent 0b7c0bf249
commit 150f12af7f

View File

@ -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;
}