From 97168183a32b2cd782411e3befc8c8316958fe5b Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 5 Oct 2025 17:41:33 +0800 Subject: [PATCH 1/5] [InstCombine] Add pre-commit tests. NFC. --- .../select-binop-foldable-floating-point.ll | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll index 253bc9e784c2f..00c4ef93e919e 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll @@ -23,6 +23,50 @@ define float @select_fpclass_fadd(i1 %cond, float nofpclass(nan) %A, float %B) { ret float %D } +define float @select_fpclass_fadd_ninf1(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fadd_ninf1( +; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fadd float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd ninf float %A, %B + %D = select i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fadd_ninf2(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fadd_ninf2( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fadd float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fadd_ninf3(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fadd_ninf3( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fadd ninf float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd ninf float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fadd_nnan_ninf(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fadd_nnan_ninf( +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fadd float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd float %A, %B + %D = select nnan ninf i1 %cond, float %C, float %A + ret float %D +} + define float @select_nnan_fadd(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fadd( ; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 From b1fbcdf188bfc3eeb10718fa9bec811800a08bdc Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 5 Oct 2025 18:30:54 +0800 Subject: [PATCH 2/5] [InstCombine] Fix flag propagation in `foldSelectIntoOp` --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 5 ++++- .../InstCombine/select-binop-foldable-floating-point.ll | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 8f60e506e8a33..fb4aaa6992702 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -544,8 +544,11 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, Swapped ? OOp : C, "", &SI); - if (isa(&SI)) + if (isa(&SI)) { cast(NewSel)->setFastMathFlags(FMF); + if (!TVI->hasNoInfs() && !FMF.noNaNs()) + cast(NewSel)->setHasNoInfs(false); + } NewSel->takeName(TVI); BinaryOperator *BO = BinaryOperator::Create(TVI->getOpcode(), FalseVal, NewSel); diff --git a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll index 00c4ef93e919e..8b5e02acfb02e 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll @@ -36,7 +36,7 @@ define float @select_fpclass_fadd_ninf1(i1 %cond, float nofpclass(nan) %A, float define float @select_fpclass_fadd_ninf2(i1 %cond, float nofpclass(nan) %A, float %B) { ; CHECK-LABEL: @select_fpclass_fadd_ninf2( -; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; From 3b28b6f56d3d16872a121a4abce087a258a5e175 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sat, 11 Oct 2025 01:20:23 +0800 Subject: [PATCH 3/5] [InstCombine] Address review comments. --- .../InstCombine/InstCombineSelect.cpp | 12 +- .../InstCombine/fold-select-fmul-if-zero.ll | 14 +-- .../select-binop-foldable-floating-point.ll | 106 ++++++++++++++++-- .../LoopVectorize/ARM/mve-selectandorcost.ll | 2 +- .../AArch64/predicated-reduction.ll | 24 ++-- 5 files changed, 126 insertions(+), 32 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index fb4aaa6992702..02fcf4e8479c8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -545,9 +545,15 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, Swapped ? OOp : C, "", &SI); if (isa(&SI)) { - cast(NewSel)->setFastMathFlags(FMF); - if (!TVI->hasNoInfs() && !FMF.noNaNs()) - cast(NewSel)->setHasNoInfs(false); + FastMathFlags NewSelFMF = FMF; + // We cannot propagate ninf from the original select, because OOp may be + // inf and the flag only guarantees that FalseVal (op OOp) is never + // infinity. Examples: -inf + +inf = NaN, -inf - -inf = NaN, 0 * inf = NaN + // Specially, if the original select has both ninf and nnan, we can safely + // propagate the flag. + NewSelFMF.setNoInfs(TVI->hasNoInfs() || + (NewSelFMF.noInfs() && NewSelFMF.noNaNs())); + cast(NewSel)->setFastMathFlags(NewSelFMF); } NewSel->takeName(TVI); BinaryOperator *BO = diff --git a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll index ff6d9aa4ea522..1ba7005f99e3d 100644 --- a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll +++ b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll @@ -481,7 +481,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_nsz_fmul(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nsz_ninf_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nsz_ninf_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -509,7 +509,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_nsz_nnan_fmul(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nnan_ninf_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nnan_ninf_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -558,7 +558,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_nsz_inverted(f define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -571,7 +571,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz(float %x, float % define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -585,7 +585,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted(float %x define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero(float %x, float nofpclass(nzero) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -598,7 +598,7 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_ne define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero_negsub(float %x, float nofpclass(nzero nsub) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero_negsub( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; @@ -705,7 +705,7 @@ define float @fmul_by_self_if_0_oeq_zero_f32(float %x) { define float @fmul_by_self_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz(float %x) { ; CHECK-LABEL: @fmul_by_self_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan ninf i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan float [[X]], [[SCALED_X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; diff --git a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll index 8b5e02acfb02e..c14dd469f1a6e 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll @@ -25,7 +25,7 @@ define float @select_fpclass_fadd(i1 %cond, float nofpclass(nan) %A, float %B) { define float @select_fpclass_fadd_ninf1(i1 %cond, float nofpclass(nan) %A, float %B) { ; CHECK-LABEL: @select_fpclass_fadd_ninf1( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -91,7 +91,7 @@ define float @select_nnan_fadd_swapped(i1 %cond, float %A, float %B) { define float @select_nnan_fadd_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fadd_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -102,7 +102,7 @@ define float @select_nnan_fadd_fast_math(i1 %cond, float %A, float %B) { define float @select_nnan_fadd_swapped_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fadd_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fadd reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -168,7 +168,7 @@ define float @select_nnan_fmul_swapped(i1 %cond, float %A, float %B) { define float @select_nnan_fmul_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fmul_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fmul reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -179,7 +179,7 @@ define float @select_nnan_fmul_fast_math(i1 %cond, float %A, float %B) { define float @select_nnan_fmul_swapped_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fmul_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fmul reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -188,6 +188,50 @@ define float @select_nnan_fmul_swapped_fast_math(i1 %cond, float %A, float %B) { ret float %D } +define float @select_fpclass_fmul_ninf1(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fmul_ninf1( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fmul float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fmul ninf float %A, %B + %D = select i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fmul_ninf2(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fmul_ninf2( +; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fmul float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fmul float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fmul_ninf3(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fmul_ninf3( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fmul ninf float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fmul ninf float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fmul_nnan_ninf(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fmul_nnan_ninf( +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fmul float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fmul float %A, %B + %D = select nnan ninf i1 %cond, float %C, float %A + ret float %D +} + define float @select_nnan_fsub(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fsub( ; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 @@ -212,7 +256,7 @@ define float @select_nnan_fsub_swapped(i1 %cond, float %A, float %B) { define float @select_nnan_fsub_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fsub_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fsub reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -223,7 +267,7 @@ define float @select_nnan_fsub_fast_math(i1 %cond, float %A, float %B) { define float @select_nnan_fsub_swapped_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fsub_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fsub reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -232,6 +276,50 @@ define float @select_nnan_fsub_swapped_fast_math(i1 %cond, float %A, float %B) { ret float %D } +define float @select_fpclass_fsub_ninf1(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fsub_ninf1( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fsub float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fsub ninf float %A, %B + %D = select i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fsub_ninf2(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fsub_ninf2( +; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fsub float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fsub float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fsub_ninf3(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fsub_ninf3( +; CHECK-NEXT: [[C:%.*]] = select ninf i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fsub ninf float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fsub ninf float %A, %B + %D = select ninf i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fsub_nnan_ninf(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fsub_nnan_ninf( +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +; CHECK-NEXT: [[D:%.*]] = fsub float [[A:%.*]], [[C]] +; CHECK-NEXT: ret float [[D]] +; + %C = fsub float %A, %B + %D = select nnan ninf i1 %cond, float %C, float %A + ret float %D +} + define <4 x float> @select_nnan_nsz_fsub_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x float> %B) { ; CHECK-LABEL: @select_nnan_nsz_fsub_v4f32( ; CHECK-NEXT: [[C:%.*]] = select nnan nsz <4 x i1> [[COND:%.*]], <4 x float> [[B:%.*]], <4 x float> zeroinitializer @@ -290,7 +378,7 @@ define float @select_nnan_fdiv_swapped(i1 %cond, float %A, float %B) { define float @select_nnan_fdiv_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fdiv_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; @@ -301,7 +389,7 @@ define float @select_nnan_fdiv_fast_math(i1 %cond, float %A, float %B) { define float @select_nnan_fdiv_swapped_fast_math(i1 %cond, float %A, float %B) { ; CHECK-LABEL: @select_nnan_fdiv_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select nnan ninf i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fdiv reassoc nnan arcp contract afn float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; diff --git a/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll b/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll index e154883ca7eca..9dbbf4cc35345 100644 --- a/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll +++ b/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll @@ -45,7 +45,7 @@ define float @test(ptr nocapture readonly %pA, ptr nocapture readonly %pB, i32 % ; CHECK-NEXT: [[TMP7:%.*]] = fsub fast <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD7]] ; CHECK-NEXT: [[TMP8:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP7]]) ; CHECK-NEXT: [[TMP9:%.*]] = fdiv fast <4 x float> [[TMP8]], [[TMP6]] -; CHECK-NEXT: [[TMP10:%.*]] = select <4 x i1> [[TMP20]], <4 x float> [[TMP9]], <4 x float> splat (float -0.000000e+00) +; CHECK-NEXT: [[TMP10:%.*]] = select ninf <4 x i1> [[TMP20]], <4 x float> [[TMP9]], <4 x float> splat (float -0.000000e+00) ; CHECK-NEXT: [[PREDPHI]] = fadd reassoc arcp contract afn <4 x float> [[VEC_PHI]], [[TMP10]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 ; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/predicated-reduction.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/predicated-reduction.ll index e8709a50524f8..55adda7d5b0f3 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/predicated-reduction.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/predicated-reduction.ll @@ -41,12 +41,12 @@ define nofpclass(nan inf) double @monte_simple(i32 noundef %nblocks, i32 noundef ; CHECK-NEXT: [[TMP9:%.*]] = fcmp fast ogt <4 x double> [[TMP7]], zeroinitializer ; CHECK-NEXT: [[TMP10:%.*]] = fmul fast <4 x double> [[TMP6]], [[TMP6]] ; CHECK-NEXT: [[TMP11:%.*]] = fmul fast <4 x double> [[TMP7]], [[TMP7]] -; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[TMP8]], <4 x double> [[TMP6]], <4 x double> splat (double -0.000000e+00) -; CHECK-NEXT: [[TMP13:%.*]] = select <4 x i1> [[TMP9]], <4 x double> [[TMP7]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP12:%.*]] = select ninf <4 x i1> [[TMP8]], <4 x double> [[TMP6]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP13:%.*]] = select ninf <4 x i1> [[TMP9]], <4 x double> [[TMP7]], <4 x double> splat (double -0.000000e+00) ; CHECK-NEXT: [[TMP14]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI16]], [[TMP12]] ; CHECK-NEXT: [[TMP15]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI17]], [[TMP13]] -; CHECK-NEXT: [[TMP16:%.*]] = select <4 x i1> [[TMP8]], <4 x double> [[TMP10]], <4 x double> splat (double -0.000000e+00) -; CHECK-NEXT: [[TMP17:%.*]] = select <4 x i1> [[TMP9]], <4 x double> [[TMP11]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP16:%.*]] = select ninf <4 x i1> [[TMP8]], <4 x double> [[TMP10]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP17:%.*]] = select ninf <4 x i1> [[TMP9]], <4 x double> [[TMP11]], <4 x double> splat (double -0.000000e+00) ; CHECK-NEXT: [[TMP18]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI]], [[TMP16]] ; CHECK-NEXT: [[TMP19]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI15]], [[TMP17]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDVARS_IV1]], 8 @@ -75,9 +75,9 @@ define nofpclass(nan inf) double @monte_simple(i32 noundef %nblocks, i32 noundef ; CHECK-NEXT: [[SUB:%.*]] = fsub fast double [[MUL]], [[Z]] ; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ogt double [[SUB]], 0.000000e+00 ; CHECK-NEXT: [[MUL3:%.*]] = fmul fast double [[SUB]], [[SUB]] -; CHECK-NEXT: [[ADD8:%.*]] = select i1 [[CMP1]], double [[SUB]], double -0.000000e+00 +; CHECK-NEXT: [[ADD8:%.*]] = select ninf i1 [[CMP1]], double [[SUB]], double -0.000000e+00 ; CHECK-NEXT: [[V0_2]] = fadd reassoc arcp contract afn double [[V0_011]], [[ADD8]] -; CHECK-NEXT: [[ADD4:%.*]] = select i1 [[CMP1]], double [[MUL3]], double -0.000000e+00 +; CHECK-NEXT: [[ADD4:%.*]] = select ninf i1 [[CMP1]], double [[MUL3]], double -0.000000e+00 ; CHECK-NEXT: [[V1_2]] = fadd reassoc arcp contract afn double [[V1_012]], [[ADD4]] ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] @@ -229,12 +229,12 @@ define nofpclass(nan inf) double @monte_exp(i32 noundef %nblocks, i32 noundef %R ; CHECK-NEXT: [[TMP13:%.*]] = fcmp fast ogt <4 x double> [[TMP11]], zeroinitializer ; CHECK-NEXT: [[TMP14:%.*]] = fmul fast <4 x double> [[TMP10]], [[TMP10]] ; CHECK-NEXT: [[TMP15:%.*]] = fmul fast <4 x double> [[TMP11]], [[TMP11]] -; CHECK-NEXT: [[TMP16:%.*]] = select <4 x i1> [[TMP12]], <4 x double> [[TMP10]], <4 x double> splat (double -0.000000e+00) -; CHECK-NEXT: [[TMP17:%.*]] = select <4 x i1> [[TMP13]], <4 x double> [[TMP11]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP16:%.*]] = select ninf <4 x i1> [[TMP12]], <4 x double> [[TMP10]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP17:%.*]] = select ninf <4 x i1> [[TMP13]], <4 x double> [[TMP11]], <4 x double> splat (double -0.000000e+00) ; CHECK-NEXT: [[TMP18]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI32]], [[TMP16]] ; CHECK-NEXT: [[TMP19]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI33]], [[TMP17]] -; CHECK-NEXT: [[TMP20:%.*]] = select <4 x i1> [[TMP12]], <4 x double> [[TMP14]], <4 x double> splat (double -0.000000e+00) -; CHECK-NEXT: [[TMP21:%.*]] = select <4 x i1> [[TMP13]], <4 x double> [[TMP15]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP20:%.*]] = select ninf <4 x i1> [[TMP12]], <4 x double> [[TMP14]], <4 x double> splat (double -0.000000e+00) +; CHECK-NEXT: [[TMP21:%.*]] = select ninf <4 x i1> [[TMP13]], <4 x double> [[TMP15]], <4 x double> splat (double -0.000000e+00) ; CHECK-NEXT: [[TMP22]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI]], [[TMP20]] ; CHECK-NEXT: [[TMP23]] = fadd reassoc arcp contract afn <4 x double> [[VEC_PHI31]], [[TMP21]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDVARS_IV1]], 8 @@ -263,9 +263,9 @@ define nofpclass(nan inf) double @monte_exp(i32 noundef %nblocks, i32 noundef %R ; CHECK-NEXT: [[SUB_US:%.*]] = fsub fast double [[MUL_US]], [[Z]] ; CHECK-NEXT: [[CMP4_US:%.*]] = fcmp fast ogt double [[SUB_US]], 0.000000e+00 ; CHECK-NEXT: [[ADD7_US:%.*]] = fmul fast double [[SUB_US]], [[SUB_US]] -; CHECK-NEXT: [[ADD12_US:%.*]] = select i1 [[CMP4_US]], double [[SUB_US]], double -0.000000e+00 +; CHECK-NEXT: [[ADD12_US:%.*]] = select ninf i1 [[CMP4_US]], double [[SUB_US]], double -0.000000e+00 ; CHECK-NEXT: [[V0_2_US]] = fadd reassoc arcp contract afn double [[V0_115_US]], [[ADD12_US]] -; CHECK-NEXT: [[ADD7_US1:%.*]] = select i1 [[CMP4_US]], double [[ADD7_US]], double -0.000000e+00 +; CHECK-NEXT: [[ADD7_US1:%.*]] = select ninf i1 [[CMP4_US]], double [[ADD7_US]], double -0.000000e+00 ; CHECK-NEXT: [[V1_2_US]] = fadd reassoc arcp contract afn double [[V1_116_US]], [[ADD7_US1]] ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[EXITCOND25_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] From dfd4bdf937536eadc4bd86ffea1af7481b3a065e Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sat, 11 Oct 2025 01:21:23 +0800 Subject: [PATCH 4/5] [InstCombine] format --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 02fcf4e8479c8..757a309993df0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -548,7 +548,8 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, FastMathFlags NewSelFMF = FMF; // We cannot propagate ninf from the original select, because OOp may be // inf and the flag only guarantees that FalseVal (op OOp) is never - // infinity. Examples: -inf + +inf = NaN, -inf - -inf = NaN, 0 * inf = NaN + // infinity. + // Examples: -inf + +inf = NaN, -inf - -inf = NaN, 0 * inf = NaN // Specially, if the original select has both ninf and nnan, we can safely // propagate the flag. NewSelFMF.setNoInfs(TVI->hasNoInfs() || From f4af43ae9c9184f96c62b0b5d8245bd11d5f331d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sat, 11 Oct 2025 01:25:40 +0800 Subject: [PATCH 5/5] Fix typo --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 757a309993df0..80b6bf1da2457 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -550,8 +550,8 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, // inf and the flag only guarantees that FalseVal (op OOp) is never // infinity. // Examples: -inf + +inf = NaN, -inf - -inf = NaN, 0 * inf = NaN - // Specially, if the original select has both ninf and nnan, we can safely - // propagate the flag. + // Specifically, if the original select has both ninf and nnan, we can + // safely propagate the flag. NewSelFMF.setNoInfs(TVI->hasNoInfs() || (NewSelFMF.noInfs() && NewSelFMF.noNaNs())); cast(NewSel)->setFastMathFlags(NewSelFMF);