mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-26 22:34:39 +00:00
[InstCombine] clean up fold for X / C -> X * (1.0/C); NFCI
This should work with vector constants too, but it's currently limited to scalar. llvm-svn: 325187
This commit is contained in:
parent
f35a8dc055
commit
019b67ac3d
@ -1317,33 +1317,34 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// CvtFDivConstToReciprocal tries to convert X/C into X*1/C if C not a special
|
||||
/// FP value and:
|
||||
/// 1) 1/C is exact, or
|
||||
/// 2) reciprocal is allowed.
|
||||
/// If the conversion was successful, the simplified expression "X * 1/C" is
|
||||
/// returned; otherwise, nullptr is returned.
|
||||
static Instruction *CvtFDivConstToReciprocal(Value *Dividend, Constant *Divisor,
|
||||
bool AllowReciprocal) {
|
||||
if (!isa<ConstantFP>(Divisor)) // TODO: handle vectors.
|
||||
/// Try to convert X/C into X * (1/C).
|
||||
static Instruction *foldFDivConstantDivisor(BinaryOperator &FDiv) {
|
||||
// TODO: Handle vector constants.
|
||||
ConstantFP *CFP;
|
||||
if (!match(FDiv.getOperand(1), m_ConstantFP(CFP)))
|
||||
return nullptr;
|
||||
|
||||
const APFloat &FpVal = cast<ConstantFP>(Divisor)->getValueAPF();
|
||||
const APFloat &FpVal = CFP->getValueAPF();
|
||||
APFloat Reciprocal(FpVal.getSemantics());
|
||||
bool Cvt = FpVal.getExactInverse(&Reciprocal);
|
||||
|
||||
if (!Cvt && AllowReciprocal && FpVal.isFiniteNonZero()) {
|
||||
// This returns false if the inverse would be a denormal.
|
||||
bool HasRecip = FpVal.getExactInverse(&Reciprocal);
|
||||
// If the inverse is not exact, we may still be able to convert if we are
|
||||
// not operating with strict math.
|
||||
if (!HasRecip && FDiv.hasAllowReciprocal() && FpVal.isFiniteNonZero()) {
|
||||
Reciprocal = APFloat(FpVal.getSemantics(), 1.0f);
|
||||
(void)Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
|
||||
Cvt = !Reciprocal.isDenormal();
|
||||
Reciprocal.divide(FpVal, APFloat::rmNearestTiesToEven);
|
||||
// Disallow denormal constants because we don't know what would happen
|
||||
// on all targets.
|
||||
// TODO: Function attributes can tell us that denorms are flushed?
|
||||
HasRecip = !Reciprocal.isDenormal();
|
||||
}
|
||||
|
||||
if (!Cvt)
|
||||
if (!HasRecip)
|
||||
return nullptr;
|
||||
|
||||
ConstantFP *R;
|
||||
R = ConstantFP::get(Dividend->getType()->getContext(), Reciprocal);
|
||||
return BinaryOperator::CreateFMul(Dividend, R);
|
||||
auto *RecipCFP = ConstantFP::get(FDiv.getContext(), Reciprocal);
|
||||
return BinaryOperator::CreateFMul(FDiv.getOperand(0), RecipCFP);
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
||||
@ -1356,14 +1357,17 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
||||
SQ.getWithInstruction(&I)))
|
||||
return replaceInstUsesWith(I, V);
|
||||
|
||||
if (Instruction *FMul = foldFDivConstantDivisor(I)) {
|
||||
FMul->copyFastMathFlags(&I);
|
||||
return FMul;
|
||||
}
|
||||
|
||||
if (isa<Constant>(Op0))
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
||||
return R;
|
||||
|
||||
bool AllowReassociate = I.isFast();
|
||||
bool AllowReciprocal = I.hasAllowReciprocal();
|
||||
|
||||
if (Constant *Op1C = dyn_cast<Constant>(Op1)) {
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
||||
@ -1377,18 +1381,14 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
||||
|
||||
if (match(Op0, m_FMul(m_Value(X), m_Constant(C1)))) {
|
||||
// (X*C1)/C2 => X * (C1/C2)
|
||||
//
|
||||
Constant *C = ConstantExpr::getFDiv(C1, C2);
|
||||
if (isNormalFp(C))
|
||||
Res = BinaryOperator::CreateFMul(X, C);
|
||||
} else if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
|
||||
// (X/C1)/C2 => X /(C2*C1) [=> X * 1/(C2*C1) if reciprocal is allowed]
|
||||
// (X/C1)/C2 => X /(C2*C1)
|
||||
Constant *C = ConstantExpr::getFMul(C1, C2);
|
||||
if (isNormalFp(C)) {
|
||||
Res = CvtFDivConstToReciprocal(X, C, AllowReciprocal);
|
||||
if (!Res)
|
||||
Res = BinaryOperator::CreateFDiv(X, C);
|
||||
}
|
||||
if (isNormalFp(C))
|
||||
Res = BinaryOperator::CreateFDiv(X, C);
|
||||
}
|
||||
|
||||
if (Res) {
|
||||
@ -1396,13 +1396,6 @@ Instruction *InstCombiner::visitFDiv(BinaryOperator &I) {
|
||||
return Res;
|
||||
}
|
||||
}
|
||||
|
||||
// X / C => X * 1/C
|
||||
if (Instruction *T = CvtFDivConstToReciprocal(Op0, Op1C, AllowReciprocal)) {
|
||||
T->copyFastMathFlags(&I);
|
||||
return T;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user