1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; https://bugs.llvm.org/show_bug.cgi?id=37603
5; https://reviews.llvm.org/D46760#1123713
6
7; Pattern:
8;   x >> y << y
9; Should be transformed into:
10;   x & (-1 << y)
11
12; ============================================================================ ;
13; Basic positive tests
14; ============================================================================ ;
15
16define i32 @positive_samevar(i32 %x, i32 %y) {
17; CHECK-LABEL: @positive_samevar(
18; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 -1, [[Y:%.*]]
19; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], [[X:%.*]]
20; CHECK-NEXT:    ret i32 [[RET]]
21;
22  %tmp0 = ashr i32 %x, %y
23  %ret = shl i32 %tmp0, %y
24  ret i32 %ret
25}
26
27define i32 @positive_sameconst(i32 %x) {
28; CHECK-LABEL: @positive_sameconst(
29; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], -32
30; CHECK-NEXT:    ret i32 [[TMP1]]
31;
32  %tmp0 = ashr i32 %x, 5
33  %ret = shl i32 %tmp0, 5
34  ret i32 %ret
35}
36
37define i32 @positive_biggerashr(i32 %x) {
38; CHECK-LABEL: @positive_biggerashr(
39; CHECK-NEXT:    [[TMP0:%.*]] = ashr i32 [[X:%.*]], 10
40; CHECK-NEXT:    [[RET:%.*]] = shl nsw i32 [[TMP0]], 5
41; CHECK-NEXT:    ret i32 [[RET]]
42;
43  %tmp0 = ashr i32 %x, 10
44  %ret = shl i32 %tmp0, 5
45  ret i32 %ret
46}
47
48define i32 @positive_biggershl(i32 %x) {
49; CHECK-LABEL: @positive_biggershl(
50; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 5
51; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[TMP1]], 10
52; CHECK-NEXT:    ret i32 [[RET]]
53;
54  %tmp0 = ashr i32 %x, 5
55  %ret = shl i32 %tmp0, 10
56  ret i32 %ret
57}
58
59; ============================================================================ ;
60; EXACT on the first shift
61; ============================================================================ ;
62
63define i32 @positive_samevar_ashrexact(i32 %x, i32 %y) {
64; CHECK-LABEL: @positive_samevar_ashrexact(
65; CHECK-NEXT:    ret i32 [[X:%.*]]
66;
67  %tmp0 = ashr exact i32 %x, %y
68  %ret = shl i32 %tmp0, %y ; this one is obviously 'nuw'.
69  ret i32 %ret
70}
71
72define i32 @positive_sameconst_ashrexact(i32 %x) {
73; CHECK-LABEL: @positive_sameconst_ashrexact(
74; CHECK-NEXT:    ret i32 [[X:%.*]]
75;
76  %tmp0 = ashr exact i32 %x, 5
77  %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
78  ret i32 %ret
79}
80
81define i32 @positive_biggerashr_ashrexact(i32 %x) {
82; CHECK-LABEL: @positive_biggerashr_ashrexact(
83; CHECK-NEXT:    [[RET:%.*]] = ashr exact i32 [[X:%.*]], 5
84; CHECK-NEXT:    ret i32 [[RET]]
85;
86  %tmp0 = ashr exact i32 %x, 10
87  %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
88  ret i32 %ret
89}
90
91define i32 @positive_biggershl_ashrexact(i32 %x) {
92; CHECK-LABEL: @positive_biggershl_ashrexact(
93; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[X:%.*]], 5
94; CHECK-NEXT:    ret i32 [[RET]]
95;
96  %tmp0 = ashr exact i32 %x, 5
97  %ret = shl i32 %tmp0, 10
98  ret i32 %ret
99}
100
101define i32 @positive_biggershl_ashrexact_shlnuw(i32 %x) {
102; CHECK-LABEL: @positive_biggershl_ashrexact_shlnuw(
103; CHECK-NEXT:    [[RET:%.*]] = shl nuw i32 [[X:%.*]], 5
104; CHECK-NEXT:    ret i32 [[RET]]
105;
106  %tmp0 = ashr exact i32 %x, 5
107  %ret = shl nuw i32 %tmp0, 10
108  ret i32 %ret
109}
110
111; ============================================================================ ;
112; Vector
113; ============================================================================ ;
114
115define <2 x i32> @positive_samevar_vec(<2 x i32> %x, <2 x i32> %y) {
116; CHECK-LABEL: @positive_samevar_vec(
117; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i32> <i32 -1, i32 -1>, [[Y:%.*]]
118; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[TMP1]], [[X:%.*]]
119; CHECK-NEXT:    ret <2 x i32> [[RET]]
120;
121  %tmp0 = ashr <2 x i32> %x, %y
122  %ret = shl <2 x i32> %tmp0, %y
123  ret <2 x i32> %ret
124}
125
126; ============================================================================ ;
127; Constant Vectors
128; ============================================================================ ;
129
130define <2 x i32> @positive_sameconst_vec(<2 x i32> %x) {
131; CHECK-LABEL: @positive_sameconst_vec(
132; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -32, i32 -32>
133; CHECK-NEXT:    ret <2 x i32> [[TMP1]]
134;
135  %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
136  %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
137  ret <2 x i32> %ret
138}
139
140define <3 x i32> @positive_sameconst_vec_undef0(<3 x i32> %x) {
141; CHECK-LABEL: @positive_sameconst_vec_undef0(
142; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
143; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5>
144; CHECK-NEXT:    ret <3 x i32> [[RET]]
145;
146  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5>
147  %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5>
148  ret <3 x i32> %ret
149}
150
151define <3 x i32> @positive_sameconst_vec_undef1(<3 x i32> %x) {
152; CHECK-LABEL: @positive_sameconst_vec_undef1(
153; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5>
154; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
155; CHECK-NEXT:    ret <3 x i32> [[RET]]
156;
157  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5>
158  %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
159  ret <3 x i32> %ret
160}
161
162define <3 x i32> @positive_sameconst_vec_undef2(<3 x i32> %x) {
163; CHECK-LABEL: @positive_sameconst_vec_undef2(
164; CHECK-NEXT:    [[RET:%.*]] = and <3 x i32> [[X:%.*]], <i32 -32, i32 undef, i32 -32>
165; CHECK-NEXT:    ret <3 x i32> [[RET]]
166;
167  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5>
168  %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
169  ret <3 x i32> %ret
170}
171
172define <2 x i32> @positive_biggerashr_vec(<2 x i32> %x) {
173; CHECK-LABEL: @positive_biggerashr_vec(
174; CHECK-NEXT:    [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 10, i32 10>
175; CHECK-NEXT:    [[RET:%.*]] = shl nsw <2 x i32> [[TMP0]], <i32 5, i32 5>
176; CHECK-NEXT:    ret <2 x i32> [[RET]]
177;
178  %tmp0 = ashr <2 x i32> %x, <i32 10, i32 10>
179  %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
180  ret <2 x i32> %ret
181}
182
183define <3 x i32> @positive_biggerashr_vec_undef0(<3 x i32> %x) {
184; CHECK-LABEL: @positive_biggerashr_vec_undef0(
185; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10>
186; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5>
187; CHECK-NEXT:    ret <3 x i32> [[RET]]
188;
189  %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10>
190  %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5>
191  ret <3 x i32> %ret
192}
193
194define <3 x i32> @positive_biggerashr_vec_undef1(<3 x i32> %x) {
195; CHECK-LABEL: @positive_biggerashr_vec_undef1(
196; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 10, i32 10>
197; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
198; CHECK-NEXT:    ret <3 x i32> [[RET]]
199;
200  %tmp0 = ashr <3 x i32> %x, <i32 10, i32 10, i32 10>
201  %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
202  ret <3 x i32> %ret
203}
204
205define <3 x i32> @positive_biggerashr_vec_undef2(<3 x i32> %x) {
206; CHECK-LABEL: @positive_biggerashr_vec_undef2(
207; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10>
208; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
209; CHECK-NEXT:    ret <3 x i32> [[RET]]
210;
211  %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10>
212  %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
213  ret <3 x i32> %ret
214}
215
216define <2 x i32> @positive_biggershl_vec(<2 x i32> %x) {
217; CHECK-LABEL: @positive_biggershl_vec(
218; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 5>
219; CHECK-NEXT:    [[RET:%.*]] = shl <2 x i32> [[TMP1]], <i32 10, i32 10>
220; CHECK-NEXT:    ret <2 x i32> [[RET]]
221;
222  %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
223  %ret = shl <2 x i32> %tmp0, <i32 10, i32 10>
224  ret <2 x i32> %ret
225}
226
227define <3 x i32> @positive_biggershl_vec_undef0(<3 x i32> %x) {
228; CHECK-LABEL: @positive_biggershl_vec_undef0(
229; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
230; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 10, i32 10>
231; CHECK-NEXT:    ret <3 x i32> [[RET]]
232;
233  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5>
234  %ret = shl <3 x i32> %tmp0, <i32 10, i32 10, i32 10>
235  ret <3 x i32> %ret
236}
237
238define <3 x i32> @positive_biggershl_vec_undef1(<3 x i32> %x) {
239; CHECK-LABEL: @positive_biggershl_vec_undef1(
240; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5>
241; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10>
242; CHECK-NEXT:    ret <3 x i32> [[RET]]
243;
244  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5>
245  %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10>
246  ret <3 x i32> %ret
247}
248
249define <3 x i32> @positive_biggershl_vec_undef2(<3 x i32> %x) {
250; CHECK-LABEL: @positive_biggershl_vec_undef2(
251; CHECK-NEXT:    [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
252; CHECK-NEXT:    [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10>
253; CHECK-NEXT:    ret <3 x i32> [[RET]]
254;
255  %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5>
256  %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10>
257  ret <3 x i32> %ret
258}
259
260; ============================================================================ ;
261; Positive multi-use tests with constant
262; ============================================================================ ;
263
264; FIXME: drop 'exact' once it is no longer needed.
265
266define i32 @positive_sameconst_multiuse(i32 %x) {
267; CHECK-LABEL: @positive_sameconst_multiuse(
268; CHECK-NEXT:    [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5
269; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
270; CHECK-NEXT:    ret i32 [[X]]
271;
272  %tmp0 = ashr exact i32 %x, 5
273  call void @use32(i32 %tmp0)
274  %ret = shl i32 %tmp0, 5
275  ret i32 %ret
276}
277
278define i32 @positive_biggerashr_multiuse(i32 %x) {
279; CHECK-LABEL: @positive_biggerashr_multiuse(
280; CHECK-NEXT:    [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 10
281; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
282; CHECK-NEXT:    [[RET:%.*]] = ashr exact i32 [[X]], 5
283; CHECK-NEXT:    ret i32 [[RET]]
284;
285  %tmp0 = ashr exact i32 %x, 10
286  call void @use32(i32 %tmp0)
287  %ret = shl i32 %tmp0, 5
288  ret i32 %ret
289}
290
291define i32 @positive_biggershl_multiuse(i32 %x) {
292; CHECK-LABEL: @positive_biggershl_multiuse(
293; CHECK-NEXT:    [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5
294; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
295; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[X]], 5
296; CHECK-NEXT:    ret i32 [[RET]]
297;
298  %tmp0 = ashr exact i32 %x, 5
299  call void @use32(i32 %tmp0)
300  %ret = shl i32 %tmp0, 10
301  ret i32 %ret
302}
303
304; ============================================================================ ;
305; Constant Non-Splat Vectors
306; ============================================================================ ;
307
308define <2 x i32> @positive_biggerashr_vec_nonsplat(<2 x i32> %x) {
309; CHECK-LABEL: @positive_biggerashr_vec_nonsplat(
310; CHECK-NEXT:    [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 5>
311; CHECK-NEXT:    [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 10>
312; CHECK-NEXT:    ret <2 x i32> [[RET]]
313;
314  %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
315  %ret = shl <2 x i32> %tmp0, <i32 5, i32 10>
316  ret <2 x i32> %ret
317}
318
319define <2 x i32> @positive_biggerLashr_vec_nonsplat(<2 x i32> %x) {
320; CHECK-LABEL: @positive_biggerLashr_vec_nonsplat(
321; CHECK-NEXT:    [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 10>
322; CHECK-NEXT:    [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 5>
323; CHECK-NEXT:    ret <2 x i32> [[RET]]
324;
325  %tmp0 = ashr <2 x i32> %x, <i32 5, i32 10>
326  %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
327  ret <2 x i32> %ret
328}
329
330; ============================================================================ ;
331; Negative tests. Should not be folded.
332; ============================================================================ ;
333
334define i32 @negative_twovars(i32 %x, i32 %y, i32 %z) {
335; CHECK-LABEL: @negative_twovars(
336; CHECK-NEXT:    [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
337; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[TMP0]], [[Z:%.*]]
338; CHECK-NEXT:    ret i32 [[RET]]
339;
340  %tmp0 = ashr i32 %x, %y
341  %ret = shl i32 %tmp0, %z ; $z, not %y
342  ret i32 %ret
343}
344
345declare void @use32(i32)
346
347; One use only.
348define i32 @negative_oneuse(i32 %x, i32 %y) {
349; CHECK-LABEL: @negative_oneuse(
350; CHECK-NEXT:    [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
351; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
352; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[TMP0]], [[Y]]
353; CHECK-NEXT:    ret i32 [[RET]]
354;
355  %tmp0 = ashr i32 %x, %y
356  call void @use32(i32 %tmp0)
357  %ret = shl i32 %tmp0, %y
358  ret i32 %ret
359}
360