-
Notifications
You must be signed in to change notification settings - Fork 13.3k
release/20.x: [InstCombine] Fix FMF propagation in foldSelectWithFCmpToFabs
(#121580)
#125338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@arsenm What do you think about merging this PR to the release branch? |
@llvm/pr-subscribers-llvm-transforms Author: None (llvmbot) ChangesBackport 3ec6a6b Requested by: @dtcxzyw Full diff: https://github.com/llvm/llvm-project/pull/125338.diff 3 Files Affected:
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
|
…#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 llvm#121430 and llvm#113989. (cherry picked from commit 3ec6a6b)
@dtcxzyw (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. |
Backport 3ec6a6b
Requested by: @dtcxzyw