[llvm] [InstCombine] Relax one-use check for min/max(fpext x, fpext y) to fpext(min/max(x, y)) fold (PR #180164)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 6 03:14:50 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

If only of the operands is one-use, the total number of fpexts stays the same, but the min/max is performed on a narrowed type. Additionally, the fpext may fold with a following fptrunc.

---
Full diff: https://github.com/llvm/llvm-project/pull/180164.diff


3 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+2-2) 
- (modified) llvm/test/Transforms/InstCombine/maxnum.ll (+22-7) 
- (modified) llvm/test/Transforms/InstCombine/minnum.ll (+22-7) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 652e94d5a9fbd..1b42ed5e4a349 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2870,8 +2870,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     }
 
     // m((fpext X), (fpext Y)) -> fpext (m(X, Y))
-    if (match(Arg0, m_OneUse(m_FPExt(m_Value(X)))) &&
-        match(Arg1, m_OneUse(m_FPExt(m_Value(Y)))) &&
+    if (match(Arg0, m_FPExt(m_Value(X))) && match(Arg1, m_FPExt(m_Value(Y))) &&
+        (Arg0->hasOneUse() || Arg1->hasOneUse()) &&
         X->getType() == Y->getType()) {
       Value *NewCall =
           Builder.CreateBinaryIntrinsic(IID, X, Y, II, II->getName());
diff --git a/llvm/test/Transforms/InstCombine/maxnum.ll b/llvm/test/Transforms/InstCombine/maxnum.ll
index 67fb7a90b3d49..5e275627414cb 100644
--- a/llvm/test/Transforms/InstCombine/maxnum.ll
+++ b/llvm/test/Transforms/InstCombine/maxnum.ll
@@ -402,11 +402,9 @@ define float @reduce_precision_fmf(float %x, float %y) {
 
 define float @reduce_precision_multi_use_0(float %x, float %y, ptr %p) {
 ; CHECK-LABEL: @reduce_precision_multi_use_0(
-; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
 ; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
-; CHECK-NEXT:    store double [[X_EXT]], ptr [[P:%.*]], align 8
-; CHECK-NEXT:    [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float
+; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P:%.*]], align 8
+; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.maxnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %x.ext = fpext float %x to double
@@ -419,11 +417,9 @@ define float @reduce_precision_multi_use_0(float %x, float %y, ptr %p) {
 
 define float @reduce_precision_multi_use_1(float %x, float %y, ptr %p) {
 ; CHECK-LABEL: @reduce_precision_multi_use_1(
-; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
 ; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
 ; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P:%.*]], align 8
-; CHECK-NEXT:    [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[MAXNUM]] to float
+; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float [[Y]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %x.ext = fpext float %x to double
@@ -434,6 +430,25 @@ define float @reduce_precision_multi_use_1(float %x, float %y, ptr %p) {
   ret float %trunc
 }
 
+define float @reduce_precision_multi_use_2(float %x, float %y, ptr %p, ptr %p2) {
+; CHECK-LABEL: @reduce_precision_multi_use_2(
+; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
+; CHECK-NEXT:    store double [[X_EXT]], ptr [[P:%.*]], align 8
+; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P2:%.*]], align 8
+; CHECK-NEXT:    [[MAXNUM:%.*]] = call double @llvm.maxnum.f64(double [[X_EXT]], double [[Y_EXT]])
+; CHECK-NEXT:    [[MAXNUM1:%.*]] = fptrunc double [[MAXNUM]] to float
+; CHECK-NEXT:    ret float [[MAXNUM1]]
+;
+  %x.ext = fpext float %x to double
+  %y.ext = fpext float %y to double
+  store double %x.ext, ptr %p
+  store double %y.ext, ptr %p2
+  %maxnum = call double @llvm.maxnum.f64(double %x.ext, double %y.ext)
+  %trunc = fptrunc double %maxnum to float
+  ret float %trunc
+}
+
 define float @negated_op(float %x) {
 ; CHECK-LABEL: @negated_op(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
diff --git a/llvm/test/Transforms/InstCombine/minnum.ll b/llvm/test/Transforms/InstCombine/minnum.ll
index cc6171b9d8e6c..093e6e78a4c11 100644
--- a/llvm/test/Transforms/InstCombine/minnum.ll
+++ b/llvm/test/Transforms/InstCombine/minnum.ll
@@ -439,11 +439,9 @@ define float @reduce_precision_fmf(float %x, float %y) {
 
 define float @reduce_precision_multi_use_0(float %x, float %y, ptr %p) {
 ; CHECK-LABEL: @reduce_precision_multi_use_0(
-; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
 ; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
-; CHECK-NEXT:    store double [[X_EXT]], ptr [[P:%.*]], align 8
-; CHECK-NEXT:    [[MINNUM:%.*]] = call double @llvm.minnum.f64(double [[X_EXT]], double [[Y_EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[MINNUM]] to float
+; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P:%.*]], align 8
+; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.minnum.f32(float [[Y]], float [[Y1:%.*]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %x.ext = fpext float %x to double
@@ -456,11 +454,9 @@ define float @reduce_precision_multi_use_0(float %x, float %y, ptr %p) {
 
 define float @reduce_precision_multi_use_1(float %x, float %y, ptr %p) {
 ; CHECK-LABEL: @reduce_precision_multi_use_1(
-; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
 ; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
 ; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P:%.*]], align 8
-; CHECK-NEXT:    [[MINNUM:%.*]] = call double @llvm.minnum.f64(double [[X_EXT]], double [[Y_EXT]])
-; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[MINNUM]] to float
+; CHECK-NEXT:    [[TRUNC:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]])
 ; CHECK-NEXT:    ret float [[TRUNC]]
 ;
   %x.ext = fpext float %x to double
@@ -471,6 +467,25 @@ define float @reduce_precision_multi_use_1(float %x, float %y, ptr %p) {
   ret float %trunc
 }
 
+define float @reduce_precision_multi_use_2(float %x, float %y, ptr %p, ptr %p2) {
+; CHECK-LABEL: @reduce_precision_multi_use_2(
+; CHECK-NEXT:    [[X_EXT:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT:    [[Y_EXT:%.*]] = fpext float [[Y:%.*]] to double
+; CHECK-NEXT:    store double [[X_EXT]], ptr [[P:%.*]], align 8
+; CHECK-NEXT:    store double [[Y_EXT]], ptr [[P2:%.*]], align 8
+; CHECK-NEXT:    [[MINNUM:%.*]] = call double @llvm.minnum.f64(double [[X_EXT]], double [[Y_EXT]])
+; CHECK-NEXT:    [[MINNUM1:%.*]] = fptrunc double [[MINNUM]] to float
+; CHECK-NEXT:    ret float [[MINNUM1]]
+;
+  %x.ext = fpext float %x to double
+  %y.ext = fpext float %y to double
+  store double %x.ext, ptr %p
+  store double %y.ext, ptr %p2
+  %minnum = call double @llvm.minnum.f64(double %x.ext, double %y.ext)
+  %trunc = fptrunc double %minnum to float
+  ret float %trunc
+}
+
 define float @negated_op(float %x) {
 ; CHECK-LABEL: @negated_op(
 ; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])

``````````

</details>


https://github.com/llvm/llvm-project/pull/180164


More information about the llvm-commits mailing list