xref: /llvm-project/llvm/test/Transforms/InstCombine/binop-cast.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(i32)
5declare void @use_vec(<2 x i32>)
6
7define i32 @testAdd(i32 %X, i32 %Y) {
8; CHECK-LABEL: @testAdd(
9; CHECK-NEXT:    [[T:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
10; CHECK-NEXT:    ret i32 [[T]]
11;
12  %t = add i32 %X, %Y
13  %tl = bitcast i32 %t to i32
14  ret i32 %tl
15}
16
17define i32 @and_sext_to_sel(i32 %x, i1 %y) {
18; CHECK-LABEL: @and_sext_to_sel(
19; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y:%.*]], i32 [[X:%.*]], i32 0
20; CHECK-NEXT:    ret i32 [[R]]
21;
22  %sext = sext i1 %y to i32
23  %r = and i32 %sext, %x
24  ret i32 %r
25}
26
27define <2 x i32> @and_sext_to_sel_constant_vec(<2 x i1> %y) {
28; CHECK-LABEL: @and_sext_to_sel_constant_vec(
29; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> <i32 42, i32 -7>, <2 x i32> zeroinitializer
30; CHECK-NEXT:    ret <2 x i32> [[R]]
31;
32  %sext = sext <2 x i1> %y to <2 x i32>
33  %r = and <2 x i32> <i32 42, i32 -7>, %sext
34  ret <2 x i32> %r
35}
36
37define <2 x i32> @and_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
38; CHECK-LABEL: @and_sext_to_sel_swap(
39; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
40; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> [[X]], <2 x i32> zeroinitializer
41; CHECK-NEXT:    ret <2 x i32> [[R]]
42;
43  %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
44  %sext = sext <2 x i1> %y to <2 x i32>
45  %r = and <2 x i32> %x, %sext
46  ret <2 x i32> %r
47}
48
49define i32 @and_sext_to_sel_multi_use(i32 %x, i1 %y) {
50; CHECK-LABEL: @and_sext_to_sel_multi_use(
51; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
52; CHECK-NEXT:    call void @use(i32 [[SEXT]])
53; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 [[X:%.*]], i32 0
54; CHECK-NEXT:    ret i32 [[R]]
55;
56  %sext = sext i1 %y to i32
57  call void @use(i32 %sext)
58  %r = and i32 %sext, %x
59  ret i32 %r
60}
61
62define i32 @and_sext_to_sel_multi_use_constant_mask(i1 %y) {
63; CHECK-LABEL: @and_sext_to_sel_multi_use_constant_mask(
64; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
65; CHECK-NEXT:    call void @use(i32 [[SEXT]])
66; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 42, i32 0
67; CHECK-NEXT:    ret i32 [[R]]
68;
69  %sext = sext i1 %y to i32
70  call void @use(i32 %sext)
71  %r = and i32 %sext, 42
72  ret i32 %r
73}
74
75define <2 x i32> @and_not_sext_to_sel(<2 x i32> %x, <2 x i1> %y) {
76; CHECK-LABEL: @and_not_sext_to_sel(
77; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
78; CHECK-NEXT:    call void @use_vec(<2 x i32> [[SEXT]])
79; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y]], <2 x i32> zeroinitializer, <2 x i32> [[X:%.*]]
80; CHECK-NEXT:    ret <2 x i32> [[R]]
81;
82  %sext = sext <2 x i1> %y to <2 x i32>
83  call void @use_vec(<2 x i32> %sext)
84  %not = xor <2 x i32> %sext, <i32 -1, i32 -1>
85  %r = and <2 x i32> %not, %x
86  ret <2 x i32> %r
87}
88
89define i32 @and_not_sext_to_sel_commute(i32 %px, i1 %y) {
90; CHECK-LABEL: @and_not_sext_to_sel_commute(
91; CHECK-NEXT:    [[X:%.*]] = mul i32 [[PX:%.*]], [[PX]]
92; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
93; CHECK-NEXT:    call void @use(i32 [[SEXT]])
94; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[SEXT]], -1
95; CHECK-NEXT:    call void @use(i32 [[NOT]])
96; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 0, i32 [[X]]
97; CHECK-NEXT:    ret i32 [[R]]
98;
99  %x = mul i32 %px, %px ; thwart complexity-based canonicalization
100  %sext = sext i1 %y to i32
101  call void @use(i32 %sext)
102  %not = xor i32 %sext, -1
103  call void @use(i32 %not)
104  %r = and i32 %x, %not
105  ret i32 %r
106}
107
108; negative test - must be 'not'
109
110define i32 @and_xor_sext_to_sel(i32 %x, i1 %y) {
111; CHECK-LABEL: @and_xor_sext_to_sel(
112; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
113; CHECK-NEXT:    call void @use(i32 [[SEXT]])
114; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[SEXT]], -2
115; CHECK-NEXT:    [[R:%.*]] = and i32 [[XOR]], [[X:%.*]]
116; CHECK-NEXT:    ret i32 [[R]]
117;
118  %sext = sext i1 %y to i32
119  call void @use(i32 %sext)
120  %xor = xor i32 %sext, -2
121  %r = and i32 %xor, %x
122  ret i32 %r
123}
124
125; negative test - must be 'sext'
126
127define i32 @and_not_zext_to_sel(i32 %x, i1 %y) {
128; CHECK-LABEL: @and_not_zext_to_sel(
129; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[Y:%.*]] to i32
130; CHECK-NEXT:    call void @use(i32 [[ZEXT]])
131; CHECK-NEXT:    [[NOT:%.*]] = xor i32 [[ZEXT]], -1
132; CHECK-NEXT:    [[R:%.*]] = and i32 [[X:%.*]], [[NOT]]
133; CHECK-NEXT:    ret i32 [[R]]
134;
135  %zext = zext i1 %y to i32
136  call void @use(i32 %zext)
137  %not = xor i32 %zext, -1
138  %r = and i32 %not, %x
139  ret i32 %r
140}
141
142define i32 @or_sext_to_sel(i32 %x, i1 %y) {
143; CHECK-LABEL: @or_sext_to_sel(
144; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y:%.*]], i32 -1, i32 [[X:%.*]]
145; CHECK-NEXT:    ret i32 [[R]]
146;
147  %sext = sext i1 %y to i32
148  %r = or i32 %sext, %x
149  ret i32 %r
150}
151
152define <2 x i32> @or_sext_to_sel_constant_vec(<2 x i1> %y) {
153; CHECK-LABEL: @or_sext_to_sel_constant_vec(
154; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> splat (i32 -1), <2 x i32> <i32 42, i32 -7>
155; CHECK-NEXT:    ret <2 x i32> [[R]]
156;
157  %sext = sext <2 x i1> %y to <2 x i32>
158  %r = or <2 x i32> <i32 42, i32 -7>, %sext
159  ret <2 x i32> %r
160}
161
162define <2 x i32> @or_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
163; CHECK-LABEL: @or_sext_to_sel_swap(
164; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
165; CHECK-NEXT:    [[R:%.*]] = select <2 x i1> [[Y:%.*]], <2 x i32> splat (i32 -1), <2 x i32> [[X]]
166; CHECK-NEXT:    ret <2 x i32> [[R]]
167;
168  %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
169  %sext = sext <2 x i1> %y to <2 x i32>
170  %r = or <2 x i32> %x, %sext
171  ret <2 x i32> %r
172}
173
174define i32 @or_sext_to_sel_multi_use(i32 %x, i1 %y) {
175; CHECK-LABEL: @or_sext_to_sel_multi_use(
176; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
177; CHECK-NEXT:    call void @use(i32 [[SEXT]])
178; CHECK-NEXT:    [[R:%.*]] = or i32 [[X:%.*]], [[SEXT]]
179; CHECK-NEXT:    ret i32 [[R]]
180;
181  %sext = sext i1 %y to i32
182  call void @use(i32 %sext)
183  %r = or i32 %sext, %x
184  ret i32 %r
185}
186
187define i32 @or_sext_to_sel_multi_use_constant_mask(i1 %y) {
188; CHECK-LABEL: @or_sext_to_sel_multi_use_constant_mask(
189; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
190; CHECK-NEXT:    call void @use(i32 [[SEXT]])
191; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 -1, i32 42
192; CHECK-NEXT:    ret i32 [[R]]
193;
194  %sext = sext i1 %y to i32
195  call void @use(i32 %sext)
196  %r = or i32 %sext, 42
197  ret i32 %r
198}
199
200define i32 @xor_sext_to_sel(i32 %x, i1 %y) {
201; CHECK-LABEL: @xor_sext_to_sel(
202; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
203; CHECK-NEXT:    [[R:%.*]] = xor i32 [[X:%.*]], [[SEXT]]
204; CHECK-NEXT:    ret i32 [[R]]
205;
206  %sext = sext i1 %y to i32
207  %r = xor i32 %sext, %x
208  ret i32 %r
209}
210
211define <2 x i32> @xor_sext_to_sel_constant_vec(<2 x i1> %y) {
212; CHECK-LABEL: @xor_sext_to_sel_constant_vec(
213; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
214; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[SEXT]], <i32 42, i32 -7>
215; CHECK-NEXT:    ret <2 x i32> [[R]]
216;
217  %sext = sext <2 x i1> %y to <2 x i32>
218  %r = xor <2 x i32> <i32 42, i32 -7>, %sext
219  ret <2 x i32> %r
220}
221
222define <2 x i32> @xor_sext_to_sel_swap(<2 x i32> %px, <2 x i1> %y) {
223; CHECK-LABEL: @xor_sext_to_sel_swap(
224; CHECK-NEXT:    [[X:%.*]] = mul <2 x i32> [[PX:%.*]], [[PX]]
225; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i1> [[Y:%.*]] to <2 x i32>
226; CHECK-NEXT:    [[R:%.*]] = xor <2 x i32> [[X]], [[SEXT]]
227; CHECK-NEXT:    ret <2 x i32> [[R]]
228;
229  %x = mul <2 x i32> %px, %px ; thwart complexity-based canonicalization
230  %sext = sext <2 x i1> %y to <2 x i32>
231  %r = xor <2 x i32> %x, %sext
232  ret <2 x i32> %r
233}
234
235define i32 @xor_sext_to_sel_multi_use(i32 %x, i1 %y) {
236; CHECK-LABEL: @xor_sext_to_sel_multi_use(
237; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
238; CHECK-NEXT:    call void @use(i32 [[SEXT]])
239; CHECK-NEXT:    [[R:%.*]] = xor i32 [[X:%.*]], [[SEXT]]
240; CHECK-NEXT:    ret i32 [[R]]
241;
242  %sext = sext i1 %y to i32
243  call void @use(i32 %sext)
244  %r = xor i32 %sext, %x
245  ret i32 %r
246}
247
248define i32 @xor_sext_to_sel_multi_use_constant_mask(i1 %y) {
249; CHECK-LABEL: @xor_sext_to_sel_multi_use_constant_mask(
250; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
251; CHECK-NEXT:    call void @use(i32 [[SEXT]])
252; CHECK-NEXT:    [[R:%.*]] = xor i32 [[SEXT]], 42
253; CHECK-NEXT:    ret i32 [[R]]
254;
255  %sext = sext i1 %y to i32
256  call void @use(i32 %sext)
257  %r = xor i32 %sext, 42
258  ret i32 %r
259}
260
261define i64 @PR63321(ptr %ptr, i64 %c) {
262; CHECK-LABEL: @PR63321(
263; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG0:![0-9]+]]
264; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[VAL]], 0
265; CHECK-NEXT:    [[RES:%.*]] = select i1 [[TMP1]], i64 [[C:%.*]], i64 0
266; CHECK-NEXT:    ret i64 [[RES]]
267;
268  %val = load i8, ptr %ptr, align 1, !range !{i8 0, i8 2}
269  %rhs = zext i8 %val to i64
270  %mask = add i64 -1, %rhs
271  %res = and i64 %mask, %c
272  ret i64 %res
273}
274
275; Negative test of PR63321
276define i64 @and_add_non_bool(ptr %ptr, i64 %c) {
277; CHECK-LABEL: @and_add_non_bool(
278; CHECK-NEXT:    [[VAL:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
279; CHECK-NEXT:    [[RHS:%.*]] = zext nneg i8 [[VAL]] to i64
280; CHECK-NEXT:    [[MASK:%.*]] = add nsw i64 [[RHS]], -1
281; CHECK-NEXT:    [[RES:%.*]] = and i64 [[MASK]], [[C:%.*]]
282; CHECK-NEXT:    ret i64 [[RES]]
283;
284  %val = load i8, ptr %ptr, align 1, !range !{i8 0, i8 3}
285  %rhs = zext i8 %val to i64
286  %mask = add i64 -1, %rhs
287  %res = and i64 %mask, %c
288  ret i64 %res
289}
290
291define i32 @and_add_bool_to_select(i1 %x, i32 %y) {
292; CHECK-LABEL: @and_add_bool_to_select(
293; CHECK-NEXT:    [[RES:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[Y:%.*]]
294; CHECK-NEXT:    ret i32 [[RES]]
295;
296  %val = zext i1 %x to i32
297  %mask = add i32 -1, %val
298  %res = and i32 %mask, %y
299  ret i32 %res
300}
301
302define i32 @and_add_bool_no_fold(i32 %y) {
303; CHECK-LABEL: @and_add_bool_no_fold(
304; CHECK-NEXT:    [[X:%.*]] = and i32 [[Y:%.*]], 1
305; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[X]], 0
306; CHECK-NEXT:    [[RES:%.*]] = select i1 [[TMP1]], i32 [[Y]], i32 0
307; CHECK-NEXT:    ret i32 [[RES]]
308;
309  %x = and i32 %y, 1
310  %mask = add i32 -1, %x
311  %res = and i32 %mask, %y
312  ret i32 %res
313}
314
315define <2 x i32> @and_add_bool_vec_to_select(<2 x i1> %x, <2 x i32> %y) {
316; CHECK-LABEL: @and_add_bool_vec_to_select(
317; CHECK-NEXT:    [[RES:%.*]] = select <2 x i1> [[X:%.*]], <2 x i32> zeroinitializer, <2 x i32> [[Y:%.*]]
318; CHECK-NEXT:    ret <2 x i32> [[RES]]
319;
320  %val = zext <2 x i1> %x to <2 x i32>
321  %mask = add <2 x i32> <i32 -1, i32 -1>, %val
322  %res = and <2 x i32> %mask, %y
323  ret <2 x i32> %res
324}
325
326; Negative test of and_add_bool_to_select
327define i32 @and_add_bool_to_select_multi_use(i1 %x, i32 %y) {
328; CHECK-LABEL: @and_add_bool_to_select_multi_use(
329; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[Y:%.*]], -1
330; CHECK-NEXT:    [[RET:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[TMP1]]
331; CHECK-NEXT:    ret i32 [[RET]]
332;
333  %val = zext i1 %x to i32
334  %mask = add i32 -1, %val
335  %res = and i32 %mask, %y
336  %ret = add i32 %res, %mask
337  ret i32 %ret
338}
339