[PATCH] D72319: [InstCombine] Adding Z / (1.0 / Y) => (Y * Z)
Raghesh Aloor via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 7 00:45:31 PST 2020
raghesh created this revision.
raghesh added reviewers: spatel, craig.topper, llvm-commits.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.
raghesh added a subscriber: llvm-commits.
This is a special case of Z / (X / Y) => (Y * Z) / X, with X = 1.0. The m_OneUse check is avoided because even in the case of the multiple uses for 1.0/Y, the number of instructions remain the same and a division is replaced by a multiplication.
The following testcase is added.
test/Transforms/InstCombine/fdiv-to-fmul-opt.ll
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D72319
Files:
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/test/Transforms/InstCombine/fdiv-to-fmul-opt.ll
Index: llvm/test/Transforms/InstCombine/fdiv-to-fmul-opt.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/InstCombine/fdiv-to-fmul-opt.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -instcombine < %s | FileCheck %s
+
+; NOTE: double fun() {
+; NOTE: double r1, r2, r3, r4, r5, r6, r7;
+; NOTE:
+; NOTE: r2 = 1.0 / sqrt(r1);
+; NOTE: r3 = r4 / r2;
+; NOTE:
+; NOTE: r7 = r6 * r2;
+; NOTE:
+; NOTE: return r7 * r3;
+; NOTE: }
+; NOTE: IR for the above C code is given below.
+
+define dso_local double @fun() #0 {
+ %r1 = alloca double, align 8
+ %r2 = alloca double, align 8
+ %r3 = alloca double, align 8
+ %r4 = alloca double, align 8
+ %r5 = alloca double, align 8
+ %r6 = alloca double, align 8
+ %r7 = alloca double, align 8
+ %A = load double, double* %r1, align 8
+ %B = call fast double @llvm.sqrt.f64(double %A)
+ %div = fdiv fast double 1.000000e+00, %B
+ store double %div, double* %r2, align 8
+ %C = load double, double* %r4, align 8
+ %D = load double, double* %r2, align 8
+ %div1 = fdiv fast double %C, %D
+ store double %div1, double* %r3, align 8
+ %E = load double, double* %r6, align 8
+ %F = load double, double* %r2, align 8
+ %mul = fmul fast double %E, %F
+ store double %mul, double* %r7, align 8
+ %G = load double, double* %r7, align 8
+ %H = load double, double* %r3, align 8
+ %mul2 = fmul fast double %G, %H
+ ret double %mul2
+
+; CHECK-NOT: fdiv fast double 1.000000e+00, %B
+; CHECK-NOT: %div1 = fdiv fast double %C, %D
+; CHECK: %B = call fast double @llvm.sqrt.f64(double %A)
+; CHECK-NEXT: %C = load double, double* %r4, align 8
+; CHECK-NEXT: %div1 = fmul fast double %B, %C
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare double @llvm.sqrt.f64(double) #1
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1239,6 +1239,15 @@
Value *YZ = Builder.CreateFMulFMF(Y, Op0, &I);
return BinaryOperator::CreateFDivFMF(YZ, X, &I);
}
+ // Z / (1.0 / Y) => (Y * Z)
+ //
+ // This is a special case of Z / (X / Y) => (Y * Z) / X, with X = 1.0. The
+ // m_OneUse check is avoided because even in the case of the multiple uses
+ // for 1.0/Y, the number of instructions remain the same and a division is
+ // replaced by a multiplication.
+ if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y))) &&
+ (!isa<Constant>(Y) || !isa<Constant>(Op0)))
+ return BinaryOperator::CreateFMulFMF(Y, Op0, &I);
}
if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D72319.236530.patch
Type: text/x-patch
Size: 2770 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200107/e0aba4ce/attachment.bin>
More information about the llvm-commits
mailing list