Skip to content

Commit 583fa4f

Browse files
authored
[InstCombine] Extend fcmp+select folding to minnum/maxnum intrinsics (#112088)
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 060d151 commit 583fa4f

File tree

9 files changed

+194
-50
lines changed

9 files changed

+194
-50
lines changed

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,32 @@ m_UnordFMin(const LHS &L, const RHS &R) {
23872387
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
23882388
}
23892389

2390+
/// Match an 'ordered' or 'unordered' floating point maximum function.
2391+
/// Floating point has one special value 'NaN'. Therefore, there is no total
2392+
/// order. However, if we can ignore the 'NaN' value (for example, because of a
2393+
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum'
2394+
/// semantics.
2395+
template <typename LHS, typename RHS>
2396+
inline match_combine_or<MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>,
2397+
MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>>
2398+
m_OrdOrUnordFMax(const LHS &L, const RHS &R) {
2399+
return m_CombineOr(MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R),
2400+
MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R));
2401+
}
2402+
2403+
/// Match an 'ordered' or 'unordered' floating point minimum function.
2404+
/// Floating point has one special value 'NaN'. Therefore, there is no total
2405+
/// order. However, if we can ignore the 'NaN' value (for example, because of a
2406+
/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
2407+
/// semantics.
2408+
template <typename LHS, typename RHS>
2409+
inline match_combine_or<MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>,
2410+
MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>>
2411+
m_OrdOrUnordFMin(const LHS &L, const RHS &R) {
2412+
return m_CombineOr(MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R),
2413+
MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R));
2414+
}
2415+
23902416
/// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
23912417
/// NOTE: we first match the 'Not' (by matching '-1'),
23922418
/// and only then match the inner matcher!

