Skip to content

Commit d3402bc

Browse files
committed
[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops
This just expands on the existing logic that worked for `Or` and applies it to any binop where `0` is the identity value on the RHS i.e: `add`, `or`, `xor`, `shl`, etc... Proofs For Some: https://alive2.llvm.org/ce/z/XZo6JD Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D148414
1 parent 00f0381 commit d3402bc

File tree

2 files changed

+73
-69
lines changed

2 files changed

+73
-69
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -689,25 +689,32 @@ static Value *foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal,
689689
}
690690

691691
/// We want to turn:
692-
/// (select (icmp eq (and X, C1), 0), Y, (or Y, C2))
692+
/// (select (icmp eq (and X, C1), 0), Y, (BinOp Y, C2))
693693
/// into:
694-
/// (or (shl (and X, C1), C3), Y)
694+
/// IF C2 u>= C1
695+
/// (BinOp (shl (and X, C1), C3), Y)
696+
/// ELSE
697+
/// (BinOp (lshr (and X, C1), C3), Y)
695698
/// iff:
699+
/// 0 on the RHS is the identity value (i.e add, xor, shl, etc...)
696700
/// C1 and C2 are both powers of 2
697701
/// where:
698-
/// C3 = Log(C2) - Log(C1)
702+
/// IF C2 u>= C1
703+
/// C3 = Log(C2) - Log(C1)
704+
/// ELSE
705+
/// C3 = Log(C1) - Log(C2)
699706
///
700707
/// This transform handles cases where:
701708
/// 1. The icmp predicate is inverted
702709
/// 2. The select operands are reversed
703710
/// 3. The magnitude of C2 and C1 are flipped
704-
static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
711+
static Value *foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal,
705712
Value *FalseVal,
706713
InstCombiner::BuilderTy &Builder) {
707714
// Only handle integer compares. Also, if this is a vector select, we need a
708715
// vector compare.
709716
if (!TrueVal->getType()->isIntOrIntVectorTy() ||
710-
TrueVal->getType()->isVectorTy() != IC->getType()->isVectorTy())
717+
TrueVal->getType()->isVectorTy() != IC->getType()->isVectorTy())
711718
return nullptr;
712719

713720
Value *CmpLHS = IC->getOperand(0);
@@ -735,21 +742,28 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
735742
NeedAnd = true;
736743
}
737744

738-
Value *Or, *Y, *V = CmpLHS;
745+
Value *Y, *V = CmpLHS;
746+
BinaryOperator *BinOp;
739747
const APInt *C2;
740748
bool NeedXor;
741-
if (match(FalseVal, m_Or(m_Specific(TrueVal), m_Power2(C2)))) {
749+
if (match(FalseVal, m_BinOp(m_Specific(TrueVal), m_Power2(C2)))) {
742750
Y = TrueVal;
743-
Or = FalseVal;
751+
BinOp = cast<BinaryOperator>(FalseVal);
744752
NeedXor = Pred == ICmpInst::ICMP_NE;
745-
} else if (match(TrueVal, m_Or(m_Specific(FalseVal), m_Power2(C2)))) {
753+
} else if (match(TrueVal, m_BinOp(m_Specific(FalseVal), m_Power2(C2)))) {
746754
Y = FalseVal;
747-
Or = TrueVal;
755+
BinOp = cast<BinaryOperator>(TrueVal);
748756
NeedXor = Pred == ICmpInst::ICMP_EQ;
749757
} else {
750758
return nullptr;
751759
}
752760

761+
// Check that 0 on RHS is identity value for this binop.
762+
if (!ConstantExpr::getBinOpIdentity(BinOp->getOpcode(), BinOp->getType(),
763+
/*AllowRHSConstant*/ true)
764+
->isNullValue())
765+
return nullptr;
766+
753767
unsigned C2Log = C2->logBase2();
754768

755769
bool NeedShift = C1Log != C2Log;
@@ -758,7 +772,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
758772

759773
// Make sure we don't create more instructions than we save.
760774
if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >
761-
(IC->hasOneUse() + Or->hasOneUse()))
775+
(IC->hasOneUse() + BinOp->hasOneUse()))
762776
return nullptr;
763777

