Skip to content

Commit 76581cb

Browse files
committed
[InstCombine] Extend fcmp+select folding to minnum/maxnum intrinsics
Today, InstCombine can fold fcmp+select patterns to minnum/maxnum intrinsics when the nnan and nsz flags are set. The ordering of the operands in both the fcmp and select instructions is important for the folding to occur. maxnum patterns: 1. (a op b) ? a : b -> maxnum(a, b), where op is one of {ogt, oge} 2. (a op b) ? b : a -> maxnum(a, b), where op is one of {ule, ult} The second pattern is supposed to make the order of the operands in the select instruction irrelevant. However, the pattern matching code uses the CmpInst::getInversePredicate method to invert the comparison predicate. This method doesn't take into account the fast-math flags, which can lead missing the folding opportunity. The patch extends the pattern matching code to handle unordered fcmp instructions. This allows the folding to occur even when the select instruction has the operands in the inverse order. New maxnum patterns: 1. (a op b) ? a : b -> maxnum(a, b), where op is one of {ugt, uge} 2. (a op b) ? b : a -> maxnum(a, b), where op is one of {ole, olt} The same changes are applied to the minnum intrinsic.
1 parent 7600713 commit 76581cb

File tree

5 files changed

+32
-38
lines changed

5 files changed

+32
-38
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,11 +3834,13 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
38343834
// minnum/maxnum intrinsics.
38353835
if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros()) {
38363836
Value *X, *Y;
3837-
if (match(&SI, m_OrdFMax(m_Value(X), m_Value(Y))))
3837+
if (match(&SI, m_OrdFMax(m_Value(X), m_Value(Y))) ||
3838+
match(&SI, m_UnordFMax(m_Value(X), m_Value(Y))))
38383839
return replaceInstUsesWith(
38393840
SI, Builder.CreateBinaryIntrinsic(Intrinsic::maxnum, X, Y, &SI));
38403841

3841-
if (match(&SI, m_OrdFMin(m_Value(X), m_Value(Y))))
3842+
if (match(&SI, m_OrdFMin(m_Value(X), m_Value(Y))) ||
3843+
match(&SI, m_UnordFMin(m_Value(X), m_Value(Y))))
38423844
return replaceInstUsesWith(
38433845
SI, Builder.CreateBinaryIntrinsic(Intrinsic::minnum, X, Y, &SI));
38443846
}

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

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ define float @clamp_float_fast_ordered_nonstrict_minmax(float %x) {
6767
; (X < C1) ? C1 : MIN(X, C2)
6868
define float @clamp_float_fast_unordered_strict_maxmin(float %x) {
6969
; CHECK-LABEL: @clamp_float_fast_unordered_strict_maxmin(
70-
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
71-
; CHECK-NEXT: [[MIN:%.*]] = select fast i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
72-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00)
73-
; CHECK-NEXT: ret float [[R1]]
70+
; CHECK-NEXT: [[MIN:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
71+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
72+
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
73+
; CHECK-NEXT: ret float [[R]]
7474
;
7575
%cmp2 = fcmp fast ult float %x, 255.0
7676
%min = select i1 %cmp2, float %x, float 255.0
@@ -82,10 +82,10 @@ define float @clamp_float_fast_unordered_strict_maxmin(float %x) {
8282
; (X <= C1) ? C1 : MIN(X, C2)
8383
define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) {
8484
; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_maxmin(
85-
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
86-
; CHECK-NEXT: [[MIN:%.*]] = select fast i1 [[CMP2_INV]], float 2.550000e+02, float [[X]]
87-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00)
88-
; CHECK-NEXT: ret float [[R1]]
85+
; CHECK-NEXT: [[MIN:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
86+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ule float [[X]], 1.000000e+00
87+
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]]
88+
; CHECK-NEXT: ret float [[R]]
8989
;
9090
%cmp2 = fcmp fast ult float %x, 255.0
9191
%min = select i1 %cmp2, float %x, float 255.0
@@ -97,10 +97,10 @@ define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) {
9797
; (X > C1) ? C1 : MAX(X, C2)
9898
define float @clamp_float_fast_unordered_strict_minmax(float %x) {
9999
; CHECK-LABEL: @clamp_float_fast_unordered_strict_minmax(
100-
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
101-
; CHECK-NEXT: [[MAX:%.*]] = select fast i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
102-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02)
103-
; CHECK-NEXT: ret float [[R1]]
100+
; CHECK-NEXT: [[MAX:%.*]] = call fast float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)
101+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast ugt float [[X]], 2.550000e+02
102+
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
103+
; CHECK-NEXT: ret float [[R]]
104104
;
105105
%cmp2 = fcmp fast ugt float %x, 1.0
106106
%max = select i1 %cmp2, float %x, float 1.0
@@ -112,10 +112,10 @@ define float @clamp_float_fast_unordered_strict_minmax(float %x) {
112112
; (X >= C1) ? C1 : MAX(X, C2)
113113
define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) {
114114
; CHECK-LABEL: @clamp_float_fast_unordered_nonstrict_minmax(
115-
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00
116-
; CHECK-NEXT: [[MAX:%.*]] = select fast i1 [[CMP2_INV]], float 1.000000e+00, float [[X]]
117-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02)
118-
; CHECK-NEXT: ret float [[R1]]
115+
; CHECK-NEXT: [[MAX:%.*]] = call fast float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)
116+
; CHECK-NEXT: [[CMP1:%.*]] = fcmp fast uge float [[X]], 2.550000e+02
117+
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]]
118+
; CHECK-NEXT: ret float [[R]]
119119
;
120120
%cmp2 = fcmp fast ugt float %x, 1.0
121121
%max = select i1 %cmp2, float %x, float 1.0
@@ -127,13 +127,12 @@ define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) {
127127
; Some more checks with fast
128128

129129
; (X > 1.0) ? min(x, 255.0) : 1.0
130-
; That did not match because select was in inverse order.
131130
define float @clamp_test_1(float %x) {
132131
; CHECK-LABEL: @clamp_test_1(
133-
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
134-
; CHECK-NEXT: [[INNER_SEL:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
135-
; CHECK-NEXT: [[R1:%.*]] = call fast float @llvm.maxnum.f32(float [[INNER_SEL]], float 1.000000e+00)
136-
; CHECK-NEXT: ret float [[R1]]
132+
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
133+
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 1.000000e+00
134+
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
135+
; CHECK-NEXT: ret float [[R]]
137136
;
138137
%inner_cmp = fcmp fast ult float %x, 255.0
139138
%inner_sel = select i1 %inner_cmp, float %x, float 255.0
@@ -147,8 +146,7 @@ define float @clamp_test_1(float %x) {
147146
; Like @clamp_test_1 but HighConst < LowConst
148147
define float @clamp_negative_wrong_const(float %x) {
149148
; CHECK-LABEL: @clamp_negative_wrong_const(
150-
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
151-
; CHECK-NEXT: [[INNER_SEL:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
149+
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
152150
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 5.120000e+02
153151
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 5.120000e+02
154152
; CHECK-NEXT: ret float [[R]]
@@ -163,8 +161,7 @@ define float @clamp_negative_wrong_const(float %x) {
163161
; Like @clamp_test_1 but both are min
164162
define float @clamp_negative_same_op(float %x) {
165163
; CHECK-LABEL: @clamp_negative_same_op(
166-
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
167-
; CHECK-NEXT: [[INNER_SEL:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
164+
; CHECK-NEXT: [[INNER_SEL:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 2.550000e+02)
168165
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
169166
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
170167
; CHECK-NEXT: ret float [[R]]

llvm/test/Transforms/InstCombine/minmax-fold.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -852,10 +852,8 @@ define i32 @common_factor_umax_extra_use_both(i32 %a, i32 %b, i32 %c) {
852852

853853
define float @not_min_of_min(i8 %i, float %x) {
854854
; CHECK-LABEL: @not_min_of_min(
855-
; CHECK-NEXT: [[CMP1_INV:%.*]] = fcmp fast oge float [[X:%.*]], 1.000000e+00
856-
; CHECK-NEXT: [[MIN1:%.*]] = select fast i1 [[CMP1_INV]], float 1.000000e+00, float [[X]]
857-
; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X]], 2.000000e+00
858-
; CHECK-NEXT: [[MIN2:%.*]] = select fast i1 [[CMP2_INV]], float 2.000000e+00, float [[X]]
855+
; CHECK-NEXT: [[MIN1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float 1.000000e+00)
856+
; CHECK-NEXT: [[MIN2:%.*]] = call fast float @llvm.minnum.f32(float [[X]], float 2.000000e+00)
859857
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i8 [[I:%.*]], 16
860858
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP3]], float [[MIN1]], float [[MIN2]]
861859
; CHECK-NEXT: ret float [[R]]

llvm/test/Transforms/InstCombine/minmax-fp.ll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ define i8 @t9(float %a) {
160160
; Either operand could be NaN, but fast modifier applied.
161161
define i8 @t11(float %a, float %b) {
162162
; CHECK-LABEL: @t11(
163-
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float [[B:%.*]], [[A:%.*]]
164-
; CHECK-NEXT: [[DOTV:%.*]] = select fast i1 [[DOTINV]], float [[A]], float [[B]]
163+
; CHECK-NEXT: [[DOTV:%.*]] = call fast float @llvm.minnum.f32(float [[B:%.*]], float [[A:%.*]])
165164
; CHECK-NEXT: [[TMP1:%.*]] = fptosi float [[DOTV]] to i8
166165
; CHECK-NEXT: ret i8 [[TMP1]]
167166
;
@@ -282,8 +281,7 @@ define float @fneg_fmax(float %x, float %y) {
282281

283282
define <2 x float> @fsub_fmax(<2 x float> %x, <2 x float> %y) {
284283
; CHECK-LABEL: @fsub_fmax(
285-
; CHECK-NEXT: [[COND_INV:%.*]] = fcmp nnan nsz ogt <2 x float> [[X:%.*]], [[Y:%.*]]
286-
; CHECK-NEXT: [[MAX_V:%.*]] = select nnan nsz <2 x i1> [[COND_INV]], <2 x float> [[Y]], <2 x float> [[X]]
284+
; CHECK-NEXT: [[MAX_V:%.*]] = call nnan nsz <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]])
287285
; CHECK-NEXT: [[MAX:%.*]] = fneg <2 x float> [[MAX_V]]
288286
; CHECK-NEXT: ret <2 x float> [[MAX]]
289287
;
@@ -310,8 +308,7 @@ define <2 x double> @fsub_fmin(<2 x double> %x, <2 x double> %y) {
310308

311309
define double @fneg_fmin(double %x, double %y) {
312310
; CHECK-LABEL: @fneg_fmin(
313-
; CHECK-NEXT: [[COND_INV:%.*]] = fcmp nnan nsz olt double [[X:%.*]], [[Y:%.*]]
314-
; CHECK-NEXT: [[MAX_V:%.*]] = select nnan nsz i1 [[COND_INV]], double [[Y]], double [[X]]
311+
; CHECK-NEXT: [[MAX_V:%.*]] = call nnan nsz double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]])
315312
; CHECK-NEXT: [[MAX:%.*]] = fneg double [[MAX_V]]
316313
; CHECK-NEXT: ret double [[MAX]]
317314
;

llvm/test/Transforms/InstCombine/unordered-fcmp-select.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ define float @select_max_ugt_2_use_cmp(float %a, float %b) {
115115
; CHECK-LABEL: @select_max_ugt_2_use_cmp(
116116
; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ugt float [[A:%.*]], [[B:%.*]]
117117
; CHECK-NEXT: call void @foo(i1 [[CMP]])
118-
; CHECK-NEXT: [[SEL:%.*]] = select fast i1 [[CMP]], float [[A]], float [[B]]
118+
; CHECK-NEXT: [[SEL:%.*]] = call fast float @llvm.maxnum.f32(float [[A]], float [[B]])
119119
; CHECK-NEXT: ret float [[SEL]]
120120
;
121121
%cmp = fcmp reassoc ugt float %a, %b

0 commit comments

Comments
 (0)