[PATCH] D87479: [InstCombine] Don't sink the fdiv from (fmul (fdiv 1.0, %x), %y) if the fdiv isn't in the same basic block as the fmul

Craig Topper via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 12:48:02 PDT 2020


craig.topper created this revision.
craig.topper added reviewers: spatel, RKSimon, lebedev.ri, nikic, efriedma.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.
craig.topper requested review of this revision.

Loop invariant code motion can pull an fdiv out of by putting a reciprocal outside and using an fmul inside. InstCombine shouldn't reverse that.

I just did a simple basic block parent check rather than checking for the loop. I can call getLoop and isInvariant if we think that would be better.


https://reviews.llvm.org/D87479

Files:
  llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
  llvm/test/Transforms/InstCombine/fmul.ll


Index: llvm/test/Transforms/InstCombine/fmul.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul.ll
+++ llvm/test/Transforms/InstCombine/fmul.ll
@@ -1027,6 +1027,44 @@
   ret float %mul
 }
 
+; Make sure we don't sink this invariant fdiv into the loop.
+define void @fmul_loop_invariant_fdiv(float* %a, float %x) {
+; CHECK-LABEL: @fmul_loop_invariant_fdiv(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = fdiv fast float 1.000000e+00, [[X:%.*]]
+; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    ret void
+; CHECK:       for.body:
+; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[I_08]] to i64
+; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = fmul fast float [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    store float [[TMP2]], float* [[ARRAYIDX]], align 4
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[INC]], 1024
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
+;
+entry:
+  %0 = fdiv fast float 1.000000e+00, %x
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.body
+  ret void
+
+for.body:                                         ; preds = %entry, %for.body
+  %i.08 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
+  %idxprom = zext i32 %i.08 to i64
+  %arrayidx = getelementptr inbounds float, float* %a, i64 %idxprom
+  %1 = load float, float* %arrayidx, align 4
+  %2 = fmul fast float %1, %0
+  store float %2, float* %arrayidx, align 4
+  %inc = add nuw nsw i32 %i.08, 1
+  %cmp.not = icmp eq i32 %inc, 1024
+  br i1 %cmp.not, label %for.cond.cleanup, label %for.body
+}
+
 ; Avoid infinite looping by moving negation out of a constant expression.
 
 @g = external global {[2 x i8*]}, align 1
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -528,11 +528,19 @@
       }
     }
 
-    Value *Z;
-    if (match(&I, m_c_FMul(m_OneUse(m_FDiv(m_Value(X), m_Value(Y))),
-                           m_Value(Z)))) {
+    if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
+        (!match(X, m_FPOne()) ||
+         cast<Instruction>(Op1)->getParent() == I.getParent())) {
+      // Sink division: (X / Y) * Z --> (X * Z) / Y
+      Value *NewFMul = Builder.CreateFMulFMF(X, Op1, &I);
+      return BinaryOperator::CreateFDivFMF(NewFMul, Y, &I);
+    }
+
+    if (match(Op1, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
+        (!match(X, m_FPOne()) ||
+         cast<Instruction>(Op1)->getParent() == I.getParent())) {
       // Sink division: (X / Y) * Z --> (X * Z) / Y
-      Value *NewFMul = Builder.CreateFMulFMF(X, Z, &I);
+      Value *NewFMul = Builder.CreateFMulFMF(X, Op0, &I);
       return BinaryOperator::CreateFDivFMF(NewFMul, Y, &I);
     }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87479.291065.patch
Type: text/x-patch
Size: 3272 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200910/91b86cd0/attachment.bin>


More information about the llvm-commits mailing list