https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/125338
Backport 3ec6a6b85aed838b7d56bd6843cad52e822b9111 Requested by: @dtcxzyw >From be5e712bcc849c9284ad813afa0d287f47b89ad5 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sat, 1 Feb 2025 15:14:17 +0800 Subject: [PATCH] [InstCombine] Fix FMF propagation in `foldSelectWithFCmpToFabs` (#121580) Consider the following pattern: ``` %cmp = fcmp <pred> double %x, 0.000000e+00 %negX = fneg <fmf> double %x %sel = select i1 %cmp, double %x, double %negX ``` We cannot propagate ninf from fneg to select since `%negX` may not be chosen. Similarly, we cannot propagate nnan unless `%negX` is guaranteed to be selected when `%x` is NaN. This patch also propagates nnan/ninf from fcmp to avoid regression in `PhaseOrdering/generate-fabs.ll`. Alive2: https://alive2.llvm.org/ce/z/t6U-tA Closes https://github.com/llvm/llvm-project/issues/121430 and https://github.com/llvm/llvm-project/issues/113989. (cherry picked from commit 3ec6a6b85aed838b7d56bd6843cad52e822b9111) --- .../InstCombine/InstCombineSelect.cpp | 11 ++++- llvm/test/Transforms/InstCombine/fabs.ll | 40 +++++++++---------- llvm/test/Transforms/InstCombine/fneg-fabs.ll | 17 ++++---- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index e2af4d4c563648..29c5cef84ccdb7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2852,10 +2852,10 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI, if (!match(TrueVal, m_FNeg(m_Specific(X)))) return nullptr; - // Forward-propagate nnan and ninf from the fneg to the select. + // Forward-propagate nnan and ninf from the fcmp to the select. // If all inputs are not those values, then the select is not either. // Note: nsz is defined differently, so it may not be correct to propagate. - FastMathFlags FMF = cast<FPMathOperator>(TrueVal)->getFastMathFlags(); + FastMathFlags FMF = cast<FPMathOperator>(CondVal)->getFastMathFlags(); if (FMF.noNaNs() && !SI.hasNoNaNs()) { SI.setHasNoNaNs(true); ChangedFMF = true; @@ -2864,6 +2864,13 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI, SI.setHasNoInfs(true); ChangedFMF = true; } + // Forward-propagate nnan from the fneg to the select. + // The nnan flag can be propagated iff fneg is selected when X is NaN. + if (!SI.hasNoNaNs() && cast<FPMathOperator>(TrueVal)->hasNoNaNs() && + (Swap ? FCmpInst::isOrdered(Pred) : FCmpInst::isUnordered(Pred))) { + SI.setHasNoNaNs(true); + ChangedFMF = true; + } // With nsz, when 'Swap' is false: // fold (X < +/-0.0) ? -X : X or (X <= +/-0.0) ? -X : X to fabs(X) diff --git a/llvm/test/Transforms/InstCombine/fabs.ll b/llvm/test/Transforms/InstCombine/fabs.ll index cccf0f4457b6ab..7b9a672f188cab 100644 --- a/llvm/test/Transforms/InstCombine/fabs.ll +++ b/llvm/test/Transforms/InstCombine/fabs.ll @@ -484,7 +484,7 @@ define double @select_fcmp_nnan_nsz_olt_zero(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %ltzero = fcmp olt double %x, 0.0 @@ -523,7 +523,7 @@ define double @select_fcmp_nnan_nsz_olt_zero_unary_fneg(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_zero_unary_fneg( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %ltzero = fcmp olt double %x, 0.0 @@ -553,7 +553,7 @@ define float @select_fcmp_nnan_nsz_olt_negzero(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %ltzero = fcmp olt float %x, -0.0 @@ -579,7 +579,7 @@ define float @select_fcmp_nnan_nsz_ult_negzero(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %ltzero = fcmp ult float %x, -0.0 @@ -592,7 +592,7 @@ define float @select_fcmp_nnan_nsz_olt_negzero_unary_fneg(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_olt_negzero_unary_fneg( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LTZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %ltzero = fcmp olt float %x, -0.0 @@ -607,7 +607,7 @@ define float @select_fcmp_nnan_nsz_ult_negzero_unary_fneg(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ult_negzero_unary_fneg( ; CHECK-NEXT: [[LTZERO:%.*]] = fcmp ult float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan ninf nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LTZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LTZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %ltzero = fcmp ult float %x, -0.0 @@ -622,7 +622,7 @@ define double @select_fcmp_nnan_nsz_ole_zero(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %lezero = fcmp ole double %x, 0.0 @@ -648,7 +648,7 @@ define double @select_fcmp_nnan_nsz_ule_zero(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %lezero = fcmp ule double %x, 0.0 @@ -661,7 +661,7 @@ define double @select_fcmp_nnan_nsz_ole_zero_unary_fneg(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_zero_unary_fneg( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %lezero = fcmp ole double %x, 0.0 @@ -676,7 +676,7 @@ define double @select_fcmp_nnan_nsz_ule_zero_unary_fneg(double %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ule_zero_unary_fneg( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ule double [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[LEZERO]], double [[NEGX]], double [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[FABS]] ; %lezero = fcmp ule double %x, 0.0 @@ -691,7 +691,7 @@ define float @select_fcmp_nnan_nsz_ole_negzero(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %lezero = fcmp ole float %x, -0.0 @@ -730,7 +730,7 @@ define float @select_fcmp_nnan_nsz_ole_negzero_unary_fneg(float %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ole_negzero_unary_fneg( ; CHECK-NEXT: [[LEZERO:%.*]] = fcmp ole float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz float [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[LEZERO]], float [[NEGX]], float [[X]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[LEZERO]], float [[NEGX]], float [[X]] ; CHECK-NEXT: ret float [[FABS]] ; %lezero = fcmp ole float %x, -0.0 @@ -802,7 +802,7 @@ define <2 x float> @select_fcmp_nnan_nsz_ugt_zero(<2 x float> %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero( ; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] ; CHECK-NEXT: ret <2 x float> [[FABS]] ; %gtzero = fcmp ugt <2 x float> %x, zeroinitializer @@ -830,7 +830,7 @@ define <2 x float> @select_fcmp_nnan_nsz_ugt_zero_unary_fneg(<2 x float> %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_zero_unary_fneg( ; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt <2 x float> [[X:%.*]], zeroinitializer ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz arcp <2 x float> [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GTZERO]], <2 x float> [[X]], <2 x float> [[NEGX]] ; CHECK-NEXT: ret <2 x float> [[FABS]] ; %gtzero = fcmp ugt <2 x float> %x, zeroinitializer @@ -845,7 +845,7 @@ define half @select_fcmp_nnan_nsz_ogt_negzero(half %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ogt_negzero( ; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ogt half [[X:%.*]], 0xH0000 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GTZERO]], half [[X]], half [[NEGX]] ; CHECK-NEXT: ret half [[FABS]] ; %gtzero = fcmp ogt half %x, -0.0 @@ -860,7 +860,7 @@ define half @select_fcmp_nnan_nsz_ugt_negzero(half %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_ugt_negzero( ; CHECK-NEXT: [[GTZERO:%.*]] = fcmp ugt half [[X:%.*]], 0xH0000 ; CHECK-NEXT: [[NEGX:%.*]] = fneg fast half [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[GTZERO]], half [[X]], half [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GTZERO]], half [[X]], half [[NEGX]] ; CHECK-NEXT: ret half [[FABS]] ; %gtzero = fcmp ugt half %x, -0.0 @@ -890,7 +890,7 @@ define <2 x double> @select_fcmp_nnan_nsz_uge_zero(<2 x double> %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero( ; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer ; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] ; CHECK-NEXT: ret <2 x double> [[FABS]] ; %gezero = fcmp uge <2 x double> %x, zeroinitializer @@ -918,7 +918,7 @@ define <2 x double> @select_fcmp_nnan_nsz_uge_zero_unary_fneg(<2 x double> %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_zero_unary_fneg( ; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge <2 x double> [[X:%.*]], zeroinitializer ; CHECK-NEXT: [[NEGX:%.*]] = fneg reassoc nnan nsz <2 x double> [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select <2 x i1> [[GEZERO]], <2 x double> [[X]], <2 x double> [[NEGX]] ; CHECK-NEXT: ret <2 x double> [[FABS]] ; %gezero = fcmp uge <2 x double> %x, zeroinitializer @@ -948,7 +948,7 @@ define half @select_fcmp_nnan_nsz_uge_negzero(half %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero( ; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] ; CHECK-NEXT: ret half [[FABS]] ; %gezero = fcmp uge half %x, -0.0 @@ -976,7 +976,7 @@ define half @select_fcmp_nnan_nsz_uge_negzero_unary_fneg(half %x) { ; CHECK-LABEL: @select_fcmp_nnan_nsz_uge_negzero_unary_fneg( ; CHECK-NEXT: [[GEZERO:%.*]] = fcmp uge half [[X:%.*]], 0xH0000 ; CHECK-NEXT: [[NEGX:%.*]] = fneg nnan nsz half [[X]] -; CHECK-NEXT: [[FABS:%.*]] = select nnan i1 [[GEZERO]], half [[X]], half [[NEGX]] +; CHECK-NEXT: [[FABS:%.*]] = select i1 [[GEZERO]], half [[X]], half [[NEGX]] ; CHECK-NEXT: ret half [[FABS]] ; %gezero = fcmp uge half %x, -0.0 diff --git a/llvm/test/Transforms/InstCombine/fneg-fabs.ll b/llvm/test/Transforms/InstCombine/fneg-fabs.ll index fdcdfd123eefa4..c013a2c9f5449c 100644 --- a/llvm/test/Transforms/InstCombine/fneg-fabs.ll +++ b/llvm/test/Transforms/InstCombine/fneg-fabs.ll @@ -20,8 +20,8 @@ define double @select_noFMF_nfabs_lt(double %x) { ; One test where the neg has fmfs. define double @select_nsz_nfabs_lt_fmfProp(double %x) { ; CHECK-LABEL: @select_nsz_nfabs_lt_fmfProp( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] ; CHECK-NEXT: ret double [[SEL]] ; %cmp = fcmp olt double %x, 0.000000e+00 @@ -32,8 +32,8 @@ define double @select_nsz_nfabs_lt_fmfProp(double %x) { define double @select_nsz_nnan_nfabs_lt_fmfProp(double %x) { ; CHECK-LABEL: @select_nsz_nnan_nfabs_lt_fmfProp( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] ; CHECK-NEXT: ret double [[SEL]] ; %cmp = fcmp olt double %x, 0.000000e+00 @@ -147,8 +147,9 @@ define double @select_noFMF_nfabs_gt(double %x) { ; One test where the neg has fmfs. define double @select_nsz_nfabs_gt_fmfProp(double %x) { ; CHECK-LABEL: @select_nsz_nfabs_gt_fmfProp( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[NEGX:%.*]] = fneg fast double [[X]] +; CHECK-NEXT: [[SEL:%.*]] = select nsz i1 [[CMP]], double [[NEGX]], double [[X]] ; CHECK-NEXT: ret double [[SEL]] ; %cmp = fcmp ogt double %x, 0.000000e+00 @@ -159,8 +160,8 @@ define double @select_nsz_nfabs_gt_fmfProp(double %x) { define double @select_nsz_nnan_nfabs_gt_fmfProp(double %x) { ; CHECK-LABEL: @select_nsz_nnan_nfabs_gt_fmfProp( -; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz double @llvm.fabs.f64(double [[X:%.*]]) -; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[SEL:%.*]] = fneg nnan nsz double [[TMP1]] ; CHECK-NEXT: ret double [[SEL]] ; %cmp = fcmp ogt double %x, 0.000000e+00 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits