mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-23 05:52:40 +00:00
[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:
parent
4d9558b08e
commit
fd8c14ece2
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user