[llvm] [InstCombine][ValueTracking] Add m_FMinNum and m_FMaxNum to matchFastFloatClamp. (PR #188149)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 3 10:46:55 PDT 2026


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/188149

>From 8628e93ba5a5906004a0799783759a3ae8744d63 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 23 Mar 2026 14:27:09 -0700
Subject: [PATCH 1/2] Pre-commit test

---
 .../Transforms/InstCombine/clamp-to-minmax.ll | 91 +++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
index 0ccaa9c393654..546d8abad131b 100644
--- a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
@@ -590,3 +590,94 @@ define <2 x float> @mixed_clamp_to_float_vec(<2 x i32> %x) {
   %r = select <2 x i1> %lo_cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %f_min
   ret <2 x float> %r
 }
+
+define i8 @clamp_float_fast_minnum_max_select_nsz_fptoui(float %x) {
+; CHECK-LABEL: @clamp_float_fast_minnum_max_select_nsz_fptoui(
+; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan olt float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 0.000000e+00, float [[MIN]]
+; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
+; CHECK-NEXT:    ret i8 [[FPTOUI]]
+;
+  %min = call float @llvm.minnum.f32(float %x, float 2.550000e+02)
+  %cmp1 = fcmp nnan olt float %x, 0.0
+  %r = select nsz i1 %cmp1, float 0.0, float %min
+  %fptoui = fptoui float %r to i8
+  ret i8 %fptoui
+}
+
+define i8 @clamp_float_fast_maxnum_min_select_nsz_fptoui(float %x) {
+; CHECK-LABEL: @clamp_float_fast_maxnum_min_select_nsz_fptoui(
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan ogt float [[X]], 2.550000e+02
+; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
+; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
+; CHECK-NEXT:    ret i8 [[FPTOUI]]
+;
+  %max = call float @llvm.maxnum.f32(float %x, float 0.000000e+00)
+  %cmp1 = fcmp nnan ogt float %x, 255.0
+  %r = select nsz i1 %cmp1, float 255.0, float %max
+  %fptoui = fptoui float %r to i8
+  ret i8 %fptoui
+}
+
+; Negative test. Constants in the wrong order.
+define i8 @clamp_float_fast_minnum_max_select_nsz_fptoui_negative(float %x) {
+; CHECK-LABEL: @clamp_float_fast_minnum_max_select_nsz_fptoui_negative(
+; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 1.270000e+02)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan olt float [[X]], 2.550000e+02
+; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 2.550000e+02, float [[MIN]]
+; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
+; CHECK-NEXT:    ret i8 [[FPTOUI]]
+;
+  %min = call float @llvm.minnum.f32(float %x, float 1.270000e+02)
+  %cmp1 = fcmp nnan olt float %x, 255.0
+  %r = select nsz i1 %cmp1, float 255.0, float %min
+  %fptoui = fptoui float %r to i8
+  ret i8 %fptoui
+}
+
+; Negative test. Constants in the wrong order.
+define i8 @clamp_float_fast_maxnum_min_select_nsz_fptoui_negative(float %x) {
+; CHECK-LABEL: @clamp_float_fast_maxnum_min_select_nsz_fptoui_negative(
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 2.550000e+02)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan ogt float [[X]], 1.280000e+02
+; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 1.280000e+02, float [[MAX]]
+; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
+; CHECK-NEXT:    ret i8 [[FPTOUI]]
+;
+  %max = call float @llvm.maxnum.f32(float %x, float 2.550000e+02)
+  %cmp1 = fcmp nnan ogt float %x, 128.0
+  %r = select nsz i1 %cmp1, float 128.0, float %max
+  %fptoui = fptoui float %r to i8
+  ret i8 %fptoui
+}
+
+; Negative test no nsz flag
+define float @clamp_float_fast_minnum_max_select_no_nsz(float %x) {
+; CHECK-LABEL: @clamp_float_fast_minnum_max_select_no_nsz(
+; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan olt float [[X]], 0.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 0.000000e+00, float [[MIN]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %min = call float @llvm.minnum.f32(float %x, float 2.550000e+02)
+  %cmp1 = fcmp nnan olt float %x, 0.0
+  %r = select i1 %cmp1, float 0.0, float %min
+  ret float %r
+}
+
+; Negative test no nsz flag
+define float @clamp_float_fast_maxnum_min_select_no_nsz(float %x) {
+; CHECK-LABEL: @clamp_float_fast_maxnum_min_select_no_nsz(
+; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan ogt float [[X]], 2.550000e+02
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
+; CHECK-NEXT:    ret float [[R]]
+;
+  %max = call float @llvm.maxnum.f32(float %x, float 0.000000e+00)
+  %cmp1 = fcmp nnan ogt float %x, 255.0
+  %r = select i1 %cmp1, float 255.0, float %max
+  ret float %r
+}
+

>From 0226f1961285b122da6e786a22889d4449fe2dd8 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 23 Mar 2026 15:44:31 -0700
Subject: [PATCH 2/2] [InstCombine][ValueTracking] Add m_FMinNum and m_FMaxNum
 to matchFastFloatClamp.

This allows us to recognize clamp patterns if the first part of the
clamp has been turned into minnum/maxnum.

The fptoui are necessary because something is losing the nsz on the
last select before the conversiont to maxnum/minnum happen.
---
 llvm/lib/Analysis/ValueTracking.cpp                 |  6 ++++++
 llvm/test/Transforms/InstCombine/clamp-to-minmax.ll | 10 ++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index dc10580aa2dea..bdad8e4bfd3c8 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8422,6 +8422,9 @@ static SelectPatternResult matchFastFloatClamp(CmpInst::Predicate Pred,
     if (match(FalseVal, m_OrdOrUnordFMin(m_Specific(CmpLHS), m_APFloat(FC2))) &&
         *FC1 < *FC2)
       return {SPF_FMAXNUM, SPNB_RETURNS_ANY, false};
+    if (match(FalseVal, m_FMinNum(m_Specific(CmpLHS), m_APFloat(FC2))) &&
+        *FC1 < *FC2)
+      return {SPF_FMAXNUM, SPNB_RETURNS_ANY, false};
     break;
   case CmpInst::FCMP_OGT:
   case CmpInst::FCMP_OGE:
@@ -8430,6 +8433,9 @@ static SelectPatternResult matchFastFloatClamp(CmpInst::Predicate Pred,
     if (match(FalseVal, m_OrdOrUnordFMax(m_Specific(CmpLHS), m_APFloat(FC2))) &&
         *FC1 > *FC2)
       return {SPF_FMINNUM, SPNB_RETURNS_ANY, false};
+    if (match(FalseVal, m_FMaxNum(m_Specific(CmpLHS), m_APFloat(FC2))) &&
+        *FC1 > *FC2)
+      return {SPF_FMINNUM, SPNB_RETURNS_ANY, false};
     break;
   default:
     break;
diff --git a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
index 546d8abad131b..8f121c6ca6cf2 100644
--- a/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
+++ b/llvm/test/Transforms/InstCombine/clamp-to-minmax.ll
@@ -594,8 +594,7 @@ define <2 x float> @mixed_clamp_to_float_vec(<2 x i32> %x) {
 define i8 @clamp_float_fast_minnum_max_select_nsz_fptoui(float %x) {
 ; CHECK-LABEL: @clamp_float_fast_minnum_max_select_nsz_fptoui(
 ; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan olt float [[X]], 0.000000e+00
-; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 0.000000e+00, float [[MIN]]
+; CHECK-NEXT:    [[R:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[MIN]], float 0.000000e+00)
 ; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
 ; CHECK-NEXT:    ret i8 [[FPTOUI]]
 ;
@@ -609,8 +608,7 @@ define i8 @clamp_float_fast_minnum_max_select_nsz_fptoui(float %x) {
 define i8 @clamp_float_fast_maxnum_min_select_nsz_fptoui(float %x) {
 ; CHECK-LABEL: @clamp_float_fast_maxnum_min_select_nsz_fptoui(
 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan ogt float [[X]], 2.550000e+02
-; CHECK-NEXT:    [[R:%.*]] = select nsz i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
+; CHECK-NEXT:    [[R:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02)
 ; CHECK-NEXT:    [[FPTOUI:%.*]] = fptoui float [[R]] to i8
 ; CHECK-NEXT:    ret i8 [[FPTOUI]]
 ;
@@ -671,8 +669,8 @@ define float @clamp_float_fast_minnum_max_select_no_nsz(float %x) {
 define float @clamp_float_fast_maxnum_min_select_no_nsz(float %x) {
 ; CHECK-LABEL: @clamp_float_fast_maxnum_min_select_no_nsz(
 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 0.000000e+00)
-; CHECK-NEXT:    [[CMP1:%.*]] = fcmp nnan ogt float [[X]], 2.550000e+02
-; CHECK-NEXT:    [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
+; CHECK-NEXT:    [[DOTINV:%.*]] = fcmp nnan ole float [[MAX]], 2.550000e+02
+; CHECK-NEXT:    [[R:%.*]] = select nnan i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %max = call float @llvm.maxnum.f32(float %x, float 0.000000e+00)



More information about the llvm-commits mailing list