LLVM: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
25
26using namespace llvm;
28
29#define DEBUG_TYPE "instcombine"
30
31namespace llvm {
33}
34
35
36
37
38
43 return TorF;
44 return Builder.CreateICmp(NewPred, LHS, RHS);
45}
46
47
48
53 return TorF;
54 return Builder.CreateFCmpFMF(NewPred, LHS, RHS, FMF);
55}
56
57
58
59
62 bool Inside) {
64 "Lo is not < Hi in range emission code!");
65
66 Type *Ty = V->getType();
67
68
69
71 if (isSigned ? Lo.isMinSignedValue() : Lo.isMinValue()) {
73 return Builder.CreateICmp(Pred, V, ConstantInt::get(Ty, Hi));
74 }
75
76
77
79 Builder.CreateSub(V, ConstantInt::get(Ty, Lo), V->getName() + ".off");
80 Constant *HiMinusLo = ConstantInt::get(Ty, Hi - Lo);
81 return Builder.CreateICmp(Pred, VMinusLo, HiMinusLo);
82}
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
123
124
125
128 const APInt *ConstA = nullptr, *ConstB = nullptr, *ConstC = nullptr;
133 bool IsAPow2 = ConstA && ConstA->isPowerOf2();
134 bool IsBPow2 = ConstB && ConstB->isPowerOf2();
135 unsigned MaskVal = 0;
136 if (ConstC && ConstC->isZero()) {
137
140 if (IsAPow2)
143 if (IsBPow2)
146 return MaskVal;
147 }
148
152 if (IsAPow2)
155 } else if (ConstA && ConstC && ConstC->isSubsetOf(*ConstA)) {
157 }
158
162 if (IsBPow2)
165 } else if (ConstB && ConstC && ConstC->isSubsetOf(*ConstB)) {
167 }
168
169 return MaskVal;
170}
171
172
173
174
175
177 unsigned NewMask;
180 << 1;
181
184 >> 1;
185
186 return NewMask;
187}
188
189
193 true);
194 if (!Res)
195 return false;
196
197 Pred = Res->Pred;
198 X = Res->X;
199 Y = ConstantInt::get(X->getType(), Res->Mask);
200 Z = ConstantInt::get(X->getType(), Res->C);
201 return true;
202}
203
204
205
206
207
208
209static std::optional<std::pair<unsigned, unsigned>>
213
214
215
216
217
218
219
220
221
222 Value *L1, *L11, *L12, *L2, *L21, *L22;
224 L21 = L22 = L1 = nullptr;
225 } else {
227 if (!LHSCMP)
228 return std::nullopt;
229
230
231 if (!LHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())
232 return std::nullopt;
233
234 PredL = LHSCMP->getPredicate();
235 L1 = LHSCMP->getOperand(0);
236 L2 = LHSCMP->getOperand(1);
237
239
240
241 L11 = L1;
243 }
244
246 L21 = L2;
248 }
249 }
250
251
253 return std::nullopt;
254
257 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
258 A = R11;
259 D = R12;
260 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
261 A = R12;
262 D = R11;
263 } else {
264 return std::nullopt;
265 }
267 } else {
269 if (!RHSCMP)
270 return std::nullopt;
271
272 if (!RHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())
273 return std::nullopt;
274
275 PredR = RHSCMP->getPredicate();
276
277 Value *R1 = RHSCMP->getOperand(0);
278 R2 = RHSCMP->getOperand(1);
279 bool Ok = false;
281
282
283 R11 = R1;
285 }
286
287 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
288 A = R11;
289 D = R12;
291 Ok = true;
292 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
293 A = R12;
294 D = R11;
296 Ok = true;
297 }
298
299
301 Ok = false;
302
303
304 if (!Ok) {
306 R11 = R2;
308 }
309
310 if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
311 A = R11;
312 D = R12;
313 E = R1;
314 } else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
315 A = R12;
316 D = R11;
317 E = R1;
318 } else {
319 return std::nullopt;
320 }
321 }
322 }
323
324
326 return std::nullopt;
327
328 if (L11 == A) {
329 B = L12;
330 C = L2;
331 } else if (L12 == A) {
332 B = L11;
333 C = L2;
334 } else if (L21 == A) {
335 B = L22;
336 C = L1;
337 } else if (L22 == A) {
338 B = L21;
339 C = L1;
340 }
341
344 return std::optional<std::pair<unsigned, unsigned>>(
345 std::make_pair(LeftType, RightType));
346}
347
348
349
350
351
352
357
358
359
360
361
362
363
364
365
366
367 const APInt *BCst, *DCst, *OrigECst;
370 return nullptr;
371
373
374
375
376
377
378 APInt ECst = *OrigECst;
379 if (PredR != NewCC)
380 ECst ^= *DCst;
381
382
383
384 if (*BCst == 0 || *DCst == 0)
385 return nullptr;
386
387
388
389
390
394 !Builder.GetInsertBlock()->getParent()->hasFnAttribute(
395 Attribute::StrictFP)) {
397 if (!Ty->isIEEELikeFPTy())
398 return nullptr;
399
401 if (ECst != ExpBits)
402 return nullptr;
403 APInt FractionBits = ~ExpBits;
405 if (*BCst != FractionBits)
406 return nullptr;
407
410 }
411 return nullptr;
412 }
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 if ((((*BCst & *DCst) & ECst) == 0) &&
431 (*BCst & (*BCst ^ *DCst)).isPowerOf2()) {
432 APInt BorD = *BCst | *DCst;
433 APInt BandBxorDorE = (*BCst & (*BCst ^ *DCst)) | ECst;
434 Value *NewMask = ConstantInt::get(A->getType(), BorD);
435 Value *NewMaskedValue = ConstantInt::get(A->getType(), BandBxorDorE);
436 Value *NewAnd = Builder.CreateAnd(A, NewMask);
437 return Builder.CreateICmp(NewCC, NewAnd, NewMaskedValue);
438 }
439
440 auto IsSubSetOrEqual = [](const APInt *C1, const APInt *C2) {
441 return (*C1 & *C2) == *C1;
442 };
443 auto IsSuperSetOrEqual = [](const APInt *C1, const APInt *C2) {
444 return (*C1 & *C2) == *C2;
445 };
446
447
448
449
450
451
452
453 if (!IsSubSetOrEqual(BCst, DCst) && !IsSuperSetOrEqual(BCst, DCst))
454 return nullptr;
455
456
457
458
459
460
461
462
463
465 if (IsSubSetOrEqual(BCst, DCst))
466 return ConstantInt::get(LHS->getType(), !IsAnd);
467 return nullptr;
468 }
469
470
471
472
473
474
475
476 if (IsSuperSetOrEqual(BCst, DCst)) {
477
479 ICmp->setSameSign(false);
480 return RHS;
481 }
482
483
484
485 assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");
486 if ((*BCst & ECst) != 0) {
487
489 ICmp->setSameSign(false);
490 return RHS;
491 }
492
493
494
495
496 return ConstantInt::get(LHS->getType(), !IsAnd);
497}
498
499
500
501
502
508 "Expected equality predicates for masked type of icmps.");
509
510
511
512
513
514 if (!IsAnd) {
517 }
520 LHS, RHS, IsAnd, A, B, D, E, PredL, PredR, Builder)) {
521 return V;
522 }
525 RHS, LHS, IsAnd, A, D, B, C, PredR, PredL, Builder)) {
526 return V;
527 }
528 }
529 return nullptr;
530}
531
532
533
535 bool IsLogical,
538 Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;
540 std::optional<std::pair<unsigned, unsigned>> MaskPair =
542 if (!MaskPair)
543 return nullptr;
545 "Expected equality predicates for masked type of icmps.");
546 unsigned LHSMask = MaskPair->first;
547 unsigned RHSMask = MaskPair->second;
548 unsigned Mask = LHSMask & RHSMask;
549 if (Mask == 0) {
550
551
553 LHS, RHS, IsAnd, A, B, C, D, E, PredL, PredR, LHSMask, RHSMask,
554 Builder))
555 return V;
556 return nullptr;
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
572 if (!IsAnd) {
573
574
576 }
577
579
580
582 return nullptr;
583 Value *NewOr = Builder.CreateOr(B, D);
584 Value *NewAnd = Builder.CreateAnd(A, NewOr);
585
586
587
589 return Builder.CreateICmp(NewCC, NewAnd, Zero);
590 }
592
593
595 return nullptr;
596 Value *NewOr = Builder.CreateOr(B, D);
597 Value *NewAnd = Builder.CreateAnd(A, NewOr);
598 return Builder.CreateICmp(NewCC, NewAnd, NewOr);
599 }
601
602
604 return nullptr;
605 Value *NewAnd1 = Builder.CreateAnd(B, D);
606 Value *NewAnd2 = Builder.CreateAnd(A, NewAnd1);
607 return Builder.CreateICmp(NewCC, NewAnd2, A);
608 }
609
610 const APInt *ConstB, *ConstD;
613
614
615
616
617
618 APInt NewMask = *ConstB & *ConstD;
619 if (NewMask == *ConstB)
620 return LHS;
621 if (NewMask == *ConstD) {
622 if (IsLogical) {
624 RHSI->dropPoisonGeneratingFlags();
625 }
626 return RHS;
627 }
628 }
629
631
632
633
634
635 APInt NewMask = *ConstB | *ConstD;
636 if (NewMask == *ConstB)
637 return LHS;
638 if (NewMask == *ConstD)
639 return RHS;
640 }
641
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665 const APInt *OldConstC, *OldConstE;
667 return nullptr;
668
671 const APInt ConstC = PredL != CC ? *ConstB ^ *OldConstC : *OldConstC;
672 const APInt ConstE = PredR != CC ? *ConstD ^ *OldConstE : *OldConstE;
673
674 if (((*ConstB & *ConstD) & (ConstC ^ ConstE)).getBoolValue())
675 return IsNot ? nullptr : ConstantInt::get(LHS->getType(), !IsAnd);
676
677 if (IsNot && !ConstB->isSubsetOf(*ConstD) &&
678 !ConstD->isSubsetOf(*ConstB))
679 return nullptr;
680
682 if (IsNot) {
683 BD = *ConstB & *ConstD;
684 CE = ConstC & ConstE;
685 } else {
686 BD = *ConstB | *ConstD;
687 CE = ConstC | ConstE;
688 }
689 Value *NewAnd = Builder.CreateAnd(A, BD);
690 Value *CEVal = ConstantInt::get(A->getType(), CE);
691 return Builder.CreateICmp(CC, NewAnd, CEVal);
692 };
693
695 return FoldBMixed(NewCC, false);
697 return FoldBMixed(NewCC, true);
698 }
699 }
700
701
702
703
704
705
709
710
711 if (IsLogical)
712 D = Builder.CreateFreeze(D);
713 Value *Mask = Builder.CreateOr(B, D);
715 return Builder.CreateICmp(NewCC, Masked, Mask);
716 }
717 return nullptr;
718}
719
720
721
722
723
725 bool Inverted) {
726
727
729 if (!RangeStart)
730 return nullptr;
731
734
735
738 return nullptr;
739
742
748
750 RangeEnd = Cmp1Op1;
752
754 RangeEnd = Cmp1Op0;
756 } else {
757 return nullptr;
758 }
759
760
762 switch (Pred1) {
765 default: return nullptr;
766 }
767
768
771 return nullptr;
772
773 if (Inverted)
775
776 return Builder.CreateICmp(NewPred, Input, RangeEnd);
777}
778
779
780
781
782
788
789 if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)
790 return nullptr;
791
792
793
796
798
799
800
801
802
803
804
805
806
811 return nullptr;
812
813 Value *And = Builder.CreateAnd(Op, Pow2);
814 return Builder.CreateICmp(Pred, And, Op);
815}
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
851
852
853 auto tryToMatchSignedTruncationCheck = [](ICmpInst *ICmp, Value *&X,
854 APInt &SignBitMask) -> bool {
855 const APInt *I01, *I1;
859 I1->ugt(*I01) && I01->shl(1) == *I1))
860 return false;
861
862 SignBitMask = *I01;
863 return true;
864 };
865
866
867
869 APInt HighestBit;
871 if (tryToMatchSignedTruncationCheck(ICmp1, X1, HighestBit))
872 OtherICmp = ICmp0;
873 else if (tryToMatchSignedTruncationCheck(ICmp0, X1, HighestBit))
874 OtherICmp = ICmp1;
875 else
876 return nullptr;
877
878 assert(HighestBit.isPowerOf2() && "expected to be power of two (non-zero)");
879
880
882 APInt &UnsetBitsMask) -> bool {
884
887 false, false,
888 true);
890 X = Res->X;
891 UnsetBitsMask = Res->Mask;
892 return true;
893 }
894
895 return false;
896 };
897
898
900 APInt UnsetBitsMask;
901 if (!tryToDecompose(OtherICmp, X0, UnsetBitsMask))
902 return nullptr;
903
904 assert(!UnsetBitsMask.isZero() && "empty mask makes no sense.");
905
906
908 if (X1 == X0) {
909
910 X = X1;
913 X = X1;
914 } else
915 return nullptr;
916
917
918
919 APInt SignBitsMask = ~(HighestBit - 1U);
920
921
922 if (!UnsetBitsMask.intersects(SignBitsMask))
923 return nullptr;
924
925
926 if (!UnsetBitsMask.isSubsetOf(SignBitsMask)) {
927 APInt OtherHighestBit = (~UnsetBitsMask) + 1U;
929 return nullptr;
930 HighestBit = APIntOps::umin(HighestBit, OtherHighestBit);
931 }
932
933
934
935 return Builder.CreateICmpULT(X, ConstantInt::get(X->getType(), HighestBit),
936 CxtI.getName() + ".simplified");
937}
938
939
940
941
942
951 return nullptr;
952
955
956 CtPop->dropPoisonGeneratingAnnotations();
958 return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));
959 }
961
962 CtPop->dropPoisonGeneratingAnnotations();
964 return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));
965 }
966
967 return nullptr;
968}
969
970
971
972
976
981
982
984 if (JoinedByAnd &&
990
991 CtPop->dropPoisonGeneratingAnnotations();
993 return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
994 }
995
996 if (!JoinedByAnd &&
1002
1003 CtPop->dropPoisonGeneratingAnnotations();
1005 return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));
1006 }
1007 return nullptr;
1008}
1009
1010
1011
1012
1013
1014
1019 "Expected equality predicates for masked type of icmps.");
1021 return nullptr;
1022
1025 return nullptr;
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038 auto isReducible = [](const Value *B, const Value *D, const Value *E) {
1039 const APInt *BCst, *DCst, *ECst;
1044 };
1045
1046
1052
1053 if (!BFVTy || !BConst || !DConst || !EConst)
1054 return nullptr;
1055
1056 for (unsigned I = 0; I != BFVTy->getNumElements(); ++I) {
1057 const auto *BElt = BConst->getAggregateElement(I);
1058 const auto *DElt = DConst->getAggregateElement(I);
1059 const auto *EElt = EConst->getAggregateElement(I);
1060
1061 if (!BElt || !DElt || !EElt)
1062 return nullptr;
1063 if (!isReducible(BElt, DElt, EElt))
1064 return nullptr;
1065 }
1066 } else {
1067
1068 if (!isReducible(B, D, E))
1069 return nullptr;
1070 }
1072}
1073
1074
1075
1076
1077
1078
1079
1080
1082 bool JoinedByAnd,
1084 if (!JoinedByAnd)
1085 return nullptr;
1086 Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;
1088
1089
1090
1091 std::optional<std::pair<unsigned, unsigned>> MaskPair =
1093 if (!MaskPair)
1094 return nullptr;
1095
1097 unsigned CmpMask0 = MaskPair->first;
1098 unsigned CmpMask1 = MaskPair->second;
1099 if ((CmpMask0 & Mask_AllZeros) && (CmpMask1 == compareBMask)) {
1101 CmpPred1, Builder))
1102 return V;
1103 } else if ((CmpMask0 == compareBMask) && (CmpMask1 & Mask_AllZeros)) {
1105 CmpPred0, Builder))
1106 return V;
1107 }
1108 return nullptr;
1109}
1110
1111
1112
1114 ICmpInst *UnsignedICmp, bool IsAnd,
1117 Value *ZeroCmpOp;
1121 return nullptr;
1122
1124
1126 if (match(UnsignedICmp,
1130 auto GetKnownNonZeroAndOther = [&](Value *&NonZero, Value *&Other) {
1134 };
1135
1136
1137
1138
1139
1140
1142 IsAnd && GetKnownNonZeroAndOther(B, A))
1143 return Builder.CreateICmpULT(Builder.CreateNeg(B), A);
1145 !IsAnd && GetKnownNonZeroAndOther(B, A))
1146 return Builder.CreateICmpUGE(Builder.CreateNeg(B), A);
1147 }
1148
1149 return nullptr;
1150}
1151
1157
1158
1162 return std::nullopt;
1163
1164 unsigned NumOriginalBits = X->getType()->getScalarSizeInBits();
1165 unsigned NumExtractedBits = V->getType()->getScalarSizeInBits();
1167 const APInt *Shift;
1168
1169
1171 Shift->ule(NumOriginalBits - NumExtractedBits))
1173 return {{X, 0, NumExtractedBits}};
1174}
1175
1176
1179 if (P.StartBit)
1180 V = Builder.CreateLShr(V, P.StartBit);
1182 if (TruncTy != V->getType())
1183 V = Builder.CreateTrunc(V, TruncTy);
1184 return V;
1185}
1186
1187
1188
1189
1190Value *InstCombinerImpl::foldEqOfParts(Value *Cmp0, Value *Cmp1, bool IsAnd) {
1192 return nullptr;
1193
1195 auto GetMatchPart = [&](Value *CmpV,
1196 unsigned OpNo) -> std::optional {
1198
1200
1201
1205 return {{OpNo == 0 ? X : Y, 0, 1}};
1206
1208 if (!Cmp)
1209 return std::nullopt;
1210
1211 if (Pred == Cmp->getPredicate())
1213
1214 const APInt *C;
1215
1216
1220 return std::nullopt;
1221 }
1222
1223
1224
1229 return std::nullopt;
1230 } else {
1231 return std::nullopt;
1232 }
1233
1234 unsigned From = Pred == CmpInst::ICMP_NE ? C->popcount() : C->countr_zero();
1236 return {{I->getOperand(OpNo), From, C->getBitWidth() - From}};
1237 };
1238
1239 std::optional L0 = GetMatchPart(Cmp0, 0);
1240 std::optional R0 = GetMatchPart(Cmp0, 1);
1241 std::optional L1 = GetMatchPart(Cmp1, 0);
1242 std::optional R1 = GetMatchPart(Cmp1, 1);
1243 if (!L0 || !R0 || !L1 || !R1)
1244 return nullptr;
1245
1246
1247
1248 if (L0->From != L1->From || R0->From != R1->From) {
1249 if (L0->From != R1->From || R0->From != L1->From)
1250 return nullptr;
1252 }
1253
1254
1255
1256 if (L0->StartBit + L0->NumBits != L1->StartBit ||
1257 R0->StartBit + R0->NumBits != R1->StartBit) {
1258 if (L1->StartBit + L1->NumBits != L0->StartBit ||
1259 R1->StartBit + R1->NumBits != R0->StartBit)
1260 return nullptr;
1263 }
1264
1265
1266 IntPart L = {L0->From, L0->StartBit, L0->NumBits + L1->NumBits};
1267 IntPart R = {R0->From, R0->StartBit, R0->NumBits + R1->NumBits};
1271}
1272
1273
1274
1275
1277 bool IsAnd, bool IsLogical,
1281
1282
1288 return nullptr;
1291 return nullptr;
1292
1293
1294
1295
1299 return nullptr;
1300
1301
1302
1303
1304
1305
1307 if (!SubstituteCmp) {
1308
1309
1311 return nullptr;
1312 SubstituteCmp = Builder.CreateICmp(Pred1, Y, C);
1313 }
1314 if (IsLogical) {
1317 return IsAnd ? Builder.CreateLogicalAnd(Cmp0, SubstituteCmp, "", MDFrom)
1318 : Builder.CreateLogicalOr(Cmp0, SubstituteCmp, "", MDFrom);
1319 }
1320 return Builder.CreateBinOp(IsAnd ? Instruction::And : Instruction::Or, Cmp0,
1321 SubstituteCmp);
1322}
1323
1324
1325
1326
1327
1328Value *InstCombinerImpl::foldAndOrOfICmpsUsingRanges(ICmpInst *ICmp1,
1330 bool IsAnd) {
1331
1332 auto MatchExactRangeCheck =
1333 [](ICmpInst *ICmp) -> std::optional<std::pair<Value *, ConstantRange>> {
1334 const APInt *C;
1336 return std::nullopt;
1337 Value *LHS = ICmp->getOperand(0);
1338 CmpPredicate Pred = ICmp->getPredicate();
1340
1341 const APInt *Mask;
1344 C->countr_zero() >= Mask->countr_zero()) {
1345 ConstantRange CR(*C, *C - *Mask);
1347 CR = CR.inverse();
1348 return std::make_pair(X, CR);
1349 }
1351
1352
1353 const APInt *C1;
1355 return std::make_pair(X, CR.subtract(*C1));
1356 return std::make_pair(LHS, CR);
1357 };
1358
1359 auto RC1 = MatchExactRangeCheck(ICmp1);
1360 if (!RC1)
1361 return nullptr;
1362
1363 auto RC2 = MatchExactRangeCheck(ICmp2);
1364 if (!RC2)
1365 return nullptr;
1366
1367 auto &[V1, CR1] = *RC1;
1368 auto &[V2, CR2] = *RC2;
1369 if (V1 != V2)
1370 return nullptr;
1371
1372
1373 if (IsAnd) {
1374 CR1 = CR1.inverse();
1375 CR2 = CR2.inverse();
1376 }
1377
1378 Type *Ty = V1->getType();
1379 Value *NewV = V1;
1380 std::optional CR = CR1.exactUnionWith(CR2);
1381 if (!CR) {
1382 if (!(ICmp1->hasOneUse() && ICmp2->hasOneUse()) || CR1.isWrappedSet() ||
1383 CR2.isWrappedSet())
1384 return nullptr;
1385
1386
1387
1388 APInt LowerDiff = CR1.getLower() ^ CR2.getLower();
1389 APInt UpperDiff = (CR1.getUpper() - 1) ^ (CR2.getUpper() - 1);
1390 APInt CR1Size = CR1.getUpper() - CR1.getLower();
1391 if (!LowerDiff.isPowerOf2() || LowerDiff != UpperDiff ||
1392 CR1Size != CR2.getUpper() - CR2.getLower())
1393 return nullptr;
1394
1395 CR = CR1.getLower().ult(CR2.getLower()) ? CR1 : CR2;
1396 NewV = Builder.CreateAnd(NewV, ConstantInt::get(Ty, ~LowerDiff));
1397 }
1398
1399 if (IsAnd)
1400 CR = CR->inverse();
1401
1404 CR->getEquivalentICmp(NewPred, NewC, Offset);
1405
1407 NewV = Builder.CreateAdd(NewV, ConstantInt::get(Ty, Offset));
1408 return Builder.CreateICmp(NewPred, NewV, ConstantInt::get(Ty, NewC));
1409}
1410
1411
1412
1419
1420
1424
1425
1430
1431
1432
1433
1436 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
1437 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
1439
1442 return nullptr;
1443
1446}
1447
1449 bool IsAnd, bool IsLogicalSelect) {
1450 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
1451 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
1453
1454 if (LHS0 == RHS1 && RHS0 == LHS1) {
1455
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474 if (LHS0 == RHS0 && LHS1 == RHS1) {
1475 unsigned FCmpCodeL = getFCmpCode(PredL);
1476 unsigned FCmpCodeR = getFCmpCode(PredR);
1477 unsigned NewPred = IsAnd ? FCmpCodeL & FCmpCodeR : FCmpCodeL | FCmpCodeR;
1478
1479
1480
1483 }
1484
1485
1486 if (!IsLogicalSelect &&
1489 !IsAnd))) {
1491 return nullptr;
1492
1493
1494
1496
1497
1498
1499 return Builder.CreateFCmpFMF(PredL, LHS0, RHS0,
1501 }
1502 }
1503
1504
1505 if (!IsLogicalSelect && IsAnd &&
1507
1508
1510 return Left;
1513 }
1514
1515
1516
1517
1518
1519
1521 auto [ClassValRHS, ClassMaskRHS] =
1523 if (ClassValRHS) {
1524 auto [ClassValLHS, ClassMaskLHS] =
1526 if (ClassValLHS == ClassValRHS) {
1527 unsigned CombinedMask = IsAnd ? (ClassMaskLHS & ClassMaskRHS)
1528 : (ClassMaskLHS | ClassMaskRHS);
1529 return Builder.CreateIntrinsic(
1530 Intrinsic::is_fpclass, {ClassValLHS->getType()},
1531 {ClassValLHS, Builder.getInt32(CombinedMask)});
1532 }
1533 }
1534 }
1535
1536
1537
1538
1539
1540
1541
1542 const APFloat *LHSC, *RHSC;
1549 switch (Pred) {
1554 return true;
1555 default:
1556 return false;
1557 }
1558 };
1559 if (IsLessThanOrLessEqual(IsAnd ? PredR : PredL)) {
1562 }
1563 if (IsLessThanOrLessEqual(IsAnd ? PredL : PredR)) {
1564 FastMathFlags NewFlag = LHS->getFastMathFlags();
1565 if (!IsLogicalSelect)
1566 NewFlag |= RHS->getFastMathFlags();
1567
1569 Builder.CreateUnaryIntrinsic(Intrinsic::fabs, LHS0, NewFlag);
1570 return Builder.CreateFCmpFMF(
1571 PredL, FAbs, ConstantFP::get(LHS0->getType(), *LHSC), NewFlag);
1572 }
1573 }
1574
1575 return nullptr;
1576}
1577
1578
1579
1583 if (!FCmp || !FCmp->hasOneUse())
1584 return false;
1585
1586 std::tie(ClassVal, ClassMask) =
1587 fcmpToClassTest(FCmp->getPredicate(), *FCmp->getParent()->getParent(),
1588 FCmp->getOperand(0), FCmp->getOperand(1));
1589 return ClassVal != nullptr;
1590}
1591
1592
1593
1594
1595
1596
1597
1600 Value *ClassVal0 = nullptr;
1601 Value *ClassVal1 = nullptr;
1602 uint64_t ClassMask0, ClassMask1;
1603
1604
1605
1606
1607
1608
1609
1610 bool IsLHSClass =
1613 bool IsRHSClass =
1618 ClassVal0 == ClassVal1) {
1619 unsigned NewClassMask;
1621 case Instruction::And:
1622 NewClassMask = ClassMask0 & ClassMask1;
1623 break;
1624 case Instruction::Or:
1625 NewClassMask = ClassMask0 | ClassMask1;
1626 break;
1627 case Instruction::Xor:
1628 NewClassMask = ClassMask0 ^ ClassMask1;
1629 break;
1630 default:
1632 }
1633
1634 if (IsLHSClass) {
1636 II->setArgOperand(
1637 1, ConstantInt::get(II->getArgOperand(1)->getType(), NewClassMask));
1639 }
1640
1641 if (IsRHSClass) {
1643 II->setArgOperand(
1644 1, ConstantInt::get(II->getArgOperand(1)->getType(), NewClassMask));
1646 }
1647
1648 CallInst *NewClass =
1649 Builder.CreateIntrinsic(Intrinsic::is_fpclass, {ClassVal0->getType()},
1650 {ClassVal0, Builder.getInt32(NewClassMask)});
1652 }
1653
1654 return nullptr;
1655}
1656
1657
1658
1659
1660
1661
1662
1663
1664Instruction *InstCombinerImpl::canonicalizeConditionalNegationViaMathToSelect(
1666 assert(I.getOpcode() == BinaryOperator::Xor && "Only for xor!");
1668
1671 ->getType()->isIntOrIntVectorTy(1) ||
1673 return nullptr;
1675 X);
1676}
1677
1678
1679
1680
1681
1685 assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
1686 "Expecting and/or op for fcmp transform");
1687
1688
1689
1693
1694
1695 Value *BO10, *BO11;
1700 return nullptr;
1701
1702
1705 X->getType() != Y->getType())
1707
1709 X->getType() != Y->getType())
1710 return nullptr;
1711
1712
1713
1714
1715 Value *NewFCmp =
1718}
1719
1720
1721
1722
1726 assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
1727 "Trying to match De Morgan's Laws with something other than and/or");
1728
1729
1731 (Opcode == Instruction::And) ? Instruction::Or : Instruction::And;
1732
1733 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1742 }
1743
1744
1745
1746
1747
1748
1754 }
1755
1756 return nullptr;
1757}
1758
1759bool InstCombinerImpl::shouldOptimizeCast(CastInst *CI) {
1761
1762
1764 return false;
1765
1766
1767
1769 if (isEliminableCastPair(PrecedingCI, CI))
1770 return false;
1771
1772 return true;
1773}
1774
1775
1779 if ()
1780 return nullptr;
1781
1782 auto LogicOpc = Logic.getOpcode();
1785
1786
1787
1788
1789
1795
1797 auto *ZExt = new ZExtInst(NewOp, DestTy);
1798 ZExt->setNonNeg(Flags.NNeg);
1799 ZExt->andIRFlags(Cast);
1800 return ZExt;
1801 }
1802 }
1803
1806
1808 return new SExtInst(NewOp, DestTy);
1809 }
1810 }
1811
1812 return nullptr;
1813}
1814
1815
1818 assert(I.isBitwiseLogicOp() && "Unexpected opcode for bitwise logic folding");
1819
1820 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1821
1822
1823
1824
1825
1826 auto FoldBitwiseICmpZeroWithICmp = [&](Value *Op0,
1827 Value *Op1) -> Instruction * {
1829 bool IsMatched =
1835
1836 if (!IsMatched)
1837 return nullptr;
1838
1839 auto *ICmpL =
1842 auto *BitwiseOp = Builder.CreateBinOp(LogicOpc, ICmpL, ICmpR);
1843
1844 return new ZExtInst(BitwiseOp, Op0->getType());
1845 };
1846
1847 if (auto *Ret = FoldBitwiseICmpZeroWithICmp(Op0, Op1))
1848 return Ret;
1849
1850 if (auto *Ret = FoldBitwiseICmpZeroWithICmp(Op1, Op0))
1851 return Ret;
1852
1854 if (!Cast0)
1855 return nullptr;
1856
1857
1858
1859 Type *DestTy = I.getType();
1862 return nullptr;
1863
1865 return Ret;
1866
1868 if (!Cast1)
1869 return nullptr;
1870
1871
1872
1874 if (CastOpcode != Cast1->getOpcode())
1875 return nullptr;
1876
1877
1879 return nullptr;
1880
1884
1885 unsigned XNumBits = X->getType()->getScalarSizeInBits();
1886 unsigned YNumBits = Y->getType()->getScalarSizeInBits();
1887 if (XNumBits != YNumBits) {
1888
1889
1891 return nullptr;
1892
1893
1894
1895 if (XNumBits < YNumBits) {
1896 X = Builder.CreateCast(CastOpcode, X, Y->getType());
1897 } else if (YNumBits < XNumBits) {
1898 Y = Builder.CreateCast(CastOpcode, Y, X->getType());
1899 }
1900 }
1901
1902
1903 Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y, I.getName());
1906 if (Disjoint && NewDisjoint)
1907 NewDisjoint->setIsDisjoint(Disjoint->isDisjoint());
1909 }
1910
1911
1912 if (SrcTy != Cast1->getSrcTy())
1913 return nullptr;
1914
1917
1918
1919 if (shouldOptimizeCast(Cast0) && shouldOptimizeCast(Cast1)) {
1920 Value *NewOp = Builder.CreateBinOp(LogicOpc, Cast0Src, Cast1Src,
1921 I.getName());
1923 }
1924
1925 return nullptr;
1926}
1927
1930 assert(I.getOpcode() == Instruction::And);
1931 Value *Op0 = I.getOperand(0);
1932 Value *Op1 = I.getOperand(1);
1934
1935
1936
1937
1940 return BinaryOperator::CreateXor(A, B);
1941
1942
1943
1944
1945
1950
1951 return nullptr;
1952}
1953
1956 assert(I.getOpcode() == Instruction::Or);
1957 Value *Op0 = I.getOperand(0);
1958 Value *Op1 = I.getOperand(1);
1960
1961
1962
1963
1968
1969
1970
1971
1976
1977
1978
1979
1980
1983 return BinaryOperator::CreateXor(A, B);
1984
1985 return nullptr;
1986}
1987
1988
1989
1991 APInt Threshold(C->getType()->getScalarSizeInBits(), BitWidth);
1993}
1994
1995
1996
1998
1999
2000
2001
2002
2003 Value *Op0 = And.getOperand(0), *Op1 = And.getOperand(1);
2010 return nullptr;
2011
2014 return nullptr;
2015
2016 Type *Ty = And.getType();
2017 if ((Ty) && !shouldChangeType(Ty, X->getType()))
2018 return nullptr;
2019
2020
2021
2022
2024 if (Opc == Instruction::LShr || Opc == Instruction::Shl)
2026 return nullptr;
2027
2028
2029
2031 Value *NewBO = Opc == Instruction::Sub ? Builder.CreateBinOp(Opc, NewC, X)
2033 return new ZExtInst(Builder.CreateAnd(NewBO, X), Ty);
2034}
2035
2036
2037
2041 assert(Opcode == Instruction::And || Opcode == Instruction::Or);
2042
2043
2045 (Opcode == Instruction::And) ? Instruction::Or : Instruction::And;
2046
2047 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
2049
2050
2051
2052
2053
2054 const auto matchNotOrAnd =
2055 [Opcode, FlippedOpcode](Value *Op, auto m_A, auto m_B, auto m_C,
2056 Value *&X, bool CountUses = false) -> bool {
2057 if (CountUses && ->hasOneUse())
2058 return false;
2059
2063 return !CountUses || X->hasOneUse();
2064
2065 return false;
2066 };
2067
2068
2069
2070
2071
2072
2074
2075
2077 true)) {
2078 Value *Xor = Builder.CreateXor(B, C);
2079 return (Opcode == Instruction::Or)
2080 ? BinaryOperator::CreateAnd(Xor, Builder.CreateNot(A))
2082 }
2083
2084
2085
2087 true)) {
2088 Value *Xor = Builder.CreateXor(A, C);
2089 return (Opcode == Instruction::Or)
2090 ? BinaryOperator::CreateAnd(Xor, Builder.CreateNot(B))
2092 }
2093
2094
2095
2099 Opcode, Builder.CreateBinOp(FlippedOpcode, B, C), A));
2100
2101
2102
2106 Opcode, Builder.CreateBinOp(FlippedOpcode, A, C), B));
2107
2108
2109
2110
2111
2112 if (Opcode == Instruction::Or && Op0->hasOneUse() &&
2117
2118
2121 }
2122 }
2123
2124
2125
2126
2127
2128
2137
2138
2139
2149 Value *Xor = Builder.CreateXor(B, C);
2150 return (Opcode == Instruction::Or)
2152 : BinaryOperator::CreateOr(Xor, X);
2153 }
2154
2155
2156
2160 FlippedOpcode, Builder.CreateBinOp(Opcode, C, Builder.CreateNot(B)),
2161 X);
2162
2163
2164
2168 FlippedOpcode, Builder.CreateBinOp(Opcode, B, Builder.CreateNot(C)),
2169 X);
2170 }
2171
2172 return nullptr;
2173}
2174
2175
2176
2177
2178
2187
2188 if (->hasOneUse()) {
2189 Value *YZ = Builder.CreateBinOp(Opcode, Y, Z);
2191 }
2192
2193 if (->hasOneUse()) {
2194 Value *XZ = Builder.CreateBinOp(Opcode, X, Z);
2196 }
2197 }
2198 }
2199
2200 return nullptr;
2201}
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2216 Value *Op0 = I.getOperand(0);
2217 Value *Op1 = I.getOperand(1);
2220
2223 return nullptr;
2224
2225 unsigned Width = Ty->getScalarSizeInBits();
2226 unsigned LastOneMath = Width - C2->countr_zero();
2227
2228 switch (OpC) {
2229 case Instruction::And:
2230 if (C->countl_one() < LastOneMath)
2231 return nullptr;
2232 break;
2233 case Instruction::Xor:
2234 case Instruction::Or:
2235 if (C->countl_zero() < LastOneMath)
2236 return nullptr;
2237 break;
2238 default:
2240 }
2241
2242 Value *NewBinOp = Builder.CreateBinOp(OpC, X, ConstantInt::get(Ty, *C));
2244 ConstantInt::get(Ty, *C2), Op0);
2245}
2246
2247
2248
2249
2251 assert((I.isBitwiseLogicOp() || I.getOpcode() == Instruction::Add) &&
2252 "Unexpected opcode");
2253
2255 Constant *ShiftedC1, *ShiftedC2, *AddC;
2262 return nullptr;
2263
2264
2265 if ((AddC,
2267 return nullptr;
2268
2269
2272 if (!Op0Inst || !Op1Inst)
2273 return nullptr;
2274
2275
2278 if (ShiftOp != Op1Inst->getOpcode())
2279 return nullptr;
2280
2281
2282 if (I.getOpcode() == Instruction::Add && ShiftOp != Instruction::Shl)
2283 return nullptr;
2284
2286 I.getOpcode(), ShiftedC1, Builder.CreateBinOp(ShiftOp, ShiftedC2, AddC));
2288}
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2302 assert(I.isBitwiseLogicOp() && "Should and/or/xor");
2303 if (.getOperand(0)->hasOneUse())
2304 return nullptr;
2306 if ()
2307 return nullptr;
2308
2310 if (Y && (->hasOneUse() || X->getIntrinsicID() != Y->getIntrinsicID()))
2311 return nullptr;
2312
2314 const APInt *RHSC;
2315
2316 if ( && (!(IID == Intrinsic::bswap || IID == Intrinsic::bitreverse) ||
2318 return nullptr;
2319
2320 switch (IID) {
2321 case Intrinsic::fshl:
2322 case Intrinsic::fshr: {
2323 if (X->getOperand(2) != Y->getOperand(2))
2324 return nullptr;
2326 Builder.CreateBinOp(I.getOpcode(), X->getOperand(0), Y->getOperand(0));
2328 Builder.CreateBinOp(I.getOpcode(), X->getOperand(1), Y->getOperand(1));
2332 }
2333 case Intrinsic::bswap:
2334 case Intrinsic::bitreverse: {
2335 Value *NewOp0 = Builder.CreateBinOp(
2336 I.getOpcode(), X->getOperand(0),
2338 : ConstantInt::get(I.getType(), IID == Intrinsic::bswap
2344 }
2345 default:
2346 return nullptr;
2347 }
2348}
2349
2350
2351
2352
2353
2354
2356 bool SimplifyOnly,
2358 unsigned Depth = 0) {
2359 if (Op == RepOp)
2360 return nullptr;
2361
2362 if (V == Op)
2363 return RepOp;
2364
2366 if ( ||
->isBitwiseLogicOp() || Depth >= 3)
2367 return nullptr;
2368
2369 if (->hasOneUse())
2370 SimplifyOnly = true;
2371
2373 SimplifyOnly, IC, Depth + 1);
2375 SimplifyOnly, IC, Depth + 1);
2376 if (!NewOp0 && !NewOp1)
2377 return nullptr;
2378
2379 if (!NewOp0)
2380 NewOp0 = I->getOperand(0);
2381 if (!NewOp1)
2382 NewOp1 = I->getOperand(1);
2383
2386 return Res;
2387
2388 if (SimplifyOnly)
2389 return nullptr;
2391}
2392
2393
2394
2395
2398 bool RHSIsLogical) {
2400
2401
2402 if (Value *Res = foldBooleanAndOr(LHS, X, I, IsAnd, false))
2403 return RHSIsLogical ? Builder.CreateLogicalOp(Opcode, Res, Y)
2404 : Builder.CreateBinOp(Opcode, Res, Y);
2405
2406
2407 if (Value *Res = foldBooleanAndOr(LHS, Y, I, IsAnd, false))
2408 return RHSIsLogical ? Builder.CreateLogicalOp(Opcode, X, Res)
2409 : Builder.CreateBinOp(Opcode, X, Res);
2410 return nullptr;
2411}
2412
2413
2414
2415
2418
2420 SQ.getWithInstruction(&I)))
2422
2424 return &I;
2425
2427 return X;
2428
2430 return Phi;
2431
2432
2433
2435 return &I;
2436
2437
2439 return Xor;
2440
2442 return X;
2443
2444
2447
2449 return R;
2450
2451 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
2452
2458
2459
2460 Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, 0));
2461 return new ZExtInst(IsZero, Ty);
2462 }
2463
2464
2471 }
2472
2473
2474
2479 return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
2480
2482 const APInt *XorC;
2484
2485 Constant *NewC = ConstantInt::get(Ty, *C & *XorC);
2487 And->takeName(Op0);
2488 return BinaryOperator::CreateXor(And, NewC);
2489 }
2490
2491 const APInt *OrC;
2493
2494
2495
2496
2497
2498
2499 APInt Together = *C & *OrC;
2500 Value *And = Builder.CreateAnd(X, ConstantInt::get(Ty, Together ^ *C));
2501 And->takeName(Op0);
2502 return BinaryOperator::CreateOr(And, ConstantInt::get(Ty, Together));
2503 }
2504
2505 unsigned Width = Ty->getScalarSizeInBits();
2506 const APInt *ShiftC;
2508 ShiftC->ult(Width)) {
2510
2511
2513 Constant *ShAmtC = ConstantInt::get(Ty, ShiftC->zext(Width));
2514 return BinaryOperator::CreateLShr(Sext, ShAmtC);
2515 }
2516 }
2517
2518
2519
2522 return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, *ShiftC));
2523
2524 const APInt *AddC;
2526
2527
2528
2529
2530 if (Op0->hasOneUse() && C->isPowerOf2() && (*AddC & (*C - 1)) == 0) {
2531 assert((*C & *AddC) != 0 && "Expected common bit");
2533 return BinaryOperator::CreateXor(NewAnd, Op1);
2534 }
2535 }
2536
2537
2538
2540 switch (B->getOpcode()) {
2541 case Instruction::Xor:
2542 case Instruction::Or:
2543 case Instruction::Mul:
2544 case Instruction::Add:
2545 case Instruction::Sub:
2546 return true;
2547 default:
2548 return false;
2549 }
2550 };
2555 const APInt *C1;
2556
2557
2558
2559
2561 C->isIntN(X->getType()->getScalarSizeInBits())) {
2562 unsigned XWidth = X->getType()->getScalarSizeInBits();
2563 Constant *TruncC1 = ConstantInt::get(X->getType(), C1->trunc(XWidth));
2565 ? Builder.CreateBinOp(BOpcode, X, TruncC1)
2566 : Builder.CreateBinOp(BOpcode, TruncC1, X);
2567 Constant *TruncC = ConstantInt::get(X->getType(), C->trunc(XWidth));
2570 }
2571
2572
2573
2574
2577 C->isMask(X->getType()->getScalarSizeInBits())) {
2579 Value *TrY = Builder.CreateTrunc(Y, X->getType(), Y->getName() + ".tr");
2581 Builder.CreateBinOp(BOpcode, X, TrY, BO->getName() + ".narrow");
2582 return new ZExtInst(NewBO, Ty);
2583 }
2584
2587 C->isMask(X->getType()->getScalarSizeInBits())) {
2589 Value *TrY = Builder.CreateTrunc(Y, X->getType(), Y->getName() + ".tr");
2591 Builder.CreateBinOp(BOpcode, TrY, X, BO->getName() + ".narrow");
2592 return new ZExtInst(NewBO, Ty);
2593 }
2594 }
2595
2596
2597
2598
2604
2605
2606 Value *NewRHS = Builder.CreateAnd(Y, Op1, Y->getName() + ".masked");
2608 }
2610
2611
2612 Value *NewLHS = Builder.CreateAnd(X, Op1, X->getName() + ".masked");
2614 }
2615 }
2616
2617
2618
2619
2620
2621 if (C->isPowerOf2() &&
2624 int Log2C = C->exactLogBase2();
2625 bool IsShiftLeft =
2627 int BitNum = IsShiftLeft ? Log2C - Log2ShiftC : Log2ShiftC - Log2C;
2628 assert(BitNum >= 0 && "Expected demanded bits to handle impossible mask");
2629 Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, BitNum));
2632 }
2633
2646
2647
2652 }
2653 }
2654
2661 if (Cmp && Cmp->isZeroValue()) {
2662
2663
2669 }
2670 }
2671 }
2672 }
2673
2674
2675
2676
2677
2678
2679
2680
2681
2685 .GetInsertBlock()->getParent()->hasFnAttribute(
2686 Attribute::NoImplicitFloat)) {
2690 Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp);
2692 }
2693 }
2694
2695
2696
2701 APInt(Ty->getScalarSizeInBits(),
2702 Ty->getScalarSizeInBits() -
2703 X->getType()->getScalarSizeInBits())))) {
2704 auto *SExt = Builder.CreateSExt(X, Ty, X->getName() + ".signext");
2705 return BinaryOperator::CreateAnd(SExt, Op1);
2706 }
2707
2709 return Z;
2710
2711 if (I.getType()->isIntOrIntVectorTy(1)) {
2713 if (auto *R =
2714 foldAndOrOfSelectUsingImpliedCond(Op1, *SI0, true))
2715 return R;
2716 }
2718 if (auto *R =
2719 foldAndOrOfSelectUsingImpliedCond(Op0, *SI1, true))
2720 return R;
2721 }
2722 }
2723
2725 return FoldedLogic;
2726
2728 return DeMorgan;
2729
2730 {
2732
2734 return BinaryOperator::CreateAnd(Op0, B);
2735
2737 return BinaryOperator::CreateAnd(Op1, B);
2738
2739
2745 if (NotC != nullptr)
2746 return BinaryOperator::CreateAnd(Op0, NotC);
2747 }
2748
2749
2755 if (NotC != nullptr)
2756 return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(C));
2757 }
2758
2759
2760
2761
2762
2765 return BinaryOperator::CreateAnd(A, B);
2766
2767
2768
2769
2770
2773 return BinaryOperator::CreateAnd(A, B);
2774
2775
2776
2777
2778
2781 return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);
2782
2783
2784
2785
2786
2789 return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);
2790 }
2791
2792 if (Value *Res =
2793 foldBooleanAndOr(Op0, Op1, I, true, false))
2795
2798 if (auto *V = reassociateBooleanAndOr(Op0, X, Y, I, true,
2799 IsLogical))
2801 }
2804 if (auto *V = reassociateBooleanAndOr(Op1, X, Y, I, true,
2805 IsLogical))
2807 }
2808
2810 return FoldedFCmps;
2811
2812 if (Instruction *CastedAnd = foldCastedBitwiseLogic(I))
2813 return CastedAnd;
2814
2815 if (Instruction *Sel = foldBinopOfSextBoolToSelect(I))
2816 return Sel;
2817
2818
2819
2820
2821
2822
2825 A->getType()->isIntOrIntVectorTy(1))
2827
2828
2829
2831 A->getType()->isIntOrIntVectorTy(1))
2833
2834
2836 A->getType()->isIntOrIntVectorTy(1))
2839
2840
2843 if (A->getType()->isIntOrIntVectorTy(1))
2849 }
2850 }
2851
2852
2856 *C == X->getType()->getScalarSizeInBits() - 1) {
2859 }
2860
2861
2865 *C == X->getType()->getScalarSizeInBits() - 1) {
2868 }
2869
2870
2872 return &I;
2873
2874
2876 Value *Start = nullptr, *Step = nullptr;
2879
2881 return R;
2882
2884 return Canonicalized;
2885
2886 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
2887 return Folded;
2888
2889 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))
2890 return Res;
2891
2893 return Res;
2894
2897 false, *this))
2898 return BinaryOperator::CreateAnd(V, Op1);
2901 false, *this))
2902 return BinaryOperator::CreateAnd(Op0, V);
2903
2904 return nullptr;
2905}
2906
2908 bool MatchBSwaps,
2909 bool MatchBitReversals) {
2912 Insts))
2913 return nullptr;
2916
2917 for (auto *Inst : Insts) {
2918 Inst->setDebugLoc(I.getDebugLoc());
2920 }
2921 return LastInst;
2922}
2923
2924std::optional<std::pair<Intrinsic::ID, SmallVector<Value *, 3>>>
2926
2927
2928 assert(Or.getOpcode() == BinaryOperator::Or && "Expecting or instruction");
2929
2930 unsigned Width = Or.getType()->getScalarSizeInBits();
2931
2935 return std::nullopt;
2936
2937 bool IsFshl = true;
2939
2940
2941
2943 Value *ShVal0, *ShVal1, *ShAmt0, *ShAmt1;
2949 return std::nullopt;
2950
2951
2952 if (Or0->getOpcode() == BinaryOperator::LShr) {
2956 }
2958 Or1->getOpcode() == BinaryOperator::LShr &&
2959 "Illegal or(shift,shift) pair");
2960
2961
2962
2963 auto matchShiftAmount = [&](Value *L, Value *R, unsigned Width) -> Value * {
2964
2965 const APInt *LI, *RI;
2967 if (LI->ult(Width) && RI->ult(Width) && (*LI + *RI) == Width)
2968 return ConstantInt::get(L->getType(), *LI);
2969
2978
2979
2980
2981
2982
2983
2986 return KnownL.getMaxValue().ult(Width) ? L : nullptr;
2987 }
2988
2989
2990
2991
2992 if (ShVal0 != ShVal1)
2993 return nullptr;
2994
2995
2996
2998 return nullptr;
2999
3000
3001
3003 unsigned Mask = Width - 1;
3006 return X;
3007
3008
3010 return L;
3011
3012
3013
3018 return L;
3019
3022 return L;
3023
3024 return nullptr;
3025 };
3026
3027 Value *ShAmt = matchShiftAmount(ShAmt0, ShAmt1, Width);
3028 if (!ShAmt) {
3029 ShAmt = matchShiftAmount(ShAmt1, ShAmt0, Width);
3030 IsFshl = false;
3031 }
3032 if (!ShAmt)
3033 return std::nullopt;
3034
3035 FShiftArgs = {ShVal0, ShVal1, ShAmt};
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3050
3052 const APInt *ZextHighShlAmt;
3055 return std::nullopt;
3056
3059 return std::nullopt;
3060
3061 unsigned HighSize = High->getType()->getScalarSizeInBits();
3062 unsigned LowSize = Low->getType()->getScalarSizeInBits();
3063
3064
3065 if (ZextHighShlAmt->ult(LowSize) || ZextHighShlAmt->ugt(Width - HighSize))
3066 return std::nullopt;
3067
3068 for (User *U : ZextHigh->users()) {
3071 continue;
3072
3075
3076 const APInt *ZextLowShlAmt;
3079 continue;
3080
3081
3082
3083 if (*ZextLowShlAmt + *ZextHighShlAmt != Width)
3084 continue;
3085
3086
3087
3088 assert(ZextLowShlAmt->uge(HighSize) &&
3089 ZextLowShlAmt->ule(Width - LowSize) && "Invalid concat");
3090
3091
3092
3093
3095
3097
3098 FShiftArgs = {U, U, ConstantInt::get(Or0->getType(), *ZextHighShlAmt)};
3099 break;
3100 }
3101 }
3102
3103 if (FShiftArgs.empty())
3104 return std::nullopt;
3105
3106 Intrinsic::ID IID = IsFshl ? Intrinsic::fshl : Intrinsic::fshr;
3107 return std::make_pair(IID, FShiftArgs);
3108}
3109
3110
3113 auto [IID, FShiftArgs] = *Opt;
3117 }
3118
3119 return nullptr;
3120}
3121
3122
3124 assert(Or.getOpcode() == Instruction::Or && "bswap requires an 'or'");
3125 Value *Op0 = Or.getOperand(0), *Op1 = Or.getOperand(1);
3127
3128 unsigned Width = Ty->getScalarSizeInBits();
3129 if ((Width & 1) != 0)
3130 return nullptr;
3131 unsigned HalfWidth = Width / 2;
3132
3133
3136
3137
3138 Value *LowerSrc, *ShlVal, *UpperSrc;
3143 return nullptr;
3144 if (*C != HalfWidth || LowerSrc->getType() != UpperSrc->getType() ||
3146 return nullptr;
3147
3149 Value *NewLower = Builder.CreateZExt(Lo, Ty);
3150 Value *NewUpper = Builder.CreateZExt(Hi, Ty);
3151 NewUpper = Builder.CreateShl(NewUpper, HalfWidth);
3152 Value *BinOp = Builder.CreateOr(NewLower, NewUpper);
3153 return Builder.CreateIntrinsic(id, Ty, BinOp);
3154 };
3155
3156
3157
3158 Value *LowerBSwap, *UpperBSwap;
3161 return ConcatIntrinsicCalls(Intrinsic::bswap, UpperBSwap, LowerBSwap);
3162
3163
3164
3165 Value *LowerBRev, *UpperBRev;
3168 return ConcatIntrinsicCalls(Intrinsic::bitreverse, UpperBRev, LowerBRev);
3169
3170
3171
3172
3173
3179 m_SpecificInt(X->getType()->getScalarSizeInBits() - 1)))))
3180 return Builder.CreateSExt(X, Ty);
3181
3182 return nullptr;
3183}
3184
3185
3188 for (unsigned i = 0; i != NumElts; ++i) {
3191 if (!EltC1 || !EltC2)
3192 return false;
3193
3194
3197 return false;
3198 }
3199 return true;
3200}
3201
3202
3203
3204
3205
3207 bool ABIsTheSame) {
3208
3209
3212 return nullptr;
3213
3214
3216
3218 return A;
3219
3220
3221
3222
3223
3224
3226 if (A->getType()->isIntOrIntVectorTy()) {
3228 if (NumSignBits == A->getType()->getScalarSizeInBits() &&
3231 }
3232 return nullptr;
3233 }
3234
3235
3236 if (ABIsTheSame)
3237 return nullptr;
3238
3239
3245
3246
3247
3251 Cond->getType()->isIntOrIntVectorTy(1)) {
3252
3254 return Cond;
3255
3256
3257
3258
3259
3263 return Cond;
3264 }
3265 }
3266
3267
3268
3270 return nullptr;
3271
3272
3273
3274
3277 Cond->getType()->isIntOrIntVectorTy(1) &&
3281 }
3282 return nullptr;
3283}
3284
3285
3286
3287
3288
3289
3291 Value *D, bool InvertFalseVal) {
3292
3293
3297 if (Value *Cond = getSelectCondition(A, C, InvertFalseVal)) {
3298
3299
3300
3301
3302 Type *SelTy = A->getType();
3304
3305 unsigned Elts = VecTy->getElementCount().getKnownMinValue();
3306
3307
3309 Type *EltTy = Builder.getIntNTy(SelEltSize / Elts);
3310 SelTy = VectorType::get(EltTy, VecTy->getElementCount());
3311 }
3312 Value *BitcastB = Builder.CreateBitCast(B, SelTy);
3313 if (InvertFalseVal)
3315 Value *BitcastD = Builder.CreateBitCast(D, SelTy);
3318 }
3319
3320 return nullptr;
3321}
3322
3323
3324
3326 bool IsAnd, bool IsLogical,
3328 Value *LHS0 = LHS->getOperand(0);
3329 Value *RHS0 = RHS->getOperand(0);
3330 Value *RHS1 = RHS->getOperand(1);
3331
3333 IsAnd ? LHS->getInversePredicate() : LHS->getPredicate();
3335 IsAnd ? RHS->getInversePredicate() : RHS->getPredicate();
3336
3337 const APInt *CInt;
3341 !(LHS->hasOneUse() || RHS->hasOneUse()))
3342 return nullptr;
3343
3344 auto MatchRHSOp = [LHS0, CInt](const Value *RHSOp) {
3345 return match(RHSOp,
3347 (CInt->isZero() && RHSOp == LHS0);
3348 };
3349
3355 else
3356 return nullptr;
3357
3358 if (IsLogical)
3359 Other = Builder.CreateFreeze(Other);
3360
3361 return Builder.CreateICmp(
3363 Builder.CreateSub(LHS0, ConstantInt::get(LHS0->getType(), *CInt + 1)),
3365}
3366
3367
3368
3369
3372 bool IsLogical) {
3373 const SimplifyQuery Q = SQ.getWithInstruction(&I);
3374
3376 Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0);
3377 Value *LHS1 = LHS->getOperand(1), *RHS1 = RHS->getOperand(1);
3378
3379 const APInt *LHSC = nullptr, *RHSC = nullptr;
3382
3383
3384
3386 if (LHS0 == RHS1 && LHS1 == RHS0) {
3389 }
3390 if (LHS0 == RHS0 && LHS1 == RHS1) {
3393 bool IsSigned = LHS->isSigned() || RHS->isSigned();
3395 }
3396 }
3397
3400 return V;
3401
3402
3404 false, Builder))
3405 return V;
3406
3409 return V;
3410
3411
3413 RHS, LHS, IsAnd, false, Builder, Q, I)) {
3414
3415 if (IsLogical && RHS->hasSameSign() && ->use_empty()) {
3416 RHS->setSameSign(false);
3418 }
3419 return V;
3420 }
3421
3423 return V;
3425 return V;
3426
3427
3428
3429 if (!IsLogical) {
3430
3431
3433 return V;
3434
3435
3436
3438 return V;
3439 }
3440
3441
3442 if (IsAnd && !IsLogical)
3444 return V;
3445
3447 return V;
3448
3450 return V;
3451
3452
3453 if (!IsLogical) {
3455 return X;
3457 return X;
3458 }
3459
3460
3461
3462
3467 Value *NewOr = Builder.CreateOr(LHS0, RHS0);
3468 return Builder.CreateICmp(PredL, NewOr,
3470 }
3471
3472
3473
3478 Value *NewAnd = Builder.CreateAnd(LHS0, RHS0);
3479 return Builder.CreateICmp(PredL, NewAnd,
3481 }
3482
3483 if (!IsLogical)
3486 return V;
3487
3488
3489 if (!LHSC || !RHSC)
3490 return nullptr;
3491
3492
3493
3494
3495
3499 const APInt *AndC, *SmallC = nullptr, *BigC = nullptr;
3500
3501
3502
3505 SmallC = RHSC;
3506 BigC = LHSC;
3509 SmallC = LHSC;
3510 BigC = RHSC;
3511 }
3512
3513 if (SmallC && BigC) {
3514 unsigned BigBitSize = BigC->getBitWidth();
3515 unsigned SmallBitSize = SmallC->getBitWidth();
3516
3517
3521 APInt N = SmallC->zext(BigBitSize) | *BigC;
3522 Value *NewVal = ConstantInt::get(NewAnd->getType(), N);
3523 return Builder.CreateICmp(PredL, NewAnd, NewVal);
3524 }
3525 }
3526 }
3527
3528
3529
3530
3531
3532
3533 bool TrueIfSignedL, TrueIfSignedR;
3538 if (IsAnd) {
3539 if ((TrueIfSignedL && !TrueIfSignedR &&
3542 (!TrueIfSignedL && TrueIfSignedR &&
3546 return Builder.CreateIsNeg(NewXor);
3547 }
3548 } else {
3549 if ((TrueIfSignedL && !TrueIfSignedR &&
3552 (!TrueIfSignedL && TrueIfSignedR &&
3556 return Builder.CreateIsNotNeg(NewXor);
3557 }
3558 }
3559 }
3560
3561
3562
3564 const APInt *MaskC;
3565 if (LHS0 == RHS0 && PredL == PredR &&
3567 .getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&
3570 X->getType()->getScalarType()->isIEEELikeFPTy() &&
3571 APFloat(X->getType()->getScalarType()->getFltSemantics(), *MaskC)
3572 .isPosInfinity() &&
3573 ((LHSC->isZero() && *RHSC == *MaskC) ||
3574 (RHSC->isZero() && *LHSC == *MaskC)))
3577
3578 return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
3579}
3580
3581
3582
3585 bool IsLogical) {
3587 return nullptr;
3588
3589
3590
3591
3593 SQ.getWithInstruction(&I)))
3594 return V;
3595
3598 if (Value *Res = foldAndOrOfICmps(LHSCmp, RHSCmp, I, IsAnd, IsLogical))
3599 return Res;
3600
3603 if (Value *Res = foldLogicOfFCmps(LHSCmp, RHSCmp, IsAnd, IsLogical))
3604 return Res;
3605
3606 if (Value *Res = foldEqOfParts(LHS, RHS, IsAnd))
3607 return Res;
3608
3609 return nullptr;
3610}
3611
3614 assert(I.getOpcode() == Instruction::Or &&
3615 "Simplification only supports or at the moment.");
3616
3617 Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;
3620 return nullptr;
3621
3622
3624 return Builder.CreateXor(Cmp1, Cmp4);
3626 return Builder.CreateXor(Cmp1, Cmp3);
3627
3628 return nullptr;
3629}
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3641 int64_t &VecOffset,
3644
3648 ShlAmt))) {
3650 if (!VecTy)
3651 return false;
3653 if (!EltTy)
3654 return false;
3655
3656 const unsigned EltBitWidth = EltTy->getBitWidth();
3658 if (TargetBitWidth % EltBitWidth != 0 || ShlAmt % EltBitWidth != 0)
3659 return false;
3660 const unsigned TargetEltWidth = TargetBitWidth / EltBitWidth;
3661 const unsigned ShlEltAmt = ShlAmt / EltBitWidth;
3662
3663 const unsigned MaskIdx =
3664 DL.isLittleEndian() ? ShlEltAmt : TargetEltWidth - ShlEltAmt - 1;
3665
3666 VecOffset = static_cast<int64_t>(VecIdx) - static_cast<int64_t>(MaskIdx);
3667 Mask.resize(TargetEltWidth);
3668 Mask.set(MaskIdx);
3669 return true;
3670 }
3671
3672
3675 return false;
3676
3678 if (!SrcTy)
3679 return false;
3680
3681 Mask.resize(SrcTy->getNumElements());
3682
3683
3688 m_Mask(ShuffleMask))))
3689 return false;
3690
3692 if (!VecTy)
3693 return false;
3694
3695 const unsigned NumVecElts = VecTy->getNumElements();
3696 bool FoundVecOffset = false;
3697 for (unsigned Idx = 0; Idx < ShuffleMask.size(); ++Idx) {
3699 return false;
3700 const unsigned ShuffleIdx = ShuffleMask[Idx];
3701 if (ShuffleIdx >= NumVecElts) {
3702 const unsigned ConstIdx = ShuffleIdx - NumVecElts;
3703 auto *ConstElt =
3705 if (!ConstElt || !ConstElt->isNullValue())
3706 return false;
3707 continue;
3708 }
3709
3710 if (FoundVecOffset) {
3711 if (VecOffset + Idx != ShuffleIdx)
3712 return false;
3713 } else {
3714 if (ShuffleIdx < Idx)
3715 return false;
3716 VecOffset = ShuffleIdx - Idx;
3717 FoundVecOffset = true;
3718 }
3719 Mask.set(Idx);
3720 }
3721 return FoundVecOffset;
3722 }
3723
3724
3726 if ((SrcVecI,
3728 return false;
3729
3731 if (!VecTy)
3732 return false;
3733 VecOffset = 0;
3734 bool AlreadyInsertedMaskedElt = Mask.test(InsertIdx);
3735 Mask.set();
3736 if (!AlreadyInsertedMaskedElt)
3737 Mask.reset(InsertIdx);
3738 return true;
3739}
3740
3741
3742
3746 assert(I.getOpcode() == Instruction::Or);
3747 Value *LhsVec, *RhsVec;
3748 int64_t LhsVecOffset, RhsVecOffset;
3751 Mask, DL))
3752 return nullptr;
3754 Mask, DL))
3755 return nullptr;
3756 if (LhsVec != RhsVec || LhsVecOffset != RhsVecOffset)
3757 return nullptr;
3758
3759
3760 const unsigned ZeroVecIdx =
3763 for (unsigned Idx : Mask.set_bits()) {
3764 assert(LhsVecOffset + Idx >= 0);
3765 ShuffleMask[Idx] = LhsVecOffset + Idx;
3766 }
3767
3768 Value *MaskedVec = Builder.CreateShuffleVector(
3770 I.getName() + ".v");
3771 return CastInst::Create(Instruction::BitCast, MaskedVec, I.getType());
3772}
3773
3774
3775
3776
3777
3778
3779
3782 bool &IsShlNSW) {
3786 return false;
3787
3790
3793 return false;
3794
3795 Value *MaskedOp0;
3796 const APInt *ShiftedMaskConst = nullptr;
3798 m_APInt(ShiftedMaskConst))),
3800 return false;
3801
3803 if ((MaskedOp0,
3806 return false;
3807
3808 if (LShrAmt > ShlAmt)
3809 return false;
3810 Offset = ShlAmt - LShrAmt;
3811
3812 Mask = ShiftedMaskConst ? ShiftedMaskConst->shl(LShrAmt)
3814 Int->getType()->getScalarSizeInBits(), LShrAmt);
3815
3816 return true;
3817}
3818
3819
3820
3823
3824 Value *LhsInt, *RhsInt;
3825 APInt LhsMask, RhsMask;
3826 uint64_t LhsOffset, RhsOffset;
3827 bool IsLhsShlNUW, IsLhsShlNSW, IsRhsShlNUW, IsRhsShlNSW;
3829 IsLhsShlNSW))
3830 return nullptr;
3832 IsRhsShlNSW))
3833 return nullptr;
3834 if (LhsInt != RhsInt || LhsOffset != RhsOffset)
3835 return nullptr;
3836
3837 APInt Mask = LhsMask | RhsMask;
3838
3840 Value *Res = Builder.CreateShl(
3841 Builder.CreateZExt(
3842 Builder.CreateAnd(LhsInt, Mask, LhsInt->getName() + ".mask"), DestTy,
3843 LhsInt->getName() + ".zext"),
3844 ConstantInt::get(DestTy, LhsOffset), "", IsLhsShlNUW && IsRhsShlNUW,
3845 IsLhsShlNSW && IsRhsShlNSW);
3847 return Res;
3848}
3849
3850
3851
3852
3853
3866
3869 if ()
3870 return std::nullopt;
3871
3872
3873 Value *Original = nullptr;
3874 const APInt *Mask = nullptr;
3875 const APInt *MulConst = nullptr;
3878 if (MulConst->isZero() || Mask->isZero())
3879 return std::nullopt;
3880
3881 return std::optional(
3882 {Original, *MulConst, *Mask,
3885 }
3886
3888 const APInt *EqZero = nullptr, *NeZero = nullptr;
3889
3890
3892 auto ICmpDecompose =
3894 false, true);
3895 if (!ICmpDecompose.has_value())
3896 return std::nullopt;
3897
3899 ICmpDecompose->C.isZero());
3900
3903
3904 if (!EqZero->isZero() || NeZero->isZero())
3905 return std::nullopt;
3906
3907 if (!ICmpDecompose->Mask.isPowerOf2() || ICmpDecompose->Mask.isZero() ||
3908 NeZero->getBitWidth() != ICmpDecompose->Mask.getBitWidth())
3909 return std::nullopt;
3910
3911 if (!NeZero->urem(ICmpDecompose->Mask).isZero())
3912 return std::nullopt;
3913
3914 return std::optional(
3915 {ICmpDecompose->X, NeZero->udiv(ICmpDecompose->Mask),
3916 ICmpDecompose->Mask, false, false});
3917 }
3918
3919 return std::nullopt;
3920}
3921
3922
3923
3924
3928 if (!Decomp1)
3929 return nullptr;
3930
3932 if (!Decomp0)
3933 return nullptr;
3934
3935 if (Decomp0->isCombineableWith(*Decomp1)) {
3936 Value *NewAnd = Builder.CreateAnd(
3937 Decomp0->X,
3938 ConstantInt::get(Decomp0->X->getType(), Decomp0->Mask + Decomp1->Mask));
3939
3940 return Builder.CreateMul(
3941 NewAnd, ConstantInt::get(NewAnd->getType(), Decomp1->Factor), "",
3942 Decomp0->NUW && Decomp1->NUW, Decomp0->NSW && Decomp1->NSW);
3943 }
3944
3945 return nullptr;
3946}
3947
3950 return Res;
3952 return Res;
3953
3954 return nullptr;
3955}
3956
3958
3961 if (Value *Res = foldDisjointOr(LHS, X))
3962 return Builder.CreateOr(Res, Y, "", true);
3963 if (Value *Res = foldDisjointOr(LHS, Y))
3964 return Builder.CreateOr(Res, X, "", true);
3965 }
3966
3968 if (Value *Res = foldDisjointOr(X, RHS))
3969 return Builder.CreateOr(Res, Y, "", true);
3970 if (Value *Res = foldDisjointOr(Y, RHS))
3971 return Builder.CreateOr(Res, X, "", true);
3972 }
3973
3974 return nullptr;
3975}
3976
3977
3978
3979
3980
3985 const APInt *C1, *C2;
3994 Constant *NewC = ConstantInt::get(X->getType(), C2->udiv(*C1));
3996 }
3997 return nullptr;
3998}
3999
4000
4001
4015 return Builder.CreateBinaryIntrinsic(Intrinsic::abs, X,
4016 Builder.getFalse());
4017 }
4018 return nullptr;
4019}
4020
4021
4022
4023
4026 SQ.getWithInstruction(&I)))
4028
4030 return &I;
4031
4033 return X;
4034
4036 return Phi;
4037
4038
4039
4041 return &I;
4042
4043
4045 return Xor;
4046
4048 return X;
4049
4051 return X;
4052
4053
4054
4057
4058
4061
4062 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
4064 if (Ty->isIntOrIntVectorTy(1)) {
4066 if (auto *R =
4067 foldAndOrOfSelectUsingImpliedCond(Op1, *SI0, false))
4068 return R;
4069 }
4071 if (auto *R =
4072 foldAndOrOfSelectUsingImpliedCond(Op0, *SI1, false))
4073 return R;
4074 }
4075 }
4076
4078 return FoldedLogic;
4079
4081 true))
4082 return BitOp;
4083
4085 return Funnel;
4086
4089
4091 return R;
4092
4094 return R;
4095
4099 true, true))
4100 return R;
4103 true, true))
4104 return R;
4105
4106 if (Value *Res = foldDisjointOr(I.getOperand(0), I.getOperand(1)))
4108
4109 if (Value *Res = reassociateDisjointOr(I.getOperand(0), I.getOperand(1)))
4111 }
4112
4114 const APInt *CV;
4117
4118
4120 return BinaryOperator::CreateXor(Or, ConstantInt::get(Ty, *CV));
4121 }
4122
4123
4124
4127 Value *IncrementY = Builder.CreateAdd(Y, ConstantInt::get(Ty, 1));
4128 return BinaryOperator::CreateMul(X, IncrementY);
4129 }
4130
4131
4135
4136
4137 const APInt *C0, *C1;
4140 if (*C0 == ~*C1) {
4141
4143 return BinaryOperator::CreateOr(Builder.CreateAnd(X, *C0), B);
4144
4146 return BinaryOperator::CreateOr(Builder.CreateAnd(X, *C1), A);
4147
4148
4150 return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C0), B);
4151
4153 return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C1), A);
4154 }
4155
4156 if ((*C0 & *C1).isZero()) {
4157
4158
4161 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);
4162 return BinaryOperator::CreateAnd(A, C01);
4163 }
4164
4165
4168 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);
4169 return BinaryOperator::CreateAnd(B, C01);
4170 }
4171
4172
4173 const APInt *C2, *C3;
4176 (*C2 & ~*C0).isZero() && (*C3 & ~*C1).isZero()) {
4178 Constant *C01 = ConstantInt::get(Ty, *C0 | *C1);
4179 return BinaryOperator::CreateAnd(Or, C01);
4180 }
4181 }
4182 }
4183
4184
4185
4186
4188
4189 if (Value *V = matchSelectFromAndOr(A, C, B, D))
4191 if (Value *V = matchSelectFromAndOr(A, C, D, B))
4193 if (Value *V = matchSelectFromAndOr(C, A, B, D))
4195 if (Value *V = matchSelectFromAndOr(C, A, D, B))
4197 if (Value *V = matchSelectFromAndOr(B, D, A, C))
4199 if (Value *V = matchSelectFromAndOr(B, D, C, A))
4201 if (Value *V = matchSelectFromAndOr(D, B, A, C))
4203 if (Value *V = matchSelectFromAndOr(D, B, C, A))
4205 }
4206 }
4207
4211
4212 if (Value *V = matchSelectFromAndOr(A, C, B, D, true))
4214 if (Value *V = matchSelectFromAndOr(A, C, D, B, true))
4216 if (Value *V = matchSelectFromAndOr(C, A, B, D, true))
4218 if (Value *V = matchSelectFromAndOr(C, A, D, B, true))
4220 }
4221
4222
4227 return BinaryOperator::CreateOr(Op0, C);
4228
4229
4234 return BinaryOperator::CreateOr(Op1, C);
4235
4237 return DeMorgan;
4238
4239
4240 bool SwappedForXor = false;
4243 SwappedForXor = true;
4244 }
4245
4247
4248
4250 return BinaryOperator::CreateOr(Op0, B);
4252 return BinaryOperator::CreateOr(Op0, A);
4253
4254
4255
4257 return BinaryOperator::CreateOr(A, B);
4258
4259
4260
4261
4265
4266
4267
4268
4278
4279
4280
4285 return BinaryOperator::CreateOr(Nand, C);
4286 }
4287 }
4288
4289 if (SwappedForXor)
4291
4292 if (Value *Res =
4293 foldBooleanAndOr(Op0, Op1, I, false, false))
4295
4298 if (auto *V = reassociateBooleanAndOr(Op0, X, Y, I, false,
4299 IsLogical))
4301 }
4304 if (auto *V = reassociateBooleanAndOr(Op1, X, Y, I, false,
4305 IsLogical))
4307 }
4308
4310 return FoldedFCmps;
4311
4312 if (Instruction *CastedOr = foldCastedBitwiseLogic(I))
4313 return CastedOr;
4314
4315 if (Instruction *Sel = foldBinopOfSextBoolToSelect(I))
4316 return Sel;
4317
4318
4319
4320
4321
4322
4324 A->getType()->isIntOrIntVectorTy(1))
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4346 return IsDisjointOuter && IsDisjointInner
4347 ? BinaryOperator::CreateDisjointOr(Inner, CI)
4348 : BinaryOperator::CreateOr(Inner, CI);
4349 }
4350
4351
4352
4353
4354 {
4355 Value *X = nullptr, *Y = nullptr;
4362 }
4363 }
4364
4365
4366 {
4375 }
4376 }
4377
4378 {
4379
4380
4381
4382
4387 return BinaryOperator::CreateXor(A, B);
4388 }
4389 return nullptr;
4390 };
4391
4392 if (Instruction *Result = TryXorOpt(Op0, Op1))
4393 return Result;
4394 if (Instruction *Result = TryXorOpt(Op1, Op0))
4395 return Result;
4396 }
4397
4400 return V;
4401
4403 Value *Mul, *Ov, *MulIsNotZero, *UMulWithOv;
4404
4405
4406
4407
4421 return BinaryOperator::CreateAnd(NotNullA, NotNullB);
4422 }
4423 }
4424
4425
4426
4427
4429 const Value *WOV;
4430 const APInt *C1, *C2;
4435 (WO->getBinaryOp() == Instruction::Add ||
4436 WO->getBinaryOp() == Instruction::Sub) &&
4440 bool Overflow;
4443 : C2->usub_ov(*C1, Overflow))
4445 : C2->uadd_ov(*C1, Overflow));
4449 return BinaryOperator::CreateOr(Ov, NewCmp);
4450 }
4451 }
4452
4453
4454
4457
4458
4460 return &I;
4461
4462
4463
4468 ConstantInt::get(Ty, Ty->getScalarSizeInBits() - 1), X);
4470 }
4471
4472
4474 Value *Start = nullptr, *Step = nullptr;
4477
4478
4479
4482
4483
4484
4485
4486
4487
4488
4489
4492 return BinaryOperator::CreateOr(
4494
4495
4496
4497
4498
4499
4500
4501
4504 return BinaryOperator::CreateOr(
4506 }
4507
4509 return R;
4510
4512 return Canonicalized;
4513
4514 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
4515 return Folded;
4516
4517 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))
4518 return Res;
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4534 .GetInsertBlock()->getParent()->hasFnAttribute(
4535 Attribute::NoImplicitFloat)) {
4539 Value *FAbs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, CastOp);
4541 return new BitCastInst(FNegFAbs, I.getType());
4542 }
4543 }
4544
4545
4549 if ((KnownX.One & *C2) == *C2)
4550 return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, *C1 | *C2));
4551 }
4552
4554 return Res;
4555
4558 false, *this))
4559 return BinaryOperator::CreateOr(V, Op1);
4562 false, *this))
4563 return BinaryOperator::CreateOr(Op0, V);
4564
4568
4571
4572 return nullptr;
4573}
4574
4575
4576
4579 assert(I.getOpcode() == Instruction::Xor);
4580 Value *Op0 = I.getOperand(0);
4581 Value *Op1 = I.getOperand(1);
4583
4584
4585
4586
4587
4588
4589
4592 return BinaryOperator::CreateXor(A, B);
4593
4594
4595
4596
4597
4600 return BinaryOperator::CreateXor(A, B);
4601
4602
4603
4604
4605
4608 return BinaryOperator::CreateXor(A, B);
4609
4610
4612 return nullptr;
4613
4614
4615
4616
4617
4618
4624
4625 return nullptr;
4626}
4627
4630 assert(I.getOpcode() == Instruction::Xor && I.getOperand(0) == LHS &&
4631 I.getOperand(1) == RHS && "Should be 'xor' with these operands");
4632
4634 Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
4635 Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
4636
4638 if (LHS0 == RHS1 && LHS1 == RHS0) {
4641 }
4642 if (LHS0 == RHS0 && LHS1 == RHS1) {
4643
4645 bool IsSigned = LHS->isSigned() || RHS->isSigned();
4647 }
4648 }
4649
4650 const APInt *LC, *RC;
4654
4655
4656
4657
4658
4659 bool TrueIfSignedL, TrueIfSignedR;
4663 Value *XorLR = Builder.CreateXor(LHS0, RHS0);
4664 return TrueIfSignedL == TrueIfSignedR ? Builder.CreateIsNeg(XorLR) :
4665 Builder.CreateIsNotNeg(XorLR);
4666 }
4667
4668
4669
4670 if (LHS0 == RHS0) {
4675 if (CRUnion && CRIntersect)
4676 if (auto CR = CRUnion->exactIntersectWith(CRIntersect->inverse())) {
4677 if (CR->isFullSet())
4679 if (CR->isEmptySet())
4681
4684 CR->getEquivalentICmp(NewPred, NewC, Offset);
4685
4688 Value *NewV = LHS0;
4690 if (.isZero())
4691 NewV = Builder.CreateAdd(NewV, ConstantInt::get(Ty, Offset));
4692 return Builder.CreateICmp(NewPred, NewV,
4693 ConstantInt::get(Ty, NewC));
4694 }
4695 }
4696 }
4697
4698
4699
4711 }
4712 }
4713
4714
4715
4716
4717
4718
4719
4721
4722
4724
4725 ICmpInst *X = nullptr, *Y = nullptr;
4726 if (OrICmp == LHS && AndICmp == RHS) {
4727
4730 }
4731 if (OrICmp == RHS && AndICmp == LHS) {
4732
4735 }
4737
4738 Y->setPredicate(Y->getInversePredicate());
4739
4740 if (->hasOneUse()) {
4741
4742
4743
4744
4746
4747 Builder.SetInsertPoint(Y->getParent(), ++(Y->getIterator()));
4748 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");
4749
4750 Worklist.pushUsersToWorkList(*Y);
4751 Y->replaceUsesWithIf(NotY,
4752 [NotY](Use &U) { return U.getUser() != NotY; });
4753 }
4754
4756 }
4757 }
4758 }
4759
4760 return nullptr;
4761}
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4785 return nullptr;
4786
4789
4790 Value *NewA = Builder.CreateAnd(D, NotM);
4791 return BinaryOperator::CreateXor(NewA, X);
4792 }
4793
4796
4797 Type *EltTy = C->getType()->getScalarType();
4799
4800 Value *LHS = Builder.CreateAnd(X, C);
4801 Value *NotC = Builder.CreateNot(C);
4802 Value *RHS = Builder.CreateAnd(B, NotC);
4803 return BinaryOperator::CreateOr(LHS, RHS);
4804 }
4805
4806 return nullptr;
4807}
4808
4812
4813
4815 return nullptr;
4816
4818 return A == C || A == D || B == C || B == D;
4819 };
4820
4822
4823
4826 Value *NotY = Builder.CreateNot(Y);
4827 return BinaryOperator::CreateOr(X, NotY);
4828 };
4829
4830
4831
4834 Value *NotX = Builder.CreateNot(X);
4835 return BinaryOperator::CreateOr(Y, NotX);
4836 };
4837
4838 return nullptr;
4839}
4840
4841
4842
4845 assert(Xor.getOpcode() == Instruction::Xor && "Expected an xor instruction.");
4846
4847
4848
4849
4850
4851 Value *Op0 = Xor.getOperand(0), *Op1 = Xor.getOperand(1);
4854
4855 Type *Ty = Xor.getType();
4857 const APInt *ShAmt;
4859 Op1->hasNUses(2) && *ShAmt == Ty->getScalarSizeInBits() - 1 &&
4861
4862
4863
4864 Value *IsNeg = Builder.CreateIsNeg(A);
4865
4867 Value *NegA = Add->hasNoUnsignedWrap()
4869 : Builder.CreateNeg(A, "", Add->hasNoSignedWrap());
4871 }
4872 return nullptr;
4873}
4874
4881
4887 Op->replaceUsesWithIf(NotOp,
4888 [NotOp](Use &U) { return U.getUser() != NotOp; });
4890 return NotOp;
4891}
4892
4893
4894
4895
4896
4897
4899 Value *Op0, *Op1;
4901 return false;
4902
4903
4904
4905 if (Op0 == Op1)
4906 return false;
4907
4908
4909
4910
4912 return false;
4913
4917
4918
4920 return false;
4921
4922
4924 return false;
4925
4928
4929 Builder.SetInsertPoint(*I.getInsertionPointAfterDef());
4930 Value *NewLogicOp;
4931 if (IsBinaryOp)
4932 NewLogicOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");
4933 else
4934 NewLogicOp =
4935 Builder.CreateLogicalOp(NewOpc, Op0, Op1, I.getName() + ".not");
4936
4938
4939
4940
4942 return true;
4943}
4944
4945
4946
4947
4948
4949
4951 Value *Op0, *Op1;
4953 return false;
4957
4958 Value *NotOp0 = nullptr;
4959 Value *NotOp1 = nullptr;
4960 Value **OpToInvert = nullptr;
4962 Op0 = NotOp0;
4963 OpToInvert = &Op1;
4966 Op1 = NotOp1;
4967 OpToInvert = &Op0;
4968 } else
4969 return false;
4970
4971
4973 return false;
4974
4975 *OpToInvert = freelyInvert(*this, *OpToInvert, &I);
4976
4977 Builder.SetInsertPoint(*I.getInsertionPointAfterDef());
4978 Value *NewBinOp;
4979 if (IsBinaryOp)
4980 NewBinOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");
4981 else
4982 NewBinOp = Builder.CreateLogicalOp(NewOpc, Op0, Op1, I.getName() + ".not");
4984
4985
4986
4988 return true;
4989}
4990
4994 return nullptr;
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5008 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");
5009 return BinaryOperator::CreateOr(X, NotY);
5010 }
5012 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");
5014 }
5015
5016
5017
5019 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");
5020 return BinaryOperator::CreateAnd(X, NotY);
5021 }
5023 Value *NotY = Builder.CreateNot(Y, Y->getName() + ".not");
5025 }
5026
5027
5028 BinaryOperator *NotVal;
5030
5031 if (match(NotVal,
5035 return BinaryOperator::CreateAnd(DecX, NotY);
5036 }
5037
5038
5040 return BinaryOperator::CreateAShr(X, Y);
5041
5042
5043
5046 return BinaryOperator::CreateAShr(X, Y);
5047
5048
5049
5052 Value *IsNotNeg = Builder.CreateIsNotNeg(X, "isnotneg");
5053 return new SExtInst(IsNotNeg, Ty);
5054 }
5055
5056
5057
5058
5059
5060
5061
5066
5067
5071
5072
5075
5076
5077
5080 return BinaryOperator::CreateAdd(Builder.CreateNot(X), Y);
5081
5082
5085 NotVal);
5086 }
5087
5088
5089 CmpPredicate Pred;
5093 nullptr))) {
5096 return &I;
5097 }
5098
5099
5103 return new BitCastInst(X, Ty);
5104 }
5105
5106
5107
5109 X->getType()->isIntOrIntVectorTy(1)) {
5112 Value *Sext = Builder.CreateSExt(NotX, SextTy);
5113 return new BitCastInst(Sext, Ty);
5114 }
5115
5118 return &I;
5119
5120
5121
5122
5124 if (II && II->hasOneUse()) {
5128 Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, NotY);
5130 }
5131
5132 if (II->getIntrinsicID() == Intrinsic::is_fpclass) {
5134 II->setArgOperand(
5135 1, ConstantInt::get(ClassMask->getType(),
5138 }
5139 }
5140
5142
5143
5144
5145
5146
5147
5148
5149
5151 Value *TV = Sel->getTrueValue();
5152 Value *FV = Sel->getFalseValue();
5155 bool InvertibleT = (CmpT && CmpT->hasOneUse()) || isa(TV);
5156 bool InvertibleF = (CmpF && CmpF->hasOneUse()) || isa(FV);
5157 if (InvertibleT && InvertibleF) {
5158 if (CmpT)
5159 CmpT->setPredicate(CmpT->getInversePredicate());
5160 else
5162 if (CmpF)
5163 CmpF->setPredicate(CmpF->getInversePredicate());
5164 else
5167 }
5168 }
5169 }
5170
5172 return NewXor;
5173
5174
5175
5178
5179 return nullptr;
5180}
5181
5182
5183
5184
5187 SQ.getWithInstruction(&I)))
5189
5191 return &I;
5192
5194 return X;
5195
5197 return Phi;
5198
5200 return NewXor;
5201
5202
5205
5206
5207
5209 return &I;
5210
5212 return R;
5213
5215 return R;
5216
5217 Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
5219
5220
5221
5225 return BinaryOperator::CreateXor(XorAC, Y);
5226
5228 return BinaryOperator::CreateXor(XorBC, X);
5229 }
5230
5231
5232
5233
5234
5238 return BinaryOperator::CreateDisjointOr(Op0, Op1);
5239 else
5240 return BinaryOperator::CreateOr(Op0, Op1);
5241 }
5242
5244 return Xor;
5245
5249
5252
5257 return BinaryOperator::CreateXor(
5259 }
5260
5261
5263
5266 }
5268
5271 }
5272
5273
5274
5275
5276
5277 const APInt *CA;
5280 *CA == X->getType()->getScalarSizeInBits() - 1 &&
5285 }
5286 }
5287
5289 {
5290 const APInt *RHSC;
5294
5296 return BinaryOperator::CreateSub(ConstantInt::get(Ty, *C + *RHSC), X);
5297
5298
5300 return BinaryOperator::CreateAdd(X, ConstantInt::get(Ty, *C + *RHSC));
5301
5302
5305 return BinaryOperator::CreateXor(X, ConstantInt::get(Ty, *C ^ *RHSC));
5306
5307
5308
5309
5311 if (II && II->hasOneUse() && *RHSC == Ty->getScalarSizeInBits() - 1) {
5313 if ((IID == Intrinsic::ctlz || IID == Intrinsic::cttz) &&
5316 IID = (IID == Intrinsic::ctlz) ? Intrinsic::cttz : Intrinsic::ctlz;
5320 }
5321 }
5322
5323
5324
5325
5329 return BinaryOperator::CreateShl(NotX, ConstantInt::get(Ty, *C));
5330 }
5331
5335 return BinaryOperator::CreateLShr(NotX, ConstantInt::get(Ty, *C));
5336 }
5337
5338
5339
5340 }
5341
5342
5343
5344
5345
5346
5347
5348
5349
5353 .GetInsertBlock()->getParent()->hasFnAttribute(
5354 Attribute::NoImplicitFloat)) {
5360 }
5361 }
5362 }
5363
5364
5365 {
5368
5373
5375 FoldConst ^= C3->getValue();
5376
5377 auto *Opnd0 = Builder.CreateLShr(X, C2);
5378 Opnd0->takeName(Op0);
5379 return BinaryOperator::CreateXor(Opnd0, ConstantInt::get(Ty, FoldConst));
5380 }
5381 }
5382
5384 return FoldedLogic;
5385
5386
5387
5389 return BinaryOperator::CreateAnd(X, Builder.CreateNot(Op0));
5390
5391
5393 return BinaryOperator::CreateAnd(X, Builder.CreateNot(Op1));
5394
5395
5396
5398 return BinaryOperator::CreateAnd(Op0, Builder.CreateNot(X));
5399
5400
5401
5402
5403
5406 return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(X));
5407
5409
5412 return BinaryOperator::CreateXor(
5414
5415
5418 return BinaryOperator::CreateXor(
5420
5421
5424 return BinaryOperator::CreateOr(A, B);
5425
5428 return BinaryOperator::CreateOr(A, B);
5429
5430
5431
5435
5436
5438 return BinaryOperator::CreateOr(A, B);
5439
5440
5443
5444
5447
5448
5449
5459 return BinaryOperator::CreateAnd(Builder.CreateXor(B, C), NotA);
5460 }
5461 }
5462
5463
5464 if (I.getType()->isIntOrIntVectorTy(1) &&
5473 if (NeedFreeze)
5477 }
5478 }
5479
5482 if (Value *V = foldXorOfICmps(LHS, RHS, I))
5484
5485 if (Instruction *CastedXor = foldCastedBitwiseLogic(I))
5486 return CastedXor;
5487
5489 return Abs;
5490
5491
5492
5493
5494
5498 return BinaryOperator::CreateXor(Builder.CreateXor(X, Y), C1);
5499
5501 return R;
5502
5504 return Canonicalized;
5505
5506 if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
5507 return Folded;
5508
5509 if (Instruction *Folded = canonicalizeConditionalNegationViaMathToSelect(I))
5510 return Folded;
5511
5512 if (Instruction *Res = foldBinOpOfDisplacedShifts(I))
5513 return Res;
5514
5516 return Res;
5517
5518 return nullptr;
5519}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isSigned(unsigned int Opcode)
static Value * foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd, bool IsLogical, InstCombiner::BuilderTy &Builder, const SimplifyQuery &Q, Instruction &I)
Reduce logic-of-compares with equality to a constant by substituting a common operand with the consta...
Definition InstCombineAndOrXor.cpp:1276
static Value * foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd, InstCombiner::BuilderTy &Builder, InstCombinerImpl &IC)
Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and fold (icmp ne ctpop(X) 1) & ...
Definition InstCombineAndOrXor.cpp:943
static Value * foldBitmaskMul(Value *Op0, Value *Op1, InstCombiner::BuilderTy &Builder)
(A & N) * C + (A & M) * C -> (A & (N + M)) & C This also accepts the equivalent select form of (A & N...
Definition InstCombineAndOrXor.cpp:3925
static unsigned conjugateICmpMask(unsigned Mask)
Convert an analysis of a masked ICmp into its equivalent if all boolean operations had the opposite s...
Definition InstCombineAndOrXor.cpp:176
static Instruction * foldNotXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:4809
static Value * foldLogOpOfMaskedICmps(Value *LHS, Value *RHS, bool IsAnd, bool IsLogical, InstCombiner::BuilderTy &Builder, const SimplifyQuery &Q)
Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...
Definition InstCombineAndOrXor.cpp:534
static Value * getFCmpValue(unsigned Code, Value *LHS, Value *RHS, InstCombiner::BuilderTy &Builder, FMFSource FMF)
This is the complement of getFCmpCode, which turns an opcode and two operands into either a FCmp inst...
Definition InstCombineAndOrXor.cpp:49
static bool matchIsFPClassLikeFCmp(Value *Op, Value *&ClassVal, uint64_t &ClassMask)
Match an fcmp against a special value that performs a test possible by llvm.is.fpclass.
Definition InstCombineAndOrXor.cpp:1580
static Value * foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1, Instruction &CxtI, InstCombiner::BuilderTy &Builder)
General pattern: X & Y.
Definition InstCombineAndOrXor.cpp:847
static Instruction * visitMaskedMerge(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
If we have a masked merge, in the canonical form of: (assuming that A only has one use....
Definition InstCombineAndOrXor.cpp:4777
static Instruction * canonicalizeAbs(BinaryOperator &Xor, InstCombiner::BuilderTy &Builder)
Canonicalize a shifty way to code absolute value to the more common pattern that uses negation and se...
Definition InstCombineAndOrXor.cpp:4843
static Value * foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd, InstCombiner::BuilderTy &Builder, InstCombinerImpl &IC)
Reduce a pair of compares that check if a value has exactly 1 bit set.
Definition InstCombineAndOrXor.cpp:973
static Value * foldUnsignedUnderflowCheck(ICmpInst *ZeroICmp, ICmpInst *UnsignedICmp, bool IsAnd, const SimplifyQuery &Q, InstCombiner::BuilderTy &Builder)
Commuted variants are assumed to be handled by calling this function again with the parameters swappe...
Definition InstCombineAndOrXor.cpp:1113
static Instruction * foldOrToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:1954
static Value * simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp, bool SimplifyOnly, InstCombinerImpl &IC, unsigned Depth=0)
Definition InstCombineAndOrXor.cpp:2355
static Instruction * matchDeMorgansLaws(BinaryOperator &I, InstCombiner &IC)
Match variations of De Morgan's Laws: (~A & ~B) == (~(A | B)) (~A | ~B) == (~(A & B))
Definition InstCombineAndOrXor.cpp:1723
static Value * foldLogOpOfMaskedICmpsAsymmetric(Value *LHS, Value *RHS, bool IsAnd, Value *A, Value *B, Value *C, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, unsigned LHSMask, unsigned RHSMask, InstCombiner::BuilderTy &Builder)
Try to fold (icmp(A & B) ==/!= 0) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...
Definition InstCombineAndOrXor.cpp:503
static Value * FoldOrOfSelectSmaxToAbs(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Fold select(X >s 0, 0, -X) | smax(X, 0) --> abs(X) select(X <s 0, -X, 0) | smax(X,...
Definition InstCombineAndOrXor.cpp:4002
static Instruction * foldAndToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:1928
static unsigned getMaskedICmpType(Value *A, Value *B, Value *C, ICmpInst::Predicate Pred)
Return the set of patterns (from MaskedICmpType) that (icmp SCC (A & B), C) satisfies.
Definition InstCombineAndOrXor.cpp:126
static Instruction * foldXorToXor(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
A ^ B can be specified using other logic ops in a variety of patterns.
Definition InstCombineAndOrXor.cpp:4577
static bool canNarrowShiftAmt(Constant *C, unsigned BitWidth)
Return true if a constant shift amount is always less than the specified bit-width.
Definition InstCombineAndOrXor.cpp:1990
static Instruction * foldLogicCastConstant(BinaryOperator &Logic, CastInst *Cast, InstCombinerImpl &IC)
Fold {and,or,xor} (cast X), C.
Definition InstCombineAndOrXor.cpp:1776
static Value * foldAndOrOfICmpEqConstantAndICmp(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, bool IsLogical, IRBuilderBase &Builder)
Definition InstCombineAndOrXor.cpp:3325
static bool canFreelyInvert(InstCombiner &IC, Value *Op, Instruction *IgnoredUser)
Definition InstCombineAndOrXor.cpp:4875
static Value * foldNegativePower2AndShiftedMask(Value *A, Value *B, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, InstCombiner::BuilderTy &Builder)
Try to fold (icmp(A & B) == 0) & (icmp(A & D) != E) into (icmp A u< D) iff B is a contiguous set of o...
Definition InstCombineAndOrXor.cpp:1015
static Value * matchIsFiniteTest(InstCombiner::BuilderTy &Builder, FCmpInst *LHS, FCmpInst *RHS)
and (fcmp ord x, 0), (fcmp u* x, inf) -> fcmp o* x, inf
Definition InstCombineAndOrXor.cpp:1434
static Value * foldPowerOf2AndShiftedMask(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd, InstCombiner::BuilderTy &Builder)
Try to fold ((icmp X u< P) & (icmp(X & M) != M)) or ((icmp X s> -1) & (icmp(X & M) !...
Definition InstCombineAndOrXor.cpp:1081
static Value * stripSignOnlyFPOps(Value *Val)
Ignore all operations which only change the sign of a value, returning the underlying magnitude value...
Definition InstCombineAndOrXor.cpp:1413
static Value * foldOrUnsignedUMulOverflowICmp(BinaryOperator &I, InstCombiner::BuilderTy &Builder, const DataLayout &DL)
Fold Res, Overflow = (umul.with.overflow x c1); (or Overflow (ugt Res c2)) --> (ugt x (c2/c1)).
Definition InstCombineAndOrXor.cpp:3981
static Value * freelyInvert(InstCombinerImpl &IC, Value *Op, Instruction *IgnoredUser)
Definition InstCombineAndOrXor.cpp:4882
static Value * foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(Value *LHS, Value *RHS, bool IsAnd, Value *A, Value *B, Value *D, Value *E, ICmpInst::Predicate PredL, ICmpInst::Predicate PredR, InstCombiner::BuilderTy &Builder)
Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single (icmp(A & X) ==/!...
Definition InstCombineAndOrXor.cpp:353
static std::optional< IntPart > matchIntPart(Value *V)
Match an extraction of bits from an integer.
Definition InstCombineAndOrXor.cpp:1159
static Instruction * canonicalizeLogicFirst(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:2212
static Instruction * reassociateFCmps(BinaryOperator &BO, InstCombiner::BuilderTy &Builder)
This a limited reassociation for a special case (see above) where we are checking if two values are e...
Definition InstCombineAndOrXor.cpp:1682
static Value * getNewICmpValue(unsigned Code, bool Sign, Value *LHS, Value *RHS, InstCombiner::BuilderTy &Builder)
This is the complement of getICmpCode, which turns an opcode and two operands into either a constant ...
Definition InstCombineAndOrXor.cpp:39
static Value * extractIntPart(const IntPart &P, IRBuilderBase &Builder)
Materialize an extraction of bits from an integer in IR.
Definition InstCombineAndOrXor.cpp:1177
static bool matchUnorderedInfCompare(FCmpInst::Predicate P, Value *LHS, Value *RHS)
Matches fcmp u__ x, +/-inf.
Definition InstCombineAndOrXor.cpp:1426
static bool matchIsNotNaN(FCmpInst::Predicate P, Value *LHS, Value *RHS)
Matches canonical form of isnan, fcmp ord x, 0.
Definition InstCombineAndOrXor.cpp:1421
static bool areInverseVectorBitmasks(Constant *C1, Constant *C2)
If all elements of two constant vectors are 0/-1 and inverses, return true.
Definition InstCombineAndOrXor.cpp:3186
MaskedICmpType
Classify (icmp eq (A & B), C) and (icmp ne (A & B), C) as matching patterns that can be simplified.
Definition InstCombineAndOrXor.cpp:111
@ BMask_NotMixed
Definition InstCombineAndOrXor.cpp:121
@ AMask_NotMixed
Definition InstCombineAndOrXor.cpp:119
@ BMask_NotAllOnes
Definition InstCombineAndOrXor.cpp:115
@ Mask_AllZeros
Definition InstCombineAndOrXor.cpp:116
@ BMask_Mixed
Definition InstCombineAndOrXor.cpp:120
@ BMask_AllOnes
Definition InstCombineAndOrXor.cpp:114
@ AMask_NotAllOnes
Definition InstCombineAndOrXor.cpp:113
@ AMask_AllOnes
Definition InstCombineAndOrXor.cpp:112
@ Mask_NotAllZeros
Definition InstCombineAndOrXor.cpp:117
@ AMask_Mixed
Definition InstCombineAndOrXor.cpp:118
static Instruction * foldComplexAndOrPatterns(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Try folding relatively complex patterns for both And and Or operations with all And and Or swapped.
Definition InstCombineAndOrXor.cpp:2038
static bool matchZExtedSubInteger(Value *V, Value *&Int, APInt &Mask, uint64_t &Offset, bool &IsShlNUW, bool &IsShlNSW)
Match V as "lshr -> mask -> zext -> shl".
Definition InstCombineAndOrXor.cpp:3780
static std::optional< DecomposedBitMaskMul > matchBitmaskMul(Value *V)
Definition InstCombineAndOrXor.cpp:3867
static Value * foldOrOfInversions(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:3612
static bool matchSubIntegerPackFromVector(Value *V, Value *&Vec, int64_t &VecOffset, SmallBitVector &Mask, const DataLayout &DL)
Match V as "shufflevector -> bitcast" or "extractelement -> zext -> shl" patterns,...
Definition InstCombineAndOrXor.cpp:3640
static Instruction * matchFunnelShift(Instruction &Or, InstCombinerImpl &IC)
Match UB-safe variants of the funnel shift intrinsic.
Definition InstCombineAndOrXor.cpp:3111
static Instruction * reassociateForUses(BinaryOperator &BO, InstCombinerImpl::BuilderTy &Builder)
Try to reassociate a pair of binops so that values with one use only are part of the same instruction...
Definition InstCombineAndOrXor.cpp:2179
static Value * matchOrConcat(Instruction &Or, InstCombiner::BuilderTy &Builder)
Attempt to combine or(zext(x),shl(zext(y),bw/2) concat packing patterns.
Definition InstCombineAndOrXor.cpp:3123
static Value * foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder, ICmpInst *LHS, ICmpInst *RHS, bool IsAnd, const SimplifyQuery &Q)
Definition InstCombineAndOrXor.cpp:784
static Instruction * foldBitwiseLogicWithIntrinsics(BinaryOperator &I, InstCombiner::BuilderTy &Builder)
Definition InstCombineAndOrXor.cpp:2300
static std::optional< std::pair< unsigned, unsigned > > getMaskedTypeForICmpPair(Value *&A, Value *&B, Value *&C, Value *&D, Value *&E, Value *LHS, Value *RHS, ICmpInst::Predicate &PredL, ICmpInst::Predicate &PredR)
Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).
Definition InstCombineAndOrXor.cpp:210
static Instruction * foldIntegerPackFromVector(Instruction &I, InstCombiner::BuilderTy &Builder, const DataLayout &DL)
Try to fold the join of two scalar integers whose contents are packed elements of the same vector.
Definition InstCombineAndOrXor.cpp:3743
static Value * foldIntegerRepackThroughZExt(Value *Lhs, Value *Rhs, InstCombiner::BuilderTy &Builder)
Try to fold the join of two scalar integers whose bits are unpacked and zexted from the same source i...
Definition InstCombineAndOrXor.cpp:3821
This file provides internal interfaces used to implement the InstCombine.
This file provides the interface for the instcombine pass implementation.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
This file implements the SmallBitVector class.
static unsigned getScalarSizeInBits(Type *Ty)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static constexpr int Concat[]
The Input class is used to parse a yaml document into in-memory structs and vectors.
static LLVM_ABI bool hasSignBitInMSB(const fltSemantics &)
bool bitwiseIsEqual(const APFloat &RHS) const
APInt bitcastToAPInt() const
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
Class for arbitrary precision integers.
LLVM_ABI APInt udiv(const APInt &RHS) const
Unsigned division operation.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
unsigned countLeadingOnes() const
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
LLVM_ABI APInt usub_ov(const APInt &RHS, bool &Overflow) const
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
LLVM_ABI APInt sadd_ov(const APInt &RHS, bool &Overflow) const
bool intersects(const APInt &RHS) const
This operation tests if there are any pairs of corresponding bits between this APInt and RHS that are...
int32_t exactLogBase2() const
LLVM_ABI APInt reverseBits() const
LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countLeadingZeros() const
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
APInt shl(unsigned shiftAmt) const
Left-shift function.
LLVM_ABI APInt byteSwap() const
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
LLVM_ABI APInt ssub_ov(const APInt &RHS, bool &Overflow) const
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
void clearSignBit()
Set the sign bit to 0.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM_ABI bool isSigned() const
Whether the intrinsic is signed or unsigned.
LLVM_ABI Instruction::BinaryOps getBinaryOp() const
Returns the binary operation underlying the intrinsic.
BinaryOps getOpcode() const
static LLVM_ABI BinaryOperator * CreateNot(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)
static LLVM_ABI 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.
static BinaryOperator * CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, Value *CopyO, const Twine &Name="", InsertPosition InsertBefore=nullptr)
This class represents a no-op cast from one type to another.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is the base class for all instructions that perform data casts.
Type * getSrcTy() const
Return the source type, as a convenience.
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
static LLVM_ABI 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 ...
Type * getDestTy() const
Return the destination type, as a convenience.
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ 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
@ 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
@ ICMP_ULT
unsigned less than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
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 LLVM_ABI bool isUnordered(Predicate predicate)
Determine if the predicate is an unordered operation.
static Predicate getOrderedPredicate(Predicate Pred)
Returns the ordered variant of a floating point compare.
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getNot(Constant *C)
static LLVM_ABI Constant * getXor(Constant *C1, Constant *C2)
static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getExactLogBase2(Constant *C)
If C is a scalar/fixed width vector of known powers of 2, then this function returns a new scalar/fix...
static LLVM_ABI Constant * getZero(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
LLVM_ABI std::optional< ConstantRange > exactUnionWith(const ConstantRange &CR) const
Union the two ranges and return the result if it can be represented exactly, otherwise return std::nu...
LLVM_ABI ConstantRange subtract(const APInt &CI) const
Subtract the specified constant from the endpoints of this constant range.
static LLVM_ABI 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...
LLVM_ABI std::optional< ConstantRange > exactIntersectWith(const ConstantRange &CR) const
Intersect the two ranges and return the result if it can be represented exactly, otherwise return std...
This is an important base class in LLVM.
static LLVM_ABI Constant * replaceUndefsWith(Constant *C, Constant *Replacement)
Try to replace undefined constant C or undefined elements in C with Replacement.
static LLVM_ABI Constant * mergeUndefsWith(Constant *C, Constant *Other)
Merges undefs of a Constant with another Constant, along with the undefs already present.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
LLVM_ABI bool isZeroValue() const
Return true if the value is negative zero or null value.
A parsed version of the target data layout string in and methods for querying it.
This instruction compares its operands according to the predicate given to the constructor.
This provides a helper for copying FMF from an instruction or setting specified flags.
static FMFSource intersect(Value *A, Value *B)
Intersect the FMF from two instructions.
This instruction compares its operands according to the predicate given to the constructor.
Predicate getSignedPredicate() const
For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
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.
Common base class shared among various IRBuilders.
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Instruction * canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(BinaryOperator &I)
Instruction * foldBinOpIntoSelectOrPhi(BinaryOperator &I)
This is a convenience wrapper function for the above two functions.
Instruction * visitOr(BinaryOperator &I)
Definition InstCombineAndOrXor.cpp:4024
bool SimplifyAssociativeOrCommutative(BinaryOperator &I)
Performs a few simplifications for operators which are associative or commutative.
Value * foldUsingDistributiveLaws(BinaryOperator &I)
Tries to simplify binary operations which some other binary operation distributes over.
Instruction * foldBinOpShiftWithShift(BinaryOperator &I)
Value * insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi, bool isSigned, bool Inside)
Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise (V < Lo || V >= Hi).
Definition InstCombineAndOrXor.cpp:60
bool sinkNotIntoLogicalOp(Instruction &I)
Definition InstCombineAndOrXor.cpp:4898
std::optional< std::pair< Intrinsic::ID, SmallVector< Value *, 3 > > > convertOrOfShiftsToFunnelShift(Instruction &Or)
Definition InstCombineAndOrXor.cpp:2925
Instruction * visitAnd(BinaryOperator &I)
Definition InstCombineAndOrXor.cpp:2416
bool sinkNotIntoOtherHandOfLogicalOp(Instruction &I)
Definition InstCombineAndOrXor.cpp:4950
Instruction * foldBinopWithPhiOperands(BinaryOperator &BO)
For a binary operator with 2 phi operands, try to hoist the binary operation before the phi.
Instruction * foldAddLikeCommutative(Value *LHS, Value *RHS, bool NSW, bool NUW)
Common transforms for add / disjoint or.
Value * simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted)
Try to fold a signed range checked with lower bound 0 to an unsigned icmp.
Definition InstCombineAndOrXor.cpp:724
Instruction * tryFoldInstWithCtpopWithNot(Instruction *I)
Value * SimplifyAddWithRemainder(BinaryOperator &I)
Tries to simplify add operations using the definition of remainder.
Instruction * visitXor(BinaryOperator &I)
Definition InstCombineAndOrXor.cpp:5185
bool SimplifyDemandedInstructionBits(Instruction &Inst)
Tries to simplify operands to an integer instruction based on its demanded bits.
Instruction * foldVectorBinop(BinaryOperator &Inst)
Canonicalize the position of binops relative to shufflevector.
Instruction * matchBSwapOrBitReverse(Instruction &I, bool MatchBSwaps, bool MatchBitReversals)
Given an initial instruction, check to see if it is the root of a bswap/bitreverse idiom.
Definition InstCombineAndOrXor.cpp:2907
void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser=nullptr)
Freely adapt every user of V as-if V was changed to !V.
The core instruction combiner logic.
const DataLayout & getDataLayout() const
IRBuilder< TargetFolder, IRBuilderCallbackInserter > BuilderTy
An IRBuilder that automatically inserts new instructions into the worklist.
bool isFreeToInvert(Value *V, bool WillInvertAllUses, bool &DoesConsume)
Return true if the specified value is free to invert (apply ~ to).
unsigned ComputeNumSignBits(const Value *Op, const Instruction *CxtI=nullptr, unsigned Depth=0) const
Instruction * replaceInstUsesWith(Instruction &I, Value *V)
A combiner-aware RAUW-like routine.
InstructionWorklist & Worklist
A worklist of the instructions that need to be simplified.
void computeKnownBits(const Value *V, KnownBits &Known, const Instruction *CxtI, unsigned Depth=0) const
static Value * peekThroughBitcast(Value *V, bool OneUseOnly=false)
Return the source operand of a potentially bitcasted value while optionally checking if it has one us...
bool canFreelyInvertAllUsersOf(Instruction *V, Value *IgnoredUser)
Given i1 V, can every user of V be freely adapted if V is changed to !V ?
void addToWorklist(Instruction *I)
bool MaskedValueIsZero(const Value *V, const APInt &Mask, const Instruction *CxtI=nullptr, unsigned Depth=0) const
Value * getFreelyInverted(Value *V, bool WillInvertAllUses, BuilderTy *Builder, bool &DoesConsume)
const SimplifyQuery & getSimplifyQuery() const
bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero=false, const Instruction *CxtI=nullptr, unsigned Depth=0)
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
This class represents a sign extension of integer types.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
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.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
LLVM_ABI const fltSemantics & getFltSemantics() const
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
iterator_range< user_iterator > users()
LLVM_ABI bool hasNUsesOrMore(unsigned N) const
Return true if this value has N uses or more.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Represents an op.with.overflow intrinsic.
This class represents zero extension of integer types.
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const APInt & umin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be unsigned.
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.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
cst_pred_ty< is_lowbit_mask > m_LowBitMask()
Match an integer or vector with only the low bit(s) set.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
cst_pred_ty< is_negative > m_Negative()
Match an integer or vector of negative values.
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)
cst_pred_ty< is_sign_mask > m_SignMask()
Match an integer or vector with only the sign bit(s) set.
BinaryOp_match< LHS, RHS, Instruction::AShr > m_AShr(const LHS &L, const RHS &R)
cstfp_pred_ty< is_inf > m_Inf()
Match a positive or negative infinity FP constant.
m_Intrinsic_Ty< Opnd0 >::Ty m_BitReverse(const Opnd0 &Op0)
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)
auto m_LogicalOp()
Matches either L && R or L || R where L and R are arbitrary values.
class_match< Constant > m_Constant()
Match an arbitrary Constant and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
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)
ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(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)
cst_pred_ty< is_shifted_mask > m_ShiftedMask()
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.
DisjointOr_match< LHS, RHS > m_DisjointOr(const LHS &L, const RHS &R)
constantexpr_match m_ConstantExpr()
Match a constant expression or a constant that contains a constant expression.
specific_intval< true > m_SpecificIntAllowPoison(const APInt &V)
ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
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.
TwoOps_match< Val_t, Idx_t, Instruction::ExtractElement > m_ExtractElt(const Val_t &Val, const Idx_t &Idx)
Matches ExtractElementInst.
cst_pred_ty< is_nonnegative > m_NonNegative()
Match an integer or vector of non-negative values.
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.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_IntrinsicIntrinsic::fabs(m_Value(X))
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
match_combine_or< CastInst_match< OpTy, SExtInst >, OpTy > m_SExtOrSelf(const OpTy &Op)
ExtractValue_match< Ind, Val_t > m_ExtractValue(const Val_t &V)
Match a single index ExtractValue instruction.
BinOpPred_match< LHS, RHS, is_logical_shift_op > m_LogicalShift(const LHS &L, const RHS &R)
Matches logical shift operations.
ShiftLike_match< LHS, Instruction::Shl > m_ShlOrSelf(const LHS &L, uint64_t &R)
Matches shl L, ConstShAmt or L itself (R will be set to zero in this case).
bind_ty< WithOverflowInst > m_WithOverflowInst(WithOverflowInst *&I)
Match a with overflow intrinsic, capturing it if we match.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
SpecificCmpClass_match< LHS, RHS, CmpInst > m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(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()...
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
class_match< CmpInst > m_Cmp()
Matches any compare instruction and ignore it.
cst_pred_ty< is_negated_power2 > m_NegatedPower2()
Match a integer or vector negated power-of-2.
match_immconstant_ty m_ImmConstant()
Match an arbitrary immediate Constant and ignore it.
DisjointOr_match< LHS, RHS, true > m_c_DisjointOr(const LHS &L, const RHS &R)
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.
SpecificCmpClass_match< LHS, RHS, FCmpInst > m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
match_combine_or< BinaryOp_match< LHS, RHS, Instruction::Add >, DisjointOr_match< LHS, RHS > > m_AddLike(const LHS &L, const RHS &R)
Match either "add" or "or disjoint".
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
match_combine_or< match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty, true >, MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty, true > >, match_combine_or< MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty, true >, MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty, true > > > m_c_MaxOrMin(const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, SExtInst >, NNegZExt_match< OpTy > > m_SExtLike(const OpTy &Op)
Match either "sext" or "zext nneg".
MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)
cst_pred_ty< is_maxsignedvalue > m_MaxSignedValue()
Match an integer or vector with values having all bits except for the high bit set (0x7f....
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)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinOpPred_match< LHS, RHS, is_shift_op > m_Shift(const LHS &L, const RHS &R)
Matches shift operations.
cstfp_pred_ty< is_pos_zero_fp > m_PosZeroFP()
Match a floating-point positive zero.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
m_Intrinsic_Ty< Opnd0 >::Ty m_BSwap(const Opnd0 &Op0)
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.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
ElementWiseBitCast_match< OpTy > m_ElementWiseBitCast(const OpTy &Op)
m_Intrinsic_Ty< Opnd0 >::Ty m_FAbs(const Opnd0 &Op0)
m_Intrinsic_Ty< Opnd0, Opnd1 >::Ty m_CopySign(const Opnd0 &Op0, const Opnd1 &Op1)
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
match_unless< Ty > m_Unless(const Ty &M)
Match if the inner matcher does NOT match.
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.
NodeAddr< CodeNode * > Code
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Intrinsic::ID getInverseMinMaxIntrinsic(Intrinsic::ID MinMaxID)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
Constant * getPredForFCmpCode(unsigned Code, Type *OpTy, CmpInst::Predicate &Pred)
This is the complement of getFCmpCode.
LLVM_ABI 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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2)
Return true if both predicates match sign or if at least one of them is an equality comparison (which...
LLVM_ABI 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.
LLVM_ABI Value * simplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for an Or, fold the result or return null.
LLVM_ABI Value * simplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for an Xor, fold the result or return null.
LLVM_ABI 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.
LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start, Value *&Step)
Attempt to match a simple first order recurrence cycle of the form: iv = phi Ty [Start,...
LLVM_ABI bool isKnownNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the given value is known be negative (i.e.
LLVM_ABI Constant * getLosslessUnsignedTrunc(Constant *C, Type *DestTy, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)
LLVM_ABI bool recognizeBSwapOrBitReverseIdiom(Instruction *I, bool MatchBSwaps, bool MatchBitReversals, SmallVectorImpl< Instruction * > &InsertedInsts)
Try to match a bswap or bitreverse idiom.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI Value * simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for an ICmpInst, fold the result or return null.
LLVM_ABI Constant * getLosslessSignedTrunc(Constant *C, Type *DestTy, const DataLayout &DL, PreservedCastFlags *Flags=nullptr)
LLVM_ABI Value * simplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for an And, fold the result or return null.
LLVM_ABI bool isKnownInversion(const Value *X, const Value *Y)
Return true iff:
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
constexpr int PoisonMaskElem
LLVM_ABI Value * simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a BinaryOperator, fold the result or return null.
std::optional< DecomposedBitTest > decomposeBitTest(Value *Cond, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
APFloat neg(APFloat X)
Returns the negated value of the argument.
cl::opt< bool > ProfcheckDisableMetadataFixes("profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), cl::desc("Disable metadata propagation fixes discovered through Issue #147390"))
unsigned getICmpCode(CmpInst::Predicate Pred)
Encode a icmp predicate into a three bit mask.
LLVM_ABI bool isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL, bool OrZero=false, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return true if the given value is known to have exactly one bit set when defined.
LLVM_ABI 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.
std::pair< Value *, FPClassTest > fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS, Value *RHS, bool LookThroughSrc=true)
Returns a pair of values, which if passed to llvm.is.fpclass, returns the same result as an fcmp with...
unsigned getFCmpCode(CmpInst::Predicate CC)
Similar to getICmpCode but for FCmpInst.
std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
Constant * getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy, CmpInst::Predicate &Pred)
This is the complement of getICmpCode.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Value * X
Definition InstCombineAndOrXor.cpp:3855
bool NSW
Definition InstCombineAndOrXor.cpp:3859
APInt Factor
Definition InstCombineAndOrXor.cpp:3856
APInt Mask
Definition InstCombineAndOrXor.cpp:3857
bool isCombineableWith(const DecomposedBitMaskMul Other)
Definition InstCombineAndOrXor.cpp:3861
bool NUW
Definition InstCombineAndOrXor.cpp:3858
unsigned NumBits
Definition InstCombineAndOrXor.cpp:1155
Value * From
Definition InstCombineAndOrXor.cpp:1153
unsigned StartBit
Definition InstCombineAndOrXor.cpp:1154
bool isNonNegative() const
Returns true if this value is known to be non-negative.
APInt getMaxValue() const
Return the maximal unsigned value possible given these KnownBits.
SimplifyQuery getWithInstruction(const Instruction *I) const