Skip to content

Commit 2d43d1f

Browse files
dtcxzywgithub-actions[bot]
authored andcommitted
Automerge: [InstCombine] Propagate FMF from select instead of fcmp (#141010)
Previously, llvm/llvm-project@3d6b539 propagates FMF from fcmp to avoid performance regressions. With the help of llvm/llvm-project#139861, llvm/llvm-project#141015, and llvm/llvm-project#141914, we can still convert SPF into fabs/minnum/maxnum intrinsics even if some flags are missing. This patch propagates FMF from select to address the long-standing issue. Closes llvm/llvm-project#140994.
2 parents b13f560 + 3ec0c5c commit 2d43d1f

File tree

7 files changed

+92
-86
lines changed

7 files changed

+92
-86
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/IR/ConstantRange.h"
2626
#include "llvm/IR/Constants.h"
2727
#include "llvm/IR/DerivedTypes.h"
28+
#include "llvm/IR/FMF.h"
2829
#include "llvm/IR/IRBuilder.h"
2930
#include "llvm/IR/InstrTypes.h"
3031
#include "llvm/IR/Instruction.h"
@@ -3879,11 +3880,16 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
38793880
// (X ugt Y) ? X : Y -> (X ole Y) ? Y : X
38803881
if (FCmp->hasOneUse() && FCmpInst::isUnordered(Pred)) {
38813882
FCmpInst::Predicate InvPred = FCmp->getInversePredicate();
3882-
// FIXME: The FMF should propagate from the select, not the fcmp.
38833883
Value *NewCond = Builder.CreateFCmpFMF(InvPred, Cmp0, Cmp1, FCmp,
38843884
FCmp->getName() + ".inv");
3885+
// Propagate ninf/nnan from fcmp to select.
3886+
FastMathFlags FMF = SI.getFastMathFlags();
3887+
if (FCmp->hasNoNaNs())
3888+
FMF.setNoNaNs(true);
3889+
if (FCmp->hasNoInfs())
3890+
FMF.setNoInfs(true);
38853891
Value *NewSel =
3886-
Builder.CreateSelectFMF(NewCond, FalseVal, TrueVal, FCmp);
3892+
Builder.CreateSelectFMF(NewCond, FalseVal, TrueVal, FMF);
38873893
return replaceInstUsesWith(SI, NewSel);
38883894
}
38893895
}

