[llvm] [InstCombine] Optimise x / sqrt(y / z) with fast-math pattern. (PR #76737)
Joshua Cranmer via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 4 14:48:19 PST 2024
================
@@ -1701,6 +1701,31 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
}
+/// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv
+/// instruction.
+static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
+ InstCombiner::BuilderTy &Builder) {
+ // X / sqrt(Y / Z) --> X * sqrt(Z / Y)
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ auto *II = dyn_cast<IntrinsicInst>(Op1);
+ if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
+ !I.hasAllowReassoc() || !I.hasAllowReciprocal())
----------------
jcranmer-intel wrote:
Using `x.recip()` as shorthand for `(1.0 / x)`, `arcp` allows us to convert between `a / b` and `a * b.recip()` freely, and arguably `(a / b).recip()` to `(b / a)` (at the very least, gcc will do this with just `-freciprocal-math`).
We can convert `x / sqrt(y / z)` to `x * sqrt(y / z).recip()` with just `arcp`, and we can also convert `x * sqrt((y / z).recip())` to `x * sqrt(z / y)` with just `arcp` as well, but the question is which flags are necessary to convert `sqrt(a).recip()` to `sqrt(a.recip())`. I think it stretches `arcp` too far to allow this kind of permutation of `recip`. `reassoc` isn't entirely the right flag either; what we probably want is a more generic "allow algebraic identity" flag, but we're already using `reassoc` for that purpose elsewhere, so we might as well use it here as well.
https://github.com/llvm/llvm-project/pull/76737
More information about the llvm-commits
mailing list