diff options
Diffstat (limited to 'lib/Transforms')
| -rw-r--r-- | lib/Transforms/InstCombine/InstCombineShifts.cpp | 74 | 
1 files changed, 39 insertions, 35 deletions
| diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index 4c14509..b31049e 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -529,19 +529,6 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,      ShiftOp = 0;    if (ShiftOp && isa<ConstantInt>(ShiftOp->getOperand(1))) { - -    // This is a constant shift of a constant shift. Be careful about hiding -    // shl instructions behind bit masks. They are used to represent multiplies -    // by a constant, and it is important that simple arithmetic expressions -    // are still recognizable by scalar evolution. -    // -    // The transforms applied to shl are very similar to the transforms applied -    // to mul by constant. We can be more aggressive about optimizing right -    // shifts. -    // -    // Combinations of right and left shifts will still be optimized in -    // DAGCombine where scalar evolution no longer applies. -      ConstantInt *ShiftAmt1C = cast<ConstantInt>(ShiftOp->getOperand(1));      uint32_t ShiftAmt1 = ShiftAmt1C->getLimitedValue(TypeBits);      uint32_t ShiftAmt2 = Op1->getLimitedValue(TypeBits); @@ -567,6 +554,13 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,      }      if (ShiftAmt1 == ShiftAmt2) { +      // If we have ((X >>? C) << C), turn this into X & (-1 << C). +      if (I.getOpcode() == Instruction::Shl && +          ShiftOp->getOpcode() != Instruction::Shl) { +        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt1)); +        return BinaryOperator::CreateAnd(X, +                                         ConstantInt::get(I.getContext(),Mask)); +      }        // If we have ((X << C) >>u C), turn this into X & (-1 >>u C).        if (I.getOpcode() == Instruction::LShr &&            ShiftOp->getOpcode() == Instruction::Shl) { @@ -576,23 +570,28 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,        }      } else if (ShiftAmt1 < ShiftAmt2) {        uint32_t ShiftDiff = ShiftAmt2-ShiftAmt1; - -      // (X >>?,exact C1) << C2 --> X << (C2-C1) -      // The inexact version is deferred to DAGCombine so we don't hide shl -      // behind a bit mask. +       +      // (X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2)        if (I.getOpcode() == Instruction::Shl && -          ShiftOp->getOpcode() != Instruction::Shl && -          ShiftOp->isExact()) { +          ShiftOp->getOpcode() != Instruction::Shl) {          assert(ShiftOp->getOpcode() == Instruction::LShr ||                 ShiftOp->getOpcode() == Instruction::AShr);          ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff); -        BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl, -                                                        X, ShiftDiffCst); -        NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); -        NewShl->setHasNoSignedWrap(I.hasNoSignedWrap()); -        return NewShl; +        if (ShiftOp->isExact()) { +          // (X >>?,exact C1) << C2 --> X << (C2-C1) +          BinaryOperator *NewShl = BinaryOperator::Create(Instruction::Shl, +                                                          X, ShiftDiffCst); +          NewShl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); +          NewShl->setHasNoSignedWrap(I.hasNoSignedWrap()); +          return NewShl; +        } +        Value *Shift = Builder->CreateShl(X, ShiftDiffCst); +         +        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2)); +        return BinaryOperator::CreateAnd(Shift, +                                         ConstantInt::get(I.getContext(),Mask));        } - +              // (X << C1) >>u C2  --> X >>u (C2-C1) & (-1 >> C2)        if (I.getOpcode() == Instruction::LShr &&            ShiftOp->getOpcode() == Instruction::Shl) { @@ -628,19 +627,24 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,        assert(ShiftAmt2 < ShiftAmt1);        uint32_t ShiftDiff = ShiftAmt1-ShiftAmt2; -      // (X >>?exact C1) << C2 --> X >>?exact (C1-C2) -      // The inexact version is deferred to DAGCombine so we don't hide shl -      // behind a bit mask. +      // (X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2)        if (I.getOpcode() == Instruction::Shl && -          ShiftOp->getOpcode() != Instruction::Shl && -          ShiftOp->isExact()) { +          ShiftOp->getOpcode() != Instruction::Shl) {          ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff); -        BinaryOperator *NewShr = BinaryOperator::Create(ShiftOp->getOpcode(), -                                                        X, ShiftDiffCst); -        NewShr->setIsExact(true); -        return NewShr; +        if (ShiftOp->isExact()) { +          // (X >>?exact C1) << C2 --> X >>?exact (C1-C2) +          BinaryOperator *NewShr = BinaryOperator::Create(ShiftOp->getOpcode(), +                                                          X, ShiftDiffCst); +          NewShr->setIsExact(true); +          return NewShr; +        } +        Value *Shift = Builder->CreateBinOp(ShiftOp->getOpcode(), +                                            X, ShiftDiffCst); +        APInt Mask(APInt::getHighBitsSet(TypeBits, TypeBits - ShiftAmt2)); +        return BinaryOperator::CreateAnd(Shift, +                                         ConstantInt::get(I.getContext(),Mask));        } - +              // (X << C1) >>u C2  --> X << (C1-C2) & (-1 >> C2)        if (I.getOpcode() == Instruction::LShr &&            ShiftOp->getOpcode() == Instruction::Shl) { | 
