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
9 ; Should be transformed into:
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 = ashr i32 %x, %y
23 %ret = shl i32 %tmp0, %y
27 define i32 @positive_sameconst(i32 %x) {
28 ; CHECK-LABEL: @positive_sameconst(
29 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -32
30 ; CHECK-NEXT: ret i32 [[TMP1]]
32 %tmp0 = ashr i32 %x, 5
33 %ret = shl i32 %tmp0, 5
37 define 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]]
43 %tmp0 = ashr i32 %x, 10
44 %ret = shl i32 %tmp0, 5
48 define 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]]
54 %tmp0 = ashr i32 %x, 5
55 %ret = shl i32 %tmp0, 10
59 ; ============================================================================ ;
60 ; EXACT on the first shift
61 ; ============================================================================ ;
63 define i32 @positive_samevar_ashrexact(i32 %x, i32 %y) {
64 ; CHECK-LABEL: @positive_samevar_ashrexact(
65 ; CHECK-NEXT: ret i32 [[X:%.*]]
67 %tmp0 = ashr exact i32 %x, %y
68 %ret = shl i32 %tmp0, %y ; this one is obviously 'nuw'.
72 define i32 @positive_sameconst_ashrexact(i32 %x) {
73 ; CHECK-LABEL: @positive_sameconst_ashrexact(
74 ; CHECK-NEXT: ret i32 [[X:%.*]]
76 %tmp0 = ashr exact i32 %x, 5
77 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
81 define 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]]
86 %tmp0 = ashr exact i32 %x, 10
87 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'.
91 define 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]]
96 %tmp0 = ashr exact i32 %x, 5
97 %ret = shl i32 %tmp0, 10
101 define 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]]
106 %tmp0 = ashr exact i32 %x, 5
107 %ret = shl nuw i32 %tmp0, 10
111 ; ============================================================================ ;
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 = ashr <2 x i32> %x, %y
122 %ret = shl <2 x i32> %tmp0, %y
126 ; ============================================================================ ;
128 ; ============================================================================ ;
130 define <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]]
135 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
136 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
140 define <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]]
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>
151 define <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]]
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>
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 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5>
168 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5>
172 define <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]]
178 %tmp0 = ashr <2 x i32> %x, <i32 10, i32 10>
179 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
183 define <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]]
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>
194 define <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]]
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>
205 define <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]]
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>
216 define <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]]
222 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
223 %ret = shl <2 x i32> %tmp0, <i32 10, i32 10>
227 define <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]]
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>
238 define <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]]
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>
249 define <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]]
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>
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:%.*]] = ashr exact i32 [[X:%.*]], 5
269 ; CHECK-NEXT: call void @use32(i32 [[TMP0]])
270 ; CHECK-NEXT: ret i32 [[X]]
272 %tmp0 = ashr exact i32 %x, 5
273 call void @use32(i32 %tmp0)
274 %ret = shl i32 %tmp0, 5
278 define 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]]
285 %tmp0 = ashr exact i32 %x, 10
286 call void @use32(i32 %tmp0)
287 %ret = shl i32 %tmp0, 5
291 define 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]]
298 %tmp0 = ashr exact i32 %x, 5
299 call void @use32(i32 %tmp0)
300 %ret = shl i32 %tmp0, 10
304 ; ============================================================================ ;
305 ; Constant Non-Splat Vectors
306 ; ============================================================================ ;
308 define <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]]
314 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5>
315 %ret = shl <2 x i32> %tmp0, <i32 5, i32 10>
319 define <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]]
325 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 10>
326 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5>
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:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]]
337 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP0]], [[Z:%.*]]
338 ; CHECK-NEXT: ret i32 [[RET]]
340 %tmp0 = ashr i32 %x, %y
341 %ret = shl i32 %tmp0, %z ; $z, not %y
345 declare void @use32(i32)
348 define 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]]
355 %tmp0 = ashr i32 %x, %y
356 call void @use32(i32 %tmp0)
357 %ret = shl i32 %tmp0, %y