[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