1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

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
This commit is contained in:
Chris Lattner 2005-09-18 05:12:10 +00:00
parent 7e94dfdc90
commit ae35713f00

View File

@ -3355,9 +3355,58 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
}
}
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 (BinaryOperator *Op0BO = dyn_cast<BinaryOperator>(Op0))
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?
@ -3401,6 +3450,7 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) {
}
}
}
}
// If this is a shift of a shift, see if we can fold the two together...
if (ShiftInst *Op0SI = dyn_cast<ShiftInst>(Op0))