[llvm] [InstCombine] Add an additional nnan constraint for xfrm fcmp + sel => fmax/fmin (PR #117977)
Rajat Bajpai via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 28 00:11:25 PST 2024
https://github.com/rajatbajpai created https://github.com/llvm/llvm-project/pull/117977
Add an additional `nnan` constraint on the `fcmp` instruction for the `fcmp` + `select` => `fmax`/`fmin` xfrm. Without the `nnan` constraint, this transformation is incorrect.
Alive2 with and without the fix: https://alive2.llvm.org/ce/z/Hpo7WX
>From fe41e3eb735e48362e5151d878280fa0ddddcbe2 Mon Sep 17 00:00:00 2001
From: rbajpai <rbajpai at nvidia.com>
Date: Thu, 14 Nov 2024 12:29:03 +0530
Subject: [PATCH] [InstCombine] Add an additional nnan constraint for xfrm fcmp
+ sel => fmax/fmin
Add an additional `nnan` constraint on the `fcmp` instruction for the
`fcmp` + `select` => `fmax`/`fmin` xfrm. Without the `nnan` constraint,
this transformation is incorrect.
Alive2 with and without the fix: https://alive2.llvm.org/ce/z/Hpo7WX
---
.../InstCombine/InstCombineSelect.cpp | 5 +-
.../InstCombine/fcmp-fadd-select.ll | 46 +++++++++----------
.../Transforms/InstCombine/fcmp-select.ll | 4 +-
llvm/test/Transforms/InstCombine/fneg.ll | 2 +-
llvm/test/Transforms/InstCombine/minmax-fp.ll | 8 ++--
.../InstCombine/unordered-fcmp-select.ll | 4 +-
6 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index e5525133e5dbb5..46473af3f99dfc 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3864,9 +3864,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
if (SIFPOp) {
// TODO: Try to forward-propagate FMF from select arms to the select.
+ auto *FCmp = dyn_cast<FCmpInst>(CondVal);
+
// Canonicalize select of FP values where NaN and -0.0 are not valid as
// minnum/maxnum intrinsics.
- if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros()) {
+ if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros() && FCmp &&
+ FCmp->hasNoNaNs()) {
Value *X, *Y;
if (match(&SI, m_OrdOrUnordFMax(m_Value(X), m_Value(Y))))
return replaceInstUsesWith(
diff --git a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
index c49aea3e82b562..0019bb1023d565 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-fadd-select.ll
@@ -10,7 +10,7 @@ define float @test_fcmp_ogt_fadd_select_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -23,7 +23,7 @@ define float @test_fcmp_ogt_fadd_select_constant_swapped(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
@@ -36,7 +36,7 @@ define float @test_fcmp_ogt_fadd_select_neg_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, -0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, -0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -49,7 +49,7 @@ define float @test_fcmp_ogt_fadd_select_fastmath_preserve(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd nnan float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -62,7 +62,7 @@ define <2 x float> @test_fcmp_ogt_fadd_select_constant_vectors(<2 x float> %in)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], splat (float 1.000000e+00)
; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
;
- %cmp1 = fcmp ogt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %cmp1 = fcmp nnan ogt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
%add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
%sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
ret <2 x float> %sel
@@ -78,7 +78,7 @@ define float @test_fcmp_olt_fadd_select_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan olt float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -91,7 +91,7 @@ define float @test_fcmp_olt_fadd_select_constant_swapped(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan olt float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
@@ -104,7 +104,7 @@ define float @test_fcmp_olt_fadd_select_neg_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, -0.000000e+00
+ %cmp1 = fcmp nnan olt float %in, -0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -117,7 +117,7 @@ define float @test_fcmp_olt_fadd_select_fastmath_preserve(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp olt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan olt float %in, 0.000000e+00
%add = fadd nnan float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -130,7 +130,7 @@ define <2 x float> @test_fcmp_olt_fadd_select_constant_vectors(<2 x float> %in)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], splat (float 1.000000e+00)
; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
;
- %cmp1 = fcmp olt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %cmp1 = fcmp nnan olt <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
%add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
%sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
ret <2 x float> %sel
@@ -146,7 +146,7 @@ define float @test_fcmp_oge_fadd_select_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp oge float %in, 0.000000e+00
+ %cmp1 = fcmp nnan oge float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -159,7 +159,7 @@ define float @test_fcmp_oge_fadd_select_constant_swapped(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp oge float %in, 0.000000e+00
+ %cmp1 = fcmp nnan oge float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
@@ -172,7 +172,7 @@ define float @test_fcmp_oge_fadd_select_neg_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp oge float %in, -0.000000e+00
+ %cmp1 = fcmp nnan oge float %in, -0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -185,7 +185,7 @@ define float @test_fcmp_oge_fadd_select_fastmath_preserve(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp oge float %in, 0.000000e+00
+ %cmp1 = fcmp nnan oge float %in, 0.000000e+00
%add = fadd nnan float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -198,7 +198,7 @@ define <2 x float> @test_fcmp_oge_fadd_select_constant_vectors(<2 x float> %in)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], splat (float 1.000000e+00)
; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
;
- %cmp1 = fcmp oge <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %cmp1 = fcmp nnan oge <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
%add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
%sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
ret <2 x float> %sel
@@ -214,7 +214,7 @@ define float @test_fcmp_ole_fadd_select_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ole float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ole float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -227,7 +227,7 @@ define float @test_fcmp_ole_fadd_select_constant_swapped(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ole float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ole float %in, 0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float 1.000000e+00, float %add
ret float %sel
@@ -240,7 +240,7 @@ define float @test_fcmp_ole_fadd_select_neg_constant(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ole float %in, -0.000000e+00
+ %cmp1 = fcmp nnan ole float %in, -0.000000e+00
%add = fadd float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -253,7 +253,7 @@ define float @test_fcmp_ole_fadd_select_fastmath_preserve(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ole float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ole float %in, 0.000000e+00
%add = fadd nnan float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -266,7 +266,7 @@ define <2 x float> @test_fcmp_ole_fadd_select_constant_vectors(<2 x float> %in)
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz <2 x float> [[SEL_NEW]], splat (float 1.000000e+00)
; CHECK-NEXT: ret <2 x float> [[ADD_NEW]]
;
- %cmp1 = fcmp ole <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
+ %cmp1 = fcmp nnan ole <2 x float> %in, <float 0.000000e+00, float 0.000000e+00>
%add = fadd <2 x float> %in, <float 1.000000e+00, float 1.000000e+00>
%sel = select nnan nsz <2 x i1> %cmp1, <2 x float> %add, <2 x float> <float 1.000000e+00, float 1.000000e+00>
ret <2 x float> %sel
@@ -641,7 +641,7 @@ define float @test_fcmp_ogt_fadd_select_rewrite_flags1(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd reassoc afn arcp contract float %in, 1.000000e+00
%sel = select nnan nsz reassoc afn arcp contract i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -654,7 +654,7 @@ define float @test_fcmp_ogt_fadd_select_rewrite_flags2(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd nnan nsz float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd reassoc float %in, 1.000000e+00
%sel = select nnan nsz i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
@@ -667,7 +667,7 @@ define float @test_fcmp_ogt_fadd_select_rewrite_and_fastmath(float %in) {
; CHECK-NEXT: [[ADD_NEW:%.*]] = fadd fast float [[SEL_NEW]], 1.000000e+00
; CHECK-NEXT: ret float [[ADD_NEW]]
;
- %cmp1 = fcmp ogt float %in, 0.000000e+00
+ %cmp1 = fcmp nnan ogt float %in, 0.000000e+00
%add = fadd fast reassoc float %in, 1.000000e+00
%sel = select fast i1 %cmp1, float %add, float 1.000000e+00
ret float %sel
diff --git a/llvm/test/Transforms/InstCombine/fcmp-select.ll b/llvm/test/Transforms/InstCombine/fcmp-select.ll
index 028de1ff8a99fa..24f9fab05f1ae8 100644
--- a/llvm/test/Transforms/InstCombine/fcmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/fcmp-select.ll
@@ -223,9 +223,9 @@ define double @test_fcmp_select_maxnum(double %x) {
; CHECK-NEXT: [[SEL2:%.*]] = call nnan nsz double @llvm.minnum.f64(double [[SEL1]], double 2.550000e+02)
; CHECK-NEXT: ret double [[SEL2]]
;
- %cmp1 = fcmp ogt double %x, 1.0
+ %cmp1 = fcmp nnan ogt double %x, 1.0
%sel1 = select nnan nsz i1 %cmp1, double %x, double 1.0
- %cmp2 = fcmp olt double %sel1, 255.0
+ %cmp2 = fcmp nnan olt double %sel1, 255.0
%sel2 = select nnan nsz i1 %cmp2, double %sel1, double 255.0
ret double %sel2
}
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 9692005edf2b6a..c531ee52842708 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -1103,7 +1103,7 @@ define float @test_fneg_select_maxnum(float %x) {
; CHECK-NEXT: [[NEG:%.*]] = fneg float [[SEL1]]
; CHECK-NEXT: ret float [[NEG]]
;
- %cmp1 = fcmp ogt float %x, 1.0
+ %cmp1 = fcmp nnan ogt float %x, 1.0
%sel1 = select nnan nsz i1 %cmp1, float %x, float 1.0
%neg = fneg float %sel1
ret float %neg
diff --git a/llvm/test/Transforms/InstCombine/minmax-fp.ll b/llvm/test/Transforms/InstCombine/minmax-fp.ll
index 1276b7b3e3867d..6625458b575b5c 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fp.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fp.ll
@@ -324,7 +324,7 @@ define float @maxnum_ogt_fmf_on_select(float %a, float %b) {
; CHECK-NEXT: [[F:%.*]] = call nnan nsz float @llvm.maxnum.f32(float [[A:%.*]], float [[B:%.*]])
; CHECK-NEXT: ret float [[F]]
;
- %cond = fcmp ogt float %a, %b
+ %cond = fcmp nnan ogt float %a, %b
%f = select nnan nsz i1 %cond, float %a, float %b
ret float %f
}
@@ -334,7 +334,7 @@ define <2 x float> @maxnum_oge_fmf_on_select(<2 x float> %a, <2 x float> %b) {
; CHECK-NEXT: [[F:%.*]] = call nnan ninf nsz <2 x float> @llvm.maxnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
; CHECK-NEXT: ret <2 x float> [[F]]
;
- %cond = fcmp oge <2 x float> %a, %b
+ %cond = fcmp nnan oge <2 x float> %a, %b
%f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b
ret <2 x float> %f
}
@@ -388,7 +388,7 @@ define float @minnum_olt_fmf_on_select(float %a, float %b) {
; CHECK-NEXT: [[F:%.*]] = call nnan nsz float @llvm.minnum.f32(float [[A:%.*]], float [[B:%.*]])
; CHECK-NEXT: ret float [[F]]
;
- %cond = fcmp olt float %a, %b
+ %cond = fcmp nnan olt float %a, %b
%f = select nnan nsz i1 %cond, float %a, float %b
ret float %f
}
@@ -398,7 +398,7 @@ define <2 x float> @minnum_ole_fmf_on_select(<2 x float> %a, <2 x float> %b) {
; CHECK-NEXT: [[F:%.*]] = call nnan ninf nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])
; CHECK-NEXT: ret <2 x float> [[F]]
;
- %cond = fcmp ole <2 x float> %a, %b
+ %cond = fcmp nnan ole <2 x float> %a, %b
%f = select ninf nnan nsz <2 x i1> %cond, <2 x float> %a, <2 x float> %b
ret <2 x float> %f
}
diff --git a/llvm/test/Transforms/InstCombine/unordered-fcmp-select.ll b/llvm/test/Transforms/InstCombine/unordered-fcmp-select.ll
index b164dd983a8925..9042c3c1fa346d 100644
--- a/llvm/test/Transforms/InstCombine/unordered-fcmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/unordered-fcmp-select.ll
@@ -113,12 +113,12 @@ declare void @foo(i1)
define float @select_max_ugt_2_use_cmp(float %a, float %b) {
; CHECK-LABEL: @select_max_ugt_2_use_cmp(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ugt float [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc nnan ugt float [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: call void @foo(i1 [[CMP]])
; CHECK-NEXT: [[SEL:%.*]] = call fast float @llvm.maxnum.f32(float [[A]], float [[B]])
; CHECK-NEXT: ret float [[SEL]]
;
- %cmp = fcmp reassoc ugt float %a, %b
+ %cmp = fcmp nnan reassoc ugt float %a, %b
call void @foo(i1 %cmp)
%sel = select fast i1 %cmp, float %a, float %b
ret float %sel
More information about the llvm-commits
mailing list