llvm/lib/Analysis/IVDescriptors.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -690,13 +690,9 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
690690
return InstDesc(Kind == RecurKind::SMax, I);
691691
if (match(I, m_SMin(m_Value(), m_Value())))
692692
return InstDesc(Kind == RecurKind::SMin, I);
693-
if (match(I, m_OrdFMin(m_Value(), m_Value())))
693+
if (match(I, m_OrdOrUnordFMin(m_Value(), m_Value())))
694694
return InstDesc(Kind == RecurKind::FMin, I);
695-
if (match(I, m_OrdFMax(m_Value(), m_Value())))
696-
return InstDesc(Kind == RecurKind::FMax, I);
697-
if (match(I, m_UnordFMin(m_Value(), m_Value())))
698-
return InstDesc(Kind == RecurKind::FMin, I);
699-
if (match(I, m_UnordFMax(m_Value(), m_Value())))
695+
if (match(I, m_OrdOrUnordFMax(m_Value(), m_Value())))
700696
return InstDesc(Kind == RecurKind::FMax, I);
701697
if (match(I, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_Value())))
702698
return InstDesc(Kind == RecurKind::FMin, I);

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8248,19 +8248,15 @@ static SelectPatternResult matchFastFloatClamp(CmpInst::Predicate Pred,
82488248
case CmpInst::FCMP_OLE:
82498249
case CmpInst::FCMP_ULT:
82508250
case CmpInst::FCMP_ULE:
8251-
if (match(FalseVal,
8252-
m_CombineOr(m_OrdFMin(m_Specific(CmpLHS), m_APFloat(FC2)),
8253-
m_UnordFMin(m_Specific(CmpLHS), m_APFloat(FC2)))) &&
8251+
if (match(FalseVal, m_OrdOrUnordFMin(m_Specific(CmpLHS), m_APFloat(FC2))) &&
82548252
*FC1 < *FC2)
82558253
return {SPF_FMAXNUM, SPNB_RETURNS_ANY, false};
82568254
break;
82578255
case CmpInst::FCMP_OGT:
82588256
case CmpInst::FCMP_OGE:
82598257
case CmpInst::FCMP_UGT:
82608258
case CmpInst::FCMP_UGE:
8261-
if (match(FalseVal,
8262-
m_CombineOr(m_OrdFMax(m_Specific(CmpLHS), m_APFloat(FC2)),
8263-
m_UnordFMax(m_Specific(CmpLHS), m_APFloat(FC2)))) &&
8259+
if (match(FalseVal, m_OrdOrUnordFMax(m_Specific(CmpLHS), m_APFloat(FC2))) &&
82648260
*FC1 > *FC2)
82658261
return {SPF_FMINNUM, SPNB_RETURNS_ANY, false};
82668262
break;

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3837,11 +3837,11 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
38373837
// minnum/maxnum intrinsics.
38383838
if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros()) {
38393839
Value *X, *Y;
3840-
if (match(&SI, m_OrdFMax(m_Value(X), m_Value(Y))))
3840+
if (match(&SI, m_OrdOrUnordFMax(m_Value(X), m_Value(Y))))
38413841
return replaceInstUsesWith(
38423842
SI, Builder.CreateBinaryIntrinsic(Intrinsic::maxnum, X, Y, &SI));
38433843

3844-
if (match(&SI, m_OrdFMin(m_Value(X), m_Value(Y))))
3844+
if (match(&SI, m_OrdOrUnordFMin(m_Value(X), m_Value(Y))))
38453845
return replaceInstUsesWith(
38463846
SI, Builder.CreateBinaryIntrinsic(Intrinsic::minnum, X, Y, &SI));
38473847
}

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

llvm/unittests/IR/PatternMatch.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,140 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
10401040
EXPECT_EQ(R, MatchR);
10411041
}
10421042

1043+
TEST_F(PatternMatchTest, FloatingPointMin) {
1044+
Type *FltTy = IRB.getFloatTy();
1045+
Value *L = ConstantFP::get(FltTy, 1.0);
1046+
Value *R = ConstantFP::get(FltTy, 2.0);
1047+
Value *MatchL, *MatchR;
1048+
1049+
// Test OLT.
1050+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1051+
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
1052+
EXPECT_EQ(L, MatchL);
1053+
EXPECT_EQ(R, MatchR);
1054+
1055+
// Test OLE.
1056+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1057+
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
1058+
EXPECT_EQ(L, MatchL);
1059+
EXPECT_EQ(R, MatchR);
1060+
1061+
// Test ULT.
1062+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1063+
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
1064+
EXPECT_EQ(L, MatchL);
1065+
EXPECT_EQ(R, MatchR);
1066+
1067+
// Test ULE.
1068+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1069+
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
1070+
EXPECT_EQ(L, MatchL);
1071+
EXPECT_EQ(R, MatchR);
1072+
1073+
// Test no match on OGE.
1074+
EXPECT_FALSE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1075+
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
1076+
1077+
// Test no match on OGT.
1078+
EXPECT_FALSE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1079+
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
1080+
1081+
// Test no match on UGE.
1082+
EXPECT_FALSE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1083+
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
1084+
1085+
// Test no match on UGT.
1086+
EXPECT_FALSE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1087+
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
1088+
1089+
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
1090+
// %cmp = fcmp oge L, R
1091+
// %min = select %cmp R, L
1092+
1093+
// [OU]GE with inverted select.
1094+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1095+
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
1096+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1097+
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
1098+
EXPECT_EQ(L, MatchL);
1099+
EXPECT_EQ(R, MatchR);
1100+
1101+
// [OU]GT with inverted select.
1102+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1103+
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
1104+
EXPECT_TRUE(m_OrdOrUnordFMin(m_Value(MatchL), m_Value(MatchR))
1105+
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
1106+
EXPECT_EQ(L, MatchL);
1107+
EXPECT_EQ(R, MatchR);
1108+
}
1109+
1110+
TEST_F(PatternMatchTest, FloatingPointMax) {
1111+
Type *FltTy = IRB.getFloatTy();
1112+
Value *L = ConstantFP::get(FltTy, 1.0);
1113+
Value *R = ConstantFP::get(FltTy, 2.0);
1114+
Value *MatchL, *MatchR;
1115+
1116+
// Test OGT.
1117+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1118+
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
1119+
EXPECT_EQ(L, MatchL);
1120+
EXPECT_EQ(R, MatchR);
1121+
1122+
// Test OGE.
1123+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1124+
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
1125+
EXPECT_EQ(L, MatchL);
1126+
EXPECT_EQ(R, MatchR);
1127+
1128+
// Test UGT.
1129+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1130+
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
1131+
EXPECT_EQ(L, MatchL);
1132+
EXPECT_EQ(R, MatchR);
1133+
1134+
// Test UGE.
1135+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1136+
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
1137+
EXPECT_EQ(L, MatchL);
1138+
EXPECT_EQ(R, MatchR);
1139+
1140+
// Test no match on OLE.
1141+
EXPECT_FALSE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1142+
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
1143+
1144+
// Test no match on OLT.
1145+
EXPECT_FALSE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1146+
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
1147+
1148+
// Test no match on ULE.
1149+
EXPECT_FALSE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1150+
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
1151+
1152+
// Test no match on ULT.
1153+
EXPECT_FALSE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1154+
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
1155+
1156+
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
1157+
// %cmp = fcmp ole L, R
1158+
// %max = select %cmp, R, L
1159+
1160+
// [OU]LE with inverted select.
1161+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1162+
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
1163+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1164+
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
1165+
EXPECT_EQ(L, MatchL);
1166+
EXPECT_EQ(R, MatchR);
1167+
1168+
// [OUT]LT with inverted select.
1169+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1170+
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
1171+
EXPECT_TRUE(m_OrdOrUnordFMax(m_Value(MatchL), m_Value(MatchR))
1172+
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
1173+
EXPECT_EQ(L, MatchL);
1174+
EXPECT_EQ(R, MatchR);
1175+
}
1176+
10431177
TEST_F(PatternMatchTest, OverflowingBinOps) {
10441178
Value *L = IRB.getInt32(1);
10451179
Value *R = IRB.getInt32(2);

0 commit comments

Comments
 (0)