• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4define i1 @test2(i1 %X, i1 %Y) {
5; CHECK-LABEL: @test2(
6; CHECK-NEXT:    [[A:%.*]] = and i1 [[X:%.*]], [[Y:%.*]]
7; CHECK-NEXT:    ret i1 [[A]]
8;
9  %a = and i1 %X, %Y
10  %b = and i1 %a, %X
11  ret i1 %b
12}
13
14define i32 @test3(i32 %X, i32 %Y) {
15; CHECK-LABEL: @test3(
16; CHECK-NEXT:    [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
17; CHECK-NEXT:    ret i32 [[A]]
18;
19  %a = and i32 %X, %Y
20  %b = and i32 %Y, %a
21  ret i32 %b
22}
23
24define i1 @test7(i32 %i, i1 %b) {
25; CHECK-LABEL: @test7(
26; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[I:%.*]], 0
27; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[B:%.*]]
28; CHECK-NEXT:    ret i1 [[TMP2]]
29;
30  %cmp1 = icmp slt i32 %i, 1
31  %cmp2 = icmp sgt i32 %i, -1
32  %and1 = and i1 %cmp1, %b
33  %and2 = and i1 %and1, %cmp2
34  ret i1 %and2
35}
36
37define i1 @test8(i32 %i) {
38; CHECK-LABEL: @test8(
39; CHECK-NEXT:    [[I_OFF:%.*]] = add i32 [[I:%.*]], -1
40; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[I_OFF]], 13
41; CHECK-NEXT:    ret i1 [[TMP1]]
42;
43  %cmp1 = icmp ne i32 %i, 0
44  %cmp2 = icmp ult i32 %i, 14
45  %cond = and i1 %cmp1, %cmp2
46  ret i1 %cond
47}
48
49; FIXME: Vectors should fold too.
50define <2 x i1> @test8vec(<2 x i32> %i) {
51; CHECK-LABEL: @test8vec(
52; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[I:%.*]], zeroinitializer
53; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i32> [[I]], <i32 14, i32 14>
54; CHECK-NEXT:    [[COND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
55; CHECK-NEXT:    ret <2 x i1> [[COND]]
56;
57  %cmp1 = icmp ne <2 x i32> %i, zeroinitializer
58  %cmp2 = icmp ult <2 x i32> %i, <i32 14, i32 14>
59  %cond = and <2 x i1> %cmp1, %cmp2
60  ret <2 x i1> %cond
61}
62
63; combine -x & 1 into x & 1
64define i64 @test9(i64 %x) {
65; CHECK-LABEL: @test9(
66; CHECK-NEXT:    [[AND:%.*]] = and i64 [[X:%.*]], 1
67; CHECK-NEXT:    ret i64 [[AND]]
68;
69  %sub = sub nsw i64 0, %x
70  %and = and i64 %sub, 1
71  ret i64 %and
72}
73
74; combine -x & 1 into x & 1
75define <2 x i64> @test9vec(<2 x i64> %x) {
76; CHECK-LABEL: @test9vec(
77; CHECK-NEXT:    [[AND:%.*]] = and <2 x i64> [[X:%.*]], <i64 1, i64 1>
78; CHECK-NEXT:    ret <2 x i64> [[AND]]
79;
80  %sub = sub nsw <2 x i64> <i64 0, i64 0>, %x
81  %and = and <2 x i64> %sub, <i64 1, i64 1>
82  ret <2 x i64> %and
83}
84
85define i64 @test10(i64 %x) {
86; CHECK-LABEL: @test10(
87; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[X:%.*]], -2
88; CHECK-NEXT:    [[ADD:%.*]] = sub i64 0, [[TMP1]]
89; CHECK-NEXT:    ret i64 [[ADD]]
90;
91  %sub = sub nsw i64 0, %x
92  %and = and i64 %sub, 1
93  %add = add i64 %sub, %and
94  ret i64 %add
95}
96
97; (1 << x) & 1 --> zext(x == 0)
98
99define i8 @and1_shl1_is_cmp_eq_0(i8 %x) {
100; CHECK-LABEL: @and1_shl1_is_cmp_eq_0(
101; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
102; CHECK-NEXT:    [[AND:%.*]] = zext i1 [[TMP1]] to i8
103; CHECK-NEXT:    ret i8 [[AND]]
104;
105  %sh = shl i8 1, %x
106  %and = and i8 %sh, 1
107  ret i8 %and
108}
109
110; Don't do it if the shift has another use.
111
112define i8 @and1_shl1_is_cmp_eq_0_multiuse(i8 %x) {
113; CHECK-LABEL: @and1_shl1_is_cmp_eq_0_multiuse(
114; CHECK-NEXT:    [[SH:%.*]] = shl i8 1, [[X:%.*]]
115; CHECK-NEXT:    [[AND:%.*]] = and i8 [[SH]], 1
116; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[SH]], [[AND]]
117; CHECK-NEXT:    ret i8 [[ADD]]
118;
119  %sh = shl i8 1, %x
120  %and = and i8 %sh, 1
121  %add = add i8 %sh, %and
122  ret i8 %add
123}
124
125; (1 << x) & 1 --> zext(x == 0)
126
127define <2 x i8> @and1_shl1_is_cmp_eq_0_vec(<2 x i8> %x) {
128; CHECK-LABEL: @and1_shl1_is_cmp_eq_0_vec(
129; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
130; CHECK-NEXT:    [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
131; CHECK-NEXT:    ret <2 x i8> [[AND]]
132;
133  %sh = shl <2 x i8> <i8 1, i8 1>, %x
134  %and = and <2 x i8> %sh, <i8 1, i8 1>
135  ret <2 x i8> %and
136}
137
138define <2 x i8> @and1_shl1_is_cmp_eq_0_vec_undef(<2 x i8> %x) {
139; CHECK-LABEL: @and1_shl1_is_cmp_eq_0_vec_undef(
140; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
141; CHECK-NEXT:    [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
142; CHECK-NEXT:    ret <2 x i8> [[AND]]
143;
144  %sh = shl <2 x i8> <i8 1, i8 undef>, %x
145  %and = and <2 x i8> %sh, <i8 1, i8 undef>
146  ret <2 x i8> %and
147}
148
149; (1 >> x) & 1 --> zext(x == 0)
150
151define i8 @and1_lshr1_is_cmp_eq_0(i8 %x) {
152; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0(
153; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
154; CHECK-NEXT:    [[AND:%.*]] = zext i1 [[TMP1]] to i8
155; CHECK-NEXT:    ret i8 [[AND]]
156;
157  %sh = lshr i8 1, %x
158  %and = and i8 %sh, 1
159  ret i8 %and
160}
161
162; Don't do it if the shift has another use.
163
164define i8 @and1_lshr1_is_cmp_eq_0_multiuse(i8 %x) {
165; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_multiuse(
166; CHECK-NEXT:    [[SH:%.*]] = lshr i8 1, [[X:%.*]]
167; CHECK-NEXT:    [[AND:%.*]] = and i8 [[SH]], 1
168; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw i8 [[SH]], [[AND]]
169; CHECK-NEXT:    ret i8 [[ADD]]
170;
171  %sh = lshr i8 1, %x
172  %and = and i8 %sh, 1
173  %add = add i8 %sh, %and
174  ret i8 %add
175}
176
177; (1 >> x) & 1 --> zext(x == 0)
178
179define <2 x i8> @and1_lshr1_is_cmp_eq_0_vec(<2 x i8> %x) {
180; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_vec(
181; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
182; CHECK-NEXT:    [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
183; CHECK-NEXT:    ret <2 x i8> [[AND]]
184;
185  %sh = lshr <2 x i8> <i8 1, i8 1>, %x
186  %and = and <2 x i8> %sh, <i8 1, i8 1>
187  ret <2 x i8> %and
188}
189
190define <2 x i8> @and1_lshr1_is_cmp_eq_0_vec_undef(<2 x i8> %x) {
191; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_vec_undef(
192; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
193; CHECK-NEXT:    [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
194; CHECK-NEXT:    ret <2 x i8> [[AND]]
195;
196  %sh = lshr <2 x i8> <i8 1, i8 undef>, %x
197  %and = and <2 x i8> %sh, <i8 1, i8 undef>
198  ret <2 x i8> %and
199}
200
201; The add in this test is unnecessary because the LSBs of the LHS are 0 and the 'and' only consumes bits from those LSBs. It doesn't matter what happens to the upper bits.
202define i32 @test11(i32 %a, i32 %b) {
203; CHECK-LABEL: @test11(
204; CHECK-NEXT:    [[X:%.*]] = shl i32 [[A:%.*]], 8
205; CHECK-NEXT:    [[Z:%.*]] = and i32 [[B:%.*]], 128
206; CHECK-NEXT:    [[W:%.*]] = mul i32 [[Z]], [[X]]
207; CHECK-NEXT:    ret i32 [[W]]
208;
209  %x = shl i32 %a, 8
210  %y = add i32 %x, %b
211  %z = and i32 %y, 128
212  %w = mul i32 %z, %x ; to keep the shift from being removed
213  ret i32 %w
214}
215
216; The add in this test is unnecessary because the LSBs of the RHS are 0 and the 'and' only consumes bits from those LSBs. It doesn't matter what happens to the upper bits.
217define i32 @test12(i32 %a, i32 %b) {
218; CHECK-LABEL: @test12(
219; CHECK-NEXT:    [[X:%.*]] = shl i32 [[A:%.*]], 8
220; CHECK-NEXT:    [[Z:%.*]] = and i32 [[B:%.*]], 128
221; CHECK-NEXT:    [[W:%.*]] = mul i32 [[Z]], [[X]]
222; CHECK-NEXT:    ret i32 [[W]]
223;
224  %x = shl i32 %a, 8
225  %y = add i32 %b, %x
226  %z = and i32 %y, 128
227  %w = mul i32 %z, %x ; to keep the shift from being removed
228  ret i32 %w
229}
230
231; The sub in this test is unnecessary because the LSBs of the RHS are 0 and the 'and' only consumes bits from those LSBs. It doesn't matter what happens to the upper bits.
232define i32 @test13(i32 %a, i32 %b) {
233; CHECK-LABEL: @test13(
234; CHECK-NEXT:    [[X:%.*]] = shl i32 [[A:%.*]], 8
235; CHECK-NEXT:    [[Z:%.*]] = and i32 [[B:%.*]], 128
236; CHECK-NEXT:    [[W:%.*]] = mul i32 [[Z]], [[X]]
237; CHECK-NEXT:    ret i32 [[W]]
238;
239  %x = shl i32 %a, 8
240  %y = sub i32 %b, %x
241  %z = and i32 %y, 128
242  %w = mul i32 %z, %x ; to keep the shift from being removed
243  ret i32 %w
244}
245
246; The sub in this test cannot be removed because we need to keep the negation of %b. TODO: But we should be able to replace the LHS of it with a 0.
247define i32 @test14(i32 %a, i32 %b) {
248; CHECK-LABEL: @test14(
249; CHECK-NEXT:    [[X:%.*]] = shl i32 [[A:%.*]], 8
250; CHECK-NEXT:    [[Y:%.*]] = sub i32 0, [[B:%.*]]
251; CHECK-NEXT:    [[Z:%.*]] = and i32 [[Y]], 128
252; CHECK-NEXT:    [[W:%.*]] = mul i32 [[Z]], [[X]]
253; CHECK-NEXT:    ret i32 [[W]]
254;
255  %x = shl i32 %a, 8
256  %y = sub i32 %x, %b
257  %z = and i32 %y, 128
258  %w = mul i32 %z, %x ; to keep the shift from being removed
259  ret i32 %w
260}
261