llvm/test/Transforms/InstCombine/clamp-to-minmax.ll

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ define float @clamp_float_fast_ordered_strict_maxmin(float %x) {
77
; CHECK-LABEL: @clamp_float_fast_ordered_strict_maxmin(
88
; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
99
; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
10-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00)
10+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
11+
; CHECK-NEXT: [[R1:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
1112
; CHECK-NEXT: ret float [[R1]]
1213
;
1314
%cmp2 = fcmp fast olt float %x, 255.0
@@ -22,7 +23,8 @@ define float @clamp_float_fast_ordered_nonstrict_maxmin(float %x) {
2223
; CHECK-LABEL: @clamp_float_fast_ordered_nonstrict_maxmin(
2324
; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02
2425
; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02
25-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00)
26+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
27+
; CHECK-NEXT: [[R1:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
2628
; CHECK-NEXT: ret float [[R1]]
2729
;
2830
%cmp2 = fcmp fast olt float %x, 255.0
@@ -37,7 +39,8 @@ define float @clamp_float_fast_ordered_strict_minmax(float %x) {
3739
; CHECK-LABEL: @clamp_float_fast_ordered_strict_minmax(
3840
; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00
3941
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
40-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02)
42+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
43+
; CHECK-NEXT: [[R1:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
4144
; CHECK-NEXT: ret float [[R1]]
4245
;
4346
%cmp2 = fcmp fast ogt float %x, 1.0
@@ -52,7 +55,8 @@ define float @clamp_float_fast_ordered_nonstrict_minmax(float %x) {
5255
; CHECK-LABEL: @clamp_float_fast_ordered_nonstrict_minmax(
5356
; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00
5457
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00
55-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02)
58+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
59+
; CHECK-NEXT: [[R1:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
5660
; CHECK-NEXT: ret float [[R1]]
5761
;
5862
%cmp2 = fcmp fast ogt float %x, 1.0
@@ -68,9 +72,10 @@ define float @clamp_float_fast_ordered_nonstrict_minmax(float %x) {
6872
; (X < C1) ? C1 : MIN(X, C2)
6973
define float @clamp_float_fast_unordered_strict_maxmin(float %x) {
7074
; CHECK-LABEL: @clamp_float_fast_unordered_strict_maxmin(
71-
; CHECK-NEXT: [[MIN:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
72-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
73-
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
75+
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
76+
; CHECK-NEXT: [[MIN:%.*]] = select nnan ninf i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
77+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
78+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
7479
; CHECK-NEXT: ret float [[R]]
7580
;
7681
%cmp2 = fcmp fast ult float %x, 255.0
@@ -83,9 +88,10 @@ define float @clamp_float_fast_unordered_strict_maxmin(float %x) {
8388
; (X <= C1) ? C1 : MIN(X, C2)
8489
define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) {
8590
; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_maxmin(
86-
; CHECK-NEXT: [[MIN:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
87-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ule float [[X]], 1.000000e+00
88-
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
91+
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
92+
; CHECK-NEXT: [[MIN:%.*]] = select nnan ninf i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
93+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float [[MIN]], 1.000000e+00
94+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MIN]], float 1.000000e+00
8995
; CHECK-NEXT: ret float [[R]]
9096
;
9197
%cmp2 = fcmp fast ult float %x, 255.0
@@ -98,9 +104,10 @@ define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) {
98104
; (X > C1) ? C1 : MAX(X, C2)
99105
define float @clamp_float_fast_unordered_strict_minmax(float %x) {
100106
; CHECK-LABEL: @clamp_float_fast_unordered_strict_minmax(
101-
; CHECK-NEXT: [[MAX:%.*]] = call fast float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)
102-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ugt float [[X]], 2.550000e+02
103-
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
107+
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
108+
; CHECK-NEXT: [[MAX:%.*]] = select nnan ninf i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
109+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
110+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
104111
; CHECK-NEXT: ret float [[R]]
105112
;
106113
%cmp2 = fcmp fast ugt float %x, 1.0
@@ -113,9 +120,10 @@ define float @clamp_float_fast_unordered_strict_minmax(float %x) {
113120
; (X >= C1) ? C1 : MAX(X, C2)
114121
define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) {
115122
; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_minmax(
116-
; CHECK-NEXT: [[MAX:%.*]] = call fast float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)
117-
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast uge float [[X]], 2.550000e+02
118-
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
123+
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
124+
; CHECK-NEXT: [[MAX:%.*]] = select nnan ninf i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
125+
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast ole float [[MAX]], 2.550000e+02
126+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[DOTINV]], float [[MAX]], float 2.550000e+02
119127
; CHECK-NEXT: ret float [[R]]
120128
;
121129
%cmp2 = fcmp fast ugt float %x, 1.0
@@ -130,9 +138,10 @@ define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) {
130138
; (X > 1.0) ? min(x, 255.0) : 1.0
131139
define float @clamp_test_1(float %x) {
132140
; CHECK-LABEL: @clamp_test_1(
133-
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
134-
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 1.000000e+00
135-
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
141+
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
142+
; CHECK-NEXT: [[INNER_SEL:%.*]] = select nnan ninf i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
143+
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast oge float [[INNER_SEL]], 1.000000e+00
144+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
136145
; CHECK-NEXT: ret float [[R]]
137146
;
138147
%inner_cmp = fcmp fast ult float %x, 255.0
@@ -147,7 +156,8 @@ define float @clamp_test_1(float %x) {
147156
; Like @clamp_test_1 but HighConst < LowConst
148157
define float @clamp_negative_wrong_const(float %x) {
149158
; CHECK-LABEL: @clamp_negative_wrong_const(
150-
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
159+
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
160+
; CHECK-NEXT: [[INNER_SEL:%.*]] = select nnan ninf i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
151161
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 5.120000e+02
152162
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 5.120000e+02
153163
; CHECK-NEXT: ret float [[R]]
@@ -162,7 +172,8 @@ define float @clamp_negative_wrong_const(float %x) {
162172
; Like @clamp_test_1 but both are min
163173
define float @clamp_negative_same_op(float %x) {
164174
; CHECK-LABEL: @clamp_negative_same_op(
165-
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
175+
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
176+
; CHECK-NEXT: [[INNER_SEL:%.*]] = select nnan ninf i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
166177
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
167178
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
168179
; CHECK-NEXT: ret float [[R]]

0 commit comments

Comments
 (0)