[llvm] [InstCombine] Optimize powi(X, Y)/ (X * Z) with Ofast (PR #87047)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 20 21:01:52 PDT 2024
================
@@ -583,44 +583,67 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) {
Value *Y, Value *Z) {
InstCombiner::BuilderTy &Builder = IC.Builder;
Value *YZ = Builder.CreateAdd(Y, Z);
- auto *NewPow = Builder.CreateIntrinsic(
+ Instruction *NewPow = Builder.CreateIntrinsic(
Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I);
- return IC.replaceInstUsesWith(I, NewPow);
+
+ return NewPow;
};
Value *X, *Y, *Z;
+ unsigned Opcode = I.getOpcode();
+ assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) &&
+ "Unexpected opcode");
// powi(X, Y) * X --> powi(X, Y+1)
// X * powi(X, Y) --> powi(X, Y+1)
if (match(&I, m_c_FMul(m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(
m_Value(X), m_Value(Y)))),
m_Deferred(X)))) {
Constant *One = ConstantInt::get(Y->getType(), 1);
- if (willNotOverflowSignedAdd(Y, One, I))
- return createPowiExpr(I, *this, X, Y, One);
+ if (willNotOverflowSignedAdd(Y, One, I)) {
+ Instruction *NewPow = createPowiExpr(I, *this, X, Y, One);
+ return replaceInstUsesWith(I, NewPow);
+ }
}
// powi(x, y) * powi(x, z) -> powi(x, y + z)
Value *Op0 = I.getOperand(0);
Value *Op1 = I.getOperand(1);
- if (I.isOnlyUserOfAnyOperand() &&
+ if (Opcode == Instruction::FMul && I.isOnlyUserOfAnyOperand() &&
match(Op0, m_AllowReassoc(
m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y)))) &&
match(Op1, m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(m_Specific(X),
m_Value(Z)))) &&
- Y->getType() == Z->getType())
- return createPowiExpr(I, *this, X, Y, Z);
-
- // powi(X, Y) / X --> powi(X, Y-1)
- // This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan
- // are required.
- // TODO: Multi-use may be also better off creating Powi(x,y-1)
- if (I.hasAllowReassoc() && I.hasNoNaNs() &&
- match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(
- m_Specific(Op1), m_Value(Y))))) &&
- willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) {
- Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType());
- return createPowiExpr(I, *this, Op1, Y, NegOne);
+ Y->getType() == Z->getType()) {
+ Instruction *NewPow = createPowiExpr(I, *this, X, Y, Z);
+ return replaceInstUsesWith(I, NewPow);
+ }
+
+ if (Opcode == Instruction::FDiv && I.hasAllowReassoc() && I.hasNoNaNs()) {
----------------
vfdff wrote:
I don't feel like adding extra no-nan operand check because It is same as the following case, where we can ignore the possibility that X is infinity because INF/INF is NaN.
> https://github.com/llvm/llvm-project/blob/6cebd3577245a687947506ff423ea726ccd80849/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.
cpp#L1885
https://github.com/llvm/llvm-project/pull/87047
More information about the llvm-commits
mailing list