forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathInstCombineAndOrXor.cpp
5031 lines (4439 loc) · 199 KB
/
InstCombineAndOrXor.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
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
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===- InstCombineAndOrXor.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the visitAnd, visitOr, and visitXor functions.
//
//===----------------------------------------------------------------------===//
#include "InstCombineInternal.h"
#include "llvm/Analysis/CmpInstAnalysis.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/InstCombine/InstCombiner.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
using namespace PatternMatch;
#define DEBUG_TYPE "instcombine"
/// This is the complement of getICmpCode, which turns an opcode and two
/// operands into either a constant true or false, or a brand new ICmp
/// instruction. The sign is passed in to determine which kind of predicate to
/// use in the new icmp instruction.
static Value *getNewICmpValue(unsigned Code, bool Sign, Value *LHS, Value *RHS,
InstCombiner::BuilderTy &Builder) {
ICmpInst::Predicate NewPred;
if (Constant *TorF = getPredForICmpCode(Code, Sign, LHS->getType(), NewPred))
return TorF;
return Builder.CreateICmp(NewPred, LHS, RHS);
}
/// This is the complement of getFCmpCode, which turns an opcode and two
/// operands into either a FCmp instruction, or a true/false constant.
static Value *getFCmpValue(unsigned Code, Value *LHS, Value *RHS,
InstCombiner::BuilderTy &Builder, FMFSource FMF) {
FCmpInst::Predicate NewPred;
if (Constant *TorF = getPredForFCmpCode(Code, LHS->getType(), NewPred))
return TorF;
return Builder.CreateFCmpFMF(NewPred, LHS, RHS, FMF);
}
/// Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise
/// (V < Lo || V >= Hi). This method expects that Lo < Hi. IsSigned indicates
/// whether to treat V, Lo, and Hi as signed or not.
Value *InstCombinerImpl::insertRangeTest(Value *V, const APInt &Lo,
const APInt &Hi, bool isSigned,
bool Inside) {
assert((isSigned ? Lo.slt(Hi) : Lo.ult(Hi)) &&
"Lo is not < Hi in range emission code!");
Type *Ty = V->getType();
// V >= Min && V < Hi --> V < Hi
// V < Min || V >= Hi --> V >= Hi
ICmpInst::Predicate Pred = Inside ? ICmpInst::ICMP_ULT : ICmpInst::ICMP_UGE;
if (isSigned ? Lo.isMinSignedValue() : Lo.isMinValue()) {
Pred = isSigned ? ICmpInst::getSignedPredicate(Pred) : Pred;
return Builder.CreateICmp(Pred, V, ConstantInt::get(Ty, Hi));
}
// V >= Lo && V < Hi --> V - Lo u< Hi - Lo
// V < Lo || V >= Hi --> V - Lo u>= Hi - Lo
Value *VMinusLo =
Builder.CreateSub(V, ConstantInt::get(Ty, Lo), V->getName() + ".off");
Constant *HiMinusLo = ConstantInt::get(Ty, Hi - Lo);
return Builder.CreateICmp(Pred, VMinusLo, HiMinusLo);
}
/// Classify (icmp eq (A & B), C) and (icmp ne (A & B), C) as matching patterns
/// that can be simplified.
/// One of A and B is considered the mask. The other is the value. This is
/// described as the "AMask" or "BMask" part of the enum. If the enum contains
/// only "Mask", then both A and B can be considered masks. If A is the mask,
/// then it was proven that (A & C) == C. This is trivial if C == A or C == 0.
/// If both A and C are constants, this proof is also easy.
/// For the following explanations, we assume that A is the mask.
///
/// "AllOnes" declares that the comparison is true only if (A & B) == A or all
/// bits of A are set in B.
/// Example: (icmp eq (A & 3), 3) -> AMask_AllOnes
///
/// "AllZeros" declares that the comparison is true only if (A & B) == 0 or all
/// bits of A are cleared in B.
/// Example: (icmp eq (A & 3), 0) -> Mask_AllZeroes
///
/// "Mixed" declares that (A & B) == C and C might or might not contain any
/// number of one bits and zero bits.
/// Example: (icmp eq (A & 3), 1) -> AMask_Mixed
///
/// "Not" means that in above descriptions "==" should be replaced by "!=".
/// Example: (icmp ne (A & 3), 3) -> AMask_NotAllOnes
///
/// If the mask A contains a single bit, then the following is equivalent:
/// (icmp eq (A & B), A) equals (icmp ne (A & B), 0)
/// (icmp ne (A & B), A) equals (icmp eq (A & B), 0)
enum MaskedICmpType {
AMask_AllOnes = 1,
AMask_NotAllOnes = 2,
BMask_AllOnes = 4,
BMask_NotAllOnes = 8,
Mask_AllZeros = 16,
Mask_NotAllZeros = 32,
AMask_Mixed = 64,
AMask_NotMixed = 128,
BMask_Mixed = 256,
BMask_NotMixed = 512
};
/// Return the set of patterns (from MaskedICmpType) that (icmp SCC (A & B), C)
/// satisfies.
static unsigned getMaskedICmpType(Value *A, Value *B, Value *C,
ICmpInst::Predicate Pred) {
const APInt *ConstA = nullptr, *ConstB = nullptr, *ConstC = nullptr;
match(A, m_APInt(ConstA));
match(B, m_APInt(ConstB));
match(C, m_APInt(ConstC));
bool IsEq = (Pred == ICmpInst::ICMP_EQ);
bool IsAPow2 = ConstA && ConstA->isPowerOf2();
bool IsBPow2 = ConstB && ConstB->isPowerOf2();
unsigned MaskVal = 0;
if (ConstC && ConstC->isZero()) {
// if C is zero, then both A and B qualify as mask
MaskVal |= (IsEq ? (Mask_AllZeros | AMask_Mixed | BMask_Mixed)
: (Mask_NotAllZeros | AMask_NotMixed | BMask_NotMixed));
if (IsAPow2)
MaskVal |= (IsEq ? (AMask_NotAllOnes | AMask_NotMixed)
: (AMask_AllOnes | AMask_Mixed));
if (IsBPow2)
MaskVal |= (IsEq ? (BMask_NotAllOnes | BMask_NotMixed)
: (BMask_AllOnes | BMask_Mixed));
return MaskVal;
}
if (A == C) {
MaskVal |= (IsEq ? (AMask_AllOnes | AMask_Mixed)
: (AMask_NotAllOnes | AMask_NotMixed));
if (IsAPow2)
MaskVal |= (IsEq ? (Mask_NotAllZeros | AMask_NotMixed)
: (Mask_AllZeros | AMask_Mixed));
} else if (ConstA && ConstC && ConstC->isSubsetOf(*ConstA)) {
MaskVal |= (IsEq ? AMask_Mixed : AMask_NotMixed);
}
if (B == C) {
MaskVal |= (IsEq ? (BMask_AllOnes | BMask_Mixed)
: (BMask_NotAllOnes | BMask_NotMixed));
if (IsBPow2)
MaskVal |= (IsEq ? (Mask_NotAllZeros | BMask_NotMixed)
: (Mask_AllZeros | BMask_Mixed));
} else if (ConstB && ConstC && ConstC->isSubsetOf(*ConstB)) {
MaskVal |= (IsEq ? BMask_Mixed : BMask_NotMixed);
}
return MaskVal;
}
/// Convert an analysis of a masked ICmp into its equivalent if all boolean
/// operations had the opposite sense. Since each "NotXXX" flag (recording !=)
/// is adjacent to the corresponding normal flag (recording ==), this just
/// involves swapping those bits over.
static unsigned conjugateICmpMask(unsigned Mask) {
unsigned NewMask;
NewMask = (Mask & (AMask_AllOnes | BMask_AllOnes | Mask_AllZeros |
AMask_Mixed | BMask_Mixed))
<< 1;
NewMask |= (Mask & (AMask_NotAllOnes | BMask_NotAllOnes | Mask_NotAllZeros |
AMask_NotMixed | BMask_NotMixed))
>> 1;
return NewMask;
}
// Adapts the external decomposeBitTestICmp for local use.
static bool decomposeBitTestICmp(Value *Cond, CmpInst::Predicate &Pred,
Value *&X, Value *&Y, Value *&Z) {
auto Res = llvm::decomposeBitTest(Cond, /*LookThroughTrunc=*/true,
/*AllowNonZeroC=*/true);
if (!Res)
return false;
Pred = Res->Pred;
X = Res->X;
Y = ConstantInt::get(X->getType(), Res->Mask);
Z = ConstantInt::get(X->getType(), Res->C);
return true;
}
/// Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).
/// Return the pattern classes (from MaskedICmpType) for the left hand side and
/// the right hand side as a pair.
/// LHS and RHS are the left hand side and the right hand side ICmps and PredL
/// and PredR are their predicates, respectively.
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) {
// Here comes the tricky part:
// LHS might be of the form L11 & L12 == X, X == L21 & L22,
// and L11 & L12 == L21 & L22. The same goes for RHS.
// Now we must find those components L** and R**, that are equal, so
// that we can extract the parameters A, B, C, D, and E for the canonical
// above.
// Check whether the icmp can be decomposed into a bit test.
Value *L1, *L11, *L12, *L2, *L21, *L22;
if (decomposeBitTestICmp(LHS, PredL, L11, L12, L2)) {
L21 = L22 = L1 = nullptr;
} else {
auto *LHSCMP = dyn_cast<ICmpInst>(LHS);
if (!LHSCMP)
return std::nullopt;
// Don't allow pointers. Splat vectors are fine.
if (!LHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())
return std::nullopt;
PredL = LHSCMP->getPredicate();
L1 = LHSCMP->getOperand(0);
L2 = LHSCMP->getOperand(1);
// Look for ANDs in the LHS icmp.
if (!match(L1, m_And(m_Value(L11), m_Value(L12)))) {
// Any icmp can be viewed as being trivially masked; if it allows us to
// remove one, it's worth it.
L11 = L1;
L12 = Constant::getAllOnesValue(L1->getType());
}
if (!match(L2, m_And(m_Value(L21), m_Value(L22)))) {
L21 = L2;
L22 = Constant::getAllOnesValue(L2->getType());
}
}
// Bail if LHS was a icmp that can't be decomposed into an equality.
if (!ICmpInst::isEquality(PredL))
return std::nullopt;
Value *R11, *R12, *R2;
if (decomposeBitTestICmp(RHS, PredR, R11, R12, R2)) {
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11;
D = R12;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12;
D = R11;
} else {
return std::nullopt;
}
E = R2;
} else {
auto *RHSCMP = dyn_cast<ICmpInst>(RHS);
if (!RHSCMP)
return std::nullopt;
// Don't allow pointers. Splat vectors are fine.
if (!RHSCMP->getOperand(0)->getType()->isIntOrIntVectorTy())
return std::nullopt;
PredR = RHSCMP->getPredicate();
Value *R1 = RHSCMP->getOperand(0);
R2 = RHSCMP->getOperand(1);
bool Ok = false;
if (!match(R1, m_And(m_Value(R11), m_Value(R12)))) {
// As before, model no mask as a trivial mask if it'll let us do an
// optimization.
R11 = R1;
R12 = Constant::getAllOnesValue(R1->getType());
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11;
D = R12;
E = R2;
Ok = true;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12;
D = R11;
E = R2;
Ok = true;
}
// Avoid matching against the -1 value we created for unmasked operand.
if (Ok && match(A, m_AllOnes()))
Ok = false;
// Look for ANDs on the right side of the RHS icmp.
if (!Ok) {
if (!match(R2, m_And(m_Value(R11), m_Value(R12)))) {
R11 = R2;
R12 = Constant::getAllOnesValue(R2->getType());
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11;
D = R12;
E = R1;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12;
D = R11;
E = R1;
} else {
return std::nullopt;
}
}
}
// Bail if RHS was a icmp that can't be decomposed into an equality.
if (!ICmpInst::isEquality(PredR))
return std::nullopt;
if (L11 == A) {
B = L12;
C = L2;
} else if (L12 == A) {
B = L11;
C = L2;
} else if (L21 == A) {
B = L22;
C = L1;
} else if (L22 == A) {
B = L21;
C = L1;
}
unsigned LeftType = getMaskedICmpType(A, B, C, PredL);
unsigned RightType = getMaskedICmpType(A, D, E, PredR);
return std::optional<std::pair<unsigned, unsigned>>(
std::make_pair(LeftType, RightType));
}
/// Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E) into a single
/// (icmp(A & X) ==/!= Y), where the left-hand side is of type Mask_NotAllZeros
/// and the right hand side is of type BMask_Mixed. For example,
/// (icmp (A & 12) != 0) & (icmp (A & 15) == 8) -> (icmp (A & 15) == 8).
/// Also used for logical and/or, must be poison safe.
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) {
// We are given the canonical form:
// (icmp ne (A & B), 0) & (icmp eq (A & D), E).
// where D & E == E.
//
// If IsAnd is false, we get it in negated form:
// (icmp eq (A & B), 0) | (icmp ne (A & D), E) ->
// !((icmp ne (A & B), 0) & (icmp eq (A & D), E)).
//
// We currently handle the case of B, C, D, E are constant.
//
const APInt *BCst, *DCst, *OrigECst;
if (!match(B, m_APInt(BCst)) || !match(D, m_APInt(DCst)) ||
!match(E, m_APInt(OrigECst)))
return nullptr;
ICmpInst::Predicate NewCC = IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
// Update E to the canonical form when D is a power of two and RHS is
// canonicalized as,
// (icmp ne (A & D), 0) -> (icmp eq (A & D), D) or
// (icmp ne (A & D), D) -> (icmp eq (A & D), 0).
APInt ECst = *OrigECst;
if (PredR != NewCC)
ECst ^= *DCst;
// If B or D is zero, skip because if LHS or RHS can be trivially folded by
// other folding rules and this pattern won't apply any more.
if (*BCst == 0 || *DCst == 0)
return nullptr;
// If B and D don't intersect, ie. (B & D) == 0, try to fold isNaN idiom:
// (icmp ne (A & FractionBits), 0) & (icmp eq (A & ExpBits), ExpBits)
// -> isNaN(A)
// Otherwise, we cannot deduce anything from it.
if (!BCst->intersects(*DCst)) {
Value *Src;
if (*DCst == ECst && match(A, m_ElementWiseBitCast(m_Value(Src))) &&
!Builder.GetInsertBlock()->getParent()->hasFnAttribute(
Attribute::StrictFP)) {
Type *Ty = Src->getType()->getScalarType();
if (!Ty->isIEEELikeFPTy())
return nullptr;
APInt ExpBits = APFloat::getInf(Ty->getFltSemantics()).bitcastToAPInt();
if (ECst != ExpBits)
return nullptr;
APInt FractionBits = ~ExpBits;
FractionBits.clearSignBit();
if (*BCst != FractionBits)
return nullptr;
return Builder.CreateFCmp(IsAnd ? FCmpInst::FCMP_UNO : FCmpInst::FCMP_ORD,
Src, ConstantFP::getZero(Src->getType()));
}
return nullptr;
}
// If the following two conditions are met:
//
// 1. mask B covers only a single bit that's not covered by mask D, that is,
// (B & (B ^ D)) is a power of 2 (in other words, B minus the intersection of
// B and D has only one bit set) and,
//
// 2. RHS (and E) indicates that the rest of B's bits are zero (in other
// words, the intersection of B and D is zero), that is, ((B & D) & E) == 0
//
// then that single bit in B must be one and thus the whole expression can be
// folded to
// (A & (B | D)) == (B & (B ^ D)) | E.
//
// For example,
// (icmp ne (A & 12), 0) & (icmp eq (A & 7), 1) -> (icmp eq (A & 15), 9)
// (icmp ne (A & 15), 0) & (icmp eq (A & 7), 0) -> (icmp eq (A & 15), 8)
if ((((*BCst & *DCst) & ECst) == 0) &&
(*BCst & (*BCst ^ *DCst)).isPowerOf2()) {
APInt BorD = *BCst | *DCst;
APInt BandBxorDorE = (*BCst & (*BCst ^ *DCst)) | ECst;
Value *NewMask = ConstantInt::get(A->getType(), BorD);
Value *NewMaskedValue = ConstantInt::get(A->getType(), BandBxorDorE);
Value *NewAnd = Builder.CreateAnd(A, NewMask);
return Builder.CreateICmp(NewCC, NewAnd, NewMaskedValue);
}
auto IsSubSetOrEqual = [](const APInt *C1, const APInt *C2) {
return (*C1 & *C2) == *C1;
};
auto IsSuperSetOrEqual = [](const APInt *C1, const APInt *C2) {
return (*C1 & *C2) == *C2;
};
// In the following, we consider only the cases where B is a superset of D, B
// is a subset of D, or B == D because otherwise there's at least one bit
// covered by B but not D, in which case we can't deduce much from it, so
// no folding (aside from the single must-be-one bit case right above.)
// For example,
// (icmp ne (A & 14), 0) & (icmp eq (A & 3), 1) -> no folding.
if (!IsSubSetOrEqual(BCst, DCst) && !IsSuperSetOrEqual(BCst, DCst))
return nullptr;
// At this point, either B is a superset of D, B is a subset of D or B == D.
// If E is zero, if B is a subset of (or equal to) D, LHS and RHS contradict
// and the whole expression becomes false (or true if negated), otherwise, no
// folding.
// For example,
// (icmp ne (A & 3), 0) & (icmp eq (A & 7), 0) -> false.
// (icmp ne (A & 15), 0) & (icmp eq (A & 3), 0) -> no folding.
if (ECst.isZero()) {
if (IsSubSetOrEqual(BCst, DCst))
return ConstantInt::get(LHS->getType(), !IsAnd);
return nullptr;
}
// At this point, B, D, E aren't zero and (B & D) == B, (B & D) == D or B ==
// D. If B is a superset of (or equal to) D, since E is not zero, LHS is
// subsumed by RHS (RHS implies LHS.) So the whole expression becomes
// RHS. For example,
// (icmp ne (A & 255), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
// (icmp ne (A & 15), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
if (IsSuperSetOrEqual(BCst, DCst)) {
// We can't guarantee that samesign hold after this fold.
if (auto *ICmp = dyn_cast<ICmpInst>(RHS))
ICmp->setSameSign(false);
return RHS;
}
// Otherwise, B is a subset of D. If B and E have a common bit set,
// ie. (B & E) != 0, then LHS is subsumed by RHS. For example.
// (icmp ne (A & 12), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");
if ((*BCst & ECst) != 0) {
// We can't guarantee that samesign hold after this fold.
if (auto *ICmp = dyn_cast<ICmpInst>(RHS))
ICmp->setSameSign(false);
return RHS;
}
// Otherwise, LHS and RHS contradict and the whole expression becomes false
// (or true if negated.) For example,
// (icmp ne (A & 7), 0) & (icmp eq (A & 15), 8) -> false.
// (icmp ne (A & 6), 0) & (icmp eq (A & 15), 8) -> false.
return ConstantInt::get(LHS->getType(), !IsAnd);
}
/// Try to fold (icmp(A & B) ==/!= 0) &/| (icmp(A & D) ==/!= E) into a single
/// (icmp(A & X) ==/!= Y), where the left-hand side and the right hand side
/// aren't of the common mask pattern type.
/// Also used for logical and/or, must be poison safe.
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) {
assert(ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) &&
"Expected equality predicates for masked type of icmps.");
// Handle Mask_NotAllZeros-BMask_Mixed cases.
// (icmp ne/eq (A & B), C) &/| (icmp eq/ne (A & D), E), or
// (icmp eq/ne (A & B), C) &/| (icmp ne/eq (A & D), E)
// which gets swapped to
// (icmp ne/eq (A & D), E) &/| (icmp eq/ne (A & B), C).
if (!IsAnd) {
LHSMask = conjugateICmpMask(LHSMask);
RHSMask = conjugateICmpMask(RHSMask);
}
if ((LHSMask & Mask_NotAllZeros) && (RHSMask & BMask_Mixed)) {
if (Value *V = foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
LHS, RHS, IsAnd, A, B, D, E, PredL, PredR, Builder)) {
return V;
}
} else if ((LHSMask & BMask_Mixed) && (RHSMask & Mask_NotAllZeros)) {
if (Value *V = foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
RHS, LHS, IsAnd, A, D, B, C, PredR, PredL, Builder)) {
return V;
}
}
return nullptr;
}
/// Try to fold (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E)
/// into a single (icmp(A & X) ==/!= Y).
static Value *foldLogOpOfMaskedICmps(Value *LHS, Value *RHS, bool IsAnd,
bool IsLogical,
InstCombiner::BuilderTy &Builder,
const SimplifyQuery &Q) {
Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;
ICmpInst::Predicate PredL, PredR;
std::optional<std::pair<unsigned, unsigned>> MaskPair =
getMaskedTypeForICmpPair(A, B, C, D, E, LHS, RHS, PredL, PredR);
if (!MaskPair)
return nullptr;
assert(ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) &&
"Expected equality predicates for masked type of icmps.");
unsigned LHSMask = MaskPair->first;
unsigned RHSMask = MaskPair->second;
unsigned Mask = LHSMask & RHSMask;
if (Mask == 0) {
// Even if the two sides don't share a common pattern, check if folding can
// still happen.
if (Value *V = foldLogOpOfMaskedICmpsAsymmetric(
LHS, RHS, IsAnd, A, B, C, D, E, PredL, PredR, LHSMask, RHSMask,
Builder))
return V;
return nullptr;
}
// In full generality:
// (icmp (A & B) Op C) | (icmp (A & D) Op E)
// == ![ (icmp (A & B) !Op C) & (icmp (A & D) !Op E) ]
//
// If the latter can be converted into (icmp (A & X) Op Y) then the former is
// equivalent to (icmp (A & X) !Op Y).
//
// Therefore, we can pretend for the rest of this function that we're dealing
// with the conjunction, provided we flip the sense of any comparisons (both
// input and output).
// In most cases we're going to produce an EQ for the "&&" case.
ICmpInst::Predicate NewCC = IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
if (!IsAnd) {
// Convert the masking analysis into its equivalent with negated
// comparisons.
Mask = conjugateICmpMask(Mask);
}
if (Mask & Mask_AllZeros) {
// (icmp eq (A & B), 0) & (icmp eq (A & D), 0)
// -> (icmp eq (A & (B|D)), 0)
if (IsLogical && !isGuaranteedNotToBeUndefOrPoison(D))
return nullptr; // TODO: Use freeze?
Value *NewOr = Builder.CreateOr(B, D);
Value *NewAnd = Builder.CreateAnd(A, NewOr);
// We can't use C as zero because we might actually handle
// (icmp ne (A & B), B) & (icmp ne (A & D), D)
// with B and D, having a single bit set.
Value *Zero = Constant::getNullValue(A->getType());
return Builder.CreateICmp(NewCC, NewAnd, Zero);
}
if (Mask & BMask_AllOnes) {
// (icmp eq (A & B), B) & (icmp eq (A & D), D)
// -> (icmp eq (A & (B|D)), (B|D))
if (IsLogical && !isGuaranteedNotToBeUndefOrPoison(D))
return nullptr; // TODO: Use freeze?
Value *NewOr = Builder.CreateOr(B, D);
Value *NewAnd = Builder.CreateAnd(A, NewOr);
return Builder.CreateICmp(NewCC, NewAnd, NewOr);
}
if (Mask & AMask_AllOnes) {
// (icmp eq (A & B), A) & (icmp eq (A & D), A)
// -> (icmp eq (A & (B&D)), A)
if (IsLogical && !isGuaranteedNotToBeUndefOrPoison(D))
return nullptr; // TODO: Use freeze?
Value *NewAnd1 = Builder.CreateAnd(B, D);
Value *NewAnd2 = Builder.CreateAnd(A, NewAnd1);
return Builder.CreateICmp(NewCC, NewAnd2, A);
}
const APInt *ConstB, *ConstD;
if (match(B, m_APInt(ConstB)) && match(D, m_APInt(ConstD))) {
if (Mask & (Mask_NotAllZeros | BMask_NotAllOnes)) {
// (icmp ne (A & B), 0) & (icmp ne (A & D), 0) and
// (icmp ne (A & B), B) & (icmp ne (A & D), D)
// -> (icmp ne (A & B), 0) or (icmp ne (A & D), 0)
// Only valid if one of the masks is a superset of the other (check "B&D"
// is the same as either B or D).
APInt NewMask = *ConstB & *ConstD;
if (NewMask == *ConstB)
return LHS;
if (NewMask == *ConstD) {
if (IsLogical) {
if (auto *RHSI = dyn_cast<Instruction>(RHS))
RHSI->dropPoisonGeneratingFlags();
}
return RHS;
}
}
if (Mask & AMask_NotAllOnes) {
// (icmp ne (A & B), B) & (icmp ne (A & D), D)
// -> (icmp ne (A & B), A) or (icmp ne (A & D), A)
// Only valid if one of the masks is a superset of the other (check "B|D"
// is the same as either B or D).
APInt NewMask = *ConstB | *ConstD;
if (NewMask == *ConstB)
return LHS;
if (NewMask == *ConstD)
return RHS;
}
if (Mask & (BMask_Mixed | BMask_NotMixed)) {
// Mixed:
// (icmp eq (A & B), C) & (icmp eq (A & D), E)
// We already know that B & C == C && D & E == E.
// If we can prove that (B & D) & (C ^ E) == 0, that is, the bits of
// C and E, which are shared by both the mask B and the mask D, don't
// contradict, then we can transform to
// -> (icmp eq (A & (B|D)), (C|E))
// Currently, we only handle the case of B, C, D, and E being constant.
// We can't simply use C and E because we might actually handle
// (icmp ne (A & B), B) & (icmp eq (A & D), D)
// with B and D, having a single bit set.
// NotMixed:
// (icmp ne (A & B), C) & (icmp ne (A & D), E)
// -> (icmp ne (A & (B & D)), (C & E))
// Check the intersection (B & D) for inequality.
// Assume that (B & D) == B || (B & D) == D, i.e B/D is a subset of D/B
// and (B & D) & (C ^ E) == 0, bits of C and E, which are shared by both
// the B and the D, don't contradict. Note that we can assume (~B & C) ==
// 0 && (~D & E) == 0, previous operation should delete these icmps if it
// hadn't been met.
const APInt *OldConstC, *OldConstE;
if (!match(C, m_APInt(OldConstC)) || !match(E, m_APInt(OldConstE)))
return nullptr;
auto FoldBMixed = [&](ICmpInst::Predicate CC, bool IsNot) -> Value * {
CC = IsNot ? CmpInst::getInversePredicate(CC) : CC;
const APInt ConstC = PredL != CC ? *ConstB ^ *OldConstC : *OldConstC;
const APInt ConstE = PredR != CC ? *ConstD ^ *OldConstE : *OldConstE;
if (((*ConstB & *ConstD) & (ConstC ^ ConstE)).getBoolValue())
return IsNot ? nullptr : ConstantInt::get(LHS->getType(), !IsAnd);
if (IsNot && !ConstB->isSubsetOf(*ConstD) &&
!ConstD->isSubsetOf(*ConstB))
return nullptr;
APInt BD, CE;
if (IsNot) {
BD = *ConstB & *ConstD;
CE = ConstC & ConstE;
} else {
BD = *ConstB | *ConstD;
CE = ConstC | ConstE;
}
Value *NewAnd = Builder.CreateAnd(A, BD);
Value *CEVal = ConstantInt::get(A->getType(), CE);
return Builder.CreateICmp(CC, CEVal, NewAnd);
};
if (Mask & BMask_Mixed)
return FoldBMixed(NewCC, false);
if (Mask & BMask_NotMixed) // can be else also
return FoldBMixed(NewCC, true);
}
}
// (icmp eq (A & B), 0) | (icmp eq (A & D), 0)
// -> (icmp ne (A & (B|D)), (B|D))
// (icmp ne (A & B), 0) & (icmp ne (A & D), 0)
// -> (icmp eq (A & (B|D)), (B|D))
// iff B and D is known to be a power of two
if (Mask & Mask_NotAllZeros &&
isKnownToBeAPowerOfTwo(B, /*OrZero=*/false, /*Depth=*/0, Q) &&
isKnownToBeAPowerOfTwo(D, /*OrZero=*/false, /*Depth=*/0, Q)) {
// If this is a logical and/or, then we must prevent propagation of a
// poison value from the RHS by inserting freeze.
if (IsLogical)
D = Builder.CreateFreeze(D);
Value *Mask = Builder.CreateOr(B, D);
Value *Masked = Builder.CreateAnd(A, Mask);
return Builder.CreateICmp(NewCC, Masked, Mask);
}
return nullptr;
}
/// Try to fold a signed range checked with lower bound 0 to an unsigned icmp.
/// Example: (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
/// If \p Inverted is true then the check is for the inverted range, e.g.
/// (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool Inverted) {
// Check the lower range comparison, e.g. x >= 0
// InstCombine already ensured that if there is a constant it's on the RHS.
ConstantInt *RangeStart = dyn_cast<ConstantInt>(Cmp0->getOperand(1));
if (!RangeStart)
return nullptr;
ICmpInst::Predicate Pred0 = (Inverted ? Cmp0->getInversePredicate() :
Cmp0->getPredicate());
// Accept x > -1 or x >= 0 (after potentially inverting the predicate).
if (!((Pred0 == ICmpInst::ICMP_SGT && RangeStart->isMinusOne()) ||
(Pred0 == ICmpInst::ICMP_SGE && RangeStart->isZero())))
return nullptr;
ICmpInst::Predicate Pred1 = (Inverted ? Cmp1->getInversePredicate() :
Cmp1->getPredicate());
Value *Input = Cmp0->getOperand(0);
Value *Cmp1Op0 = Cmp1->getOperand(0);
Value *Cmp1Op1 = Cmp1->getOperand(1);
Value *RangeEnd;
if (match(Cmp1Op0, m_SExtOrSelf(m_Specific(Input)))) {
// For the upper range compare we have: icmp x, n
Input = Cmp1Op0;
RangeEnd = Cmp1Op1;
} else if (match(Cmp1Op1, m_SExtOrSelf(m_Specific(Input)))) {
// For the upper range compare we have: icmp n, x
Input = Cmp1Op1;
RangeEnd = Cmp1Op0;
Pred1 = ICmpInst::getSwappedPredicate(Pred1);
} else {
return nullptr;
}
// Check the upper range comparison, e.g. x < n
ICmpInst::Predicate NewPred;
switch (Pred1) {
case ICmpInst::ICMP_SLT: NewPred = ICmpInst::ICMP_ULT; break;
case ICmpInst::ICMP_SLE: NewPred = ICmpInst::ICMP_ULE; break;
default: return nullptr;
}
// This simplification is only valid if the upper range is not negative.
KnownBits Known = computeKnownBits(RangeEnd, /*Depth=*/0, Cmp1);
if (!Known.isNonNegative())
return nullptr;
if (Inverted)
NewPred = ICmpInst::getInversePredicate(NewPred);
return Builder.CreateICmp(NewPred, Input, RangeEnd);
}
// (or (icmp eq X, 0), (icmp eq X, Pow2OrZero))
// -> (icmp eq (and X, Pow2OrZero), X)
// (and (icmp ne X, 0), (icmp ne X, Pow2OrZero))
// -> (icmp ne (and X, Pow2OrZero), X)
static Value *
foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder,
ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
const SimplifyQuery &Q) {
CmpPredicate Pred = IsAnd ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
// Make sure we have right compares for our op.
if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)
return nullptr;
// Make it so we can match LHS against the (icmp eq/ne X, 0) just for
// simplicity.
if (match(RHS->getOperand(1), m_Zero()))
std::swap(LHS, RHS);
Value *Pow2, *Op;
// Match the desired pattern:
// LHS: (icmp eq/ne X, 0)
// RHS: (icmp eq/ne X, Pow2OrZero)
// Skip if Pow2OrZero is 1. Either way it gets folded to (icmp ugt X, 1) but
// this form ends up slightly less canonical.
// We could potentially be more sophisticated than requiring LHS/RHS
// be one-use. We don't create additional instructions if only one
// of them is one-use. So cases where one is one-use and the other
// is two-use might be profitable.
if (!match(LHS, m_OneUse(m_ICmp(Pred, m_Value(Op), m_Zero()))) ||
!match(RHS, m_OneUse(m_c_ICmp(Pred, m_Specific(Op), m_Value(Pow2)))) ||
match(Pow2, m_One()) ||
!isKnownToBeAPowerOfTwo(Pow2, Q.DL, /*OrZero=*/true, /*Depth=*/0, Q.AC,
Q.CxtI, Q.DT))
return nullptr;
Value *And = Builder.CreateAnd(Op, Pow2);
return Builder.CreateICmp(Pred, And, Op);
}
/// General pattern:
/// X & Y
///
/// Where Y is checking that all the high bits (covered by a mask 4294967168)
/// are uniform, i.e. %arg & 4294967168 can be either 4294967168 or 0
/// Pattern can be one of:
/// %t = add i32 %arg, 128
/// %r = icmp ult i32 %t, 256
/// Or
/// %t0 = shl i32 %arg, 24
/// %t1 = ashr i32 %t0, 24
/// %r = icmp eq i32 %t1, %arg
/// Or
/// %t0 = trunc i32 %arg to i8
/// %t1 = sext i8 %t0 to i32
/// %r = icmp eq i32 %t1, %arg
/// This pattern is a signed truncation check.
///
/// And X is checking that some bit in that same mask is zero.
/// I.e. can be one of:
/// %r = icmp sgt i32 %arg, -1
/// Or
/// %t = and i32 %arg, 2147483648
/// %r = icmp eq i32 %t, 0
///
/// Since we are checking that all the bits in that mask are the same,
/// and a particular bit is zero, what we are really checking is that all the
/// masked bits are zero.
/// So this should be transformed to:
/// %r = icmp ult i32 %arg, 128
static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
Instruction &CxtI,
InstCombiner::BuilderTy &Builder) {
assert(CxtI.getOpcode() == Instruction::And);
// Match icmp ult (add %arg, C01), C1 (C1 == C01 << 1; powers of two)
auto tryToMatchSignedTruncationCheck = [](ICmpInst *ICmp, Value *&X,
APInt &SignBitMask) -> bool {
const APInt *I01, *I1; // powers of two; I1 == I01 << 1
if (!(match(ICmp, m_SpecificICmp(ICmpInst::ICMP_ULT,
m_Add(m_Value(X), m_Power2(I01)),
m_Power2(I1))) &&
I1->ugt(*I01) && I01->shl(1) == *I1))
return false;
// Which bit is the new sign bit as per the 'signed truncation' pattern?
SignBitMask = *I01;
return true;
};
// One icmp needs to be 'signed truncation check'.
// We need to match this first, else we will mismatch commutative cases.
Value *X1;
APInt HighestBit;
ICmpInst *OtherICmp;
if (tryToMatchSignedTruncationCheck(ICmp1, X1, HighestBit))
OtherICmp = ICmp0;
else if (tryToMatchSignedTruncationCheck(ICmp0, X1, HighestBit))
OtherICmp = ICmp1;
else
return nullptr;
assert(HighestBit.isPowerOf2() && "expected to be power of two (non-zero)");
// Try to match/decompose into: icmp eq (X & Mask), 0
auto tryToDecompose = [](ICmpInst *ICmp, Value *&X,
APInt &UnsetBitsMask) -> bool {
CmpPredicate Pred = ICmp->getPredicate();
// Can it be decomposed into icmp eq (X & Mask), 0 ?
auto Res =
llvm::decomposeBitTestICmp(ICmp->getOperand(0), ICmp->getOperand(1),
Pred, /*LookThroughTrunc=*/false);
if (Res && Res->Pred == ICmpInst::ICMP_EQ) {
X = Res->X;
UnsetBitsMask = Res->Mask;
return true;
}
// Is it icmp eq (X & Mask), 0 already?
const APInt *Mask;
if (match(ICmp, m_ICmp(Pred, m_And(m_Value(X), m_APInt(Mask)), m_Zero())) &&
Pred == ICmpInst::ICMP_EQ) {
UnsetBitsMask = *Mask;
return true;
}
return false;
};
// And the other icmp needs to be decomposable into a bit test.
Value *X0;
APInt UnsetBitsMask;
if (!tryToDecompose(OtherICmp, X0, UnsetBitsMask))
return nullptr;
assert(!UnsetBitsMask.isZero() && "empty mask makes no sense.");
// Are they working on the same value?
Value *X;
if (X1 == X0) {
// Ok as is.
X = X1;
} else if (match(X0, m_Trunc(m_Specific(X1)))) {
UnsetBitsMask = UnsetBitsMask.zext(X1->getType()->getScalarSizeInBits());
X = X1;
} else
return nullptr;
// So which bits should be uniform as per the 'signed truncation check'?
// (all the bits starting with (i.e. including) HighestBit)
APInt SignBitsMask = ~(HighestBit - 1U);
// UnsetBitsMask must have some common bits with SignBitsMask,
if (!UnsetBitsMask.intersects(SignBitsMask))
return nullptr;
// Does UnsetBitsMask contain any bits outside of SignBitsMask?
if (!UnsetBitsMask.isSubsetOf(SignBitsMask)) {
APInt OtherHighestBit = (~UnsetBitsMask) + 1U;
if (!OtherHighestBit.isPowerOf2())
return nullptr;
HighestBit = APIntOps::umin(HighestBit, OtherHighestBit);
}
// Else, if it does not, then all is ok as-is.
// %r = icmp ult %X, SignBit
return Builder.CreateICmpULT(X, ConstantInt::get(X->getType(), HighestBit),
CxtI.getName() + ".simplified");
}
/// Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
/// fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
/// Also used for logical and/or, must be poison safe if range attributes are
/// dropped.
static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
InstCombiner::BuilderTy &Builder,
InstCombinerImpl &IC) {
CmpPredicate Pred0, Pred1;
Value *X;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
m_SpecificInt(1))) ||
!match(Cmp1, m_ICmp(Pred1, m_Specific(X), m_ZeroInt())))
return nullptr;
auto *CtPop = cast<Instruction>(Cmp0->getOperand(0));
if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE) {
// Drop range attributes and re-infer them in the next iteration.
CtPop->dropPoisonGeneratingAnnotations();
IC.addToWorklist(CtPop);
return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ) {
// Drop range attributes and re-infer them in the next iteration.
CtPop->dropPoisonGeneratingAnnotations();
IC.addToWorklist(CtPop);
return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));
}
return nullptr;
}
/// Reduce a pair of compares that check if a value has exactly 1 bit set.
/// Also used for logical and/or, must be poison safe if range attributes are
/// dropped.
static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
InstCombiner::BuilderTy &Builder,
InstCombinerImpl &IC) {
// Handle 'and' / 'or' commutation: make the equality check the first operand.
if (JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_NE)
std::swap(Cmp0, Cmp1);
else if (!JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_EQ)
std::swap(Cmp0, Cmp1);
// (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1
Value *X;
if (JoinedByAnd &&
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_ULT,
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(2)))) {
auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
// Drop range attributes and re-infer them in the next iteration.
CtPop->dropPoisonGeneratingAnnotations();
IC.addToWorklist(CtPop);
return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
// (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
if (!JoinedByAnd &&
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(X), m_ZeroInt())) &&
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_UGT,
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(1)))) {
auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));