[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / canonicalize-shl-lshr-to-masking.ll
blob9de0b337de2866bffca0d7e7569a667dd0e1f412
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=37603
6 ; Pattern:
7 ;   x << y >> y
8 ; Should be transformed into:
9 ;   x & (-1 >> y)
11 ; ============================================================================ ;
12 ; Basic positive tests
13 ; ============================================================================ ;
15 define i32 @positive_samevar(i32 %x, i32 %y) {
16 ; CHECK-LABEL: @positive_samevar(
17 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 -1, [[Y:%.*]]
18 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], [[X:%.*]]
19 ; CHECK-NEXT:    ret i32 [[RET]]
21   %tmp0 = shl i32 %x, %y
22   %ret = lshr i32 %tmp0, %y
23   ret i32 %ret
26 define i32 @positive_sameconst(i32 %x) {
27 ; CHECK-LABEL: @positive_sameconst(
28 ; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[X:%.*]], 134217727
29 ; CHECK-NEXT:    ret i32 [[TMP0]]
31   %tmp0 = shl i32 %x, 5
32   %ret = lshr i32 %tmp0, 5
33   ret i32 %ret
36 define i32 @positive_biggerShl(i32 %x) {
37 ; CHECK-LABEL: @positive_biggerShl(
38 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 5
39 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], 134217696
40 ; CHECK-NEXT:    ret i32 [[RET]]
42   %tmp0 = shl i32 %x, 10
43   %ret = lshr i32 %tmp0, 5
44   ret i32 %ret
47 define i32 @positive_biggerLshr(i32 %x) {
48 ; CHECK-LABEL: @positive_biggerLshr(
49 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 5
50 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], 4194303
51 ; CHECK-NEXT:    ret i32 [[RET]]
53   %tmp0 = shl i32 %x, 5
54   %ret = lshr i32 %tmp0, 10
55   ret i32 %ret
58 define i32 @positive_biggerLshr_lshrexact(i32 %x) {
59 ; CHECK-LABEL: @positive_biggerLshr_lshrexact(
60 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 5
61 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], 4194303
62 ; CHECK-NEXT:    ret i32 [[RET]]
64   %tmp0 = shl i32 %x, 5
65   %ret = lshr exact i32 %tmp0, 10
66   ret i32 %ret
69 ; ============================================================================ ;
70 ; NUW on the first shift
71 ; ============================================================================ ;
73 define i32 @positive_samevar_shlnuw(i32 %x, i32 %y) {
74 ; CHECK-LABEL: @positive_samevar_shlnuw(
75 ; CHECK-NEXT:    ret i32 [[X:%.*]]
77   %tmp0 = shl nuw i32 %x, %y
78   %ret = lshr i32 %tmp0, %y ; this one is obviously 'exact'.
79   ret i32 %ret
82 define i32 @positive_sameconst_shlnuw(i32 %x) {
83 ; CHECK-LABEL: @positive_sameconst_shlnuw(
84 ; CHECK-NEXT:    ret i32 [[X:%.*]]
86   %tmp0 = shl nuw i32 %x, 5
87   %ret = lshr i32 %tmp0, 5 ; this one is obviously 'exact'.
88   ret i32 %ret
91 define i32 @positive_biggerShl_shlnuw(i32 %x) {
92 ; CHECK-LABEL: @positive_biggerShl_shlnuw(
93 ; CHECK-NEXT:    [[RET:%.*]] = shl nuw i32 [[X:%.*]], 5
94 ; CHECK-NEXT:    ret i32 [[RET]]
96   %tmp0 = shl nuw i32 %x, 10
97   %ret = lshr i32 %tmp0, 5 ; this one is obviously 'exact'.
98   ret i32 %ret
101 define i32 @positive_biggerLshr_shlnuw(i32 %x) {
102 ; CHECK-LABEL: @positive_biggerLshr_shlnuw(
103 ; CHECK-NEXT:    [[RET:%.*]] = lshr i32 [[X:%.*]], 5
104 ; CHECK-NEXT:    ret i32 [[RET]]
106   %tmp0 = shl nuw i32 %x, 5
107   %ret = lshr i32 %tmp0, 10
108   ret i32 %ret
111 define i32 @positive_biggerLshr_shlnuw_lshrexact(i32 %x) {
112 ; CHECK-LABEL: @positive_biggerLshr_shlnuw_lshrexact(
113 ; CHECK-NEXT:    [[RET:%.*]] = lshr exact i32 [[X:%.*]], 5
114 ; CHECK-NEXT:    ret i32 [[RET]]
116   %tmp0 = shl nuw i32 %x, 5
117   %ret = lshr exact i32 %tmp0, 10
118   ret i32 %ret
121 ; ============================================================================ ;
122 ; Vector
123 ; ============================================================================ ;
125 define <2 x i32> @positive_samevar_vec(<2 x i32> %x, <2 x i32> %y) {
126 ; CHECK-LABEL: @positive_samevar_vec(
127 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> <i32 -1, i32 -1>, [[Y:%.*]]
128 ; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[TMP1]], [[X:%.*]]
129 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
131   %tmp0 = shl <2 x i32> %x, %y
132   %ret = lshr <2 x i32> %tmp0, %y
133   ret <2 x i32> %ret
136 ; ============================================================================ ;
137 ; Constant Vectors
138 ; ============================================================================ ;
140 define <2 x i32> @positive_sameconst_vec(<2 x i32> %x) {
141 ; CHECK-LABEL: @positive_sameconst_vec(
142 ; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i32> [[X:%.*]], <i32 134217727, i32 134217727>
143 ; CHECK-NEXT:    ret <2 x i32> [[TMP0]]
145   %tmp0 = shl <2 x i32> %x, <i32 5, i32 5>
146   %ret = lshr <2 x i32> %tmp0, <i32 5, i32 5>
147   ret <2 x i32> %ret
150 define <3 x i32> @positive_sameconst_vec_undef0(<3 x i32> %x) {
151 ; CHECK-LABEL: @positive_sameconst_vec_undef0(
152 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
153 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5>
154 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
156   %tmp0 = shl <3 x i32> %x, <i32 5, i32 undef, i32 5>
157   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 5, i32 5>
158   ret <3 x i32> %ret
161 define <3 x i32> @positive_sameconst_vec_undef1(<3 x i32> %x) {
162 ; CHECK-LABEL: @positive_sameconst_vec_undef1(
163 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5>
164 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
165 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
167   %tmp0 = shl <3 x i32> %x, <i32 5, i32 5, i32 5>
168   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
169   ret <3 x i32> %ret
172 define <3 x i32> @positive_sameconst_vec_undef2(<3 x i32> %x) {
173 ; CHECK-LABEL: @positive_sameconst_vec_undef2(
174 ; CHECK-NEXT:    [[RET:%.*]] = and <3 x i32> [[X:%.*]], <i32 134217727, i32 undef, i32 134217727>
175 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
177   %tmp0 = shl <3 x i32> %x, <i32 5, i32 undef, i32 5>
178   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
179   ret <3 x i32> %ret
182 define <2 x i32> @positive_biggerShl_vec(<2 x i32> %x) {
183 ; CHECK-LABEL: @positive_biggerShl_vec(
184 ; CHECK-NEXT:    [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 5>
185 ; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[TMP1]], <i32 134217696, i32 134217696>
186 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
188   %tmp0 = shl <2 x i32> %x, <i32 10, i32 10>
189   %ret = lshr <2 x i32> %tmp0, <i32 5, i32 5>
190   ret <2 x i32> %ret
193 define <3 x i32> @positive_biggerShl_vec_undef0(<3 x i32> %x) {
194 ; CHECK-LABEL: @positive_biggerShl_vec_undef0(
195 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10>
196 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5>
197 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
199   %tmp0 = shl <3 x i32> %x, <i32 10, i32 undef, i32 10>
200   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 5, i32 5>
201   ret <3 x i32> %ret
204 define <3 x i32> @positive_biggerShl_vec_undef1(<3 x i32> %x) {
205 ; CHECK-LABEL: @positive_biggerShl_vec_undef1(
206 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 10, i32 10, i32 10>
207 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
208 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
210   %tmp0 = shl <3 x i32> %x, <i32 10, i32 10, i32 10>
211   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
212   ret <3 x i32> %ret
215 define <3 x i32> @positive_biggerShl_vec_undef2(<3 x i32> %x) {
216 ; CHECK-LABEL: @positive_biggerShl_vec_undef2(
217 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10>
218 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5>
219 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
221   %tmp0 = shl <3 x i32> %x, <i32 10, i32 undef, i32 10>
222   %ret = lshr <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
223   ret <3 x i32> %ret
226 define <2 x i32> @positive_biggerLshr_vec(<2 x i32> %x) {
227 ; CHECK-LABEL: @positive_biggerLshr_vec(
228 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 5>
229 ; CHECK-NEXT:    [[RET:%.*]] = and <2 x i32> [[TMP1]], <i32 4194303, i32 4194303>
230 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
232   %tmp0 = shl <2 x i32> %x, <i32 5, i32 5>
233   %ret = lshr <2 x i32> %tmp0, <i32 10, i32 10>
234   ret <2 x i32> %ret
237 define <3 x i32> @positive_biggerLshr_vec_undef0(<3 x i32> %x) {
238 ; CHECK-LABEL: @positive_biggerLshr_vec_undef0(
239 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
240 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 10, i32 10, i32 10>
241 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
243   %tmp0 = shl <3 x i32> %x, <i32 5, i32 undef, i32 5>
244   %ret = lshr <3 x i32> %tmp0, <i32 10, i32 10, i32 10>
245   ret <3 x i32> %ret
248 define <3 x i32> @positive_biggerLshr_vec_undef1(<3 x i32> %x) {
249 ; CHECK-LABEL: @positive_biggerLshr_vec_undef1(
250 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5>
251 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10>
252 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
254   %tmp0 = shl <3 x i32> %x, <i32 5, i32 5, i32 5>
255   %ret = lshr <3 x i32> %tmp0, <i32 10, i32 undef, i32 10>
256   ret <3 x i32> %ret
259 define <3 x i32> @positive_biggerLshr_vec_undef2(<3 x i32> %x) {
260 ; CHECK-LABEL: @positive_biggerLshr_vec_undef2(
261 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5>
262 ; CHECK-NEXT:    [[RET:%.*]] = lshr <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10>
263 ; CHECK-NEXT:    ret <3 x i32> [[RET]]
265   %tmp0 = shl <3 x i32> %x, <i32 5, i32 undef, i32 5>
266   %ret = lshr <3 x i32> %tmp0, <i32 10, i32 undef, i32 10>
267   ret <3 x i32> %ret
270 ; ============================================================================ ;
271 ; Positive multi-use tests with constant
272 ; ============================================================================ ;
274 define i32 @positive_sameconst_multiuse(i32 %x) {
275 ; CHECK-LABEL: @positive_sameconst_multiuse(
276 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i32 [[X:%.*]], 5
277 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
278 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[X]], 134217727
279 ; CHECK-NEXT:    ret i32 [[RET]]
281   %tmp0 = shl i32 %x, 5
282   call void @use32(i32 %tmp0)
283   %ret = lshr i32 %tmp0, 5
284   ret i32 %ret
287 define i32 @positive_biggerShl_shlnuw_multiuse(i32 %x) {
288 ; CHECK-LABEL: @positive_biggerShl_shlnuw_multiuse(
289 ; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[X:%.*]], 10
290 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
291 ; CHECK-NEXT:    [[RET:%.*]] = shl nuw i32 [[X]], 5
292 ; CHECK-NEXT:    ret i32 [[RET]]
294   %tmp0 = shl nuw i32 %x, 10
295   call void @use32(i32 %tmp0)
296   %ret = lshr i32 %tmp0, 5
297   ret i32 %ret
300 define i32 @positive_biggerLshr_shlnuw_multiuse(i32 %x) {
301 ; CHECK-LABEL: @positive_biggerLshr_shlnuw_multiuse(
302 ; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[X:%.*]], 5
303 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
304 ; CHECK-NEXT:    [[RET:%.*]] = lshr i32 [[X]], 5
305 ; CHECK-NEXT:    ret i32 [[RET]]
307   %tmp0 = shl nuw i32 %x, 5
308   call void @use32(i32 %tmp0)
309   %ret = lshr i32 %tmp0, 10
310   ret i32 %ret
313 ; NOTE: creates one extra instruction, but this seems intentional.
314 define i32 @positive_biggerShl_multiuse_extrainstr(i32 %x) {
315 ; CHECK-LABEL: @positive_biggerShl_multiuse_extrainstr(
316 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i32 [[X:%.*]], 10
317 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
318 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X]], 5
319 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], 134217696
320 ; CHECK-NEXT:    ret i32 [[RET]]
322   %tmp0 = shl i32 %x, 10
323   call void @use32(i32 %tmp0)
324   %ret = lshr i32 %tmp0, 5
325   ret i32 %ret
328 ; NOTE: creates one extra instruction, but this seems intentional.
329 define i32 @positive_biggerLshr_multiuse_extrainstr(i32 %x) {
330 ; CHECK-LABEL: @positive_biggerLshr_multiuse_extrainstr(
331 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i32 [[X:%.*]], 5
332 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
333 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X]], 5
334 ; CHECK-NEXT:    [[RET:%.*]] = and i32 [[TMP1]], 4194303
335 ; CHECK-NEXT:    ret i32 [[RET]]
337   %tmp0 = shl i32 %x, 5
338   call void @use32(i32 %tmp0)
339   %ret = lshr i32 %tmp0, 10
340   ret i32 %ret
343 ; ============================================================================ ;
344 ; Constant Non-Splat Vectors
345 ; ============================================================================ ;
347 define <2 x i32> @positive_biggerShl_vec_nonsplat(<2 x i32> %x) {
348 ; CHECK-LABEL: @positive_biggerShl_vec_nonsplat(
349 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 5>
350 ; CHECK-NEXT:    [[RET:%.*]] = lshr <2 x i32> [[TMP0]], <i32 5, i32 10>
351 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
353   %tmp0 = shl <2 x i32> %x, <i32 5, i32 5>
354   %ret = lshr <2 x i32> %tmp0, <i32 5, i32 10>
355   ret <2 x i32> %ret
358 define <2 x i32> @positive_biggerLshl_vec_nonsplat(<2 x i32> %x) {
359 ; CHECK-LABEL: @positive_biggerLshl_vec_nonsplat(
360 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <2 x i32> [[X:%.*]], <i32 5, i32 10>
361 ; CHECK-NEXT:    [[RET:%.*]] = lshr <2 x i32> [[TMP0]], <i32 5, i32 5>
362 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
364   %tmp0 = shl <2 x i32> %x, <i32 5, i32 10>
365   %ret = lshr <2 x i32> %tmp0, <i32 5, i32 5>
366   ret <2 x i32> %ret
369 ; ============================================================================ ;
370 ; Negative tests. Should not be folded.
371 ; ============================================================================ ;
373 define i32 @negative_twovars(i32 %x, i32 %y, i32 %z) {
374 ; CHECK-LABEL: @negative_twovars(
375 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
376 ; CHECK-NEXT:    [[RET:%.*]] = lshr i32 [[TMP0]], [[Z:%.*]]
377 ; CHECK-NEXT:    ret i32 [[RET]]
379   %tmp0 = shl i32 %x, %y
380   %ret = lshr i32 %tmp0, %z ; $z, not %y
381   ret i32 %ret
384 declare void @use32(i32)
386 ; One use only.
387 define i32 @negative_oneuse(i32 %x, i32 %y) {
388 ; CHECK-LABEL: @negative_oneuse(
389 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
390 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
391 ; CHECK-NEXT:    [[RET:%.*]] = lshr i32 [[TMP0]], [[Y]]
392 ; CHECK-NEXT:    ret i32 [[RET]]
394   %tmp0 = shl i32 %x, %y
395   call void @use32(i32 %tmp0)
396   %ret = lshr i32 %tmp0, %y
397   ret i32 %ret