llvm.org GIT mirror llvm / 2f0aeb5
[InstCombine] Try to reuse constant from select in leading comparison Summary: If we have e.g.: ``` %t = icmp ult i32 %x, 65536 %r = select i1 %t, i32 %y, i32 65535 ``` the constants `65535` and `65536` are suspiciously close. We could perform a transformation to deduplicate them: ``` Name: ult %t = icmp ult i32 %x, 65536 %r = select i1 %t, i32 %y, i32 65535 => %t.inv = icmp ugt i32 %x, 65535 %r = select i1 %t.inv, i32 65535, i32 %y ``` https://rise4fun.com/Alive/avb While this may seem esoteric, this should certainly be good for vectors (less constant pool usage) and for opt-for-size - need to have only one constant. But the real fun part here is that it allows further transformation, in particular it finishes cleaning up the `clamp` folding, see e.g. `canonicalize-clamp-with-select-of-constant-threshold-pattern.ll`. We start with e.g. ``` %dont_need_to_clamp_positive = icmp sle i32 %X, 32767 %dont_need_to_clamp_negative = icmp sge i32 %X, -32768 %clamp_limit = select i1 %dont_need_to_clamp_positive, i32 -32768, i32 32767 %dont_need_to_clamp = and i1 %dont_need_to_clamp_positive, %dont_need_to_clamp_negative %R = select i1 %dont_need_to_clamp, i32 %X, i32 %clamp_limit ``` without this patch we currently produce ``` %1 = icmp slt i32 %X, 32768 %2 = icmp sgt i32 %X, -32768 %3 = select i1 %2, i32 %X, i32 -32768 %R = select i1 %1, i32 %3, i32 32767 ``` which isn't really a `clamp` - both comparisons are performed on the original value, this patch changes it into ``` %1.inv = icmp sgt i32 %X, 32767 %2 = icmp sgt i32 %X, -32768 %3 = select i1 %2, i32 %X, i32 -32768 %R = select i1 %1.inv, i32 32767, i32 %3 ``` and then the magic happens! Some further transform finishes polishing it and we finally get: ``` %t1 = icmp sgt i32 %X, -32768 %t2 = select i1 %t1, i32 %X, i32 -32768 %t3 = icmp slt i32 %t2, 32767 %R = select i1 %t3, i32 %t2, i32 32767 ``` which is beautiful and just what we want. Proofs for `getFlippedStrictnessPredicateAndConstant()` for de-canonicalization: https://rise4fun.com/Alive/THl Proofs for the fold itself: https://rise4fun.com/Alive/THl Reviewers: spatel, dmgreen, nikic, xbolva00 Reviewed By: spatel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66232 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369840 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Lebedev 22 days ago
6 changed file(s) with 200 addition(s) and 92 deletion(s). Raw diff Collapse all Expand all
49114911 llvm::getFlippedStrictnessPredicateAndConstant(CmpInst::Predicate Pred,
49124912 Constant *C) {
49134913 assert(ICmpInst::isRelational(Pred) && ICmpInst::isIntPredicate(Pred) &&
4914 !isCanonicalPredicate(Pred) &&
4915 "Only for non-canonical relational integer predicates.");
4916
4917 // Check if the constant operand can be safely incremented/decremented without
4918 // overflowing/underflowing. For scalars, SimplifyICmpInst should have already
4919 // handled the edge cases for us, so we just assert on them.
4920 // For vectors, we must handle the edge cases.
4914 "Only for relational integer predicates.");
4915
49214916 Type *Type = C->getType();
49224917 bool IsSigned = ICmpInst::isSigned(Pred);
4923 bool IsLE = (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_ULE);
4924 auto *CI = dyn_cast(C);
4925 if (CI) {
4918
4919 CmpInst::Predicate UnsignedPred = ICmpInst::getUnsignedPredicate(Pred);
4920 bool WillIncrement =
4921 UnsignedPred == ICmpInst::ICMP_ULE || UnsignedPred == ICmpInst::ICMP_UGT;
4922
4923 // Check if the constant operand can be safely incremented/decremented
4924 // without overflowing/underflowing.
4925 auto ConstantIsOk = [WillIncrement, IsSigned](ConstantInt *C) {
4926 return WillIncrement ? !C->isMaxValue(IsSigned) : !C->isMinValue(IsSigned);
4927 };
4928
4929 // For scalars, SimplifyICmpInst should have already handled
4930 // the edge cases for us, so we just assert on them.
4931 // For vectors, we must handle the edge cases.
4932 if (auto *CI = dyn_cast(C)) {
49264933 // A <= MAX -> TRUE ; A >= MIN -> TRUE
4927 assert(IsLE ? !CI->isMaxValue(IsSigned) : !CI->isMinValue(IsSigned));
4934 assert(ConstantIsOk(CI));
49284935 } else if (Type->isVectorTy()) {
49294936 // TODO? If the edge cases for vectors were guaranteed to be handled as they
49304937 // are for scalar, we could remove the min/max checks. However, to do that,
49414948 // Bail out if we can't determine if this constant is min/max or if we
49424949 // know that this constant is min/max.
49434950 auto *CI = dyn_cast(Elt);
4944 if (!CI || (IsLE ? CI->isMaxValue(IsSigned) : CI->isMinValue(IsSigned)))
4951 if (!CI || !ConstantIsOk(CI))
49454952 return llvm::None;
49464953 }
49474954 } else {
49524959 CmpInst::Predicate NewPred = CmpInst::getFlippedStrictnessPredicate(Pred);
49534960
49544961 // Increment or decrement the constant.
4955 Constant *OneOrNegOne = ConstantInt::get(Type, IsLE ? 1 : -1, true);
4962 Constant *OneOrNegOne = ConstantInt::get(Type, WillIncrement ? 1 : -1, true);
49564963 Constant *NewC = ConstantExpr::getAdd(C, OneOrNegOne);
49574964
49584965 return std::make_pair(NewPred, NewC);
12601260 return MaybeReplacedHigh;
12611261 }
12621262
1263 // If we have
1264 // %cmp = icmp [canonical predicate] i32 %x, C0
1265 // %r = select i1 %cmp, i32 %y, i32 C1
1266 // Where C0 != C1 and %x may be different from %y, see if the constant that we
1267 // will have if we flip the strictness of the predicate (i.e. without changing
1268 // the result) is identical to the C1 in select. If it matches we can change
1269 // original comparison to one with swapped predicate, reuse the constant,
1270 // and swap the hands of select.
1271 static Instruction *
1272 tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp,
1273 InstCombiner::BuilderTy &Builder) {
1274 ICmpInst::Predicate Pred;
1275 Value *X;
1276 Constant *C0;
1277 if (!match(&Cmp, m_OneUse(m_ICmp(
1278 Pred, m_Value(X),
1279 m_CombineAnd(m_AnyIntegralConstant(), m_Constant(C0))))))
1280 return nullptr;
1281
1282 // If comparison predicate is non-relational, we won't be able to do anything.
1283 if (ICmpInst::isEquality(Pred))
1284 return nullptr;
1285
1286 // If comparison predicate is non-canonical, then we certainly won't be able
1287 // to make it canonical; canonicalizeCmpWithConstant() already tried.
1288 if (!isCanonicalPredicate(Pred))
1289 return nullptr;
1290
1291 // If the [input] type of comparison and select type are different, lets abort
1292 // for now. We could try to compare constants with trunc/[zs]ext though.
1293 if (C0->getType() != Sel.getType())
1294 return nullptr;
1295
1296 // FIXME: are there any magic icmp predicate+constant pairs we must not touch?
1297
1298 auto ConstantsAreElementWiseEqual = [](Constant *Cx, Value *Y) {
1299 // Are they fully identical?
1300 if (Cx == Y)
1301 return true;
1302 // They may still be identical element-wise (if they have `undef`s).
1303 auto *Cy = dyn_cast(Y);
1304 if (!Cy)
1305 return false;
1306 return match(ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_EQ, Cx, Cy),
1307 m_One());
1308 };
1309
1310 Value *SelVal0, *SelVal1; // We do not care which one is from where.
1311 match(&Sel, m_Select(m_Value(), m_Value(SelVal0), m_Value(SelVal1)));
1312 // At least one of these values we are selecting between must be a constant
1313 // else we'll never succeed.
1314 if (!match(SelVal0, m_AnyIntegralConstant()) &&
1315 !match(SelVal1, m_AnyIntegralConstant()))
1316 return nullptr;
1317
1318 // Does this constant C match any of the `select` values?
1319 auto MatchesSelectValue = [ConstantsAreElementWiseEqual, SelVal0,
1320 SelVal1](Constant *C) {
1321 return ConstantsAreElementWiseEqual(C, SelVal0) ||
1322 ConstantsAreElementWiseEqual(C, SelVal1);
1323 };
1324
1325 // If C0 *already* matches true/false value of select, we are done.
1326 if (MatchesSelectValue(C0))
1327 return nullptr;
1328
1329 // Check the constant we'd have with flipped-strictness predicate.
1330 auto FlippedStrictness = getFlippedStrictnessPredicateAndConstant(Pred, C0);
1331 if (!FlippedStrictness)
1332 return nullptr;
1333
1334 // If said constant doesn't match either, then there is no hope,
1335 if (!MatchesSelectValue(FlippedStrictness->second))
1336 return nullptr;
1337
1338 // It matched! Lets insert the new comparison just before select.
1339 InstCombiner::BuilderTy::InsertPointGuard Guard(Builder);
1340 Builder.SetInsertPoint(&Sel);
1341
1342 Pred = ICmpInst::getSwappedPredicate(Pred); // Yes, swapped.
1343 Value *NewCmp = Builder.CreateICmp(Pred, X, FlippedStrictness->second,
1344 Cmp.getName() + ".inv");
1345 Sel.setCondition(NewCmp);
1346 Sel.swapValues();
1347 Sel.swapProfMetadata();
1348
1349 return &Sel;
1350 }
1351
12631352 /// Visit a SelectInst that has an ICmpInst as its first operand.
12641353 Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI,
12651354 ICmpInst *ICI) {
12741363
12751364 if (Instruction *NewAbs = canonicalizeClampLike(SI, *ICI, Builder))
12761365 return NewAbs;
1366
1367 if (Instruction *NewSel =
1368 tryToReuseConstantFromSelectInComparison(SI, *ICI, Builder))
1369 return NewSel;
12771370
12781371 bool Changed = adjustMinMax(SI, *ICI);
12791372
66
77 define i32 @t0_select_cond_and_v0(i32 %X) {
88 ; CHECK-LABEL: @t0_select_cond_and_v0(
9 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
10 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
11 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
12 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
9 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
10 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 -32768
11 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 32767
12 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 32767
1313 ; CHECK-NEXT: ret i32 [[R]]
1414 ;
1515 %dont_need_to_clamp_positive = icmp sle i32 %X, 32767
2121 }
2222 define i32 @t1_select_cond_and_v1(i32 %X) {
2323 ; CHECK-LABEL: @t1_select_cond_and_v1(
24 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
25 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
26 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
27 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
24 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
25 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 -32768
26 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 32767
27 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 32767
2828 ; CHECK-NEXT: ret i32 [[R]]
2929 ;
3030 %dont_need_to_clamp_positive = icmp sle i32 %X, 32767
3939
4040 define i32 @t2_select_cond_or_v0(i32 %X) {
4141 ; CHECK-LABEL: @t2_select_cond_or_v0(
42 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
43 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
44 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
45 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
42 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
43 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 -32768
44 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 32767
45 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 32767
4646 ; CHECK-NEXT: ret i32 [[R]]
4747 ;
4848 %need_to_clamp_positive = icmp sgt i32 %X, 32767
5454 }
5555 define i32 @t3_select_cond_or_v1(i32 %X) {
5656 ; CHECK-LABEL: @t3_select_cond_or_v1(
57 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
58 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
59 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
60 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
57 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
58 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 -32768
59 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 32767
60 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 32767
6161 ; CHECK-NEXT: ret i32 [[R]]
6262 ;
6363 %need_to_clamp_positive = icmp sgt i32 %X, 32767
7272
7373 define i32 @t4_select_cond_xor_v0(i32 %X) {
7474 ; CHECK-LABEL: @t4_select_cond_xor_v0(
75 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
76 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
77 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
78 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
75 ; CHECK-NEXT: [[DOTINV1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
76 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV1]], i32 [[X]], i32 -32768
77 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 32767
78 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 32767
7979 ; CHECK-NEXT: ret i32 [[R]]
8080 ;
8181 %need_to_clamp_positive = icmp sgt i32 %X, 32767
8787 }
8888 define i32 @t4_select_cond_xor_v1(i32 %X) {
8989 ; CHECK-LABEL: @t4_select_cond_xor_v1(
90 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
91 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
92 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
93 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
90 ; CHECK-NEXT: [[DOTINV1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
91 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV1]], i32 [[X]], i32 -32768
92 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 32767
93 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 32767
9494 ; CHECK-NEXT: ret i32 [[R]]
9595 ;
9696 %need_to_clamp_positive = icmp sgt i32 %X, 32767
103103
104104 define i32 @t5_select_cond_xor_v2(i32 %X) {
105105 ; CHECK-LABEL: @t5_select_cond_xor_v2(
106 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
107 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
108 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
109 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
106 ; CHECK-NEXT: [[DOTINV1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
107 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV1]], i32 [[X]], i32 -32768
108 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 32767
109 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 32767
110110 ; CHECK-NEXT: ret i32 [[R]]
111111 ;
112112 %dont_need_to_clamp_positive = icmp sle i32 %X, 32767
118118 }
119119 define i32 @t5_select_cond_xor_v3(i32 %X) {
120120 ; CHECK-LABEL: @t5_select_cond_xor_v3(
121 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768
122 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768
123 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768
124 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767
121 ; CHECK-NEXT: [[DOTINV1:%.*]] = icmp sgt i32 [[X:%.*]], -32768
122 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV1]], i32 [[X]], i32 -32768
123 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 32767
124 ; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 32767
125125 ; CHECK-NEXT: ret i32 [[R]]
126126 ;
127127 %dont_need_to_clamp_positive = icmp sle i32 %X, 32767
1717
1818 define i32 @p0_ult_65536(i32 %x, i32 %y) {
1919 ; CHECK-LABEL: @p0_ult_65536(
20 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
21 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535, !prof !0
20 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
21 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]], !prof !0
2222 ; CHECK-NEXT: ret i32 [[R]]
2323 ;
2424 %t = icmp ult i32 %x, 65536
2727 }
2828 define i32 @p1_ugt(i32 %x, i32 %y) {
2929 ; CHECK-LABEL: @p1_ugt(
30 ; CHECK-NEXT: [[T:%.*]] = icmp ugt i32 [[X:%.*]], 65534
31 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
30 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ult i32 [[X:%.*]], 65535
31 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
3232 ; CHECK-NEXT: ret i32 [[R]]
3333 ;
3434 %t = icmp ugt i32 %x, 65534
3737 }
3838 define i32 @p2_slt_65536(i32 %x, i32 %y) {
3939 ; CHECK-LABEL: @p2_slt_65536(
40 ; CHECK-NEXT: [[T:%.*]] = icmp slt i32 [[X:%.*]], 65536
41 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
40 ; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], 65535
41 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
4242 ; CHECK-NEXT: ret i32 [[R]]
4343 ;
4444 %t = icmp slt i32 %x, 65536
4747 }
4848 define i32 @p3_sgt(i32 %x, i32 %y) {
4949 ; CHECK-LABEL: @p3_sgt(
50 ; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 [[X:%.*]], 65534
51 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 [[Y:%.*]], i32 65535
50 ; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 65535
51 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 [[Y:%.*]]
5252 ; CHECK-NEXT: ret i32 [[R]]
5353 ;
5454 %t = icmp sgt i32 %x, 65534
6262
6363 define <2 x i32> @p4_vec_splat_ult_65536(<2 x i32> %x, <2 x i32> %y) {
6464 ; CHECK-LABEL: @p4_vec_splat_ult_65536(
65 ; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]],
66 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
65 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]],
66 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
6767 ; CHECK-NEXT: ret <2 x i32> [[R]]
6868 ;
6969 %t = icmp ult <2 x i32> %x,
7272 }
7373 define <2 x i32> @p5_vec_splat_ugt(<2 x i32> %x, <2 x i32> %y) {
7474 ; CHECK-LABEL: @p5_vec_splat_ugt(
75 ; CHECK-NEXT: [[T:%.*]] = icmp ugt <2 x i32> [[X:%.*]],
76 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
75 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ult <2 x i32> [[X:%.*]],
76 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
7777 ; CHECK-NEXT: ret <2 x i32> [[R]]
7878 ;
7979 %t = icmp ugt <2 x i32> %x,
8282 }
8383 define <2 x i32> @p6_vec_splat_slt_65536(<2 x i32> %x, <2 x i32> %y) {
8484 ; CHECK-LABEL: @p6_vec_splat_slt_65536(
85 ; CHECK-NEXT: [[T:%.*]] = icmp slt <2 x i32> [[X:%.*]],
86 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
85 ; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt <2 x i32> [[X:%.*]],
86 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
8787 ; CHECK-NEXT: ret <2 x i32> [[R]]
8888 ;
8989 %t = icmp slt <2 x i32> %x,
9292 }
9393 define <2 x i32> @p7_vec_splat_sgt(<2 x i32> %x, <2 x i32> %y) {
9494 ; CHECK-LABEL: @p7_vec_splat_sgt(
95 ; CHECK-NEXT: [[T:%.*]] = icmp sgt <2 x i32> [[X:%.*]],
96 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
95 ; CHECK-NEXT: [[T_INV:%.*]] = icmp slt <2 x i32> [[X:%.*]],
96 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
9797 ; CHECK-NEXT: ret <2 x i32> [[R]]
9898 ;
9999 %t = icmp sgt <2 x i32> %x,
105105
106106 define <2 x i32> @p8_vec_nonsplat_undef0(<2 x i32> %x, <2 x i32> %y) {
107107 ; CHECK-LABEL: @p8_vec_nonsplat_undef0(
108 ; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]],
109 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> >
108 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], >
109 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
110110 ; CHECK-NEXT: ret <2 x i32> [[R]]
111111 ;
112112 %t = icmp ult <2 x i32> %x,
115115 }
116116 define <2 x i32> @p9_vec_nonsplat_undef1(<2 x i32> %x, <2 x i32> %y) {
117117 ; CHECK-LABEL: @p9_vec_nonsplat_undef1(
118 ; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]],
119 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32> >
118 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]], >
119 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
120120 ; CHECK-NEXT: ret <2 x i32> [[R]]
121121 ;
122122 %t = icmp ult <2 x i32> %x,
125125 }
126126 define <2 x i32> @p10_vec_nonsplat_undef2(<2 x i32> %x, <2 x i32> %y) {
127127 ; CHECK-LABEL: @p10_vec_nonsplat_undef2(
128 ; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]],
129 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
128 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]],
129 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
130130 ; CHECK-NEXT: ret <2 x i32> [[R]]
131131 ;
132132 %t = icmp ult <2 x i32> %x,
138138
139139 define <2 x i32> @p11_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
140140 ; CHECK-LABEL: @p11_vec_nonsplat(
141 ; CHECK-NEXT: [[T:%.*]] = icmp ult <2 x i32> [[X:%.*]],
142 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T]], <2 x i32> [[Y:%.*]], <2 x i32>
141 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt <2 x i32> [[X:%.*]],
142 ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T_INV]], <2 x i32> , <2 x i32> [[Y:%.*]]
143143 ; CHECK-NEXT: ret <2 x i32> [[R]]
144144 ;
145145 %t = icmp ult <2 x i32> %x,
173173 ; We don't care if the constant in select is true value or false value
174174 define i32 @p13_commutativity0(i32 %x, i32 %y) {
175175 ; CHECK-LABEL: @p13_commutativity0(
176 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
177 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65535, i32 [[Y:%.*]]
176 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
177 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 65535
178178 ; CHECK-NEXT: ret i32 [[R]]
179179 ;
180180 %t = icmp ult i32 %x, 65536
185185 ; Which means, if both possibilities are constants, we must check both of them.
186186 define i32 @p14_commutativity1(i32 %x, i32 %y) {
187187 ; CHECK-LABEL: @p14_commutativity1(
188 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
189 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 65535, i32 42
188 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
189 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 42, i32 65535
190190 ; CHECK-NEXT: ret i32 [[R]]
191191 ;
192192 %t = icmp ult i32 %x, 65536
195195 }
196196 define i32 @p15_commutativity2(i32 %x, i32 %y) {
197197 ; CHECK-LABEL: @p15_commutativity2(
198 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[X:%.*]], 65536
199 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 42, i32 65535
198 ; CHECK-NEXT: [[T_INV:%.*]] = icmp ugt i32 [[X:%.*]], 65535
199 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 65535, i32 42
200200 ; CHECK-NEXT: ret i32 [[R]]
201201 ;
202202 %t = icmp ult i32 %x, 65536
265265 ; There is nothing special about sign-bit-tests, we can fold them.
266266 define i32 @t22_sign_check(i32 %x, i32 %y) {
267267 ; CHECK-LABEL: @t22_sign_check(
268 ; CHECK-NEXT: [[T:%.*]] = icmp slt i32 [[X:%.*]], 0
269 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 -1, i32 [[Y:%.*]]
268 ; CHECK-NEXT: [[T_INV:%.*]] = icmp sgt i32 [[X:%.*]], -1
269 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 -1
270270 ; CHECK-NEXT: ret i32 [[R]]
271271 ;
272272 %t = icmp slt i32 %x, 0
275275 }
276276 define i32 @t22_sign_check2(i32 %x, i32 %y) {
277277 ; CHECK-LABEL: @t22_sign_check2(
278 ; CHECK-NEXT: [[T:%.*]] = icmp sgt i32 [[X:%.*]], -1
279 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T]], i32 0, i32 [[Y:%.*]]
278 ; CHECK-NEXT: [[T_INV:%.*]] = icmp slt i32 [[X:%.*]], 0
279 ; CHECK-NEXT: [[R:%.*]] = select i1 [[T_INV]], i32 [[Y:%.*]], i32 0
280280 ; CHECK-NEXT: ret i32 [[R]]
281281 ;
282282 %t = icmp sgt i32 %x, -1
332332
333333
334334
335 ; CHECK: !0 = !{!"branch_weights", i32 2000, i32 1}
335 ; CHECK: !0 = !{!"branch_weights", i32 1, i32 2000}
3535 define i32 @compare_against_zero(i32 %x) {
3636 ; CHECK-LABEL: @compare_against_zero(
3737 ; CHECK-NEXT: entry:
38 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 0
39 ; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
40 ; CHECK: callfoo:
41 ; CHECK-NEXT: call void @foo(i32 1)
38 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[X:%.*]], 0
39 ; CHECK-NEXT: [[CMP2_INV:%.*]] = icmp sgt i32 [[X]], -1
40 ; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[CMP2_INV]], i32 1, i32 -1
41 ; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP1]], i32 0, i32 [[SELECT1]]
42 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[SELECT2]], 0
43 ; CHECK-NEXT: br i1 [[COND]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
44 ; CHECK: callfoo:
45 ; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
4246 ; CHECK-NEXT: br label [[EXIT]]
4347 ; CHECK: exit:
4448 ; CHECK-NEXT: ret i32 42
9195 define i32 @compare_against_two(i32 %x) {
9296 ; CHECK-LABEL: @compare_against_two(
9397 ; CHECK-NEXT: entry:
94 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[X:%.*]], 2
95 ; CHECK-NEXT: br i1 [[TMP0]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
96 ; CHECK: callfoo:
97 ; CHECK-NEXT: call void @foo(i32 1)
98 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[X:%.*]], 2
99 ; CHECK-NEXT: [[CMP2_INV:%.*]] = icmp sgt i32 [[X]], 1
100 ; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[CMP2_INV]], i32 1, i32 -1
101 ; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP1]], i32 0, i32 [[SELECT1]]
102 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[SELECT2]], 0
103 ; CHECK-NEXT: br i1 [[COND]], label [[CALLFOO:%.*]], label [[EXIT:%.*]]
104 ; CHECK: callfoo:
105 ; CHECK-NEXT: call void @foo(i32 [[SELECT2]])
98106 ; CHECK-NEXT: br label [[EXIT]]
99107 ; CHECK: exit:
100108 ; CHECK-NEXT: ret i32 42
66 ; %cond0 is extra-used in select, which is freely invertible.
77 define i1 @v0_select_of_consts(i32 %X, i32* %selected) {
88 ; CHECK-LABEL: @v0_select_of_consts(
9 ; CHECK-NEXT: [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
10 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND0]], i32 -32768, i32 32767
9 ; CHECK-NEXT: [[COND0_INV:%.*]] = icmp sgt i32 [[X:%.*]], 32767
10 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND0_INV]], i32 32767, i32 -32768
1111 ; CHECK-NEXT: store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
1212 ; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767
1313 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535
3838 }
3939 define i1 @v2_select_of_const_and_var(i32 %X, i32 %Y, i32* %selected) {
4040 ; CHECK-LABEL: @v2_select_of_const_and_var(
41 ; CHECK-NEXT: [[COND0:%.*]] = icmp slt i32 [[X:%.*]], 32768
42 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND0]], i32 [[Y:%.*]], i32 32767
41 ; CHECK-NEXT: [[COND0_INV:%.*]] = icmp sgt i32 [[X:%.*]], 32767
42 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND0_INV]], i32 32767, i32 [[Y:%.*]]
4343 ; CHECK-NEXT: store i32 [[SELECT]], i32* [[SELECTED:%.*]], align 4
4444 ; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767
4545 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535