1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=avr -mattr=movw -verify-machineinstrs | FileCheck %s
4 define i32 @shl_i32_1(i32 %a) {
5 ; CHECK-LABEL: shl_i32_1:
16 define i32 @shl_i32_2(i32 %a) {
17 ; CHECK-LABEL: shl_i32_2:
32 define i32 @shl_i32_4(i32 %a) {
33 ; CHECK-LABEL: shl_i32_4:
35 ; CHECK-NEXT: swap r25
36 ; CHECK-NEXT: andi r25, 240
37 ; CHECK-NEXT: swap r24
38 ; CHECK-NEXT: eor r25, r24
39 ; CHECK-NEXT: andi r24, 240
40 ; CHECK-NEXT: eor r25, r24
41 ; CHECK-NEXT: swap r23
42 ; CHECK-NEXT: eor r24, r23
43 ; CHECK-NEXT: andi r23, 240
44 ; CHECK-NEXT: eor r24, r23
45 ; CHECK-NEXT: swap r22
46 ; CHECK-NEXT: eor r23, r22
47 ; CHECK-NEXT: andi r22, 240
48 ; CHECK-NEXT: eor r23, r22
54 ; shift four bits and then shift one bit
55 define i32 @shl_i32_5(i32 %a) {
56 ; CHECK-LABEL: shl_i32_5:
58 ; CHECK-NEXT: swap r25
59 ; CHECK-NEXT: andi r25, 240
60 ; CHECK-NEXT: swap r24
61 ; CHECK-NEXT: eor r25, r24
62 ; CHECK-NEXT: andi r24, 240
63 ; CHECK-NEXT: eor r25, r24
64 ; CHECK-NEXT: swap r23
65 ; CHECK-NEXT: eor r24, r23
66 ; CHECK-NEXT: andi r23, 240
67 ; CHECK-NEXT: eor r24, r23
68 ; CHECK-NEXT: swap r22
69 ; CHECK-NEXT: eor r23, r22
70 ; CHECK-NEXT: andi r22, 240
71 ; CHECK-NEXT: eor r23, r22
81 ; shift two to the right and move the registers around
82 define i32 @shl_i32_6(i32 %a) {
83 ; CHECK-LABEL: shl_i32_6:
89 ; CHECK-NEXT: mov r18, r1
96 ; CHECK-NEXT: mov r25, r24
97 ; CHECK-NEXT: mov r24, r23
98 ; CHECK-NEXT: mov r19, r22
99 ; CHECK-NEXT: movw r22, r18
106 ; shift one to the right and move registers around
107 define i32 @shl_i32_7(i32 %a) {
108 ; CHECK-LABEL: shl_i32_7:
110 ; CHECK-NEXT: lsr r25
111 ; CHECK-NEXT: ror r24
112 ; CHECK-NEXT: ror r23
113 ; CHECK-NEXT: ror r22
114 ; CHECK-NEXT: mov r18, r1
115 ; CHECK-NEXT: ror r18
116 ; CHECK-NEXT: mov r25, r24
117 ; CHECK-NEXT: mov r24, r23
118 ; CHECK-NEXT: mov r19, r22
119 ; CHECK-NEXT: movw r22, r18
125 define i32 @shl_i32_8(i32 %a) {
126 ; CHECK-LABEL: shl_i32_8:
128 ; CHECK-NEXT: mov r25, r24
129 ; CHECK-NEXT: mov r24, r23
130 ; CHECK-NEXT: mov r23, r22
131 ; CHECK-NEXT: mov r22, r1
137 define i32 @shl_i32_9(i32 %a) {
138 ; CHECK-LABEL: shl_i32_9:
140 ; CHECK-NEXT: lsl r22
141 ; CHECK-NEXT: rol r23
142 ; CHECK-NEXT: rol r24
143 ; CHECK-NEXT: mov r25, r24
144 ; CHECK-NEXT: mov r24, r23
145 ; CHECK-NEXT: mov r23, r22
146 ; CHECK-NEXT: mov r22, r1
152 ; shift 3 of 4 registers and move the others around
153 define i32 @shl_i32_12(i32 %a) {
154 ; CHECK-LABEL: shl_i32_12:
156 ; CHECK-NEXT: swap r24
157 ; CHECK-NEXT: andi r24, 240
158 ; CHECK-NEXT: swap r23
159 ; CHECK-NEXT: eor r24, r23
160 ; CHECK-NEXT: andi r23, 240
161 ; CHECK-NEXT: eor r24, r23
162 ; CHECK-NEXT: swap r22
163 ; CHECK-NEXT: eor r23, r22
164 ; CHECK-NEXT: andi r22, 240
165 ; CHECK-NEXT: eor r23, r22
166 ; CHECK-NEXT: mov r25, r24
167 ; CHECK-NEXT: mov r24, r23
168 ; CHECK-NEXT: mov r23, r22
169 ; CHECK-NEXT: mov r22, r1
171 %res = shl i32 %a, 12
175 define i32 @shl_i32_15(i32 %a) {
176 ; CHECK-LABEL: shl_i32_15:
178 ; CHECK-NEXT: movw r18, r22
179 ; CHECK-NEXT: lsr r24
180 ; CHECK-NEXT: ror r19
181 ; CHECK-NEXT: ror r18
182 ; CHECK-NEXT: mov r23, r1
183 ; CHECK-NEXT: ror r23
184 ; CHECK-NEXT: mov r22, r1
185 ; CHECK-NEXT: movw r24, r18
187 %res = shl i32 %a, 15
191 ; This is a special case: this shift is performed directly inside SelectionDAG
192 ; instead of as a custom lowering like the other shift operations.
193 define i32 @shl_i32_16(i32 %a) {
194 ; CHECK-LABEL: shl_i32_16:
196 ; CHECK-NEXT: movw r24, r22
197 ; CHECK-NEXT: ldi r22, 0
198 ; CHECK-NEXT: ldi r23, 0
200 %res = shl i32 %a, 16
204 ; Combined with the register allocator, shift instructions can sometimes be
205 ; optimized away entirely. The least significant registers are simply stored
206 ; directly instead of moving them first.
207 define void @shl_i32_16_ptr(i32 %a, ptr %ptr) {
208 ; CHECK-LABEL: shl_i32_16_ptr:
210 ; CHECK-NEXT: movw r30, r20
211 ; CHECK-NEXT: std Z+3, r23
212 ; CHECK-NEXT: std Z+2, r22
213 ; CHECK-NEXT: ldi r24, 0
214 ; CHECK-NEXT: ldi r25, 0
215 ; CHECK-NEXT: std Z+1, r25
216 ; CHECK-NEXT: st Z, r24
218 %res = shl i32 %a, 16
219 store i32 %res, ptr %ptr
223 ; shift only the most significant byte and then move it
224 define i32 @shl_i32_28(i32 %a) {
225 ; CHECK-LABEL: shl_i32_28:
227 ; CHECK-NEXT: swap r22
228 ; CHECK-NEXT: andi r22, 240
229 ; CHECK-NEXT: mov r25, r22
230 ; CHECK-NEXT: mov r24, r1
231 ; CHECK-NEXT: mov r23, r1
232 ; CHECK-NEXT: mov r22, r1
234 %res = shl i32 %a, 28
238 ; move the rightmost bit to the leftmost bit and clear the rest
239 define i32 @shl_i32_31(i32 %a) {
240 ; CHECK-LABEL: shl_i32_31:
242 ; CHECK-NEXT: lsr r22
243 ; CHECK-NEXT: mov r25, r1
244 ; CHECK-NEXT: ror r25
245 ; CHECK-NEXT: mov r24, r1
246 ; CHECK-NEXT: mov r23, r1
247 ; CHECK-NEXT: mov r22, r1
249 %res = shl i32 %a, 31
253 define i32 @lshr_i32_1(i32 %a) {
254 ; CHECK-LABEL: lshr_i32_1:
256 ; CHECK-NEXT: lsr r25
257 ; CHECK-NEXT: ror r24
258 ; CHECK-NEXT: ror r23
259 ; CHECK-NEXT: ror r22
261 %res = lshr i32 %a, 1
265 define i32 @lshr_i32_2(i32 %a) {
266 ; CHECK-LABEL: lshr_i32_2:
268 ; CHECK-NEXT: lsr r25
269 ; CHECK-NEXT: ror r24
270 ; CHECK-NEXT: ror r23
271 ; CHECK-NEXT: ror r22
272 ; CHECK-NEXT: lsr r25
273 ; CHECK-NEXT: ror r24
274 ; CHECK-NEXT: ror r23
275 ; CHECK-NEXT: ror r22
277 %res = lshr i32 %a, 2
281 define i32 @lshr_i32_4(i32 %a) {
282 ; CHECK-LABEL: lshr_i32_4:
284 ; CHECK-NEXT: swap r22
285 ; CHECK-NEXT: andi r22, 15
286 ; CHECK-NEXT: swap r23
287 ; CHECK-NEXT: eor r22, r23
288 ; CHECK-NEXT: andi r23, 15
289 ; CHECK-NEXT: eor r22, r23
290 ; CHECK-NEXT: swap r24
291 ; CHECK-NEXT: eor r23, r24
292 ; CHECK-NEXT: andi r24, 15
293 ; CHECK-NEXT: eor r23, r24
294 ; CHECK-NEXT: swap r25
295 ; CHECK-NEXT: eor r24, r25
296 ; CHECK-NEXT: andi r25, 15
297 ; CHECK-NEXT: eor r24, r25
299 %res = lshr i32 %a, 4
303 define i32 @lshr_i32_6(i32 %a) {
304 ; CHECK-LABEL: lshr_i32_6:
306 ; CHECK-NEXT: lsl r22
307 ; CHECK-NEXT: rol r23
308 ; CHECK-NEXT: rol r24
309 ; CHECK-NEXT: rol r25
310 ; CHECK-NEXT: mov r19, r1
311 ; CHECK-NEXT: rol r19
312 ; CHECK-NEXT: lsl r22
313 ; CHECK-NEXT: rol r23
314 ; CHECK-NEXT: rol r24
315 ; CHECK-NEXT: rol r25
316 ; CHECK-NEXT: rol r19
317 ; CHECK-NEXT: mov r22, r23
318 ; CHECK-NEXT: mov r23, r24
319 ; CHECK-NEXT: mov r18, r25
320 ; CHECK-NEXT: movw r24, r18
322 %res = lshr i32 %a, 6
326 define i32 @lshr_i32_7(i32 %a) {
327 ; CHECK-LABEL: lshr_i32_7:
329 ; CHECK-NEXT: lsl r22
330 ; CHECK-NEXT: rol r23
331 ; CHECK-NEXT: rol r24
332 ; CHECK-NEXT: rol r25
333 ; CHECK-NEXT: mov r19, r1
334 ; CHECK-NEXT: rol r19
335 ; CHECK-NEXT: mov r22, r23
336 ; CHECK-NEXT: mov r23, r24
337 ; CHECK-NEXT: mov r18, r25
338 ; CHECK-NEXT: movw r24, r18
340 %res = lshr i32 %a, 7
344 define i32 @lshr_i32_8(i32 %a) {
345 ; CHECK-LABEL: lshr_i32_8:
347 ; CHECK-NEXT: mov r22, r23
348 ; CHECK-NEXT: mov r23, r24
349 ; CHECK-NEXT: mov r24, r25
350 ; CHECK-NEXT: mov r25, r1
352 %res = lshr i32 %a, 8
356 define i32 @lshr_i32_9(i32 %a) {
357 ; CHECK-LABEL: lshr_i32_9:
359 ; CHECK-NEXT: lsr r25
360 ; CHECK-NEXT: ror r24
361 ; CHECK-NEXT: ror r23
362 ; CHECK-NEXT: mov r22, r23
363 ; CHECK-NEXT: mov r23, r24
364 ; CHECK-NEXT: mov r24, r25
365 ; CHECK-NEXT: mov r25, r1
367 %res = lshr i32 %a, 9
371 define i32 @lshr_i32_16(i32 %a) {
372 ; CHECK-LABEL: lshr_i32_16:
374 ; CHECK-NEXT: movw r22, r24
375 ; CHECK-NEXT: ldi r24, 0
376 ; CHECK-NEXT: ldi r25, 0
378 %res = lshr i32 %a, 16
382 define i32 @lshr_i32_24(i32 %a) {
383 ; CHECK-LABEL: lshr_i32_24:
385 ; CHECK-NEXT: mov r22, r25
386 ; CHECK-NEXT: mov r23, r1
387 ; CHECK-NEXT: mov r24, r1
388 ; CHECK-NEXT: mov r25, r1
390 %res = lshr i32 %a, 24
394 define i32 @lshr_i32_31(i32 %a) {
395 ; CHECK-LABEL: lshr_i32_31:
397 ; CHECK-NEXT: lsl r25
398 ; CHECK-NEXT: mov r22, r1
399 ; CHECK-NEXT: rol r22
400 ; CHECK-NEXT: mov r23, r1
401 ; CHECK-NEXT: mov r24, r1
402 ; CHECK-NEXT: mov r25, r1
404 %res = lshr i32 %a, 31
408 define i32 @ashr_i32_1(i32 %a) {
409 ; CHECK-LABEL: ashr_i32_1:
411 ; CHECK-NEXT: asr r25
412 ; CHECK-NEXT: ror r24
413 ; CHECK-NEXT: ror r23
414 ; CHECK-NEXT: ror r22
416 %res = ashr i32 %a, 1
420 define i32 @ashr_i32_2(i32 %a) {
421 ; CHECK-LABEL: ashr_i32_2:
423 ; CHECK-NEXT: asr r25
424 ; CHECK-NEXT: ror r24
425 ; CHECK-NEXT: ror r23
426 ; CHECK-NEXT: ror r22
427 ; CHECK-NEXT: asr r25
428 ; CHECK-NEXT: ror r24
429 ; CHECK-NEXT: ror r23
430 ; CHECK-NEXT: ror r22
432 %res = ashr i32 %a, 2
436 ; can't use the swap/andi/eor trick here
437 define i32 @ashr_i32_4(i32 %a) {
438 ; CHECK-LABEL: ashr_i32_4:
440 ; CHECK-NEXT: asr r25
441 ; CHECK-NEXT: ror r24
442 ; CHECK-NEXT: ror r23
443 ; CHECK-NEXT: ror r22
444 ; CHECK-NEXT: asr r25
445 ; CHECK-NEXT: ror r24
446 ; CHECK-NEXT: ror r23
447 ; CHECK-NEXT: ror r22
448 ; CHECK-NEXT: asr r25
449 ; CHECK-NEXT: ror r24
450 ; CHECK-NEXT: ror r23
451 ; CHECK-NEXT: ror r22
452 ; CHECK-NEXT: asr r25
453 ; CHECK-NEXT: ror r24
454 ; CHECK-NEXT: ror r23
455 ; CHECK-NEXT: ror r22
457 %res = ashr i32 %a, 4
461 define i32 @ashr_i32_7(i32 %a) {
462 ; CHECK-LABEL: ashr_i32_7:
464 ; CHECK-NEXT: lsl r22
465 ; CHECK-NEXT: rol r23
466 ; CHECK-NEXT: rol r24
467 ; CHECK-NEXT: rol r25
468 ; CHECK-NEXT: sbc r19, r19
469 ; CHECK-NEXT: mov r22, r23
470 ; CHECK-NEXT: mov r23, r24
471 ; CHECK-NEXT: mov r18, r25
472 ; CHECK-NEXT: movw r24, r18
474 %res = ashr i32 %a, 7
478 ; TODO: this could be optimized to 4 movs, instead of 5.
479 define i32 @ashr_i32_8(i32 %a) {
480 ; CHECK-LABEL: ashr_i32_8:
482 ; CHECK-NEXT: mov r19, r25
483 ; CHECK-NEXT: lsl r19
484 ; CHECK-NEXT: sbc r19, r19
485 ; CHECK-NEXT: mov r22, r23
486 ; CHECK-NEXT: mov r23, r24
487 ; CHECK-NEXT: mov r18, r25
488 ; CHECK-NEXT: movw r24, r18
490 %res = ashr i32 %a, 8
494 define i32 @ashr_i32_16(i32 %a) {
495 ; CHECK-LABEL: ashr_i32_16:
497 ; CHECK-NEXT: movw r22, r24
498 ; CHECK-NEXT: lsl r25
499 ; CHECK-NEXT: sbc r25, r25
500 ; CHECK-NEXT: mov r24, r25
502 %res = ashr i32 %a, 16
506 define i32 @ashr_i32_17(i32 %a) {
507 ; CHECK-LABEL: ashr_i32_17:
509 ; CHECK-NEXT: movw r22, r24
510 ; CHECK-NEXT: lsl r25
511 ; CHECK-NEXT: sbc r25, r25
512 ; CHECK-NEXT: asr r23
513 ; CHECK-NEXT: ror r22
514 ; CHECK-NEXT: mov r24, r25
516 %res = ashr i32 %a, 17
520 define i32 @ashr_i32_22(i32 %a) {
521 ; CHECK-LABEL: ashr_i32_22:
523 ; CHECK-NEXT: lsl r24
524 ; CHECK-NEXT: rol r25
525 ; CHECK-NEXT: sbc r18, r18
526 ; CHECK-NEXT: lsl r24
527 ; CHECK-NEXT: rol r25
528 ; CHECK-NEXT: mov r19, r18
529 ; CHECK-NEXT: mov r23, r18
530 ; CHECK-NEXT: rol r23
531 ; CHECK-NEXT: mov r22, r25
532 ; CHECK-NEXT: movw r24, r18
534 %res = ashr i32 %a, 22
538 define i32 @ashr_i32_23(i32 %a) {
539 ; CHECK-LABEL: ashr_i32_23:
541 ; CHECK-NEXT: lsl r24
542 ; CHECK-NEXT: rol r25
543 ; CHECK-NEXT: sbc r23, r23
544 ; CHECK-NEXT: mov r22, r25
545 ; CHECK-NEXT: mov r24, r23
546 ; CHECK-NEXT: mov r25, r23
548 %res = ashr i32 %a, 23
552 define i32 @ashr_i32_30(i32 %a) {
553 ; CHECK-LABEL: ashr_i32_30:
555 ; CHECK-NEXT: lsl r25
556 ; CHECK-NEXT: sbc r23, r23
557 ; CHECK-NEXT: lsl r25
558 ; CHECK-NEXT: mov r22, r23
559 ; CHECK-NEXT: rol r22
560 ; CHECK-NEXT: mov r24, r23
561 ; CHECK-NEXT: mov r25, r23
563 %res = ashr i32 %a, 30
567 define i32 @ashr_i32_31(i32 %a) {
568 ; CHECK-LABEL: ashr_i32_31:
570 ; CHECK-NEXT: lsl r25
571 ; CHECK-NEXT: sbc r22, r22
572 ; CHECK-NEXT: mov r23, r22
573 ; CHECK-NEXT: movw r24, r22
575 %res = ashr i32 %a, 31