| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc < %s -mtriple=avr -mcpu=avrtiny | FileCheck %s | |
| ; NOTE: Both %a(i8) and %b(i8) cost two registers. | |
| define i8 @foo0(i8 %a, i8 %b) { | |
| ; CHECK-LABEL: foo0: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: sub r24, r22 | |
| ; CHECK-NEXT: ret | |
| %c = sub i8 %a, %b | |
| ret i8 %c | |
| } | |
| ; NOTE: Both %a(i16) and %b(i16) cost two registers. | |
| define i16 @foo1(i16 %a, i16 %b) { | |
| ; CHECK-LABEL: foo1: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: sub r24, r22 | |
| ; CHECK-NEXT: sbc r25, r23 | |
| ; CHECK-NEXT: ret | |
| %c = sub i16 %a, %b | |
| ret i16 %c | |
| } | |
| ; NOTE: %a(i16), %b(i16) and %c(i16) each costs two registers. | |
| define i16 @foo2(i16 %a, i16 %b, i16 %c) { | |
| ; CHECK-LABEL: foo2: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: sub r22, r24 | |
| ; CHECK-NEXT: sbc r23, r25 | |
| ; CHECK-NEXT: add r22, r20 | |
| ; CHECK-NEXT: adc r23, r21 | |
| ; CHECK-NEXT: mov r24, r22 | |
| ; CHECK-NEXT: mov r25, r23 | |
| ; CHECK-NEXT: ret | |
| %d = sub i16 %a, %b | |
| %e = sub i16 %c, %d | |
| ret i16 %e | |
| } | |
| ; NOTE: %a(i16), %b(i16) and %c(i16) each costs two registers, | |
| ; while %d(i16) is passed via the stack. | |
| define i16 @foo3(i16 %a, i16 %b, i16 %c, i16 %d) { | |
| ; CHECK-LABEL: foo3: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: in r16, 63 | |
| ; CHECK-NEXT: subi r28, 251 | |
| ; CHECK-NEXT: sbci r29, 255 | |
| ; CHECK-NEXT: ld r30, Y+ | |
| ; CHECK-NEXT: ld r31, Y+ | |
| ; CHECK-NEXT: subi r28, 2 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: subi r28, 5 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: out 63, r16 | |
| ; CHECK-NEXT: sub r20, r30 | |
| ; CHECK-NEXT: sbc r21, r31 | |
| ; CHECK-NEXT: sub r24, r22 | |
| ; CHECK-NEXT: sbc r25, r23 | |
| ; CHECK-NEXT: add r24, r20 | |
| ; CHECK-NEXT: adc r25, r21 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %e = sub i16 %a, %b | |
| %g = sub i16 %c, %d | |
| %h = add i16 %e, %g | |
| ret i16 %h | |
| } | |
| ; NOTE: %a(i32) costs four registers, while %b(i32) is passed via the stack. | |
| define i32 @foo4(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: foo4: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: in r16, 63 | |
| ; CHECK-NEXT: subi r28, 251 | |
| ; CHECK-NEXT: sbci r29, 255 | |
| ; CHECK-NEXT: ld r20, Y+ | |
| ; CHECK-NEXT: ld r21, Y+ | |
| ; CHECK-NEXT: subi r28, 2 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: subi r28, 5 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: out 63, r16 | |
| ; CHECK-NEXT: in r16, 63 | |
| ; CHECK-NEXT: subi r28, 249 | |
| ; CHECK-NEXT: sbci r29, 255 | |
| ; CHECK-NEXT: ld r30, Y+ | |
| ; CHECK-NEXT: ld r31, Y+ | |
| ; CHECK-NEXT: subi r28, 2 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: subi r28, 7 | |
| ; CHECK-NEXT: sbci r29, 0 | |
| ; CHECK-NEXT: out 63, r16 | |
| ; CHECK-NEXT: sub r20, r22 | |
| ; CHECK-NEXT: sbc r21, r23 | |
| ; CHECK-NEXT: sbc r30, r24 | |
| ; CHECK-NEXT: sbc r31, r25 | |
| ; CHECK-NEXT: mov r22, r20 | |
| ; CHECK-NEXT: mov r23, r21 | |
| ; CHECK-NEXT: mov r24, r30 | |
| ; CHECK-NEXT: mov r25, r31 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %c = sub i32 %b, %a | |
| ret i32 %c | |
| } | |
| ; NOTE: %0 costs six registers, while %1 is passed via the stack. | |
| define i8 @foo5([5 x i8] %0, i8 %1) { | |
| ; CHECK-LABEL: foo5: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 251 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r24, X | |
| ; CHECK-NEXT: add r24, r20 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %3 = extractvalue [5 x i8] %0, 0 | |
| %4 = add i8 %3, %1 | |
| ret i8 %4 | |
| } | |
| ; NOTE: %0 costs two registers and %1 costs four registers. | |
| define i8 @foo6([2 x i8] %0, [4 x i8] %1) { | |
| ; CHECK-LABEL: foo6: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: add r24, r20 | |
| ; CHECK-NEXT: ret | |
| %3 = extractvalue [2 x i8] %0, 0 | |
| %4 = extractvalue [4 x i8] %1, 0 | |
| %5 = add i8 %3, %4 | |
| ret i8 %5 | |
| } | |
| ; NOTE: %0 cost four registers, while %1 is passed via the stack, | |
| ; though there are two vacant registers. | |
| define i8 @foo7([3 x i8] %0, [3 x i8] %1) { | |
| ; CHECK-LABEL: foo7: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 251 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r24, X | |
| ; CHECK-NEXT: add r24, r22 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %3 = extractvalue [3 x i8] %0, 0 | |
| %4 = extractvalue [3 x i8] %1, 0 | |
| %5 = add i8 %3, %4 | |
| ret i8 %5 | |
| } | |
| ; NOTE: %0 costs four registers, and %1 costs two registers, while %2 is | |
| ; passed via the stack, though there is one vacant register. | |
| define i8 @foo8([3 x i8] %0, i8 %1, i8 %2) { | |
| ; CHECK-LABEL: foo8: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: add r22, r20 | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 251 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r24, X | |
| ; CHECK-NEXT: sub r24, r22 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %4 = extractvalue [3 x i8] %0, 0 | |
| %5 = add i8 %4, %1 | |
| %6 = sub i8 %2, %5 | |
| ret i8 %6 | |
| } | |
| ; NOTE: %0 is passed via registers, though there are 6 vacant registers. | |
| define i8 @foo9([7 x i8] %0) { | |
| ; CHECK-LABEL: foo9: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 250 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r25, X | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 251 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r24, X | |
| ; CHECK-NEXT: add r24, r25 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %2 = extractvalue [7 x i8] %0, 0 | |
| %3 = extractvalue [7 x i8] %0, 1 | |
| %4 = add i8 %2, %3 | |
| ret i8 %4 | |
| } | |
| ; NOTE: %0 costs six registers, while %1 and %2 are passed via the stack. | |
| define i8 @fooa([6 x i8] %0, i8 %1, i8 %2) { | |
| ; CHECK-LABEL: fooa: | |
| ; CHECK: ; %bb.0: | |
| ; CHECK-NEXT: push r28 | |
| ; CHECK-NEXT: push r29 | |
| ; CHECK-NEXT: in r28, 61 | |
| ; CHECK-NEXT: clr r29 | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 251 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r25, X | |
| ; CHECK-NEXT: mov r26, r28 | |
| ; CHECK-NEXT: mov r27, r29 | |
| ; CHECK-NEXT: subi r26, 250 | |
| ; CHECK-NEXT: sbci r27, 255 | |
| ; CHECK-NEXT: ld r24, X | |
| ; CHECK-NEXT: sub r24, r25 | |
| ; CHECK-NEXT: sub r24, r20 | |
| ; CHECK-NEXT: pop r29 | |
| ; CHECK-NEXT: pop r28 | |
| ; CHECK-NEXT: ret | |
| %4 = extractvalue [6 x i8] %0, 0 | |
| %5 = sub i8 %2, %1 | |
| %6 = sub i8 %5, %4 | |
| ret i8 %6 | |
| } |