[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