xref: /llvm-project/llvm/test/Transforms/InstCombine/binop-of-displaced-shifts.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4define i8 @shl_or(i8 %x) {
5; CHECK-LABEL: define i8 @shl_or
6; CHECK-SAME: (i8 [[X:%.*]]) {
7; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 22, [[X]]
8; CHECK-NEXT:    ret i8 [[BINOP]]
9;
10  %shift = shl i8 16, %x
11  %add = add i8 %x, 1
12  %shift2 = shl i8 3, %add
13  %binop = or i8 %shift, %shift2
14  ret i8 %binop
15}
16
17define i8 @lshr_or(i8 %x) {
18; CHECK-LABEL: define i8 @lshr_or
19; CHECK-SAME: (i8 [[X:%.*]]) {
20; CHECK-NEXT:    [[BINOP:%.*]] = lshr i8 17, [[X]]
21; CHECK-NEXT:    ret i8 [[BINOP]]
22;
23  %shift = lshr i8 16, %x
24  %add = add i8 %x, 1
25  %shift2 = lshr i8 3, %add
26  %binop = or i8 %shift, %shift2
27  ret i8 %binop
28}
29
30define i8 @ashr_or(i8 %x) {
31; CHECK-LABEL: define i8 @ashr_or
32; CHECK-SAME: (i8 [[X:%.*]]) {
33; CHECK-NEXT:    [[BINOP:%.*]] = ashr i8 -64, [[X]]
34; CHECK-NEXT:    ret i8 [[BINOP]]
35;
36  %shift = ashr i8 -64, %x
37  %add = add i8 %x, 1
38  %shift2 = ashr i8 -128, %add
39  %binop = or i8 %shift, %shift2
40  ret i8 %binop
41}
42
43define i8 @shl_xor(i8 %x) {
44; CHECK-LABEL: define i8 @shl_xor
45; CHECK-SAME: (i8 [[X:%.*]]) {
46; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 22, [[X]]
47; CHECK-NEXT:    ret i8 [[BINOP]]
48;
49  %shift = shl i8 16, %x
50  %add = add i8 %x, 1
51  %shift2 = shl i8 3, %add
52  %binop = xor i8 %shift, %shift2
53  ret i8 %binop
54}
55
56define i8 @lshr_xor(i8 %x) {
57; CHECK-LABEL: define i8 @lshr_xor
58; CHECK-SAME: (i8 [[X:%.*]]) {
59; CHECK-NEXT:    [[BINOP:%.*]] = lshr i8 17, [[X]]
60; CHECK-NEXT:    ret i8 [[BINOP]]
61;
62  %shift = lshr i8 16, %x
63  %add = add i8 %x, 1
64  %shift2 = lshr i8 3, %add
65  %binop = xor i8 %shift, %shift2
66  ret i8 %binop
67}
68
69define i8 @ashr_xor(i8 %x) {
70; CHECK-LABEL: define i8 @ashr_xor
71; CHECK-SAME: (i8 [[X:%.*]]) {
72; CHECK-NEXT:    [[BINOP:%.*]] = lshr i8 96, [[X]]
73; CHECK-NEXT:    ret i8 [[BINOP]]
74;
75  %shift = ashr i8 -128, %x
76  %add = add i8 %x, 1
77  %shift2 = ashr i8 -64, %add
78  %binop = xor i8 %shift, %shift2
79  ret i8 %binop
80}
81
82define i8 @shl_and(i8 %x) {
83; CHECK-LABEL: define i8 @shl_and
84; CHECK-SAME: (i8 [[X:%.*]]) {
85; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 16, [[X]]
86; CHECK-NEXT:    ret i8 [[BINOP]]
87;
88  %shift = shl i8 48, %x
89  %add = add i8 %x, 1
90  %shift2 = shl i8 8, %add
91  %binop = and i8 %shift, %shift2
92  ret i8 %binop
93}
94
95define i8 @lshr_and(i8 %x) {
96; CHECK-LABEL: define i8 @lshr_and
97; CHECK-SAME: (i8 [[X:%.*]]) {
98; CHECK-NEXT:    [[BINOP:%.*]] = lshr i8 32, [[X]]
99; CHECK-NEXT:    ret i8 [[BINOP]]
100;
101  %shift = lshr i8 48, %x
102  %add = add i8 %x, 1
103  %shift2 = lshr i8 64, %add
104  %binop = and i8 %shift, %shift2
105  ret i8 %binop
106}
107
108define i8 @ashr_and(i8 %x) {
109; CHECK-LABEL: define i8 @ashr_and
110; CHECK-SAME: (i8 [[X:%.*]]) {
111; CHECK-NEXT:    [[BINOP:%.*]] = ashr i8 -64, [[X]]
112; CHECK-NEXT:    ret i8 [[BINOP]]
113;
114  %shift = ashr i8 -64, %x
115  %add = add i8 %x, 1
116  %shift2 = ashr i8 -128, %add
117  %binop = and i8 %shift, %shift2
118  ret i8 %binop
119}
120
121define i8 @shl_add(i8 %x) {
122; CHECK-LABEL: define i8 @shl_add
123; CHECK-SAME: (i8 [[X:%.*]]) {
124; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 30, [[X]]
125; CHECK-NEXT:    ret i8 [[BINOP]]
126;
127  %shift = shl i8 16, %x
128  %add = add i8 %x, 1
129  %shift2 = shl i8 7, %add
130  %binop = add i8 %shift, %shift2
131  ret i8 %binop
132}
133
134define i8 @lshr_add_fail(i8 %x) {
135; CHECK-LABEL: define i8 @lshr_add_fail
136; CHECK-SAME: (i8 [[X:%.*]]) {
137; CHECK-NEXT:    [[SHIFT:%.*]] = lshr i8 16, [[X]]
138; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
139; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 7, [[ADD]]
140; CHECK-NEXT:    [[BINOP:%.*]] = add nuw nsw i8 [[SHIFT]], [[SHIFT2]]
141; CHECK-NEXT:    ret i8 [[BINOP]]
142;
143  %shift = lshr i8 16, %x
144  %add = add i8 %x, 1
145  %shift2 = lshr i8 7, %add
146  %binop = add i8 %shift, %shift2
147  ret i8 %binop
148}
149
150define i8 @ashr_add_fail(i8 %x) {
151; CHECK-LABEL: define i8 @ashr_add_fail
152; CHECK-SAME: (i8 [[X:%.*]]) {
153; CHECK-NEXT:    [[SHIFT:%.*]] = ashr exact i8 -128, [[X]]
154; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
155; CHECK-NEXT:    [[SHIFT2:%.*]] = ashr exact i8 -128, [[ADD]]
156; CHECK-NEXT:    [[BINOP:%.*]] = add i8 [[SHIFT]], [[SHIFT2]]
157; CHECK-NEXT:    ret i8 [[BINOP]]
158;
159  %shift = ashr i8 -128, %x
160  %add = add i8 %x, 1
161  %shift2 = ashr i8 -128, %add
162  %binop = add i8 %shift, %shift2
163  ret i8 %binop
164}
165
166define i8 @shl_or_commuted(i8 %x) {
167; CHECK-LABEL: define i8 @shl_or_commuted
168; CHECK-SAME: (i8 [[X:%.*]]) {
169; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 22, [[X]]
170; CHECK-NEXT:    ret i8 [[BINOP]]
171;
172  %shift = shl i8 16, %x
173  %add = add i8 %x, 1
174  %shift2 = shl i8 3, %add
175  %binop = or i8 %shift2, %shift
176  ret i8 %binop
177}
178
179define <2 x i8> @shl_or_splat(<2 x i8> %x) {
180; CHECK-LABEL: define <2 x i8> @shl_or_splat
181; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
182; CHECK-NEXT:    [[BINOP:%.*]] = shl <2 x i8> splat (i8 22), [[X]]
183; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
184;
185  %shift = shl <2 x i8> <i8 16, i8 16>, %x
186  %add = add <2 x i8> %x, <i8 1, i8 1>
187  %shift2 = shl <2 x i8> <i8 3, i8 3>, %add
188  %binop = or <2 x i8> %shift, %shift2
189  ret <2 x i8> %binop
190}
191
192define <2 x i8> @shl_or_non_splat(<2 x i8> %x) {
193; CHECK-LABEL: define <2 x i8> @shl_or_non_splat
194; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
195; CHECK-NEXT:    [[BINOP:%.*]] = shl <2 x i8> <i8 22, i8 60>, [[X]]
196; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
197;
198  %shift = shl <2 x i8> <i8 16, i8 32>, %x
199  %add = add <2 x i8> %x, <i8 1, i8 2>
200  %shift2 = shl <2 x i8> <i8 3, i8 7>, %add
201  %binop = or <2 x i8> %shift, %shift2
202  ret <2 x i8> %binop
203}
204
205define <2 x i8> @shl_or_poison_in_add(<2 x i8> %x) {
206; CHECK-LABEL: define <2 x i8> @shl_or_poison_in_add
207; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
208; CHECK-NEXT:    [[BINOP:%.*]] = shl <2 x i8> <i8 22, i8 poison>, [[X]]
209; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
210;
211  %shift = shl <2 x i8> <i8 16, i8 16>, %x
212  %add = add <2 x i8> %x, <i8 1, i8 poison>
213  %shift2 = shl <2 x i8> <i8 3, i8 3>, %add
214  %binop = or <2 x i8> %shift, %shift2
215  ret <2 x i8> %binop
216}
217
218define <2 x i8> @shl_or_poison_in_shift1(<2 x i8> %x) {
219; CHECK-LABEL: define <2 x i8> @shl_or_poison_in_shift1
220; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
221; CHECK-NEXT:    [[BINOP:%.*]] = shl <2 x i8> <i8 22, i8 poison>, [[X]]
222; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
223;
224  %shift = shl <2 x i8> <i8 16, i8 poison>, %x
225  %add = add <2 x i8> %x, <i8 1, i8 1>
226  %shift2 = shl <2 x i8> <i8 3, i8 3>, %add
227  %binop = or <2 x i8> %shift, %shift2
228  ret <2 x i8> %binop
229}
230
231define <2 x i8> @shl_or_poison_in_shift2(<2 x i8> %x) {
232; CHECK-LABEL: define <2 x i8> @shl_or_poison_in_shift2
233; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
234; CHECK-NEXT:    [[BINOP:%.*]] = shl <2 x i8> <i8 22, i8 poison>, [[X]]
235; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
236;
237  %shift = shl <2 x i8> <i8 16, i8 16>, %x
238  %add = add <2 x i8> %x, <i8 1, i8 1>
239  %shift2 = shl <2 x i8> <i8 3, i8 poison>, %add
240  %binop = or <2 x i8> %shift, %shift2
241  ret <2 x i8> %binop
242}
243
244declare void @use(i8)
245
246define i8 @shl_or_multiuse(i8 %x) {
247; CHECK-LABEL: define i8 @shl_or_multiuse
248; CHECK-SAME: (i8 [[X:%.*]]) {
249; CHECK-NEXT:    [[SHIFT:%.*]] = shl i8 16, [[X]]
250; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
251; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 3, [[ADD]]
252; CHECK-NEXT:    call void @use(i8 [[SHIFT]])
253; CHECK-NEXT:    call void @use(i8 [[ADD]])
254; CHECK-NEXT:    call void @use(i8 [[SHIFT2]])
255; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 22, [[X]]
256; CHECK-NEXT:    ret i8 [[BINOP]]
257;
258  %shift = shl i8 16, %x
259  %add = add i8 %x, 1
260  %shift2 = shl i8 3, %add
261  call void @use(i8 %shift)
262  call void @use(i8 %add)
263  call void @use(i8 %shift2)
264  %binop = or i8 %shift, %shift2
265  ret i8 %binop
266}
267
268define i8 @mismatched_shifts(i8 %x) {
269; CHECK-LABEL: define i8 @mismatched_shifts
270; CHECK-SAME: (i8 [[X:%.*]]) {
271; CHECK-NEXT:    [[SHIFT:%.*]] = shl i8 16, [[X]]
272; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 1
273; CHECK-NEXT:    [[SHIFT2:%.*]] = lshr i8 3, [[ADD]]
274; CHECK-NEXT:    [[BINOP:%.*]] = or disjoint i8 [[SHIFT]], [[SHIFT2]]
275; CHECK-NEXT:    ret i8 [[BINOP]]
276;
277  %shift = shl i8 16, %x
278  %add = add i8 %x, 1
279  %shift2 = lshr i8 3, %add
280  %binop = or i8 %shift, %shift2
281  ret i8 %binop
282}
283
284define i8 @mismatched_ops(i8 %x, i8 %y) {
285; CHECK-LABEL: define i8 @mismatched_ops
286; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
287; CHECK-NEXT:    [[SHIFT:%.*]] = shl i8 16, [[X]]
288; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[Y]], 1
289; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 3, [[ADD]]
290; CHECK-NEXT:    [[BINOP:%.*]] = or i8 [[SHIFT]], [[SHIFT2]]
291; CHECK-NEXT:    ret i8 [[BINOP]]
292;
293  %shift = shl i8 16, %x
294  %add = add i8 %y, 1
295  %shift2 = shl i8 3, %add
296  %binop = or i8 %shift, %shift2
297  ret i8 %binop
298}
299
300define i8 @add_out_of_range(i8 %x) {
301; CHECK-LABEL: define i8 @add_out_of_range
302; CHECK-SAME: (i8 [[X:%.*]]) {
303; CHECK-NEXT:    [[SHIFT:%.*]] = shl i8 16, [[X]]
304; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X]], 32
305; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 3, [[ADD]]
306; CHECK-NEXT:    [[BINOP:%.*]] = or i8 [[SHIFT]], [[SHIFT2]]
307; CHECK-NEXT:    ret i8 [[BINOP]]
308;
309  %shift = shl i8 16, %x
310  %add = add i8 %x, 32
311  %shift2 = shl i8 3, %add
312  %binop = or i8 %shift, %shift2
313  ret i8 %binop
314}
315
316define <2 x i8> @shl_or_non_splat_out_of_range(<2 x i8> %x) {
317; CHECK-LABEL: define <2 x i8> @shl_or_non_splat_out_of_range
318; CHECK-SAME: (<2 x i8> [[X:%.*]]) {
319; CHECK-NEXT:    [[SHIFT:%.*]] = shl <2 x i8> <i8 16, i8 32>, [[X]]
320; CHECK-NEXT:    [[ADD:%.*]] = add <2 x i8> [[X]], <i8 1, i8 32>
321; CHECK-NEXT:    [[SHIFT2:%.*]] = shl <2 x i8> <i8 3, i8 7>, [[ADD]]
322; CHECK-NEXT:    [[BINOP:%.*]] = or <2 x i8> [[SHIFT]], [[SHIFT2]]
323; CHECK-NEXT:    ret <2 x i8> [[BINOP]]
324;
325  %shift = shl <2 x i8> <i8 16, i8 32>, %x
326  %add = add <2 x i8> %x, <i8 1, i8 32>
327  %shift2 = shl <2 x i8> <i8 3, i8 7>, %add
328  %binop = or <2 x i8> %shift, %shift2
329  ret <2 x i8> %binop
330}
331
332define i8 @shl_or_with_or_disjoint_instead_of_add(i8 %x) {
333; CHECK-LABEL: define i8 @shl_or_with_or_disjoint_instead_of_add
334; CHECK-SAME: (i8 [[X:%.*]]) {
335; CHECK-NEXT:    [[BINOP:%.*]] = shl i8 22, [[X]]
336; CHECK-NEXT:    ret i8 [[BINOP]]
337;
338  %shift = shl i8 16, %x
339  %add = or disjoint i8 %x, 1
340  %shift2 = shl i8 3, %add
341  %binop = or i8 %shift, %shift2
342  ret i8 %binop
343}
344
345define i8 @shl_or_with_or_instead_of_add(i8 %x) {
346; CHECK-LABEL: define i8 @shl_or_with_or_instead_of_add
347; CHECK-SAME: (i8 [[X:%.*]]) {
348; CHECK-NEXT:    [[SHIFT:%.*]] = shl i8 16, [[X]]
349; CHECK-NEXT:    [[ADD:%.*]] = or i8 [[X]], 1
350; CHECK-NEXT:    [[SHIFT2:%.*]] = shl i8 3, [[ADD]]
351; CHECK-NEXT:    [[BINOP:%.*]] = or i8 [[SHIFT]], [[SHIFT2]]
352; CHECK-NEXT:    ret i8 [[BINOP]]
353;
354  %shift = shl i8 16, %x
355  %add = or i8 %x, 1
356  %shift2 = shl i8 3, %add
357  %binop = or i8 %shift, %shift2
358  ret i8 %binop
359}
360