[InstCombine] move foldICmpShrConstConst() contents to foldICmpShrConst(); NFCI

There will only be 3 lines of code in foldICmpShrConst() when the cleanup is done,
so it doesn't make much sense to have a separate function for a single fold.

llvm-svn: 279575
This commit is contained in:
Sanjay Patel 2016-08-23 21:25:13 +00:00
parent 4d9558b08e
commit fd8c14ece2
2 changed files with 65 additions and 77 deletions

View File

@ -1336,80 +1336,6 @@ Instruction *InstCombiner::foldICmpDivConstConst(ICmpInst &ICI,
}
}
/// Handle "icmp(([al]shr X, cst1), cst2)".
Instruction *InstCombiner::foldICmpShrConstConst(ICmpInst &ICI,
BinaryOperator *Shr,
ConstantInt *ShAmt) {
const APInt &CmpRHSV = cast<ConstantInt>(ICI.getOperand(1))->getValue();
// Check that the shift amount is in range. If not, don't perform
// undefined shifts. When the shift is visited it will be
// simplified.
uint32_t TypeBits = CmpRHSV.getBitWidth();
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
if (ShAmtVal >= TypeBits || ShAmtVal == 0)
return nullptr;
if (!ICI.isEquality()) {
// If we have an unsigned comparison and an ashr, we can't simplify this.
// Similarly for signed comparisons with lshr.
if (ICI.isSigned() != (Shr->getOpcode() == Instruction::AShr))
return nullptr;
// Otherwise, all lshr and most exact ashr's are equivalent to a udiv/sdiv
// by a power of 2. Since we already have logic to simplify these,
// transform to div and then simplify the resultant comparison.
if (Shr->getOpcode() == Instruction::AShr &&
(!Shr->isExact() || ShAmtVal == TypeBits - 1))
return nullptr;
// Revisit the shift (to delete it).
Worklist.Add(Shr);
Constant *DivCst =
ConstantInt::get(Shr->getType(), APInt::getOneBitSet(TypeBits, ShAmtVal));
Value *Tmp =
Shr->getOpcode() == Instruction::AShr ?
Builder->CreateSDiv(Shr->getOperand(0), DivCst, "", Shr->isExact()) :
Builder->CreateUDiv(Shr->getOperand(0), DivCst, "", Shr->isExact());
ICI.setOperand(0, Tmp);
// If the builder folded the binop, just return it.
BinaryOperator *TheDiv = dyn_cast<BinaryOperator>(Tmp);
if (!TheDiv)
return &ICI;
// Otherwise, fold this div/compare.
assert(TheDiv->getOpcode() == Instruction::SDiv ||
TheDiv->getOpcode() == Instruction::UDiv);
Instruction *Res =
foldICmpDivConstConst(ICI, TheDiv, cast<ConstantInt>(DivCst));
assert(Res && "This div/cst should have folded!");
return Res;
}
// Check if the bits shifted out are known to be zero. If so, we can compare
// against the unshifted value:
// (X & 4) >> 1 == 2 --> (X & 4) == 4.
ConstantInt *ShiftedCmpRHS = Builder->getInt(CmpRHSV << ShAmtVal);
if (Shr->hasOneUse() && Shr->isExact())
return new ICmpInst(ICI.getPredicate(), Shr->getOperand(0), ShiftedCmpRHS);
if (Shr->hasOneUse()) {
// Otherwise strength reduce the shift into an and.
APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal));
Constant *Mask = Builder->getInt(Val);
Value *And = Builder->CreateAnd(Shr->getOperand(0),
Mask, Shr->getName()+".mask");
return new ICmpInst(ICI.getPredicate(), And, ShiftedCmpRHS);
}
return nullptr;
}
/// Handle "(icmp eq/ne (ashr/lshr const2, A), const1)" ->
/// (icmp eq/ne A, Log2(const2/const1)) ->
/// (icmp eq/ne A, Log2(const2) - Log2(const1)).
@ -2067,8 +1993,72 @@ Instruction *InstCombiner::foldICmpShrConstant(ICmpInst &Cmp,
if (!ShAmt)
return nullptr;
if (Instruction *Res = foldICmpShrConstConst(Cmp, Shr, ShAmt))
// Check that the shift amount is in range. If not, don't perform
// undefined shifts. When the shift is visited it will be
// simplified.
uint32_t TypeBits = C->getBitWidth();
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
if (ShAmtVal >= TypeBits || ShAmtVal == 0)
return nullptr;
if (!Cmp.isEquality()) {
// If we have an unsigned comparison and an ashr, we can't simplify this.
// Similarly for signed comparisons with lshr.
if (Cmp.isSigned() != (Shr->getOpcode() == Instruction::AShr))
return nullptr;
// Otherwise, all lshr and most exact ashr's are equivalent to a udiv/sdiv
// by a power of 2. Since we already have logic to simplify these,
// transform to div and then simplify the resultant comparison.
if (Shr->getOpcode() == Instruction::AShr &&
(!Shr->isExact() || ShAmtVal == TypeBits - 1))
return nullptr;
// Revisit the shift (to delete it).
Worklist.Add(Shr);
Constant *DivCst = ConstantInt::get(
Shr->getType(), APInt::getOneBitSet(TypeBits, ShAmtVal));
Value *Tmp = Shr->getOpcode() == Instruction::AShr
? Builder->CreateSDiv(Shr->getOperand(0), DivCst, "",
Shr->isExact())
: Builder->CreateUDiv(Shr->getOperand(0), DivCst, "",
Shr->isExact());
Cmp.setOperand(0, Tmp);
// If the builder folded the binop, just return it.
BinaryOperator *TheDiv = dyn_cast<BinaryOperator>(Tmp);
if (!TheDiv)
return &Cmp;
// Otherwise, fold this div/compare.
assert(TheDiv->getOpcode() == Instruction::SDiv ||
TheDiv->getOpcode() == Instruction::UDiv);
Instruction *Res =
foldICmpDivConstConst(Cmp, TheDiv, cast<ConstantInt>(DivCst));
assert(Res && "This div/cst should have folded!");
return Res;
}
// Check if the bits shifted out are known to be zero. If so, we can compare
// against the unshifted value:
// (X & 4) >> 1 == 2 --> (X & 4) == 4.
ConstantInt *ShiftedCmpRHS = Builder->getInt(*C << ShAmtVal);
if (Shr->hasOneUse() && Shr->isExact())
return new ICmpInst(Pred, Shr->getOperand(0), ShiftedCmpRHS);
if (Shr->hasOneUse()) {
// Otherwise strength reduce the shift into an and.
APInt Val(APInt::getHighBitsSet(TypeBits, TypeBits - ShAmtVal));
Constant *Mask = Builder->getInt(Val);
Value *And =
Builder->CreateAnd(Shr->getOperand(0), Mask, Shr->getName() + ".mask");
return new ICmpInst(Pred, And, ShiftedCmpRHS);
}
return nullptr;
}

View File

@ -550,8 +550,6 @@ private:
Constant *RHSC);
Instruction *foldICmpDivConstConst(ICmpInst &ICI, BinaryOperator *DivI,
ConstantInt *DivRHS);
Instruction *foldICmpShrConstConst(ICmpInst &ICI, BinaryOperator *DivI,
ConstantInt *DivRHS);
Instruction *foldICmpCstShrConst(ICmpInst &I, Value *Op, Value *A,
ConstantInt *CI1, ConstantInt *CI2);
Instruction *foldICmpCstShlConst(ICmpInst &I, Value *Op, Value *A,