764778
if (NeedAnd) {
@@ -779,7 +793,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
779793
if (NeedXor)
780794
V = Builder.CreateXor(V, *C2);
781795

782-
return Builder.CreateOr(V, Y);
796+
return Builder.CreateBinOp(BinOp->getOpcode(), V, Y);
783797
}
784798

785799
/// Canonicalize a set or clear of a masked set of constant bits to
@@ -1788,7 +1802,7 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
17881802
if (Instruction *V = foldSelectZeroOrOnes(ICI, TrueVal, FalseVal, Builder))
17891803
return V;
17901804

1791-
if (Value *V = foldSelectICmpAndOr(ICI, TrueVal, FalseVal, Builder))
1805+
if (Value *V = foldSelectICmpAndBinOp(ICI, TrueVal, FalseVal, Builder))
17921806
return replaceInstUsesWith(SI, V);
17931807

17941808
if (Value *V = foldSelectICmpLshrAshr(ICI, TrueVal, FalseVal, Builder))

llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll

Lines changed: 46 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ define <2 x i32> @select_icmp_eq_and_1_0_or_2_vec(<2 x i32> %x, <2 x i32> %y) {
3636

3737
define i32 @select_icmp_eq_and_1_0_xor_2(i32 %x, i32 %y) {
3838
; CHECK-LABEL: @select_icmp_eq_and_1_0_xor_2(
39-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1
40-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
41-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 2
42-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
39+
; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1
40+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
41+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
4342
; CHECK-NEXT: ret i32 [[SELECT]]
4443
;
4544
%and = and i32 %x, 1
@@ -94,10 +93,9 @@ define <2 x i32> @select_icmp_eq_and_32_0_or_8_vec(<2 x i32> %x, <2 x i32> %y) {
9493

9594
define i32 @select_icmp_eq_and_32_0_xor_8(i32 %x, i32 %y) {
9695
; CHECK-LABEL: @select_icmp_eq_and_32_0_xor_8(
97-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 32
98-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
99-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 8
100-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
96+
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 2
97+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 8
98+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
10199
; CHECK-NEXT: ret i32 [[SELECT]]
102100
;
103101
%and = and i32 %x, 32
@@ -153,9 +151,8 @@ define <2 x i32> @select_icmp_ne_0_and_4096_or_4096_vec(<2 x i32> %x, <2 x i32>
153151
define i32 @select_icmp_ne_0_and_4096_xor_4096(i32 %x, i32 %y) {
154152
; CHECK-LABEL: @select_icmp_ne_0_and_4096_xor_4096(
155153
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
156-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
157-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
158-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
154+
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], [[Y:%.*]]
155+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], 4096
159156
; CHECK-NEXT: ret i32 [[SELECT]]
160157
;
161158
%and = and i32 %x, 4096
@@ -209,9 +206,7 @@ define <2 x i32> @select_icmp_eq_and_4096_0_or_4096_vec(<2 x i32> %x, <2 x i32>
209206
define i32 @select_icmp_eq_and_4096_0_xor_4096(i32 %x, i32 %y) {
210207
; CHECK-LABEL: @select_icmp_eq_and_4096_0_xor_4096(
211208
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
212-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
213-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
214-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
209+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[AND]], [[Y:%.*]]
215210
; CHECK-NEXT: ret i32 [[SELECT]]
216211
;
217212
%and = and i32 %x, 4096
@@ -267,8 +262,8 @@ define <2 x i32> @select_icmp_eq_0_and_1_or_1_vec(<2 x i64> %x, <2 x i32> %y) {
267262
define i32 @select_icmp_eq_0_and_1_xor_1(i64 %x, i32 %y) {
268263
; CHECK-LABEL: @select_icmp_eq_0_and_1_xor_1(
269264
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
270-
; CHECK-NEXT: [[XOR:%.*]] = and i32 [[TMP1]], 1
271-
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[XOR]], [[Y:%.*]]
265+
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 1
266+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP2]], [[Y:%.*]]
272267
; CHECK-NEXT: ret i32 [[SELECT]]
273268
;
274269
%and = and i64 %x, 1
@@ -310,10 +305,10 @@ define i32 @select_icmp_ne_0_and_4096_or_32(i32 %x, i32 %y) {
310305

311306
define i32 @select_icmp_ne_0_and_4096_xor_32(i32 %x, i32 %y) {
312307
; CHECK-LABEL: @select_icmp_ne_0_and_4096_xor_32(
313-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
314-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
315-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 32
316-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
308+
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 7
309+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 32
310+
; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
311+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP2]], 32
317312
; CHECK-NEXT: ret i32 [[SELECT]]
318313
;
319314
%and = and i32 %x, 4096
@@ -370,10 +365,10 @@ define <2 x i32> @select_icmp_ne_0_and_32_or_4096_vec(<2 x i32> %x, <2 x i32> %y
370365

371366
define i32 @select_icmp_ne_0_and_32_xor_4096(i32 %x, i32 %y) {
372367
; CHECK-LABEL: @select_icmp_ne_0_and_32_xor_4096(
373-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 32
374-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
375-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
376-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
368+
; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 7
369+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 4096
370+
; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
371+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP2]], 4096
377372
; CHECK-NEXT: ret i32 [[SELECT]]
378373
;
379374
%and = and i32 %x, 32
@@ -532,9 +527,8 @@ define i32 @select_icmp_and_8_eq_0_xor_8(i32 %x) {
532527
define i64 @select_icmp_x_and_8_eq_0_y_xor_8(i32 %x, i64 %y) {
533528
; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_xor_8(
534529
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 8
535-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
536-
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[Y:%.*]], 8
537-
; CHECK-NEXT: [[Y_XOR:%.*]] = select i1 [[CMP]], i64 [[Y]], i64 [[XOR]]
530+
; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[AND]] to i64
531+
; CHECK-NEXT: [[Y_XOR:%.*]] = xor i64 [[TMP1]], [[Y:%.*]]
538532
; CHECK-NEXT: ret i64 [[Y_XOR]]
539533
;
540534
%and = and i32 %x, 8
@@ -547,9 +541,9 @@ define i64 @select_icmp_x_and_8_eq_0_y_xor_8(i32 %x, i64 %y) {
547541
define i64 @select_icmp_x_and_8_ne_0_y_xor_8(i32 %x, i64 %y) {
548542
; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_xor_8(
549543
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 8
550-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
551-
; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[Y:%.*]], 8
552-
; CHECK-NEXT: [[XOR_Y:%.*]] = select i1 [[CMP]], i64 [[XOR]], i64 [[Y]]
544+
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 8
545+
; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64
546+
; CHECK-NEXT: [[XOR_Y:%.*]] = xor i64 [[TMP2]], [[Y:%.*]]
553547
; CHECK-NEXT: ret i64 [[XOR_Y]]
554548
;
555549
%and = and i32 %x, 8
@@ -670,10 +664,9 @@ define <2 x i32> @test68vec(<2 x i32> %x, <2 x i32> %y) {
670664

671665
define i32 @test68_xor(i32 %x, i32 %y) {
672666
; CHECK-LABEL: @test68_xor(
673-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 128
674-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
675-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 2
676-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
667+
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 6
668+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
669+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
677670
; CHECK-NEXT: ret i32 [[SELECT]]
678671
;
679672
%and = and i32 %x, 128
@@ -730,10 +723,10 @@ define <2 x i32> @test69vec(<2 x i32> %x, <2 x i32> %y) {
730723

731724
define i32 @test69_xor(i32 %x, i32 %y) {
732725
; CHECK-LABEL: @test69_xor(
733-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 128
734-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
735-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 2
736-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
726+
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 6
727+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
728+
; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
729+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP2]], 2
737730
; CHECK-NEXT: ret i32 [[SELECT]]
738731
;
739732
%and = and i32 %x, 128
@@ -805,10 +798,10 @@ define i32 @shift_no_xor_multiuse_or(i32 %x, i32 %y) {
805798

806799
define i32 @shift_no_xor_multiuse_xor(i32 %x, i32 %y) {
807800
; CHECK-LABEL: @shift_no_xor_multiuse_xor(
808-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1
809-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
810801
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 2
811-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
802+
; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1
803+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
804+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], [[Y]]
812805
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[XOR]]
813806
; CHECK-NEXT: ret i32 [[RES]]
814807
;
@@ -856,9 +849,8 @@ define i32 @no_shift_no_xor_multiuse_or(i32 %x, i32 %y) {
856849
define i32 @no_shift_no_xor_multiuse_xor(i32 %x, i32 %y) {
857850
; CHECK-LABEL: @no_shift_no_xor_multiuse_xor(
858851
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
859-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
860852
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
861-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
853+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[AND]], [[Y]]
862854
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[XOR]]
863855
; CHECK-NEXT: ret i32 [[RES]]
864856
;
@@ -907,9 +899,9 @@ define i32 @no_shift_xor_multiuse_or(i32 %x, i32 %y) {
907899
define i32 @no_shift_xor_multiuse_xor(i32 %x, i32 %y) {
908900
; CHECK-LABEL: @no_shift_xor_multiuse_xor(
909901
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
910-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
911902
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
912-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
903+
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], [[Y]]
904+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], 4096
913905
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[XOR]]
914906
; CHECK-NEXT: ret i32 [[RES]]
915907
;
@@ -1012,8 +1004,8 @@ define i32 @shift_no_xor_multiuse_cmp_with_xor(i32 %x, i32 %y, i32 %z, i32 %w) {
10121004
; CHECK-LABEL: @shift_no_xor_multiuse_cmp_with_xor(
10131005
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1
10141006
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
1015-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 2
1016-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
1007+
; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i32 [[AND]], 1
1008+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], [[Y:%.*]]
10171009
; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
10181010
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[SELECT2]]
10191011
; CHECK-NEXT: ret i32 [[RES]]
@@ -1068,8 +1060,7 @@ define i32 @no_shift_no_xor_multiuse_cmp_with_xor(i32 %x, i32 %y, i32 %z, i32 %w
10681060
; CHECK-LABEL: @no_shift_no_xor_multiuse_cmp_with_xor(
10691061
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
10701062
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
1071-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
1072-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
1063+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[AND]], [[Y:%.*]]
10731064
; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
10741065
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[SELECT2]]
10751066
; CHECK-NEXT: ret i32 [[RES]]
@@ -1125,8 +1116,8 @@ define i32 @no_shift_xor_multiuse_cmp_with_xor(i32 %x, i32 %y, i32 %z, i32 %w) {
11251116
; CHECK-LABEL: @no_shift_xor_multiuse_cmp_with_xor(
11261117
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
11271118
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[AND]], 0
1128-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
1129-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP_NOT]], i32 [[XOR]], i32 [[Y]]
1119+
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], [[Y:%.*]]
1120+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[TMP1]], 4096
11301121
; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP_NOT]], i32 [[W:%.*]], i32 [[Z:%.*]]
11311122
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[SELECT2]]
11321123
; CHECK-NEXT: ret i32 [[RES]]
@@ -1305,7 +1296,7 @@ define i32 @no_shift_no_xor_multiuse_cmp_xor(i32 %x, i32 %y, i32 %z, i32 %w) {
13051296
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
13061297
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
13071298
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], 4096
1308-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[XOR]]
1299+
; CHECK-NEXT: [[SELECT:%.*]] = xor i32 [[AND]], [[Y]]
13091300
; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
13101301
; CHECK-NEXT: [[RES:%.*]] = mul i32 [[SELECT]], [[SELECT2]]
13111302
; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[XOR]]
@@ -1606,10 +1597,9 @@ define i64 @xor_i8_to_i64_shl_save_and_eq(i8 %x, i64 %y) {
16061597

16071598
define i64 @xor_i8_to_i64_shl_save_and_ne(i8 %x, i64 %y) {
16081599
; CHECK-LABEL: @xor_i8_to_i64_shl_save_and_ne(
1609-
; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 1
1610-
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[XX]], 0
1611-
; CHECK-NEXT: [[Z:%.*]] = xor i64 [[Y:%.*]], -9223372036854775808
1612-
; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP_NOT]], i64 [[Y]], i64 [[Z]]
1600+
; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[X:%.*]] to i64
1601+
; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 63
1602+
; CHECK-NEXT: [[R:%.*]] = xor i64 [[TMP2]], [[Y:%.*]]
16131603
; CHECK-NEXT: ret i64 [[R]]
16141604
;
16151605
%xx = and i8 %x, 1

0 commit comments

Comments
 (0)