[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / canonicalize-lshr-shl-to-masking.ll
bloba1ba4e3852556cbf87d46add771b54ad9403bf9b
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
5 ; https://reviews.llvm.org/D46760#1123713
7 ; Pattern:
8 ;   x >> y << y
9 ; Should be transformed into:
10 ;   x & (-1 << y)
12 ; ============================================================================ ;
13 ; Basic positive tests
14 ; ============================================================================ ;
16 define 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]]
22   %tmp0 = lshr i32 %x, %y
23   %ret = shl i32 %tmp0, %y
24   ret i32 %ret
27 define i32 @positive_sameconst(i32 %x) {
28 ; CHECK-LABEL: @positive_sameconst(
29 ; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[X:%.*]], -32
30 ; CHECK-NEXT:    ret i32 [[TMP0]]
32   %tmp0 = lshr i32 %x, 5
33   %ret = shl i32 %tmp0, 5
34   ret i32 %ret
37 define i32 @positive_biggerlshr(i32 %x) {
38 ; CHECK-LABEL: @positive_biggerlshr(
39 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i32 [[X:%.*]], 10
40 ; CHECK-NEXT:    [[RET:%.*]] = shl nuw nsw i32 [[TMP0]], 5
41 ; CHECK-NEXT:    ret i32 [[RET]]
43   %tmp0 = lshr i32 %x, 10
44   %ret = shl i32 %tmp0, 5
45   ret i32 %ret
48 define i32 @positive_biggershl(i32 %x) {
49 ; CHECK-LABEL: @positive_biggershl(
50 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i32 [[X:%.*]], 5
51 ; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[TMP0]], 10
52 ; CHECK-NEXT:    ret i32 [[RET]]
54   %tmp0 = lshr i32 %x, 5
55   %ret = shl i32 %tmp0, 10
56   ret i32 %ret
59 ; ============================================================================ ;
60 ; EXACT on the first shift
61 ; ============================================================================ ;
63 define i32 @positive_samevar_lshrexact(i32 %x, i32 %y) {
64 ; CHECK-LABEL: @positive_samevar_lshrexact(
65 ; CHECK-NEXT:    ret i32 [[X:%.*]]
67   %tmp0 = lshr exact i32 %x, %y
68   %ret = shl i32 %tmp0, %y ; this one is obviously 'nuw'.
69   ret i32 %ret
72 define i32 @positive_sameconst_lshrexact(i32 %x) {
73 ; CHECK-LABEL: @positive_sameconst_lshrexact(
74 ; CHECK-NEXT:    ret i32 [[X:%.*]]
76   %tmp0 = lshr exact i32 %x, 5
77   %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
78   ret i32 %ret
81 define i32 @positive_biggerlshr_lshrexact(i32 %x) {
82 ; CHECK-LABEL: @positive_biggerlshr_lshrexact(
83 ; CHECK-NEXT:    [[RET:%.*]] = lshr exact i32 [[X:%.*]], 5
84 ; CHECK-NEXT:    ret i32 [[RET]]
86   %tmp0 = lshr exact i32 %x, 10
87   %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
88   ret i32 %ret
91 define i32 @positive_biggershl_lshrexact(i32 %x) {
92 ; CHECK-LABEL: @positive_biggershl_lshrexact(
93 ; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[X:%.*]], 5
94 ; CHECK-NEXT:    ret i32 [[RET]]
96   %tmp0 = lshr exact i32 %x, 5
97   %ret = shl i32 %tmp0, 10
98   ret i32 %ret
101 define i32 @positive_biggershl_lshrexact_shlnuw(i32 %x) {
102 ; CHECK-LABEL: @positive_biggershl_lshrexact_shlnuw(
103 ; CHECK-NEXT:    [[RET:%.*]] = shl nuw i32 [[X:%.*]], 5
104 ; CHECK-NEXT:    ret i32 [[RET]]
106   %tmp0 = lshr exact i32 %x, 5
107   %ret = shl nuw i32 %tmp0, 10
108   ret i32 %ret
111 ; ============================================================================ ;
112 ; Vector
113 ; ============================================================================ ;
115 define <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]]
121   %tmp0 = lshr <2 x i32> %x, %y
122   %ret = shl <2 x i32> %tmp0, %y
123   ret <2 x i32> %ret
126 ; ============================================================================ ;
127 ; Constant Vectors
128 ; ============================================================================ ;
130 define <2 x i32> @positive_sameconst_vec(<2 x i32> %x) {
131 ; CHECK-LABEL: @positive_sameconst_vec(
132 ; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i32> [[X:%.*]], <i32 -32, i32 -32>
133 ; CHECK-NEXT:    ret <2 x i32> [[TMP0]]
135   %tmp0 = lshr <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
140 define <3 x i32> @positive_sameconst_vec_undef0(<3 x i32> %x) {
141 ; CHECK-LABEL: @positive_sameconst_vec_undef0(
142 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
146   %tmp0 = lshr <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
151 define <3 x i32> @positive_sameconst_vec_undef1(<3 x i32> %x) {
152 ; CHECK-LABEL: @positive_sameconst_vec_undef1(
153 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
157   %tmp0 = lshr <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
162 define <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]]
167   %tmp0 = lshr <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
172 define <2 x i32> @positive_biggerlshr_vec(<2 x i32> %x) {
173 ; CHECK-LABEL: @positive_biggerlshr_vec(
174 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 10, i32 10>
175 ; CHECK-NEXT:    [[RET:%.*]] = shl nuw nsw <2 x i32> [[TMP0]], <i32 5, i32 5>
176 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
178   %tmp0 = lshr <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
183 define <3 x i32> @positive_biggerlshr_vec_undef0(<3 x i32> %x) {
184 ; CHECK-LABEL: @positive_biggerlshr_vec_undef0(
185 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
189   %tmp0 = lshr <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
194 define <3 x i32> @positive_biggerlshr_vec_undef1(<3 x i32> %x) {
195 ; CHECK-LABEL: @positive_biggerlshr_vec_undef1(
196 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
200   %tmp0 = lshr <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
205 define <3 x i32> @positive_biggerlshr_vec_undef2(<3 x i32> %x) {
206 ; CHECK-LABEL: @positive_biggerlshr_vec_undef2(
207 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
211   %tmp0 = lshr <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
216 define <2 x i32> @positive_biggershl_vec(<2 x i32> %x) {
217 ; CHECK-LABEL: @positive_biggershl_vec(
218 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 5>
219 ; CHECK-NEXT:    [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 10, i32 10>
220 ; CHECK-NEXT:    ret <2 x i32> [[RET]]
222   %tmp0 = lshr <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
227 define <3 x i32> @positive_biggershl_vec_undef0(<3 x i32> %x) {
228 ; CHECK-LABEL: @positive_biggershl_vec_undef0(
229 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
233   %tmp0 = lshr <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
238 define <3 x i32> @positive_biggershl_vec_undef1(<3 x i32> %x) {
239 ; CHECK-LABEL: @positive_biggershl_vec_undef1(
240 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
244   %tmp0 = lshr <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
249 define <3 x i32> @positive_biggershl_vec_undef2(<3 x i32> %x) {
250 ; CHECK-LABEL: @positive_biggershl_vec_undef2(
251 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
255   %tmp0 = lshr <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
260 ; ============================================================================ ;
261 ; Positive multi-use tests with constant
262 ; ============================================================================ ;
264 ; FIXME: drop 'exact' once it is no longer needed.
266 define i32 @positive_sameconst_multiuse(i32 %x) {
267 ; CHECK-LABEL: @positive_sameconst_multiuse(
268 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr exact i32 [[X:%.*]], 5
269 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
270 ; CHECK-NEXT:    ret i32 [[X]]
272   %tmp0 = lshr exact i32 %x, 5
273   call void @use32(i32 %tmp0)
274   %ret = shl i32 %tmp0, 5
275   ret i32 %ret
278 define i32 @positive_biggerlshr_multiuse(i32 %x) {
279 ; CHECK-LABEL: @positive_biggerlshr_multiuse(
280 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr exact i32 [[X:%.*]], 10
281 ; CHECK-NEXT:    call void @use32(i32 [[TMP0]])
282 ; CHECK-NEXT:    [[RET:%.*]] = lshr exact i32 [[X]], 5
283 ; CHECK-NEXT:    ret i32 [[RET]]
285   %tmp0 = lshr exact i32 %x, 10
286   call void @use32(i32 %tmp0)
287   %ret = shl i32 %tmp0, 5
288   ret i32 %ret
291 define i32 @positive_biggershl_multiuse(i32 %x) {
292 ; CHECK-LABEL: @positive_biggershl_multiuse(
293 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr 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]]
298   %tmp0 = lshr exact i32 %x, 5
299   call void @use32(i32 %tmp0)
300   %ret = shl i32 %tmp0, 10
301   ret i32 %ret
304 ; ============================================================================ ;
305 ; Constant Non-Splat Vectors
306 ; ============================================================================ ;
308 define <2 x i32> @positive_biggerlshr_vec_nonsplat(<2 x i32> %x) {
309 ; CHECK-LABEL: @positive_biggerlshr_vec_nonsplat(
310 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
314   %tmp0 = lshr <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
319 define <2 x i32> @positive_biggerLlshr_vec_nonsplat(<2 x i32> %x) {
320 ; CHECK-LABEL: @positive_biggerLlshr_vec_nonsplat(
321 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr <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]]
325   %tmp0 = lshr <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
330 ; ============================================================================ ;
331 ; Negative tests. Should not be folded.
332 ; ============================================================================ ;
334 define i32 @negative_twovars(i32 %x, i32 %y, i32 %z) {
335 ; CHECK-LABEL: @negative_twovars(
336 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
337 ; CHECK-NEXT:    [[RET:%.*]] = shl i32 [[TMP0]], [[Z:%.*]]
338 ; CHECK-NEXT:    ret i32 [[RET]]
340   %tmp0 = lshr i32 %x, %y
341   %ret = shl i32 %tmp0, %z ; $z, not %y
342   ret i32 %ret
345 declare void @use32(i32)
347 ; One use only.
348 define i32 @negative_oneuse(i32 %x, i32 %y) {
349 ; CHECK-LABEL: @negative_oneuse(
350 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr 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]]
355   %tmp0 = lshr i32 %x, %y
356   call void @use32(i32 %tmp0)
357   %ret = shl i32 %tmp0, %y
358   ret i32 %ret