[llvm] [InstCombine] Canonicalize reassoc contract fmuladd to fmul + fadd (PR #90434)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 8 03:02:07 PDT 2024


https://github.com/vfdff updated https://github.com/llvm/llvm-project/pull/90434

>From cb3c8fc6bf39c0f09056f76f860dd664131c4285 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sun, 28 Apr 2024 20:48:32 -0400
Subject: [PATCH 1/2] [InstCombine] Canonicalize reassoc contract fmuladd to
 fmul + fadd

According https://llvm.org/docs/LangRef.html#fast-math-flags, I think
only contract and reassoc is required for this transformation.
a) contract:  fusing a multiply followed by an addition into a fused multiply-and-add
b) reassoc: reassociation transformations when there may be other fp operations.

Fix https://github.com/llvm/llvm-project/issues/90379
---
 .../InstCombine/InstCombineCalls.cpp          | 14 +++++-----
 llvm/test/Transforms/InstCombine/fma.ll       | 28 +++++++++++++++++++
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index e5652458f150b..bf5472f4fd1e4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2389,12 +2389,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     break;
   }
   case Intrinsic::fmuladd: {
-    // Canonicalize fast fmuladd to the separate fmul + fadd.
-    if (II->isFast()) {
+    // Canonicalize reassoc contract fmuladd to the separate fmul + fadd.
+    FastMathFlags FMF = II->getFastMathFlags();
+    if (FMF.allowReassoc() && FMF.allowContract()) {
       BuilderTy::FastMathFlagGuard Guard(Builder);
-      Builder.setFastMathFlags(II->getFastMathFlags());
-      Value *Mul = Builder.CreateFMul(II->getArgOperand(0),
-                                      II->getArgOperand(1));
+      Builder.setFastMathFlags(FMF);
+      Value *Mul =
+          Builder.CreateFMul(II->getArgOperand(0), II->getArgOperand(1));
       Value *Add = Builder.CreateFAdd(Mul, II->getArgOperand(2));
       Add->takeName(II);
       return replaceInstUsesWith(*II, Add);
@@ -2402,8 +2403,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
 
     // Try to simplify the underlying FMul.
     if (Value *V = simplifyFMulInst(II->getArgOperand(0), II->getArgOperand(1),
-                                    II->getFastMathFlags(),
-                                    SQ.getWithInstruction(II))) {
+                                    FMF, SQ.getWithInstruction(II))) {
       auto *FAdd = BinaryOperator::CreateFAdd(V, II->getArgOperand(2));
       FAdd->copyFastMathFlags(II);
       return FAdd;
diff --git a/llvm/test/Transforms/InstCombine/fma.ll b/llvm/test/Transforms/InstCombine/fma.ll
index cf3d7f3c525a5..42e584e9ef9a1 100644
--- a/llvm/test/Transforms/InstCombine/fma.ll
+++ b/llvm/test/Transforms/InstCombine/fma.ll
@@ -204,6 +204,34 @@ define float @fmuladd_fneg_x_fneg_y_fast(float %x, float %y, float %z) {
   ret float %fmuladd
 }
 
+define float @fmuladd_unfold(float %x, float %y, float %z) {
+; CHECK-LABEL: @fmuladd_unfold(
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc contract float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[FMULADD:%.*]] = fadd reassoc contract float [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret float [[FMULADD]]
+;
+  %fmuladd = call reassoc contract float @llvm.fmuladd.f32(float %x, float %y, float %z)
+  ret float %fmuladd
+}
+
+define float @fmuladd_unfold_missing_reassoc(float %x, float %y, float %z) {
+; CHECK-LABEL: @fmuladd_unfold_missing_reassoc(
+; CHECK-NEXT:    [[FMULADD:%.*]] = call contract float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[FMULADD]]
+;
+  %fmuladd = call contract float @llvm.fmuladd.f32(float %x, float %y, float %z)
+  ret float %fmuladd
+}
+
+define float @fmuladd_unfold_missing_contract(float %x, float %y, float %z) {
+; CHECK-LABEL: @fmuladd_unfold_missing_contract(
+; CHECK-NEXT:    [[FMULADD:%.*]] = call reassoc float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    ret float [[FMULADD]]
+;
+  %fmuladd = call reassoc float @llvm.fmuladd.f32(float %x, float %y, float %z)
+  ret float %fmuladd
+}
+
 define float @fmuladd_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y_fast(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]

>From c20b02466009ba02dce04ce6ad4402588090e054 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Wed, 8 May 2024 05:41:30 -0400
Subject: [PATCH 2/2] [InstCombine] Add test with vector type

---
 llvm/test/Transforms/InstCombine/fma.ll | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/fma.ll b/llvm/test/Transforms/InstCombine/fma.ll
index 42e584e9ef9a1..547852104fb6d 100644
--- a/llvm/test/Transforms/InstCombine/fma.ll
+++ b/llvm/test/Transforms/InstCombine/fma.ll
@@ -214,21 +214,31 @@ define float @fmuladd_unfold(float %x, float %y, float %z) {
   ret float %fmuladd
 }
 
+define <8 x half> @fmuladd_unfold_vec(<8 x half> %x, <8 x half> %y, <8 x half> %z) {
+; CHECK-LABEL: @fmuladd_unfold_vec(
+; CHECK-NEXT:    [[TMP1:%.*]] = fmul reassoc contract <8 x half> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[FMULADD:%.*]] = fadd reassoc contract <8 x half> [[TMP1]], [[Z:%.*]]
+; CHECK-NEXT:    ret <8 x half> [[FMULADD]]
+;
+  %fmuladd = call reassoc contract <8 x half> @llvm.fmuladd.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> %z)
+  ret <8 x half> %fmuladd
+}
+
 define float @fmuladd_unfold_missing_reassoc(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmuladd_unfold_missing_reassoc(
-; CHECK-NEXT:    [[FMULADD:%.*]] = call contract float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[FMULADD:%.*]] = call nnan ninf nsz arcp contract afn float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[FMULADD]]
 ;
-  %fmuladd = call contract float @llvm.fmuladd.f32(float %x, float %y, float %z)
+  %fmuladd = call nnan ninf nsz arcp afn contract float @llvm.fmuladd.f32(float %x, float %y, float %z)
   ret float %fmuladd
 }
 
 define float @fmuladd_unfold_missing_contract(float %x, float %y, float %z) {
 ; CHECK-LABEL: @fmuladd_unfold_missing_contract(
-; CHECK-NEXT:    [[FMULADD:%.*]] = call reassoc float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
+; CHECK-NEXT:    [[FMULADD:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]])
 ; CHECK-NEXT:    ret float [[FMULADD]]
 ;
-  %fmuladd = call reassoc float @llvm.fmuladd.f32(float %x, float %y, float %z)
+  %fmuladd = call nnan ninf nsz arcp afn reassoc float @llvm.fmuladd.f32(float %x, float %y, float %z)
   ret float %fmuladd
 }
 



More information about the llvm-commits mailing list