LLVM: lib/Transforms/InstCombine/InstCombineSelect.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
43#include
44#include
45
46#define DEBUG_TYPE "instcombine"
48
49using namespace llvm;
50using namespace PatternMatch;
51
52
53
54
58
63 return nullptr;
64
65 bool IsEq;
67 IsEq = Pred == ICmpInst::ICMP_EQ;
68 else if (Pred == FCmpInst::FCMP_OEQ)
69 IsEq = true;
70 else if (Pred == FCmpInst::FCMP_UNE)
71 IsEq = false;
72 else
73 return nullptr;
74
75
78 return nullptr;
79
80
81
84 if (IdC != C) {
86 return nullptr;
88 return nullptr;
89 }
90
91
94 return nullptr;
96 return nullptr;
97
98
99
100 if (isa(BO))
104 return nullptr;
105
106
107
108
109
111}
112
113
114
115
116
117
118
119
120
121
124 const APInt *SelTC, *SelFC;
127 return nullptr;
128
129
131 if (SelType->isVectorTy() != Cmp->getType()->isVectorTy())
132 return nullptr;
133
136 bool CreateAnd = false;
139 if ((Cmp->getOperand(1), m_Zero()))
140 return nullptr;
141
142 V = Cmp->getOperand(0);
143 const APInt *AndRHS;
145 return nullptr;
146
147 AndMask = *AndRHS;
149 Cmp->getOperand(1), Pred)) {
151 if (!Res->Mask.isPowerOf2())
152 return nullptr;
153
154 V = Res->X;
155 AndMask = Res->Mask;
156 Pred = Res->Pred;
157 CreateAnd = true;
158 } else {
159 return nullptr;
160 }
161 if (Pred == ICmpInst::ICMP_NE)
163
164
165
166
167
168 const APInt &TC = *SelTC;
169 const APInt &FC = *SelFC;
170 if (!TC.isZero() && !FC.isZero()) {
172 return nullptr;
173
174
175 if (CreateAnd && !Cmp->hasOneUse())
176 return nullptr;
177
178
179
180
181
182 Constant *TCC = ConstantInt::get(SelType, TC);
183 Constant *FCC = ConstantInt::get(SelType, FC);
184 Constant *MaskC = ConstantInt::get(SelType, AndMask);
185 for (auto Opc : {Instruction::Or, Instruction::Xor, Instruction::Add,
186 Instruction::Sub}) {
188 FCC) {
189 if (CreateAnd)
192 }
193 }
194
195 return nullptr;
196 }
197
198
199 if (!TC.isPowerOf2() && !FC.isPowerOf2())
200 return nullptr;
201
202
203
204 const APInt &ValC = !TC.isZero() ? TC : FC;
205 unsigned ValZeros = ValC.logBase2();
206 unsigned AndZeros = AndMask.logBase2();
207 bool ShouldNotVal = !TC.isZero();
208
209
210
211
212 if (CreateAnd && ShouldNotVal && ValZeros != AndZeros)
213 return nullptr;
214
215
216 if (CreateAnd)
217 V = Builder.CreateAnd(V, ConstantInt::get(V->getType(), AndMask));
218
219
220
221 if (ValZeros > AndZeros) {
223 V = Builder.CreateShl(V, ValZeros - AndZeros);
224 } else if (ValZeros < AndZeros) {
225 V = Builder.CreateLShr(V, AndZeros - ValZeros);
227 } else {
229 }
230
231
232
233 if (ShouldNotVal)
235
236 return V;
237}
238
239
240
241
242
243
244
245
246
247
248
250 switch (I->getOpcode()) {
251 case Instruction::Add:
252 case Instruction::FAdd:
253 case Instruction::Mul:
254 case Instruction::FMul:
255 case Instruction::And:
256 case Instruction::Or:
257 case Instruction::Xor:
258 return 3;
259 case Instruction::Sub:
260 case Instruction::FSub:
261 case Instruction::FDiv:
262 case Instruction::Shl:
263 case Instruction::LShr:
264 case Instruction::AShr:
265 return 1;
266 default:
267 return 0;
268 }
269}
270
271
274
275
276
277
282 return nullptr;
283
284
286 Type *CondTy = Cond->getType();
290 return nullptr;
291
292
293
294 if (auto *CondVTy = dyn_cast(CondTy)) {
296 CondVTy->getElementCount() !=
297 cast(FIOpndTy)->getElementCount())
298 return nullptr;
299
300
301
302
303
304
305
306
307
308 if (TI->getOpcode() != Instruction::BitCast &&
310 return nullptr;
312
313
314
315 return nullptr;
316 }
317
318
321 SI.getName() + ".v", &SI);
324 }
325
326 Value *OtherOpT, *OtherOpF;
327 bool MatchIsOpZero;
329 bool Swapped = false) -> Value * {
330 assert(!(Commute && Swapped) &&
331 "Commute and Swapped can't set at the same time");
332 if (!Swapped) {
336 MatchIsOpZero = true;
341 MatchIsOpZero = false;
343 }
344 }
345
346 if (!Commute && !Swapped)
347 return nullptr;
348
349
350
351
355 MatchIsOpZero = true;
360 MatchIsOpZero = false;
362 }
363 return nullptr;
364 };
365
367
370
371
374 FMF |= SI.getFastMathFlags();
377 if (auto *NewSelI = dyn_cast(NewSel))
378 NewSelI->setFastMathFlags(FMF);
379 Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewSel);
381 return NewFNeg;
382 }
383
384
385
386
387
388 auto *TII = dyn_cast(TI);
389 auto *FII = dyn_cast(FI);
390 if (TII && FII && TII->getIntrinsicID() == FII->getIntrinsicID()) {
392 if (Value *MatchOp = getCommonOp(TI, FI, true)) {
396 }
397 }
398
399
400
401
402
403
404 if (TII->getIntrinsicID() == Intrinsic::ldexp) {
405 Value *LdexpVal0 = TII->getArgOperand(0);
406 Value *LdexpExp0 = TII->getArgOperand(1);
407 Value *LdexpVal1 = FII->getArgOperand(0);
408 Value *LdexpExp1 = FII->getArgOperand(1);
410 FPMathOperator *SelectFPOp = cast(&SI);
411 FastMathFlags FMF = cast(TII)->getFastMathFlags();
412 FMF &= cast(FII)->getFastMathFlags();
414
417
419 TII->getType(), Intrinsic::ldexp, {SelectVal, SelectExp});
422 }
423 }
424 }
425
426
427
435 if (Value *MatchOp =
438 SI.getName() + ".v", &SI);
441 MatchOp, NewSel);
442 }
443 }
444 }
445 }
446
447
448
449
450
453 (!isa(TI) && !isa(TI)) ||
455 return nullptr;
456
457
459 if (!MatchOp)
460 return nullptr;
461
462
463
464
467 return nullptr;
468
469
470
471
472
473
474
475 auto *BO = dyn_cast(TI);
477
478
479 if (BO->getOpcode() == Instruction::SDiv ||
480 BO->getOpcode() == Instruction::SRem || MatchIsOpZero)
482 }
483
484
486 SI.getName() + ".v", &SI);
487 Value *Op0 = MatchIsOpZero ? MatchOp : NewSI;
488 Value *Op1 = MatchIsOpZero ? NewSI : MatchOp;
489 if (auto *BO = dyn_cast(TI)) {
493 return NewBO;
494 }
495 if (auto *TGEP = dyn_cast(TI)) {
496 auto *FGEP = cast(FI);
497 Type *ElementType = TGEP->getSourceElementType();
499 ElementType, Op0, Op1, TGEP->getNoWrapFlags() & FGEP->getNoWrapFlags());
500 }
502 return nullptr;
503}
504
506 if (!C1I.isZero() && !C2I.isZero())
507 return false;
509}
510
511
512
514 Value *FalseVal) {
515
516
517 auto TryFoldSelectIntoOp = [&](SelectInst &SI, Value *TrueVal,
520 auto *TVI = dyn_cast(TrueVal);
521 if (!TVI || !TVI->hasOneUse() || isa(FalseVal))
522 return nullptr;
523
525 unsigned OpToFold = 0;
526 if ((SFO & 1) && FalseVal == TVI->getOperand(0))
527 OpToFold = 1;
528 else if ((SFO & 2) && FalseVal == TVI->getOperand(1))
529 OpToFold = 2;
530
531 if (!OpToFold)
532 return nullptr;
533
535 if (isa(&SI))
536 FMF = SI.getFastMathFlags();
538 TVI->getOpcode(), TVI->getType(), true, FMF.noSignedZeros());
539 Value *OOp = TVI->getOperand(2 - OpToFold);
540
541
542 const APInt *OOpC;
544 if (isa(OOp) &&
545 (!OOpIsAPInt || (C->getUniqueInteger(), *OOpC)))
546 return nullptr;
547
548
549
550
551
552
553
554 if (isa(&SI) &&
556 return nullptr;
557
559 Swapped ? OOp : C, "", &SI);
560 if (isa(&SI))
561 cast(NewSel)->setFastMathFlags(FMF);
566 if (isa(&SI)) {
567
570
571
573 }
574 return BO;
575 };
576
577 if (Instruction *R = TryFoldSelectIntoOp(SI, TrueVal, FalseVal, false))
578 return R;
579
580 if (Instruction *R = TryFoldSelectIntoOp(SI, FalseVal, TrueVal, true))
581 return R;
582
583 return nullptr;
584}
585
586
587
588
589
590
591
592
593
597 if (!(Cmp->hasOneUse() && Cmp->getOperand(0)->hasOneUse() &&
600 return nullptr;
601
602
605 return nullptr;
606
607
610
611
612
613
614 if (HasShift &&
618 return nullptr;
619
620 if (!HasShift)
622
625 return nullptr;
626
627
628
629 Constant *One = ConstantInt::get(SelType, 1);
630 Value *MaskB = HasShift ? Builder.CreateShl(One, Z) : One;
634 return new ZExtInst(ICmpNeZero, SelType);
635}
636
637
638
639
640
641
648 return nullptr;
649
653 }
654
656 const APInt *C2, *C1;
660 return nullptr;
661
664 return nullptr;
665
666 auto *FI = dyn_cast(FVal);
667 if (!FI)
668 return nullptr;
669
670 FI->setHasNoSignedWrap(false);
671 FI->setHasNoUnsignedWrap(false);
672 return FVal;
673}
674
675
676
677
678
679
687 return nullptr;
688
697 return nullptr;
698
699
702
706 const auto *Ashr = cast(FalseVal);
707
708 bool IsExact = Ashr->isExact() && cast(TrueVal)->isExact();
710 }
711
712 return nullptr;
713}
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
738
739
740 if (!TrueVal->getType()->isIntOrIntVectorTy() ||
742 return nullptr;
743
746
747 unsigned C1Log;
752 return nullptr;
753
756 return nullptr;
757
759 } else {
761 if (!Res || !Res->Mask.isPowerOf2())
762 return nullptr;
763
764 CmpLHS = Res->X;
765 Pred = Res->Pred;
766 C1Log = Res->Mask.logBase2();
768 }
769
773 bool NeedXor;
775 Y = TrueVal;
776 BinOp = cast(FalseVal);
779 Y = FalseVal;
780 BinOp = cast(TrueVal);
782 } else {
783 return nullptr;
784 }
785
786
787 auto *IdentityC =
789 true);
790 if (IdentityC == nullptr || !IdentityC->isNullValue())
791 return nullptr;
792
793 unsigned C2Log = C2->logBase2();
794
795 bool NeedShift = C1Log != C2Log;
796 bool NeedZExtTrunc = Y->getType()->getScalarSizeInBits() !=
797 V->getType()->getScalarSizeInBits();
798
799
800 if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >
802 return nullptr;
803
805
807 V = Builder.CreateAnd(V, ConstantInt::get(V->getType(), C1));
808 }
809
810 if (C2Log > C1Log) {
812 V = Builder.CreateShl(V, C2Log - C1Log);
813 } else if (C1Log > C2Log) {
814 V = Builder.CreateLShr(V, C1Log - C2Log);
816 } else
818
819 if (NeedXor)
821
823}
824
825
826
835
836
840 Constant *OrC = ConstantInt::get(Ty, *C);
842 return BinaryOperator::CreateOr(T, NewSel);
843 }
844
845
849 Constant *OrC = ConstantInt::get(Ty, *C);
851 return BinaryOperator::CreateOr(F, NewSel);
852 }
853
854 return nullptr;
855}
856
857
858
859
860
861
862
863
864
865
866
868 auto *CondVal = SI.getCondition();
869 auto *TrueVal = SI.getTrueValue();
870 auto *FalseVal = SI.getFalseValue();
873
874
875
876
879 return nullptr;
880
883
884
885
886
887
888 auto *TrueValC = dyn_cast(TrueVal);
889 if (TrueValC == nullptr ||
891 !isa(FalseVal))
892 return nullptr;
893
894 auto *ZeroC = cast(cast(CondVal)->getOperand(1));
896
897
898
900 return nullptr;
901
902 auto *FalseValI = cast(FalseVal);
905 IC.replaceOperand(*FalseValI, FalseValI->getOperand(0) == Y ? 0 : 1, FrY);
907}
908
909
910
912 const Value *TrueVal,
913 const Value *FalseVal,
918
919
920
924 }
925
927 return nullptr;
928
929
930
934 ConstantInt::get(A->getType(), 1));
935 return nullptr;
936 }
937
939 return nullptr;
940
942
945 }
946
948 "Unexpected isUnsigned predicate!");
949
950
951
952
953
954 bool IsNegative = false;
959 IsNegative = true;
963 return nullptr;
964
965
966
967 if (IsNegative && !TrueVal->hasOneUse() && !ICI->hasOneUse())
968 return nullptr;
969
970
971
973 if (IsNegative)
974 Result = Builder.CreateNeg(Result);
975 return Result;
976}
977
980 if (!Cmp->hasOneUse())
981 return nullptr;
982
983
984 Value *Cmp0 = Cmp->getOperand(0);
985 Value *Cmp1 = Cmp->getOperand(1);
989
990
991
992
996 }
998 return nullptr;
999
1000
1001
1006 Intrinsic::uadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), 1));
1007 }
1008 return nullptr;
1009 }
1010
1014
1015
1017 ConstantInt::get(Cmp0->getType(), *C));
1018 }
1019
1020
1021
1025
1027 ConstantInt::get(Cmp0->getType(), *C));
1028 }
1029
1030
1031
1035
1037 ConstantInt::get(Cmp0->getType(), *C));
1038 }
1039
1040
1044 }
1046 return nullptr;
1047
1048
1049
1053
1054
1056 }
1057
1058
1059 X = Cmp0;
1060 Y = Cmp1;
1062
1063
1067 }
1068
1069
1073
1074
1076 }
1077
1078 return nullptr;
1079}
1080
1081
1084 auto *TI = dyn_cast(TVal);
1085 auto *FI = dyn_cast(FVal);
1086 if (!TI || !FI)
1087 return nullptr;
1088
1089
1091 Value *A = Cmp->getOperand(0);
1092 Value *B = Cmp->getOperand(1);
1093
1094
1098 }
1099
1100
1101
1105 (TI->hasNoSignedWrap() || TI->hasNoUnsignedWrap()) &&
1106 (FI->hasNoSignedWrap() || FI->hasNoUnsignedWrap())) {
1107
1108
1109
1110
1111
1112
1113 TI->setHasNoUnsignedWrap(false);
1114 if (!TI->hasNoSignedWrap())
1115 TI->setHasNoSignedWrap(TI->hasOneUse());
1117 }
1118
1119 return nullptr;
1120}
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1133 Value *FalseVal,
1135 unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();
1137 return nullptr;
1138
1141
1143 if ((FalseVal,
1145 return nullptr;
1146
1147 if ((Ctlz, m_IntrinsicIntrinsic::ctlz()))
1148 return nullptr;
1149
1151 return nullptr;
1152
1154 auto *II = cast(Ctlz);
1156 return nullptr;
1157
1159 II->getModule(), Intrinsic::cttz, II->getType());
1161}
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1180
1181
1183 return nullptr;
1184
1188 std::swap(SelectArg, ValueOnZero);
1189
1190
1191 Value *Count = nullptr;
1194 Count = SelectArg;
1195
1196
1197
1199 if ((Count, m_IntrinsicIntrinsic::cttz(m_Value(X))) &&
1200 (Count, m_IntrinsicIntrinsic::ctlz(m_Value(X))))
1201 return nullptr;
1202
1203
1204
1205 if ((X != CmpLHS || (CmpRHS, m_Zero())) &&
1207 return nullptr;
1208
1210
1211
1212
1215
1216
1218
1219 II->dropPoisonGeneratingAnnotations();
1221 return SelectArg;
1222 }
1223
1224
1225
1226
1227 if (II->hasOneUse() && SelectArg->hasOneUse() &&
1230
1231 II->dropUBImplyingAttrsAndMetadata();
1233 }
1234
1235 return nullptr;
1236}
1237
1241
1242 if (->getType()->isIntOrIntVectorTy())
1243 return nullptr;
1244
1250 return nullptr;
1251
1252
1256 ConstantInt::get(Type::getInt1Ty(Cmp.getContext()), IntMinIsPoison);
1259
1261 return IC.Builder.CreateNeg(Abs);
1262 return Abs;
1263 }
1264
1268 }
1269
1270 return nullptr;
1271}
1272
1274 unsigned Depth) {
1275
1277 return false;
1278
1279 assert(!isa(Old) && "Only replace non-constant values");
1280
1281 auto *I = dyn_cast(V);
1282 if ( ||
->hasOneUse() ||
1284 return false;
1285
1286
1288 return false;
1289
1290 bool Changed = false;
1291 for (Use &U : I->operands()) {
1292 if (U == Old) {
1295 Changed = true;
1296 } else {
1298 }
1299 }
1300 return Changed;
1301}
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1321
1322
1324 bool Swapped = false;
1325 if (Cmp.isEquivalence(true)) {
1327 Swapped = true;
1328 } else if (.isEquivalence()) {
1329 return nullptr;
1330 }
1331
1332 Value *CmpLHS = Cmp.getOperand(0), *CmpRHS = Cmp.getOperand(1);
1333 auto ReplaceOldOpWithNewOp = [&](Value *OldOp,
1335
1336
1337
1338
1339
1340
1341 if (TrueVal == OldOp && (isa(OldOp) || !isa(NewOp)))
1342 return nullptr;
1343
1345 true)) {
1346
1347
1348
1352
1353
1354
1358 return nullptr;
1359 }
1360 }
1361
1362
1363
1364
1365
1366
1367
1372 return &Sel;
1373 return nullptr;
1374 };
1375
1376 if (Instruction *R = ReplaceOldOpWithNewOp(CmpLHS, CmpRHS))
1377 return R;
1378 if (Instruction *R = ReplaceOldOpWithNewOp(CmpRHS, CmpLHS))
1379 return R;
1380
1381 auto *FalseInst = dyn_cast(FalseVal);
1382 if (!FalseInst)
1383 return nullptr;
1384
1385
1386
1387
1388
1389
1390
1391
1392
1395 false,
1396 &DropFlags) == TrueVal ||
1398 false,
1399 &DropFlags) == TrueVal) {
1401 I->dropPoisonGeneratingAnnotations();
1403 }
1404
1406 }
1407
1408 return nullptr;
1409}
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1426
1428 return nullptr;
1429
1430 if ((YeqZ,
1433
1434 if ((YeqZ,
1436 return nullptr;
1437
1440 return nullptr;
1441
1442 if ((XeqY,
1444 return nullptr;
1445
1446 cast(XeqY)->setSameSign(false);
1448}
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1469
1470
1471
1473 return nullptr;
1479 return nullptr;
1480
1481 if (!isa(Sel1)) {
1484 }
1485
1486
1487
1488 switch (Pred0) {
1491
1492
1493
1497 return nullptr;
1498 break;
1501
1502
1507 return nullptr;
1510 break;
1511 default:
1512 return nullptr;
1513 }
1514
1515
1516
1518 return nullptr;
1519
1520
1521
1522 if (Cmp00->getType() != X->getType() && X->hasOneUse())
1524
1525
1526
1528 if (Cmp00 == X)
1530 else if ((Cmp00,
1533 return nullptr;
1534
1538 Value *ReplacementLow, *ReplacementHigh;
1540 m_Value(ReplacementHigh))) ||
1544 return nullptr;
1545
1547 return nullptr;
1548
1549
1550
1551
1552
1553 switch (Pred1) {
1555 break;
1557
1558
1559
1560 return nullptr;
1562
1563
1568 return nullptr;
1570 [[fallthrough]];
1572
1573
1575 std::swap(ReplacementLow, ReplacementHigh);
1576 break;
1577 default:
1578 return nullptr;
1579 }
1581 "Unexpected predicate type.");
1582
1583
1586
1589 "Unexpected predicate type.");
1591 std::swap(ThresholdLowIncl, ThresholdHighExcl);
1592
1593
1596 if (!Precond1 || (Precond1, m_One()))
1597 return nullptr;
1598
1601 if (!Precond2 || (Precond2, m_One()))
1602 return nullptr;
1603
1604
1605
1606
1607 if (X->getType() != Sel0.getType()) {
1611 return nullptr;
1613 ReplacementLow =
1615 ReplacementHigh =
1617 assert(ReplacementLow && ReplacementHigh &&
1618 "Constant folding of ImmConstant cannot fail");
1619 }
1620
1621
1624 Value *MaybeReplacedLow =
1625 Builder.CreateSelect(ShouldReplaceLow, ReplacementLow, X);
1626
1627
1628
1630 ShouldReplaceHigh, ReplacementHigh, MaybeReplacedLow);
1632}
1633
1634
1635
1636
1637
1638
1639
1640
1641
1643tryToReuseConstantFromSelectInComparison(SelectInst &Sel, ICmpInst &Cmp,
1651 return nullptr;
1652
1653
1655 return nullptr;
1656
1657
1658
1660 return nullptr;
1661
1662
1663
1665 return nullptr;
1666
1667
1668
1669
1671 return nullptr;
1672
1673
1674 Value *SelVal0, *SelVal1;
1676
1677
1680 return nullptr;
1681
1682
1683 auto MatchesSelectValue = [SelVal0, SelVal1](Constant *C) {
1684 return C->isElementWiseEqual(SelVal0) || C->isElementWiseEqual(SelVal1);
1685 };
1686
1687
1688 if (MatchesSelectValue(C0))
1689 return nullptr;
1690
1691
1693 if (!FlippedStrictness)
1694 return nullptr;
1695
1696
1697 if (!MatchesSelectValue(FlippedStrictness->second))
1698 return nullptr;
1699
1700
1703
1706 Cmp.getName() + ".inv");
1710
1711 return &Sel;
1712}
1713
1717 if (->hasOneUse())
1718 return nullptr;
1719
1720 const APInt *CmpC;
1722 return nullptr;
1723
1724
1729
1730
1734
1735 return nullptr;
1736}
1737
1740 const APInt *CmpC;
1744 return nullptr;
1745
1746
1747 Value *TVal = SI.getTrueValue();
1748 Value *FVal = SI.getFalseValue();
1750
1753
1756
1759
1762 }
1763
1771 else
1772 return nullptr;
1773
1774 const APInt *BinOpC;
1776 return nullptr;
1777
1780 if (R == *C) {
1782 return BO;
1783 }
1784 return nullptr;
1785}
1786
1787
1788
1791 Value *FalseVal) {
1793
1795 return nullptr;
1796
1799
1801 return nullptr;
1802
1806 return nullptr;
1807
1810
1817 } else {
1818 return nullptr;
1819 }
1820
1822 return nullptr;
1823
1824 return new ICmpInst(Pred, CmpLHS, B);
1825}
1826
1831 return nullptr;
1832
1837
1840
1842 foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
1843 return Res;
1844
1845 return nullptr;
1846}
1847
1848
1849
1850static Value *foldSelectWithConstOpToBinOp(ICmpInst *Cmp, Value *TrueVal,
1851 Value *FalseVal,
1857
1859 return nullptr;
1860
1862 return nullptr;
1863
1867 }
1868
1870 return nullptr;
1871
1872 unsigned Opcode = BOp->getOpcode();
1873
1874
1875
1876
1878 return nullptr;
1879
1881 return nullptr;
1882
1887
1890 RHS = C1;
1892 Opcode, Flipped->second, C2, DL)) {
1894 RHS = Flipped->second;
1895 } else {
1896 return nullptr;
1897 }
1898
1902}
1903
1904
1908 canonicalizeSPF(*ICI, SI.getTrueValue(), SI.getFalseValue(), *this))
1910
1911 if (Value *V = foldSelectInstWithICmpConst(SI, ICI, Builder))
1913
1914 if (Value *V = canonicalizeClampLike(SI, *ICI, Builder, *this))
1916
1918 tryToReuseConstantFromSelectInComparison(SI, *ICI, *this))
1919 return NewSel;
1920
1923
1924
1925 bool Changed = false;
1931
1932 if (Instruction *NewSel = foldSelectICmpEq(SI, ICI, *this))
1933 return NewSel;
1934
1935
1936
1937
1938
1946 SI.swapValues();
1947 SI.swapProfMetadata();
1948 return &SI;
1949 }
1950
1953 return V;
1954
1957
1958 if (Instruction *V = foldSelectCtlzToCttz(ICI, TrueVal, FalseVal, Builder))
1959 return V;
1960
1961 if (Instruction *V = foldSelectZeroOrOnes(ICI, TrueVal, FalseVal, Builder))
1962 return V;
1963
1966
1969
1970 if (Value *V = foldSelectCttzCtlz(ICI, TrueVal, FalseVal, *this))
1972
1975
1978
1981
1982 if (Value *V = foldSelectWithConstOpToBinOp(ICI, TrueVal, FalseVal, Builder))
1984
1985 return Changed ? &SI : nullptr;
1986}
1987
1988
1989
1996 return nullptr;
1997
1999
2000
2001
2004 }
2005
2006 return nullptr;
2007}
2008
2009
2010
2013 Value *CondVal = SI.getCondition();
2016 auto *TI = dyn_cast(TrueVal);
2017 auto *FI = dyn_cast(FalseVal);
2018 if (!TI || !FI || !TI->hasOneUse() || !FI->hasOneUse())
2019 return nullptr;
2020
2021 Instruction *AddOp = nullptr, *SubOp = nullptr;
2022 if ((TI->getOpcode() == Instruction::Sub &&
2023 FI->getOpcode() == Instruction::Add) ||
2024 (TI->getOpcode() == Instruction::FSub &&
2025 FI->getOpcode() == Instruction::FAdd)) {
2026 AddOp = FI;
2027 SubOp = TI;
2028 } else if ((FI->getOpcode() == Instruction::Sub &&
2029 TI->getOpcode() == Instruction::Add) ||
2030 (FI->getOpcode() == Instruction::FSub &&
2031 TI->getOpcode() == Instruction::FAdd)) {
2032 AddOp = TI;
2033 SubOp = FI;
2034 }
2035
2036 if (AddOp) {
2037 Value *OtherAddOp = nullptr;
2038 if (SubOp->getOperand(0) == AddOp->getOperand(0)) {
2040 } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) {
2042 }
2043
2044 if (OtherAddOp) {
2045
2046
2047 Value *NegVal;
2048 if (SI.getType()->isFPOrFPVectorTy()) {
2049 NegVal = Builder.CreateFNeg(SubOp->getOperand(1));
2050 if (Instruction *NegInst = dyn_cast(NegVal)) {
2052 Flags &= SubOp->getFastMathFlags();
2053 NegInst->setFastMathFlags(Flags);
2054 }
2055 } else {
2056 NegVal = Builder.CreateNeg(SubOp->getOperand(1));
2057 }
2058
2059 Value *NewTrueOp = OtherAddOp;
2060 Value *NewFalseOp = NegVal;
2061 if (AddOp != TI)
2062 std::swap(NewTrueOp, NewFalseOp);
2063 Value *NewSel = Builder.CreateSelect(CondVal, NewTrueOp, NewFalseOp,
2064 SI.getName() + ".p", &SI);
2065
2066 if (SI.getType()->isFPOrFPVectorTy()) {
2068 BinaryOperator::CreateFAdd(SubOp->getOperand(0), NewSel);
2069
2071 Flags &= SubOp->getFastMathFlags();
2073 return RI;
2074 } else
2075 return BinaryOperator::CreateAdd(SubOp->getOperand(0), NewSel);
2076 }
2077 }
2078 return nullptr;
2079}
2080
2081
2082
2083
2084
2085
2088 Value *CondVal = SI.getCondition();
2091
2095 return nullptr;
2096
2099
2100 auto IsSignedSaturateLimit = [&](Value *Limit, bool IsAdd) {
2102
2108 return false;
2109
2110 auto IsZeroOrOne = [](const APInt &C) { return C.isZero() || C.isOne(); };
2116 };
2117
2119 return false;
2120
2121 if (IsAdd) {
2122
2123
2124
2125
2127 IsMinMax(TrueVal, FalseVal))
2128 return true;
2129
2130
2131
2132
2134 IsMinMax(FalseVal, TrueVal))
2135 return true;
2136 } else {
2137
2138
2140 IsMinMax(TrueVal, FalseVal))
2141 return true;
2142
2143
2145 IsMinMax(FalseVal, TrueVal))
2146 return true;
2147
2148
2150 IsMinMax(FalseVal, TrueVal))
2151 return true;
2152
2153
2155 IsMinMax(TrueVal, FalseVal))
2156 return true;
2157 }
2158
2159 return false;
2160 };
2161
2163 if (II->getIntrinsicID() == Intrinsic::uadd_with_overflow &&
2165
2166 NewIntrinsicID = Intrinsic::uadd_sat;
2167 else if (II->getIntrinsicID() == Intrinsic::usub_with_overflow &&
2169
2170 NewIntrinsicID = Intrinsic::usub_sat;
2171 else if (II->getIntrinsicID() == Intrinsic::sadd_with_overflow &&
2172 IsSignedSaturateLimit(TrueVal, true))
2173
2174
2175
2176
2177
2178
2179
2180
2181 NewIntrinsicID = Intrinsic::sadd_sat;
2182 else if (II->getIntrinsicID() == Intrinsic::ssub_with_overflow &&
2183 IsSignedSaturateLimit(TrueVal, false))
2184
2185
2186
2187
2188
2189
2190
2191
2192 NewIntrinsicID = Intrinsic::ssub_sat;
2193 else
2194 return nullptr;
2195
2197 NewIntrinsicID, SI.getType());
2199}
2200
2205 return nullptr;
2206
2210 return nullptr;
2211
2212 auto ExtOpcode = ExtInst->getOpcode();
2213 if (ExtOpcode != Instruction::ZExt && ExtOpcode != Instruction::SExt)
2214 return nullptr;
2215
2216
2217
2219 Type *SmallType = X->getType();
2221 auto *Cmp = dyn_cast(Cond);
2223 (!Cmp || Cmp->getOperand(0)->getType() != SmallType))
2224 return nullptr;
2225
2226
2227
2230 if (TruncC && ExtInst->hasOneUse()) {
2231 Value *TruncCVal = cast(TruncC);
2234
2235
2236
2239 }
2240
2241 return nullptr;
2242}
2243
2244
2245
2247 Value *CondVal = SI.getCondition();
2249 auto *CondValTy = dyn_cast(CondVal->getType());
2251 return nullptr;
2252
2253 unsigned NumElts = CondValTy->getNumElements();
2255 Mask.reserve(NumElts);
2256 for (unsigned i = 0; i != NumElts; ++i) {
2258 if (!Elt)
2259 return nullptr;
2260
2262
2263 Mask.push_back(i);
2265
2266 Mask.push_back(i + NumElts);
2267 } else if (isa(Elt)) {
2268
2269
2270
2271 return nullptr;
2272 } else {
2273
2274 return nullptr;
2275 }
2276 }
2277
2279}
2280
2281
2282
2283
2284
2287 auto *Ty = dyn_cast(Sel.getType());
2288 if (!Ty)
2289 return nullptr;
2290
2291
2294 return nullptr;
2295
2296
2297
2298
2301}
2302
2303
2304
2305
2311
2315 return nullptr;
2316
2317
2318
2319 if (TVal == A || TVal == B || FVal == A || FVal == B)
2320 return nullptr;
2321
2324 return nullptr;
2325
2326
2327 Value *TSrc, *FSrc;
2330 return nullptr;
2331
2332
2333
2334
2336 if (TSrc == C && FSrc == D) {
2337
2338
2340 } else if (TSrc == D && FSrc == C) {
2341
2342
2344 } else {
2345 return nullptr;
2346 }
2348}
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2374
2375
2376
2377
2379 auto *Extract = dyn_cast(V);
2380 if (!Extract)
2381 return nullptr;
2382 if (Extract->getIndices()[0] != I)
2383 return nullptr;
2384 return dyn_cast(Extract->getAggregateOperand());
2385 };
2386
2387
2388
2389 if (SI.hasOneUse())
2390 if (auto *Select = dyn_cast(SI.user_back()))
2391 if (Select->getCondition() == SI.getCondition())
2392 if (Select->getFalseValue() == SI.getTrueValue() ||
2393 Select->getTrueValue() == SI.getFalseValue())
2394 return nullptr;
2395
2396
2397 auto *CmpXchg = isExtractFromCmpXchg(SI.getCondition(), 1);
2398 if (!CmpXchg)
2399 return nullptr;
2400
2401
2402
2403
2404 if (auto *X = isExtractFromCmpXchg(SI.getTrueValue(), 0))
2405 if (X == CmpXchg && X->getCompareOperand() == SI.getFalseValue())
2406 return SI.getFalseValue();
2407
2408
2409
2410
2411 if (auto *X = isExtractFromCmpXchg(SI.getFalseValue(), 0))
2412 if (X == CmpXchg && X->getCompareOperand() == SI.getTrueValue())
2413 return SI.getFalseValue();
2414
2415 return nullptr;
2416}
2417
2418
2419
2420
2421
2422
2423
2424
2425
2428
2431 return nullptr;
2432
2435 return nullptr;
2436
2437 Value *SV0, *SV1, *SA0, *SA1;
2443 return nullptr;
2444
2445
2446 if (Or0->getOpcode() == BinaryOperator::LShr) {
2450 }
2452 Or1->getOpcode() == BinaryOperator::LShr &&
2453 "Illegal or(shift,shift) pair");
2454
2455
2458 ShAmt = SA0;
2460 ShAmt = SA1;
2461 else
2462 return nullptr;
2463
2464
2465
2466
2467
2468 bool IsFshl = (ShAmt == SA0);
2470 if ((IsFshl && TVal != SV0) || (!IsFshl && TVal != SV1))
2471 return nullptr;
2472
2473
2477 return nullptr;
2478
2479
2480
2481 if (SV0 != SV1) {
2486 }
2487
2488
2489
2490 Intrinsic::ID IID = IsFshl ? Intrinsic::fshl : Intrinsic::fshr;
2495}
2496
2503
2504
2505
2510 return nullptr;
2511
2512 assert(TC != FC && "Expected equal select arms to simplify");
2513
2516 bool IsTrueIfSignSet;
2520 (Pred, *C, IsTrueIfSignSet) || X->getType() != SelType)
2521 return nullptr;
2522
2523
2524
2525
2526
2527
2528
2529 if (IsTrueIfSignSet ^ TC->isNegative())
2531
2532
2533
2534 Value *MagArg = ConstantFP::get(SelType, abs(*TC));
2538}
2539
2541 if (!isa(Sel.getType()))
2542 return nullptr;
2543
2548
2552 if (auto *I = dyn_cast(V))
2553 I->copyIRFlags(&Sel);
2556 M, Intrinsic::vector_reverse, V->getType());
2558 };
2559
2561
2564 return createSelReverse(C, X, Y);
2565
2566
2568 return createSelReverse(C, X, FVal);
2569 }
2570
2573 return createSelReverse(C, TVal, Y);
2574 }
2575
2576 auto *VecTy = dyn_cast(Sel.getType());
2577 if (!VecTy)
2578 return nullptr;
2579
2580 unsigned NumElts = VecTy->getNumElements();
2581 APInt PoisonElts(NumElts, 0);
2584 if (V != &Sel)
2586 return &Sel;
2587 }
2588
2589
2590
2591
2595 cast(TVal)->isSelect()) {
2596 if (X == FVal) {
2597
2600 }
2601 if (Y == FVal) {
2602
2605 }
2606 }
2609 cast(FVal)->isSelect()) {
2610 if (X == TVal) {
2611
2614 }
2615 if (Y == TVal) {
2616
2619 }
2620 }
2621
2622 return nullptr;
2623}
2624
2628
2629
2630 auto *IDomNode = DT[BB]->getIDom();
2631 if (!IDomNode)
2632 return nullptr;
2633 BasicBlock *IDom = IDomNode->getBlock();
2634
2636 Value *IfTrue, *IfFalse;
2648 } else
2649 return nullptr;
2650
2651
2652 if (TrueSucc == FalseSucc)
2653 return nullptr;
2654
2655
2656
2657
2658
2659
2664
2670 else
2671 return nullptr;
2672
2673 if (auto *Insn = dyn_cast(Inputs[Pred]))
2675 return nullptr;
2676 }
2677
2682 PN->takeName(&Sel);
2683 return PN;
2684}
2685
2688
2692 if (auto *I = dyn_cast(V))
2693 CandidateBlocks.insert(I->getParent());
2694
2695 for (BasicBlock *BB : CandidateBlocks)
2696 if (auto *PN = foldSelectToPhiImpl(Sel, BB, DT, Builder))
2697 return PN;
2698 return nullptr;
2699}
2700
2701
2702
2703
2704
2705
2706
2709 Value *CondVal = SI.getCondition();
2712
2714 Value *Op, *RemRes, *Remainder;
2716 bool TrueIfSigned = false;
2717
2720 return nullptr;
2721
2722
2723
2724 if (!TrueIfSigned)
2726
2727 auto FoldToBitwiseAnd = [&](Value *Remainder) -> Instruction * {
2730 return BinaryOperator::CreateAnd(Op, Add);
2731 };
2732
2733
2734
2735
2736
2737
2741 FalseVal == RemRes)
2742 return FoldToBitwiseAnd(Remainder);
2743
2744
2745
2746
2747
2750 FalseVal == RemRes)
2751 return FoldToBitwiseAnd(ConstantInt::get(RemRes->getType(), 2));
2752
2753 return nullptr;
2754}
2755
2758 if (!FI)
2759 return nullptr;
2760
2763
2764
2765
2766
2767
2768
2769
2770
2771
2777 }
2778
2779 return nullptr;
2780}
2781
2782
2783static Value *simplifyNestedSelectsUsingImpliedCond(SelectInst &SI,
2785 bool CondIsTrue,
2787 Value *InnerCondVal = SI.getCondition();
2788 Value *InnerTrueVal = SI.getTrueValue();
2789 Value *InnerFalseVal = SI.getFalseValue();
2791 "The type of inner condition must match with the outer.");
2792 if (auto Implied = isImpliedCondition(CondVal, InnerCondVal, DL, CondIsTrue))
2793 return *Implied ? InnerTrueVal : InnerFalseVal;
2794 return nullptr;
2795}
2796
2797Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond(Value *Op,
2799 bool IsAnd) {
2800 assert(Op->getType()->isIntOrIntVectorTy(1) &&
2801 "Op must be either i1 or vector of i1.");
2802 if (SI.getCondition()->getType() != Op->getType())
2803 return nullptr;
2804 if (Value *V = simplifyNestedSelectsUsingImpliedCond(SI, Op, IsAnd, DL))
2808 return nullptr;
2809}
2810
2811
2812
2815 Value *CondVal = SI.getCondition();
2816
2817 bool ChangedFMF = false;
2818 for (bool Swap : {false, true}) {
2820 Value *X = SI.getFalseValue();
2822
2823 if (Swap)
2825
2827 continue;
2828
2829
2830
2835 }
2839 }
2840 }
2841
2843 return nullptr;
2844
2845
2846
2847
2848 FastMathFlags FMF = cast(TrueVal)->getFastMathFlags();
2849 if (FMF.noNaNs() && .hasNoNaNs()) {
2850 SI.setHasNoNaNs(true);
2851 ChangedFMF = true;
2852 }
2853 if (FMF.noInfs() && .hasNoInfs()) {
2854 SI.setHasNoInfs(true);
2855 ChangedFMF = true;
2856 }
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868 if (.hasNoSignedZeros() ||
.hasNoNaNs())
2869 return nullptr;
2870
2871 if (Swap)
2873
2878
2879 if (IsLTOrLE) {
2882 }
2883 if (IsGTOrGE) {
2885 Instruction *NewFNeg = UnaryOperator::CreateFNeg(Fabs);
2887 return NewFNeg;
2888 }
2889 }
2890
2891
2892
2893
2894 for (bool Swap : {false, true}) {
2896 Value *X = SI.getFalseValue();
2897
2898 if (Swap)
2900
2903 bool TrueIfSigned;
2904 if ((CondVal,
2907 continue;
2909 return nullptr;
2910 if (Swap == TrueIfSigned && !CondVal->hasOneUse() && ->hasOneUse())
2911 return nullptr;
2912
2913
2914
2916 if (Swap != TrueIfSigned)
2919 }
2920
2921 return ChangedFMF ? &SI : nullptr;
2922}
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2939foldRoundUpIntegerWithPow2Alignment(SelectInst &SI,
2942 Value *X = SI.getTrueValue();
2943 Value *XBiasedHighBits = SI.getFalseValue();
2944
2946 Value *XLowBits;
2949 return nullptr;
2950
2953
2954
2955
2956 const APInt *LowBitMaskCst;
2958 return nullptr;
2959
2960
2961 const APInt *BiasCst, *HighBitMaskCst;
2962 if ((XBiasedHighBits,
2965 (XBiasedHighBits,
2968 return nullptr;
2969
2970 if (!LowBitMaskCst->isMask())
2971 return nullptr;
2972
2973 APInt InvertedLowBitMaskCst = ~*LowBitMaskCst;
2974 if (InvertedLowBitMaskCst != *HighBitMaskCst)
2975 return nullptr;
2976
2977 APInt AlignmentCst = *LowBitMaskCst + 1;
2978
2979 if (*BiasCst != AlignmentCst && *BiasCst != *LowBitMaskCst)
2980 return nullptr;
2981
2982 if (!XBiasedHighBits->hasOneUse()) {
2983
2984 if (*BiasCst == *LowBitMaskCst && impliesPoison(XBiasedHighBits, X))
2985 return XBiasedHighBits;
2986 return nullptr;
2987 }
2988
2989
2991 Value *XOffset = Builder.CreateAdd(X, ConstantInt::get(Ty, *LowBitMaskCst),
2992 X->getName() + ".biased");
2993 Value *R = Builder.CreateAnd(XOffset, ConstantInt::get(Ty, *HighBitMaskCst));
2994 R->takeName(&SI);
2995 return R;
2996}
2997
2998namespace {
2999struct DecomposedSelect {
3003};
3004}
3005
3006
3007
3008
3009
3011foldSelectOfSymmetricSelect(SelectInst &OuterSelVal,
3013
3014 Value *OuterCond, *InnerCond, *InnerTrueVal, *InnerFalseVal;
3016 &OuterSelVal,
3019 m_Value(InnerFalseVal))),
3023 return nullptr;
3024
3026 return nullptr;
3027
3030}
3031
3032
3033
3034
3035
3036
3037
3038
3041
3042 DecomposedSelect OuterSel;
3043 match(&OuterSelVal,
3045 m_Value(OuterSel.FalseVal)));
3046
3047
3049 std::swap(OuterSel.TrueVal, OuterSel.FalseVal);
3050
3051
3053 return nullptr;
3054
3055
3057 Value *InnerSelVal = IsAndVariant ? OuterSel.FalseVal : OuterSel.TrueVal;
3058
3059
3061 [](Value *V) { return V->hasOneUse(); }))
3062 return nullptr;
3063
3064
3065 DecomposedSelect InnerSel;
3066 if ((InnerSelVal,
3068 m_Value(InnerSel.FalseVal))))
3069 return nullptr;
3070
3071
3073 std::swap(InnerSel.TrueVal, InnerSel.FalseVal);
3074
3075 Value *AltCond = nullptr;
3076 auto matchOuterCond = [OuterSel, IsAndVariant, &AltCond](auto m_InnerCond) {
3077
3078
3079
3080
3081 return IsAndVariant ? match(OuterSel.Cond,
3085 };
3086
3087
3088
3089
3090
3091 if (matchOuterCond(m_Specific(InnerSel.Cond))) {
3092
3095
3096 std::swap(InnerSel.TrueVal, InnerSel.FalseVal);
3097 InnerSel.Cond = NotInnerCond;
3098 } else
3099 return nullptr;
3100
3102 AltCond, IsAndVariant ? OuterSel.TrueVal : InnerSel.FalseVal,
3103 IsAndVariant ? InnerSel.TrueVal : OuterSel.FalseVal);
3104 SelInner->takeName(InnerSelVal);
3106 IsAndVariant ? SelInner : InnerSel.TrueVal,
3107 !IsAndVariant ? SelInner : InnerSel.FalseVal);
3108}
3109
3110
3111
3112
3113static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V,
3116 return true;
3117
3118
3119
3120 if (auto *ICmp = dyn_cast(ValAssumedPoison)) {
3121 Value *LHS = ICmp->getOperand(0);
3122 const APInt *RHSC1;
3123 const APInt *RHSC2;
3125 if (ICmp->hasSameSign() &&
3136 *RHSC2);
3137 }
3138 }
3139
3140 return false;
3141}
3142
3144 Value *CondVal = SI.getCondition();
3147 Type *SelType = SI.getType();
3148
3149
3150
3151
3154 return nullptr;
3155
3159
3160
3161
3162
3164 if (impliesPoisonOrCond(FalseVal, CondVal, false)) {
3165
3166 return BinaryOperator::CreateOr(CondVal, FalseVal);
3167 }
3168
3170 impliesPoisonOrCond(FalseVal, B, false)) {
3171
3174 }
3175
3176
3180 bool CondLogicAnd = isa(CondVal);
3181 bool FalseLogicAnd = isa(FalseVal);
3182 auto AndFactorization = [&](Value *Common, Value *InnerCond,
3183 Value *InnerVal,
3184 bool SelFirst = false) -> Instruction * {
3186 if (SelFirst)
3188 if (FalseLogicAnd || (CondLogicAnd && Common == A))
3190 else
3191 return BinaryOperator::CreateAnd(Common, InnerSel);
3192 };
3193
3195 return AndFactorization(A, B, D);
3197 return AndFactorization(A, B, C);
3199 return AndFactorization(B, A, D);
3201 return AndFactorization(B, A, C, CondLogicAnd && FalseLogicAnd);
3202 }
3203 }
3204
3206 if (impliesPoisonOrCond(TrueVal, CondVal, true)) {
3207
3208 return BinaryOperator::CreateAnd(CondVal, TrueVal);
3209 }
3210
3212 impliesPoisonOrCond(TrueVal, B, true)) {
3213
3216 }
3217
3218
3222 bool CondLogicOr = isa(CondVal);
3223 bool TrueLogicOr = isa(TrueVal);
3224 auto OrFactorization = [&](Value *Common, Value *InnerCond,
3225 Value *InnerVal,
3226 bool SelFirst = false) -> Instruction * {
3228 if (SelFirst)
3230 if (TrueLogicOr || (CondLogicOr && Common == A))
3232 else
3233 return BinaryOperator::CreateOr(Common, InnerSel);
3234 };
3235
3237 return OrFactorization(A, B, D);
3239 return OrFactorization(A, B, C);
3241 return OrFactorization(B, A, D);
3243 return OrFactorization(B, A, C, CondLogicOr && TrueLogicOr);
3244 }
3245 }
3246
3247
3248
3249
3253 }
3254
3258 }
3259
3260
3261
3266
3267
3268
3273
3274
3278
3282
3283
3286 return BinaryOperator::CreateXor(A, B);
3287
3288
3289 if (match(CondVal,
3293 }
3294
3299 }
3300 }
3301
3306 }
3307 }
3308
3309 if (match(CondVal,
3313 }
3314
3320 auto *FI = new FreezeInst(*Y, (*Y)->getName() + ".fr");
3324 }
3325
3326 if (auto *V = foldBooleanAndOr(CondVal, Op1, SI, IsAnd,
3327 true))
3329 }
3330
3331
3332
3333
3337 if (Res && *Res == false)
3339 }
3343 if (Res && *Res == false)
3345 }
3346
3347
3348
3352 if (Res && *Res == true)
3354 }
3358 if (Res && *Res == true)
3360 }
3361
3364
3365
3366
3367
3368
3371 auto *SelCond = dyn_cast(CondVal);
3372 auto *SelFVal = dyn_cast(FalseVal);
3373 bool MayNeedFreeze = SelCond && SelFVal &&
3374 match(SelFVal->getTrueValue(),
3376 if (MayNeedFreeze)
3379 }
3380
3381
3382
3383
3384
3387 auto *SelCond = dyn_cast(CondVal);
3388 auto *SelFVal = dyn_cast(FalseVal);
3389 bool MayNeedFreeze = SelCond && SelFVal &&
3390 match(SelCond->getTrueValue(),
3392 if (MayNeedFreeze)
3395 }
3396 }
3397
3398 return nullptr;
3399}
3400
3401
3402
3406 bool &ShouldDropNUW) {
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3428
3429 ShouldDropNUW = false;
3430
3431
3432
3433
3434
3435 auto MatchForward = [&](Value *CommonAncestor) {
3436 const APInt *C = nullptr;
3437 if (CtlzOp == CommonAncestor)
3438 return true;
3441 return true;
3442 }
3444 ShouldDropNUW = true;
3446 return true;
3447 }
3450 return true;
3451 }
3452 return false;
3453 };
3454
3455 const APInt *C = nullptr;
3456 Value *CommonAncestor;
3457 if (MatchForward(Cond0)) {
3458
3461 if (!MatchForward(CommonAncestor))
3462 return false;
3463
3464 } else {
3465 return false;
3466 }
3467
3468
3469
3470
3471
3475}
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3499 Type *SelType = SI.getType();
3501
3505 const APInt *Cond1;
3506 Value *Cond0, *Ctlz, *CtlzOp;
3508 return nullptr;
3509
3513 }
3514
3515 bool ShouldDropNUW;
3516
3521 (Ctlz, m_IntrinsicIntrinsic::ctlz(m_Value(CtlzOp), m_Zero())) ||
3522 !isSafeToRemoveBitCeilSelect(Pred, Cond0, Cond1, CtlzOp, BitWidth,
3523 ShouldDropNUW))
3524 return nullptr;
3525
3526 if (ShouldDropNUW)
3527 cast(CtlzOp)->setHasNoUnsignedWrap(false);
3528
3529
3530
3531
3532
3533
3534
3535 cast(Ctlz)->dropPoisonGeneratingAnnotations();
3539 Builder.CreateAnd(Neg, ConstantInt::get(SelType, BitWidth - 1));
3542}
3543
3544
3545
3546
3547
3548
3549
3550
3552 Value *TV = SI.getTrueValue();
3553 Value *FV = SI.getFalseValue();
3554
3558 return nullptr;
3559
3561 return nullptr;
3562
3563
3564
3565
3566
3571 }
3573
3574 bool Replace = false;
3576
3577
3583 Replace = true;
3584
3585
3586
3592 Replace = true;
3593
3594
3596 const APInt *InnerTV, *InnerFV;
3602 FalseBranchSelectPredicate =
3605 }
3606
3607 if (!InnerTV->isOne()) {
3610 }
3611
3615 Replace = true;
3616 }
3617 }
3618
3619 Intrinsic::ID IID = IsSigned ? Intrinsic::scmp : Intrinsic::ucmp;
3620 if (Replace)
3623 return nullptr;
3624}
3625
3629
3632}
3633
3637 bool SelectIsNSZ) {
3641 FastMathFlags FMF = cast(TrueVal)->getFastMathFlags();
3642
3643
3646 }
3647
3648 return false;
3649}
3650
3651
3652
3654 unsigned Depth) {
3656 return false;
3657
3658
3659
3661 return true;
3662
3663 if (auto *I = dyn_cast(V)) {
3664 if (isa(I)) {
3666 return false;
3668 }
3670 return Op->getType()->isIntOrIntVectorTy() &&
3671 hasAffectedValue(Op, Affected, Depth + 1);
3672 });
3673 }
3674
3675 return false;
3676}
3677
3678
3679
3682
3683
3684 auto *SIFOp = dyn_cast(&SI);
3685 if (!SIFOp || !SIFOp->hasNoSignedZeros() || !SIFOp->hasNoNaNs())
3686 return nullptr;
3687
3688 auto TryFoldIntoAddConstant =
3691
3692
3694 return nullptr;
3695
3697 return nullptr;
3698
3700 Swapped ? X : Z, "", &SI);
3702
3705
3706
3711 cast(NewFAdd)->setFastMathFlags(NewFMF);
3712 cast(NewSelect)->setFastMathFlags(NewFMF);
3713
3714 return NewFAdd;
3715 };
3716
3717
3718
3719
3720
3725
3726
3727
3728
3731 return TryFoldIntoAddConstant(Pred, X, Z, FAdd, C, false);
3732
3735 return TryFoldIntoAddConstant(Pred, X, Z, FAdd, C, true);
3736
3737 return nullptr;
3738}
3739
3741 Value *CondVal = SI.getCondition();
3744 Type *SelType = SI.getType();
3745
3749
3750 if (Instruction *I = canonicalizeSelectToShuffle(SI))
3751 return I;
3752
3753 if (Instruction *I = canonicalizeScalarSelectOfVecs(SI, *this))
3754 return I;
3755
3756
3757
3758
3764 true))
3766
3769 true))
3771
3776 return &SI;
3777 }
3778
3780 return R;
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3793
3795 return new ZExtInst(CondVal, SelType);
3796
3797
3799 return new SExtInst(CondVal, SelType);
3800
3801
3804 return new ZExtInst(NotCond, SelType);
3805 }
3806
3807
3810 return new SExtInst(NotCond, SelType);
3811 }
3812 }
3813
3814 auto *SIFPOp = dyn_cast(&SI);
3815
3816 if (auto *FCmp = dyn_cast(CondVal)) {
3818 Value *Cmp0 = FCmp->getOperand(0), *Cmp1 = FCmp->getOperand(1);
3819
3820 if ((Cmp0 == TrueVal && Cmp1 == FalseVal) ||
3821 (Cmp0 == FalseVal && Cmp1 == TrueVal)) {
3822
3823
3824
3825
3826
3829
3831 FCmp->getName() + ".inv");
3835 }
3836 }
3837
3838 if (SIFPOp) {
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852 Value *MatchCmp0 = nullptr;
3853 Value *MatchCmp1 = nullptr;
3854
3855
3856
3863 }
3864
3865 if (Cmp0 == MatchCmp0 &&
3866 matchFMulByZeroIfResultEqZero(*this, Cmp0, Cmp1, MatchCmp1, MatchCmp0,
3867 SI, SIFPOp->hasNoSignedZeros()))
3869 }
3870 }
3871
3872 if (SIFPOp) {
3873
3874
3875 auto *FCmp = dyn_cast(CondVal);
3876
3877
3878
3879 if (SIFPOp->hasNoNaNs() && SIFPOp->hasNoSignedZeros()) {
3882 Value *BinIntr =
3884 if (auto *BinIntrInst = dyn_cast(BinIntr))
3885 BinIntrInst->setHasNoNaNs(FCmp->hasNoNaNs());
3887 }
3888
3890 Value *BinIntr =
3892 if (auto *BinIntrInst = dyn_cast(BinIntr))
3893 BinIntrInst->setHasNoNaNs(FCmp->hasNoNaNs());
3895 }
3896 }
3897 }
3898
3899
3900 if (Instruction *Fabs = foldSelectWithFCmpToFabs(SI, *this))
3901 return Fabs;
3902
3903
3904 if (CmpInst *CI = dyn_cast(CondVal))
3906 return NewSel;
3907
3908 if (ICmpInst *ICI = dyn_cast(CondVal))
3911
3913 return Add;
3915 return Add;
3917 return Or;
3919 return Mul;
3920
3921
3922 auto *TI = dyn_cast(TrueVal);
3923 auto *FI = dyn_cast(FalseVal);
3924 if (TI && FI && TI->getOpcode() == FI->getOpcode())
3926 return IV;
3927
3929 return I;
3930
3932 return I;
3933
3934
3935
3941 return nullptr;
3943 if (isa(CondVal->getType()) && !isa(Idx->getType()))
3944 return nullptr;
3948 if (Swap)
3954 };
3955 if (auto *TrueGep = dyn_cast(TrueVal))
3956 if (auto *NewGep = SelectGepWithBase(TrueGep, FalseVal, false))
3957 return NewGep;
3958 if (auto *FalseGep = dyn_cast(FalseVal))
3959 if (auto *NewGep = SelectGepWithBase(FalseGep, TrueVal, true))
3960 return NewGep;
3961
3962
3965 return FoldI;
3966
3970 auto SPF = SPR.Flavor;
3971 if (SPF) {
3972 Value *LHS2, *RHS2;
3975 RHS2, SI, SPF, RHS))
3976 return R;
3979 RHS2, SI, SPF, LHS))
3980 return R;
3981 }
3982
3984
3985
3986
3987
3988 bool IsCastNeeded = LHS->getType() != SelType;
3989 Value *CmpLHS = cast(CondVal)->getOperand(0);
3990 Value *CmpRHS = cast(CondVal)->getOperand(1);
3991 if (IsCastNeeded ||
3993 ((CmpLHS != LHS && CmpLHS != RHS) ||
3994 (CmpRHS != LHS && CmpRHS != RHS)))) {
3996
4000 else
4002 cast(SI.getCondition()));
4003
4005 if (!IsCastNeeded)
4007
4010 }
4011 }
4012 }
4013
4014
4015 if (auto *PN = dyn_cast(SI.getCondition()))
4017 return NV;
4018
4019 if (SelectInst *TrueSI = dyn_cast(TrueVal)) {
4020 if (TrueSI->getCondition()->getType() == CondVal->getType()) {
4021
4022
4023 if (Value *V = simplifyNestedSelectsUsingImpliedCond(
4024 *TrueSI, CondVal, true, DL))
4026
4027
4028
4029
4030
4031 if (TrueSI->getFalseValue() == FalseVal && TrueSI->hasOneUse()) {
4035 return &SI;
4036 }
4037 }
4038 }
4039 if (SelectInst *FalseSI = dyn_cast(FalseVal)) {
4040 if (FalseSI->getCondition()->getType() == CondVal->getType()) {
4041
4042
4043 if (Value *V = simplifyNestedSelectsUsingImpliedCond(
4044 *FalseSI, CondVal, false, DL))
4046
4047
4048 if (FalseSI->getTrueValue() == TrueVal && FalseSI->hasOneUse()) {
4052 return &SI;
4053 }
4054 }
4055 }
4056
4057
4058
4059
4060
4061
4062
4065 if (auto *TrueBOSI = dyn_cast(TrueBO->getOperand(0))) {
4066 if (TrueBOSI->getCondition() == CondVal) {
4067 replaceOperand(*TrueBO, 0, TrueBOSI->getTrueValue());
4069 return &SI;
4070 }
4071 }
4072 if (auto *TrueBOSI = dyn_cast(TrueBO->getOperand(1))) {
4073 if (TrueBOSI->getCondition() == CondVal) {
4074 replaceOperand(*TrueBO, 1, TrueBOSI->getTrueValue());
4076 return &SI;
4077 }
4078 }
4079 }
4080
4081
4084 if (auto *FalseBOSI = dyn_cast(FalseBO->getOperand(0))) {
4085 if (FalseBOSI->getCondition() == CondVal) {
4086 replaceOperand(*FalseBO, 0, FalseBOSI->getFalseValue());
4088 return &SI;
4089 }
4090 }
4091 if (auto *FalseBOSI = dyn_cast(FalseBO->getOperand(1))) {
4092 if (FalseBOSI->getCondition() == CondVal) {
4093 replaceOperand(*FalseBO, 1, FalseBOSI->getFalseValue());
4095 return &SI;
4096 }
4097 }
4098 }
4099
4104 SI.swapValues();
4105 SI.swapProfMetadata();
4106 return &SI;
4107 }
4108
4110 return I;
4111
4112
4113
4114
4115
4116
4120 if (Known.One.isOne())
4122 if (Known.Zero.isOne())
4124 }
4125
4127 return BitCastSel;
4128
4129
4130 if (Value *V = foldSelectCmpXchg(SI))
4132
4135
4137 return Funnel;
4138
4140 return Copysign;
4141
4144
4145 if (Value *Fr = foldSelectWithFrozenICmp(SI, Builder))
4147
4148 if (Value *V = foldRoundUpIntegerWithPow2Alignment(SI, Builder))
4150
4151 if (Value *V = foldSelectIntoAddConstant(SI, Builder))
4153
4154
4155
4161 auto *MaskedInst = cast(TrueVal);
4162 if (isa(MaskedInst->getArgOperand(3)))
4163 MaskedInst->setArgOperand(3, FalseVal );
4165 }
4166
4173 (CondVal->getType() == Mask->getType())) {
4174
4175
4176
4177
4178 bool CanMergeSelectIntoLoad = false;
4180 CanMergeSelectIntoLoad = match(V, m_Zero());
4181
4182 if (CanMergeSelectIntoLoad) {
4183 auto *MaskedInst = cast(FalseVal);
4184 if (isa(MaskedInst->getArgOperand(3)))
4185 MaskedInst->setArgOperand(3, TrueVal );
4187 }
4188 }
4189
4191 return I;
4192
4194 return I;
4195
4196
4197
4198
4199
4201 return &SI;
4202
4204 return I;
4205
4207 return I;
4208
4210 return I;
4211
4212
4213
4214
4215
4216
4217 auto FoldSelectWithAndOrCond = [&](bool IsAnd, Value *A,
4221 return SelectInst::Create(A, IsAnd ? V : TrueVal, IsAnd ? FalseVal : V);
4222
4223
4225 if (ICmpInst *Cmp = dyn_cast(B))
4226 if (Value *V = canonicalizeSPF(*Cmp, TrueVal, FalseVal, *this))
4228 IsAnd ? FalseVal : V);
4229 }
4230
4231 return nullptr;
4232 };
4233
4236 if (Instruction *I = FoldSelectWithAndOrCond( true, LHS, RHS))
4237 return I;
4238 if (Instruction *I = FoldSelectWithAndOrCond( true, RHS, LHS))
4239 return I;
4241 if (Instruction *I = FoldSelectWithAndOrCond( false, LHS, RHS))
4242 return I;
4243 if (Instruction *I = FoldSelectWithAndOrCond( false, RHS, LHS))
4244 return I;
4245 } else {
4246
4247
4249 if (Instruction *I = FoldSelectWithAndOrCond( true, LHS, RHS))
4250 return I;
4252 if (Instruction *I = FoldSelectWithAndOrCond( false, LHS, RHS))
4253 return I;
4254 }
4255 }
4256
4257
4259 return BinaryOperator::CreateXor(CondVal, FalseVal);
4260
4261
4262
4264 (!isa(TrueVal) || !isa(FalseVal))) {
4265
4268 CC.AffectedValues.insert(V);
4269 });
4271 if (.AffectedValues.empty()) {
4272 if (!isa(TrueVal) &&
4273 hasAffectedValue(TrueVal, CC.AffectedValues, 0)) {
4277 ConstantInt::get(SelType, Known.getConstant()));
4278 }
4279
4280 CC.Invert = true;
4281 if (!isa(FalseVal) &&
4282 hasAffectedValue(FalseVal, CC.AffectedValues, 0)) {
4286 ConstantInt::get(SelType, Known.getConstant()));
4287 }
4288 }
4289 }
4290
4291
4292
4293
4294
4297 if (TrueVal == Trunc)
4299 if (FalseVal == Trunc)
4301 }
4303 if (TrueVal == Trunc)
4306 if (FalseVal == Trunc)
4308 }
4309
4310 return nullptr;
4311}
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
This file provides internal interfaces used to implement the InstCombine.
static Value * canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)
static Instruction * foldSetClearBits(SelectInst &Sel, InstCombiner::BuilderTy &Builder)
Canonicalize a set or clear of a masked set of constant bits to select-of-constants form.
static Instruction * foldSelectICmpAndAnd(Type *SelType, const ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)
We want to turn: (select (icmp eq (and X, Y), 0), (and (lshr X, Z), 1), 1) into: zext (icmp ne i32 (a...
static unsigned getSelectFoldableOperands(BinaryOperator *I)
We want to turn code that looks like this: C = or A, B D = select cond, C, A into: C = select cond,...
static Instruction * foldSelectZeroOrMul(SelectInst &SI, InstCombinerImpl &IC)
static Value * canonicalizeSaturatedSubtract(const ICmpInst *ICI, const Value *TrueVal, const Value *FalseVal, InstCombiner::BuilderTy &Builder)
Transform patterns such as (a > b) ? a - b : 0 into usub.sat(a, b).
static Value * foldAbsDiff(ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)
Try to match patterns with select and subtract as absolute difference.
static Instruction * foldSelectBinOpIdentity(SelectInst &Sel, const TargetLibraryInfo &TLI, InstCombinerImpl &IC)
Replace a select operand based on an equality comparison with the identity constant of a binop.
static Value * foldSelectICmpAndZeroShl(const ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder)
We want to turn: (select (icmp eq (and X, C1), 0), 0, (shl [nsw/nuw] X, C2)); iff C1 is a mask and th...
static Value * foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal, Value *FalseVal, InstCombiner::BuilderTy &Builder)
We want to turn: (select (icmp eq (and X, C1), 0), Y, (BinOp Y, C2)) into: IF C2 u>= C1 (BinOp Y,...
static Value * foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal, Value *FalseVal, InstCombiner::BuilderTy &Builder)
We want to turn: (select (icmp sgt x, C), lshr (X, Y), ashr (X, Y)); iff C s>= -1 (select (icmp slt x...
static bool isSelect01(const APInt &C1I, const APInt &C2I)
static Value * foldSelectICmpAnd(SelectInst &Sel, ICmpInst *Cmp, InstCombiner::BuilderTy &Builder)
This folds: select (icmp eq (and X, C1)), TC, FC iff C1 is a power 2 and the difference between TC an...
This file provides the interface for the instcombine pass implementation.
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static const uint32_t IV[8]
bool bitwiseIsEqual(const APFloat &RHS) const
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
bool isMinSignedValue() const
Determine if this is the smallest signed value.
uint64_t getZExtValue() const
Get zero extended value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isMinValue() const
Determine if this is the smallest unsigned value.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned countLeadingZeros() const
unsigned logBase2() const
bool isMask(unsigned numBits) const
bool isMaxSignedValue() const
Determine if this is the largest signed value.
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
bool isMaxValue() const
Determine if this is the largest unsigned value.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< ResultElem > assumptions()
Access the list of assumption handles currently tracked for this function.
An instruction that atomically checks whether a specified value is in a memory location,...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
BinaryOps getOpcode() const
static BinaryOperator * CreateNot(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
This class represents a no-op cast from one type to another.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
bool isFPPredicate() const
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Predicate getPredicate() const
Return the predicate for this instruction.
static bool isUnordered(Predicate predicate)
Determine if the predicate is an unordered operation.
Predicate getFlippedStrictnessPredicate() const
For predicate of kind "is X or equal to 0" returns the predicate "is X".
bool isIntPredicate() const
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)
Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...
static Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
static Constant * getNeg(Constant *C, bool HasNSW=false)
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
This class represents a range of values.
ConstantRange add(const ConstantRange &Other) const
Return a new range representing the possible values resulting from an addition of a value in this ran...
bool icmp(CmpInst::Predicate Pred, const ConstantRange &Other) const
Does the predicate Pred hold between ranges this and Other? NOTE: false does not mean that inverse pr...
static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other)
Produce the exact range such that all values in the returned range satisfy the given predicate with a...
ConstantRange binaryNot() const
Return a new range representing the possible values resulting from a binary-xor of a value in this ra...
ConstantRange binaryOp(Instruction::BinaryOps BinOp, const ConstantRange &Other) const
Return a new range representing the possible values resulting from an application of the specified bi...
ConstantRange sub(const ConstantRange &Other) const
Return a new range representing the possible values resulting from a subtraction of a value in this r...
This is an important base class in LLVM.
static Constant * mergeUndefsWith(Constant *C, Constant *Other)
Merges undefs of a Constant with another Constant, along with the undefs already present.
static Constant * getAllOnesValue(Type *Ty)
bool isOneValue() const
Returns true if the value is one.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Tagged union holding either a T or a Error.
Utility class for floating point operations which can have information about relaxed accuracy require...
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
Convenience struct for specifying and reasoning about fast-math flags.
static FastMathFlags intersectRewrite(FastMathFlags LHS, FastMathFlags RHS)
Intersect rewrite-based flags.
bool noSignedZeros() const
static FastMathFlags unionValue(FastMathFlags LHS, FastMathFlags RHS)
Union value flags.
void setNoSignedZeros(bool B=true)
This class represents a freeze function that returns random concrete value if an operand is either a ...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * getPointerOperand()
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Type * getSourceElementType() const
GEPNoWrapFlags getNoWrapFlags() const
Get the nowrap flags for the GEP instruction.
uint64_t getType(const MachineInstr &MI) const
This instruction compares its operands according to the predicate given to the constructor.
CmpPredicate getSwappedCmpPredicate() const
static bool isLT(Predicate P)
Return true if the predicate is SLT or ULT.
CmpPredicate getInverseCmpPredicate() const
static bool isGT(Predicate P)
Return true if the predicate is SGT or UGT.
bool isEquality() const
Return true if this predicate is either EQ or NE.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
Common base class shared among various IRBuilders.
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateSelectFMF(Value *C, Value *True, Value *False, FMFSource FMFSource, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
ConstantInt * getTrue()
Get the constant value for i1 true.
Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateFreeze(Value *V, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Value * CreateFCmpFMF(CmpInst::Predicate P, Value *LHS, Value *RHS, FMFSource FMFSource, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 2 operands which is mangled on the first type.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateIsNeg(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg < 0.
CallInst * CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 1 operand which is mangled on its type.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateLogicalAnd(Value *Cond1, Value *Cond2, const Twine &Name="")
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateLogicalOr(Value *Cond1, Value *Cond2, const Twine &Name="")
Value * CreateFNeg(Value *V, const Twine &Name="", MDNode *FPMathTag=nullptr)
Instruction * foldSelectToCmp(SelectInst &SI)
bool fmulByZeroIsZero(Value *MulVal, FastMathFlags FMF, const Instruction *CtxI) const
Check if fmul MulVal, +0.0 will yield +0.0 (or signed zero is ignorable).
KnownFPClass computeKnownFPClass(Value *Val, FastMathFlags FMF, FPClassTest Interested=fcAllFlags, const Instruction *CtxI=nullptr, unsigned Depth=0) const
Instruction * foldSelectEqualityTest(SelectInst &SI)
Instruction * foldSelectValueEquivalence(SelectInst &SI, CmpInst &CI)
Instruction * foldOpIntoPhi(Instruction &I, PHINode *PN, bool AllowMultipleUses=false)
Given a binary operator, cast instruction, or select which has a PHI node as operand #0,...
Instruction * foldVectorSelect(SelectInst &Sel)
Value * SimplifyDemandedVectorElts(Value *V, APInt DemandedElts, APInt &PoisonElts, unsigned Depth=0, bool AllowMultipleUsers=false) override
The specified value produces a vector with any number of elements.
Instruction * foldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1, Value *A, Value *B, Instruction &Outer, SelectPatternFlavor SPF2, Value *C)
Instruction * foldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI)
We have (select c, TI, FI), and we know that TI and FI have the same opcode.
bool replaceInInstruction(Value *V, Value *Old, Value *New, unsigned Depth=0)
Instruction * foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI)
bool sinkNotIntoOtherHandOfLogicalOp(Instruction &I)
Constant * getLosslessTrunc(Constant *C, Type *TruncTy, unsigned ExtOp)
Instruction * foldSelectIntoOp(SelectInst &SI, Value *, Value *)
Try to fold the select into one of the operands to allow further optimization.
Instruction * visitSelectInst(SelectInst &SI)
Instruction * foldSelectOfBools(SelectInst &SI)
Instruction * foldSelectExtConst(SelectInst &Sel)
The core instruction combiner logic.
const DataLayout & getDataLayout() const
bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero=false, unsigned Depth=0, const Instruction *CxtI=nullptr)
Instruction * InsertNewInstBefore(Instruction *New, BasicBlock::iterator Old)
Inserts an instruction New before instruction Old.
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
static bool shouldAvoidAbsorbingNotIntoSelect(const SelectInst &SI)
void replaceUse(Use &U, Value *NewValue)
Replace use and add the previously used value to the worklist.
static bool isCanonicalPredicate(CmpPredicate Pred)
Predicate canonicalization reduces the number of patterns that need to be matched by other transforms...
InstructionWorklist & Worklist
A worklist of the instructions that need to be simplified.
void addToWorklist(Instruction *I)
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth, const Instruction *CxtI) const
Value * getFreelyInverted(Value *V, bool WillInvertAllUses, BuilderTy *Builder, bool &DoesConsume)
const SimplifyQuery & getSimplifyQuery() const
static Constant * AddOne(Constant *C)
Add one to a Constant.
void add(Instruction *I)
Add instruction to the worklist.
void push(Instruction *I)
Push the instruction onto the worklist stack.
bool hasNoNaNs() const LLVM_READONLY
Determine whether the no-NaNs flag is set.
bool hasNoInfs() const LLVM_READONLY
Determine whether the no-infs flag is set.
bool isSameOperationAs(const Instruction *I, unsigned flags=0) const LLVM_READONLY
This function determines if the specified instruction executes the same operation as the current one.
void setHasNoSignedZeros(bool B)
Set or clear the no-signed-zeros flag on this instruction, which must be an operator which supports t...
bool hasNoSignedZeros() const LLVM_READONLY
Determine whether the no-signed-zeros flag is set.
void copyIRFlags(const Value *V, bool IncludeWrapFlags=true)
Convenience method to copy supported exact, fast-math, and (optionally) wrapping flags from V to this...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
void setHasNoNaNs(bool B)
Set or clear the no-nans flag on this instruction, which must be an operator which supports this flag...
bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
void setFastMathFlags(FastMathFlags FMF)
Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...
void swapProfMetadata()
If the instruction has "branch_weights" MD_prof metadata and the MDNode has three operands (including...
void setHasNoInfs(bool B)
Set or clear the no-infs flag on this instruction, which must be an operator which supports this flag...
FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void dropPoisonGeneratingFlags()
Drops flags that may cause this instruction to evaluate to poison despite having non-poison inputs.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
A wrapper class for inspecting calls to intrinsic functions.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
This class represents a sign extension of integer types.
This class represents the LLVM 'select' instruction.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)
const Value * getFalseValue() const
void swapValues()
Swap the true and false values of the select instruction.
const Value * getCondition() const
const Value * getTrueValue() const
bool insert(const value_type &X)
Insert a new element into the SetVector.
This instruction constructs a fixed permutation of two input vectors.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool contains(ConstPtrType Ptr) const
A SetVector that performs no allocations if smaller than a certain size.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
static IntegerType * getInt1Ty(LLVMContext &C)
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
static UnaryOperator * CreateFNegFMF(Value *Op, Instruction *FMFSource, const Twine &Name="", InsertPosition InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
const Value * DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) const
Translate PHI node to its predecessor from the given basic block.
bool hasOneUse() const
Return true if there is exactly one use of this value.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
Represents an op.with.overflow intrinsic.
This class represents zero extension of integer types.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
int getMinValue(MCInstrInfo const &MCII, MCInst const &MCI)
Return the minimum value of an extendable operand.
int getMaxValue(MCInstrInfo const &MCII, MCInst const &MCI)
Return the maximum value of an extendable operand.
Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< cst_pred_ty< is_all_ones, false >, ValTy, Instruction::Xor, true > m_NotForbidPoison(const ValTy &V)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
CmpClass_match< LHS, RHS, FCmpInst > m_FCmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FMul, true > m_c_FMul(const LHS &L, const RHS &R)
Matches FMul with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
cst_pred_ty< is_power2 > m_Power2()
Match an integer or vector power-of-2.
match_combine_or< CastInst_match< OpTy, TruncInst >, OpTy > m_TruncOrSelf(const OpTy &Op)
class_match< Constant > m_Constant()
Match an arbitrary Constant and ignore it.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()
Match a floating-point negative zero or positive zero.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
constantexpr_match m_ConstantExpr()
Match a constant expression or a constant that contains a constant expression.
specific_intval< true > m_SpecificIntAllowPoison(const APInt &V)
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
OverflowingBinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWNeg(const ValTy &V)
Matches a 'Neg' as 'sub nsw 0, V'.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
match_combine_or< MaxMin_match< FCmpInst, LHS, RHS, ofmin_pred_ty >, MaxMin_match< FCmpInst, LHS, RHS, ufmin_pred_ty > > m_OrdOrUnordFMin(const LHS &L, const RHS &R)
Match an 'ordered' or 'unordered' floating point minimum function.
BinOpPred_match< LHS, RHS, is_logical_shift_op > m_LogicalShift(const LHS &L, const RHS &R)
Matches logical shift operations.
match_combine_and< LTy, RTy > m_CombineAnd(const LTy &L, const RTy &R)
Combine two pattern matchers matching L && R.
MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > m_SMin(const LHS &L, const RHS &R)
cst_pred_ty< is_any_apint > m_AnyIntegralConstant()
Match an integer or vector with any integral constant.
bind_ty< WithOverflowInst > m_WithOverflowInst(WithOverflowInst *&I)
Match a with overflow intrinsic, capturing it if we match.
BinaryOp_match< LHS, RHS, Instruction::FAdd > m_FAdd(const LHS &L, const RHS &R)
deferredval_ty< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
cst_pred_ty< is_zero_int > m_ZeroInt()
Match an integer 0 or a vector with all elements equal to 0.
apint_match m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
NoWrapTrunc_match< OpTy, TruncInst::NoSignedWrap > m_NSWTrunc(const OpTy &Op)
Matches trunc nsw.
OneUse_match< T > m_OneUse(const T &SubPattern)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)
Matches a 'Neg' as 'sub 0, V'.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
match_combine_and< class_match< Constant >, match_unless< constantexpr_match > > m_ImmConstant()
Match an arbitrary immediate Constant and ignore it.
m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2, Opnd3 >::Ty m_MaskedLoad(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2, const Opnd3 &Op3)
Matches MaskedLoad Intrinsic.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
apint_match m_APIntForbidPoison(const APInt *&Res)
Match APInt while forbidding poison in splat vector constants.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty > m_UMax(const LHS &L, const RHS &R)
class_match< CmpInst > m_Cmp()
Matches any compare instruction and ignore it.
brc_match< Cond_t, bind_ty< BasicBlock >, bind_ty< BasicBlock > > m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F)
auto m_c_LogicalOp(const LHS &L, const RHS &R)
Matches either L && R or L || R with LHS and RHS in either order.
NoWrapTrunc_match< OpTy, TruncInst::NoUnsignedWrap > m_NUWTrunc(const OpTy &Op)
Matches trunc nuw.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
apfloat_match m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
match_combine_or< MaxMin_match< FCmpInst, LHS, RHS, ofmax_pred_ty >, MaxMin_match< FCmpInst, LHS, RHS, ufmax_pred_ty > > m_OrdOrUnordFMax(const LHS &L, const RHS &R)
Match an 'ordered' or 'unordered' floating point maximum function.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)
apint_match m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
cstfp_pred_ty< is_pos_zero_fp > m_PosZeroFP()
Match a floating-point positive zero.
LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
m_Intrinsic_Ty< Opnd0 >::Ty m_VecReverse(const Opnd0 &Op0)
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
match_combine_or< match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty >, MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > >, match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty >, MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > > > m_MaxOrMin(const LHS &L, const RHS &R)
class_match< BasicBlock > m_BasicBlock()
Match an arbitrary basic block value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::SRem > m_SRem(const LHS &L, const RHS &R)
auto m_Undef()
Match an arbitrary undef constant.
BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinaryOp_match< LHS, RHS, Instruction::Or, true > m_c_Or(const LHS &L, const RHS &R)
Matches an Or with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::Or, true > m_c_LogicalOr(const LHS &L, const RHS &R)
Matches L || R with LHS and RHS in either order.
SpecificCmpClass_match< LHS, RHS, ICmpInst, true > m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
ElementWiseBitCast_match< OpTy > m_ElementWiseBitCast(const OpTy &Op)
BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)
Matches a Mul with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > m_UMin(const LHS &L, const RHS &R)
m_Intrinsic_Ty< Opnd0, Opnd1, Opnd2, Opnd3 >::Ty m_MaskedGather(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2, const Opnd3 &Op3)
Matches MaskedGather Intrinsic.
match_combine_or< LTy, RTy > m_CombineOr(const LTy &L, const RTy &R)
Combine two pattern matchers matching L || R.
cst_pred_ty< icmp_pred_with_threshold > m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold)
Match an integer or vector with every element comparing 'pred' (eg/ne/...) to Threshold.
ElementType
The element type of an SRV or UAV resource.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
bool isSafeToSpeculativelyExecuteWithVariableReplaced(const Instruction *I)
Don't use information from its non-constant operands.
bool isSignBitCheck(ICmpInst::Predicate Pred, const APInt &RHS, bool &TrueIfSigned)
Given an exploded icmp instruction, return true if the comparison only checks the sign bit.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)
Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.
CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF, bool Ordered=false)
Return the canonical comparison predicate for the specified minimum/maximum flavor.
bool isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be undef, but may be poison.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isSplatValue(const Value *V, int Index=-1, unsigned Depth=0)
Return true if each element of the vector value V is poisoned or equal to every other non-poisoned el...
constexpr unsigned MaxAnalysisRecursionDepth
SelectPatternFlavor
Specific patterns of select instructions we can match.
@ SPF_ABS
Floating point maxnum.
@ SPF_NABS
Absolute value.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool impliesPoison(const Value *ValAssumedPoison, const Value *V)
Return true if V is poison given that ValAssumedPoison is already poison.
SelectPatternResult getSelectPattern(CmpInst::Predicate Pred, SelectPatternNaNBehavior NaNBehavior=SPNB_NA, bool Ordered=false)
Determine the pattern for predicate X Pred Y ? X : Y.
SelectPatternResult matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, Instruction::CastOps *CastOp=nullptr, unsigned Depth=0)
Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind and providing the out param...
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Constant * ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL)
Attempt to constant fold a cast with the specified operand.
Value * simplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for an And, fold the result or return null.
bool isKnownInversion(const Value *X, const Value *Y)
Return true iff:
bool isNotCrossLaneOperation(const Instruction *I)
Return true if the instruction doesn't potentially cross vector lanes.
Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)
Attempt to constant fold a binary operation with the specified operands.
constexpr int PoisonMaskElem
Intrinsic::ID getMinMaxIntrinsic(SelectPatternFlavor SPF)
Convert given SPF to equivalent min/max intrinsic.
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
DWARFExpression::Operation Op
constexpr unsigned BitWidth
SelectPatternResult matchDecomposedSelectPattern(CmpInst *CmpI, Value *TrueVal, Value *FalseVal, Value *&LHS, Value *&RHS, Instruction::CastOps *CastOp=nullptr, unsigned Depth=0)
Determine the pattern that a select with the given compare as its predicate and given values as its t...
Value * simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, const SimplifyQuery &Q, bool AllowRefinement, SmallVectorImpl< Instruction * > *DropFlags=nullptr)
See if V simplifies when its operand Op is replaced with RepOp.
auto predecessors(const MachineBasicBlock *BB)
std::optional< std::pair< CmpPredicate, Constant * > > getFlippedStrictnessPredicateAndConstant(CmpPredicate Pred, Constant *C)
Convert an integer comparison with a constant RHS into an equivalent form with the strictness flipped...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool cannotBeNegativeZero(const Value *V, unsigned Depth, const SimplifyQuery &SQ)
Return true if we can prove that the specified FP value is never equal to -0.0.
bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ)
Return true if the floating-point scalar value is not a NaN or if the floating-point vector value has...
bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
bool isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd, Use *&Y)
Match one of the patterns up to the select/logic op: Op0 = icmp ne i4 X, 0 Agg = call { i4,...
Value * simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, const SimplifyQuery &Q)
Given operands for a SelectInst, fold the result or return null.
std::optional< bool > isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL, bool LHSIsTrue=true, unsigned Depth=0)
Return true if RHS is known to be implied true by LHS.
void findValuesAffectedByCondition(Value *Cond, bool IsAssume, function_ref< void(Value *)> InsertAffected)
Call InsertAffected on all Values whose known bits / value may be affected by the condition Cond.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Evaluate query assuming this condition holds.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
bool isConstant() const
Returns true if we know the value of all bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
bool isKnownNeverInfinity() const
Return true if it's known this can never be an infinity.
bool isKnownNeverNaN() const
Return true if it's known this can never be a nan.
bool signBitIsZeroOrNaN() const
Return true if the sign bit must be 0, ignoring the sign of nans.
SelectPatternFlavor Flavor
bool Ordered
Only applicable if Flavor is SPF_FMINNUM or SPF_FMAXNUM.
static bool isMinOrMax(SelectPatternFlavor SPF)
When implementing this min/max pattern as fcmp; select, does the fcmp have to be ordered?
SimplifyQuery getWithCondContext(const CondContext &CC) const
SimplifyQuery getWithInstruction(const Instruction *I) const