[InstCombine] Avoid ConstantExpr::getFNeg() calls (NFCI)

Instead call the constant folding API, which can fail. For now,
this should be NFC, as we still allow the creation of fneg
constant expressions.
This commit is contained in:
Nikita Popov 2022-07-29 15:45:56 +02:00
parent 226086230c
commit 5eaeeed8cb
3 changed files with 34 additions and 28 deletions

View File

@ -2238,7 +2238,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
/// This eliminates floating-point negation in either 'fneg(X)' or
/// 'fsub(-0.0, X)' form by combining into a constant operand.
static Instruction *foldFNegIntoConstant(Instruction &I) {
static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
// This is limited with one-use because fneg is assumed better for
// reassociation and cheaper in codegen than fmul/fdiv.
// TODO: Should the m_OneUse restriction be removed?
@ -2252,28 +2252,31 @@ static Instruction *foldFNegIntoConstant(Instruction &I) {
// Fold negation into constant operand.
// -(X * C) --> X * (-C)
if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFMulFMF(X, NegC, &I);
// -(X / C) --> X / (-C)
if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C))))
return BinaryOperator::CreateFDivFMF(X, ConstantExpr::getFNeg(C), &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFDivFMF(X, NegC, &I);
// -(C / X) --> (-C) / X
if (match(FNegOp, m_FDiv(m_Constant(C), m_Value(X)))) {
Instruction *FDiv =
BinaryOperator::CreateFDivFMF(ConstantExpr::getFNeg(C), X, &I);
if (match(FNegOp, m_FDiv(m_Constant(C), m_Value(X))))
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
Instruction *FDiv = BinaryOperator::CreateFDivFMF(NegC, X, &I);
// Intersect 'nsz' and 'ninf' because those special value exceptions may not
// apply to the fdiv. Everything else propagates from the fneg.
// TODO: We could propagate nsz/ninf from fdiv alone?
FastMathFlags FMF = I.getFastMathFlags();
FastMathFlags OpFMF = FNegOp->getFastMathFlags();
FDiv->setHasNoSignedZeros(FMF.noSignedZeros() && OpFMF.noSignedZeros());
FDiv->setHasNoInfs(FMF.noInfs() && OpFMF.noInfs());
return FDiv;
}
// Intersect 'nsz' and 'ninf' because those special value exceptions may
// not apply to the fdiv. Everything else propagates from the fneg.
// TODO: We could propagate nsz/ninf from fdiv alone?
FastMathFlags FMF = I.getFastMathFlags();
FastMathFlags OpFMF = FNegOp->getFastMathFlags();
FDiv->setHasNoSignedZeros(FMF.noSignedZeros() && OpFMF.noSignedZeros());
FDiv->setHasNoInfs(FMF.noInfs() && OpFMF.noInfs());
return FDiv;
}
// With NSZ [ counter-example with -0.0: -(-0.0 + 0.0) != 0.0 + -0.0 ]:
// -(X + C) --> -X + -C --> -C - X
if (I.hasNoSignedZeros() && match(FNegOp, m_FAdd(m_Value(X), m_Constant(C))))
return BinaryOperator::CreateFSubFMF(ConstantExpr::getFNeg(C), X, &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFSubFMF(NegC, X, &I);
return nullptr;
}
@ -2301,7 +2304,7 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
getSimplifyQuery().getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
if (Instruction *X = foldFNegIntoConstant(I))
if (Instruction *X = foldFNegIntoConstant(I, DL))
return X;
Value *X, *Y;
@ -2370,7 +2373,7 @@ Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) {
if (match(&I, m_FNeg(m_Value(Op))))
return UnaryOperator::CreateFNegFMF(Op, &I);
if (Instruction *X = foldFNegIntoConstant(I))
if (Instruction *X = foldFNegIntoConstant(I, DL))
return X;
if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
@ -2409,7 +2412,8 @@ Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) {
// But don't transform constant expressions because there's an inverse fold
// for X + (-Y) --> X - Y.
if (match(Op1, m_ImmConstant(C)))
return BinaryOperator::CreateFAddFMF(Op0, ConstantExpr::getFNeg(C), &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFAddFMF(Op0, NegC, &I);
// X - (-Y) --> X + Y
if (match(Op1, m_FNeg(m_Value(Y))))

View File

@ -6866,10 +6866,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
if (match(Op0, m_FNeg(m_Value(X)))) {
// fcmp pred (fneg X), C --> fcmp swap(pred) X, -C
Constant *C;
if (match(Op1, m_Constant(C))) {
Constant *NegC = ConstantExpr::getFNeg(C);
return new FCmpInst(I.getSwappedPredicate(), X, NegC, "", &I);
}
if (match(Op1, m_Constant(C)))
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return new FCmpInst(I.getSwappedPredicate(), X, NegC, "", &I);
}
if (match(Op0, m_FPExt(m_Value(X)))) {

View File

@ -492,7 +492,8 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
Value *X, *Y;
Constant *C;
if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Constant(C)))
return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFMulFMF(X, NegC, &I);
// (select A, B, C) * (select A, D, E) --> select A, (B*D), (C*E)
if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
@ -1226,8 +1227,10 @@ static Instruction *foldFDivConstantDivisor(BinaryOperator &I) {
// -X / C --> X / -C
Value *X;
const DataLayout &DL = I.getModule()->getDataLayout();
if (match(I.getOperand(0), m_FNeg(m_Value(X))))
return BinaryOperator::CreateFDivFMF(X, ConstantExpr::getFNeg(C), &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFDivFMF(X, NegC, &I);
// If the constant divisor has an exact inverse, this is always safe. If not,
// then we can still create a reciprocal if fast-math-flags allow it and the
@ -1239,7 +1242,6 @@ static Instruction *foldFDivConstantDivisor(BinaryOperator &I) {
// on all targets.
// TODO: Use Intrinsic::canonicalize or let function attributes tell us that
// denorms are flushed?
const DataLayout &DL = I.getModule()->getDataLayout();
auto *RecipC = ConstantFoldBinaryOpOperands(
Instruction::FDiv, ConstantFP::get(I.getType(), 1.0), C, DL);
if (!RecipC || !RecipC->isNormalFP())
@ -1257,15 +1259,16 @@ static Instruction *foldFDivConstantDividend(BinaryOperator &I) {
// C / -X --> -C / X
Value *X;
const DataLayout &DL = I.getModule()->getDataLayout();
if (match(I.getOperand(1), m_FNeg(m_Value(X))))
return BinaryOperator::CreateFDivFMF(ConstantExpr::getFNeg(C), X, &I);
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
return BinaryOperator::CreateFDivFMF(NegC, X, &I);
if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
return nullptr;
// Try to reassociate C / X expressions where X includes another constant.
Constant *C2, *NewC = nullptr;
const DataLayout &DL = I.getModule()->getDataLayout();
if (match(I.getOperand(1), m_FMul(m_Value(X), m_Constant(C2)))) {
// C / (X * C2) --> (C / C2) / X
NewC = ConstantFoldBinaryOpOperands(Instruction::FDiv, C, C2, DL);