[llvm] [InstCombine] Transform high latency, dependent FSQRT/FDIV into FMUL (PR #87474)
Joshua Cranmer via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 10 08:35:10 PDT 2024
================
@@ -626,6 +626,127 @@ Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) {
return nullptr;
}
+bool isFSqrtDivToFMulLegal(Instruction *X, SmallSetVector<Instruction *, 2> &R1,
+ SmallSetVector<Instruction *, 2> &R2) {
+
+ BasicBlock *BBx = X->getParent();
+ BasicBlock *BBr1 = R1[0]->getParent();
+ BasicBlock *BBr2 = R2[0]->getParent();
+
+ auto IsStrictFP = [](Instruction *I) {
+ IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
+ return II && II->isStrictFP();
+ };
+
+ // Check the constaints on instruction X.
+ auto XConstraintsSatisfied = [X, &IsStrictFP]() {
+ if (IsStrictFP(X))
+ return false;
+ // X must atleast have 4 uses.
+ // 3 uses as part of
+ // r1 = x * x
+ // r2 = a * x
+ // Now, post-transform, r1/r2 will no longer have usage of 'x' and if the
+ // changes to 'x' need to persist, we must have one more usage of 'x'
+ if (!X->hasNUsesOrMore(4))
+ return false;
+ // Check if reciprocalFP is enabled.
+ bool RecipFPMath = dyn_cast<FPMathOperator>(X)->hasAllowReciprocal();
----------------
jcranmer-intel wrote:
The definition of most of our fast-math flags are about as clear as mud. However, the `arcp` flag is generally treated as allowing the transformation `x / y` => `x * (1.0 / y)`, and only that transformation.
`1.0 / sqrt(a)` is *not* the same as `sqrt(a) / a`--it is for real numbers, but FP numbers are not real numbers--so converting `1.0 / sqrt(a)` to `sqrt(a) / a` requires a fast-math flag of some kind, and the one that we've been abusing here is the `reassoc` flag, which has kind of devolved in practice into "permit algebraic rewrites".
https://github.com/llvm/llvm-project/pull/87474
More information about the llvm-commits
mailing list