diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -1216,8 +1216,12 @@ unsigned NumArgs = Args.size(); unsigned TotalBytes = getTotalArgumentsSizeInBytes(Args); // CanLowerReturn() guarantees this assertion. - assert(TotalBytes <= 8 && - "return values greater than 8 bytes cannot be lowered"); + if (Tiny) + assert(TotalBytes <= 4 && + "return values greater than 4 bytes cannot be lowered on AVRTiny"); + else + assert(TotalBytes <= 8 && + "return values greater than 8 bytes cannot be lowered on AVR"); // Choose the proper register list for argument passing according to the ABI. ArrayRef RegList8; @@ -1578,7 +1582,7 @@ } unsigned TotalBytes = getTotalArgumentsSizeInBytes(Outs); - return TotalBytes <= 8; + return TotalBytes <= (Subtarget.hasTinyEncoding() ? 4 : 8); } SDValue diff --git a/llvm/test/CodeGen/AVR/return.ll b/llvm/test/CodeGen/AVR/return.ll --- a/llvm/test/CodeGen/AVR/return.ll +++ b/llvm/test/CodeGen/AVR/return.ll @@ -1,136 +1,348 @@ -; RUN: llc -mattr=avr6,sram < %s -march=avr | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mattr=avr6,sram -mtriple=avr < %s | FileCheck %s --check-prefix=AVR +; RUN: llc -mattr=tinyencoding -mtriple=avr < %s | FileCheck %s --check-prefix=TINY ;TODO: test returning byval structs ; TODO: test naked functions define void @return_void() { -; CHECK: return_void:{{[a-zA-Z0-9 #@]*}} -; CHECK-NEXT: {{.*}}: -; CHECK-NEXT: ret +; AVR-LABEL: return_void: +; AVR: ; %bb.0: +; AVR-NEXT: ret +; +; TINY-LABEL: return_void: +; TINY: ; %bb.0: +; TINY-NEXT: ret ret void } define i8 @return8_imm() { -; CHECK-LABEL: return8_imm: -; CHECK: ldi r24, 5 +; AVR-LABEL: return8_imm: +; AVR: ; %bb.0: +; AVR-NEXT: ldi r24, 5 +; AVR-NEXT: ret +; +; TINY-LABEL: return8_imm: +; TINY: ; %bb.0: +; TINY-NEXT: ldi r24, 5 +; TINY-NEXT: ret ret i8 5 } define i8 @return8_arg(i8 %x) { -; CHECK: return8_arg:{{[a-zA-Z0-9 #@]*}} -; CHECK-NEXT: {{.*}}: -; CHECK-NEXT: ret +; AVR-LABEL: return8_arg: +; AVR: ; %bb.0: +; AVR-NEXT: ret +; +; TINY-LABEL: return8_arg: +; TINY: ; %bb.0: +; TINY-NEXT: ret ret i8 %x } define i8 @return8_arg2(i8 %x, i8 %y, i8 %z) { -; CHECK-LABEL: return8_arg2: -; CHECK: mov r24, r20 +; AVR-LABEL: return8_arg2: +; AVR: ; %bb.0: +; AVR-NEXT: mov r24, r20 +; AVR-NEXT: ret +; +; TINY-LABEL: return8_arg2: +; TINY: ; %bb.0: +; TINY-NEXT: mov r24, r20 +; TINY-NEXT: ret ret i8 %z } define i16 @return16_imm() { -; CHECK-LABEL: return16_imm: -; CHECK: ldi r24, 57 -; CHECK: ldi r25, 48 +; AVR-LABEL: return16_imm: +; AVR: ; %bb.0: +; AVR-NEXT: ldi r24, 57 +; AVR-NEXT: ldi r25, 48 +; AVR-NEXT: ret +; +; TINY-LABEL: return16_imm: +; TINY: ; %bb.0: +; TINY-NEXT: ldi r24, 57 +; TINY-NEXT: ldi r25, 48 +; TINY-NEXT: ret ret i16 12345 } define i16 @return16_arg(i16 %x) { -; CHECK: return16_arg:{{[a-zA-Z0-9 #@]*}} -; CHECK-NEXT: {{.*}}: -; CHECK-NEXT: ret +; AVR-LABEL: return16_arg: +; AVR: ; %bb.0: +; AVR-NEXT: ret +; +; TINY-LABEL: return16_arg: +; TINY: ; %bb.0: +; TINY-NEXT: ret ret i16 %x } define i16 @return16_arg2(i16 %x, i16 %y, i16 %z) { -; CHECK-LABEL: return16_arg2: -; CHECK: movw r24, r20 +; AVR-LABEL: return16_arg2: +; AVR: ; %bb.0: +; AVR-NEXT: movw r24, r20 +; AVR-NEXT: ret +; +; TINY-LABEL: return16_arg2: +; TINY: ; %bb.0: +; TINY-NEXT: mov r24, r20 +; TINY-NEXT: mov r25, r21 +; TINY-NEXT: ret ret i16 %z } define i32 @return32_imm() { -; CHECK-LABEL: return32_imm: -; CHECK: ldi r22, 21 -; CHECK: ldi r23, 205 -; CHECK: ldi r24, 91 -; CHECK: ldi r25, 7 +; AVR-LABEL: return32_imm: +; AVR: ; %bb.0: +; AVR-NEXT: ldi r22, 21 +; AVR-NEXT: ldi r23, 205 +; AVR-NEXT: ldi r24, 91 +; AVR-NEXT: ldi r25, 7 +; AVR-NEXT: ret +; +; TINY-LABEL: return32_imm: +; TINY: ; %bb.0: +; TINY-NEXT: ldi r22, 21 +; TINY-NEXT: ldi r23, 205 +; TINY-NEXT: ldi r24, 91 +; TINY-NEXT: ldi r25, 7 +; TINY-NEXT: ret ret i32 123456789 } define i32 @return32_arg(i32 %x) { -; CHECK: return32_arg:{{[a-zA-Z0-9 #@]*}} -; CHECK-NEXT: {{.*}}: -; CHECK-NEXT: ret +; AVR-LABEL: return32_arg: +; AVR: ; %bb.0: +; AVR-NEXT: ret +; +; TINY-LABEL: return32_arg: +; TINY: ; %bb.0: +; TINY-NEXT: ret ret i32 %x } define i32 @return32_arg2(i32 %x, i32 %y, i32 %z) { -; CHECK-LABEL: return32_arg2: -; CHECK: movw r22, r14 -; CHECK: movw r24, r16 +; AVR-LABEL: return32_arg2: +; AVR: ; %bb.0: +; AVR-NEXT: movw r22, r14 +; AVR-NEXT: movw r24, r16 +; AVR-NEXT: ret +; +; TINY-LABEL: return32_arg2: +; TINY: ; %bb.0: +; TINY-NEXT: push r28 +; TINY-NEXT: push r29 +; TINY-NEXT: in r28, 61 +; TINY-NEXT: in r29, 62 +; TINY-NEXT: ldd r22, Y+9 +; TINY-NEXT: ldd r23, Y+10 +; TINY-NEXT: ldd r24, Y+11 +; TINY-NEXT: ldd r25, Y+12 +; TINY-NEXT: pop r29 +; TINY-NEXT: pop r28 +; TINY-NEXT: ret ret i32 %z } define i64 @return64_imm() { -; CHECK-LABEL: return64_imm: -; CHECK: ldi r18, 204 -; CHECK: ldi r19, 204 -; CHECK: ldi r20, 104 -; CHECK: ldi r21, 37 -; CHECK: ldi r22, 25 -; CHECK: ldi r23, 22 -; CHECK: ldi r24, 236 -; CHECK: ldi r25, 190 +; AVR-LABEL: return64_imm: +; AVR: ; %bb.0: +; AVR-NEXT: ldi r18, 204 +; AVR-NEXT: ldi r19, 204 +; AVR-NEXT: ldi r20, 104 +; AVR-NEXT: ldi r21, 37 +; AVR-NEXT: ldi r22, 25 +; AVR-NEXT: ldi r23, 22 +; AVR-NEXT: ldi r24, 236 +; AVR-NEXT: ldi r25, 190 +; AVR-NEXT: ret +; +; TINY-LABEL: return64_imm: +; TINY: ; %bb.0: +; TINY-NEXT: ldi r20, 236 +; TINY-NEXT: ldi r21, 190 +; TINY-NEXT: mov r30, r24 +; TINY-NEXT: mov r31, r25 +; TINY-NEXT: std Z+6, r20 +; TINY-NEXT: std Z+7, r21 +; TINY-NEXT: ldi r24, 25 +; TINY-NEXT: ldi r25, 22 +; TINY-NEXT: std Z+4, r24 +; TINY-NEXT: std Z+5, r25 +; TINY-NEXT: ldi r24, 104 +; TINY-NEXT: ldi r25, 37 +; TINY-NEXT: std Z+2, r24 +; TINY-NEXT: std Z+3, r25 +; TINY-NEXT: ldi r24, 204 +; TINY-NEXT: ldi r25, 204 +; TINY-NEXT: st Z, r24 +; TINY-NEXT: std Z+1, r25 +; TINY-NEXT: ret ret i64 13757395258967641292 } define i64 @return64_arg(i64 %x) { -; CHECK: return64_arg:{{[a-zA-Z0-9 #@]*}} -; CHECK-NEXT: {{.*}}: -; CHECK-NEXT: ret +; AVR-LABEL: return64_arg: +; AVR: ; %bb.0: +; AVR-NEXT: ret +; +; TINY-LABEL: return64_arg: +; TINY: ; %bb.0: +; TINY-NEXT: push r28 +; TINY-NEXT: push r29 +; TINY-NEXT: in r28, 61 +; TINY-NEXT: in r29, 62 +; TINY-NEXT: ldd r20, Y+11 +; TINY-NEXT: ldd r21, Y+12 +; TINY-NEXT: mov r30, r24 +; TINY-NEXT: mov r31, r25 +; TINY-NEXT: std Z+6, r20 +; TINY-NEXT: std Z+7, r21 +; TINY-NEXT: ldd r24, Y+9 +; TINY-NEXT: ldd r25, Y+10 +; TINY-NEXT: std Z+4, r24 +; TINY-NEXT: std Z+5, r25 +; TINY-NEXT: ldd r24, Y+7 +; TINY-NEXT: ldd r25, Y+8 +; TINY-NEXT: std Z+2, r24 +; TINY-NEXT: std Z+3, r25 +; TINY-NEXT: ldd r24, Y+5 +; TINY-NEXT: ldd r25, Y+6 +; TINY-NEXT: st Z, r24 +; TINY-NEXT: std Z+1, r25 +; TINY-NEXT: pop r29 +; TINY-NEXT: pop r28 +; TINY-NEXT: ret ret i64 %x } define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) { -; CHECK-LABEL: return64_arg2: -; CHECK: push r28 -; CHECK: push r29 -; CHECK: ldd r18, Y+5 -; CHECK: ldd r19, Y+6 -; CHECK: ldd r20, Y+7 -; CHECK: ldd r21, Y+8 -; CHECK: ldd r22, Y+9 -; CHECK: ldd r23, Y+10 -; CHECK: ldd r24, Y+11 -; CHECK: ldd r25, Y+12 -; CHECK: pop r29 -; CHECK: pop r28 +; AVR-LABEL: return64_arg2: +; AVR: ; %bb.0: +; AVR-NEXT: push r28 +; AVR-NEXT: push r29 +; AVR-NEXT: in r28, 61 +; AVR-NEXT: in r29, 62 +; AVR-NEXT: ldd r18, Y+5 +; AVR-NEXT: ldd r19, Y+6 +; AVR-NEXT: ldd r20, Y+7 +; AVR-NEXT: ldd r21, Y+8 +; AVR-NEXT: ldd r22, Y+9 +; AVR-NEXT: ldd r23, Y+10 +; AVR-NEXT: ldd r24, Y+11 +; AVR-NEXT: ldd r25, Y+12 +; AVR-NEXT: pop r29 +; AVR-NEXT: pop r28 +; AVR-NEXT: ret +; +; TINY-LABEL: return64_arg2: +; TINY: ; %bb.0: +; TINY-NEXT: push r28 +; TINY-NEXT: push r29 +; TINY-NEXT: in r28, 61 +; TINY-NEXT: in r29, 62 +; TINY-NEXT: ldd r20, Y+27 +; TINY-NEXT: ldd r21, Y+28 +; TINY-NEXT: mov r30, r24 +; TINY-NEXT: mov r31, r25 +; TINY-NEXT: std Z+6, r20 +; TINY-NEXT: std Z+7, r21 +; TINY-NEXT: ldd r24, Y+25 +; TINY-NEXT: ldd r25, Y+26 +; TINY-NEXT: std Z+4, r24 +; TINY-NEXT: std Z+5, r25 +; TINY-NEXT: ldd r24, Y+23 +; TINY-NEXT: ldd r25, Y+24 +; TINY-NEXT: std Z+2, r24 +; TINY-NEXT: std Z+3, r25 +; TINY-NEXT: ldd r24, Y+21 +; TINY-NEXT: ldd r25, Y+22 +; TINY-NEXT: st Z, r24 +; TINY-NEXT: std Z+1, r25 +; TINY-NEXT: pop r29 +; TINY-NEXT: pop r28 +; TINY-NEXT: ret ret i64 %z } define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) { -; CHECK-LABEL: return64_trunc: -; CHECK: push r28 -; CHECK: push r29 -; CHECK: ldd r22, Y+5 -; CHECK: ldd r23, Y+6 -; CHECK: ldd r24, Y+7 -; CHECK: ldd r25, Y+8 -; CHECK: pop r29 -; CHECK: pop r28 +; AVR-LABEL: return64_trunc: +; AVR: ; %bb.0: +; AVR-NEXT: push r28 +; AVR-NEXT: push r29 +; AVR-NEXT: in r28, 61 +; AVR-NEXT: in r29, 62 +; AVR-NEXT: ldd r22, Y+5 +; AVR-NEXT: ldd r23, Y+6 +; AVR-NEXT: ldd r24, Y+7 +; AVR-NEXT: ldd r25, Y+8 +; AVR-NEXT: pop r29 +; AVR-NEXT: pop r28 +; AVR-NEXT: ret +; +; TINY-LABEL: return64_trunc: +; TINY: ; %bb.0: +; TINY-NEXT: push r28 +; TINY-NEXT: push r29 +; TINY-NEXT: in r28, 61 +; TINY-NEXT: in r29, 62 +; TINY-NEXT: ldd r22, Y+13 +; TINY-NEXT: ldd r23, Y+14 +; TINY-NEXT: ldd r24, Y+15 +; TINY-NEXT: ldd r25, Y+16 +; TINY-NEXT: pop r29 +; TINY-NEXT: pop r28 +; TINY-NEXT: ret %result = trunc i64 %d to i32 ret i32 %result } define avr_intrcc void @interrupt_handler() { -; CHECK-LABEL: interrupt_handler: -; CHECK: reti +; AVR-LABEL: interrupt_handler: +; AVR: ; %bb.0: +; AVR-NEXT: sei +; AVR-NEXT: push r0 +; AVR-NEXT: in r0, 63 +; AVR-NEXT: push r0 +; AVR-NEXT: pop r0 +; AVR-NEXT: out 63, r0 +; AVR-NEXT: pop r0 +; AVR-NEXT: reti +; +; TINY-LABEL: interrupt_handler: +; TINY: ; %bb.0: +; TINY-NEXT: sei +; TINY-NEXT: push r0 +; TINY-NEXT: in r0, 63 +; TINY-NEXT: push r0 +; TINY-NEXT: pop r0 +; TINY-NEXT: out 63, r0 +; TINY-NEXT: pop r0 +; TINY-NEXT: reti ret void } define avr_signalcc void @signal_handler() { -; CHECK-LABEL: signal_handler: -; CHECK: reti +; AVR-LABEL: signal_handler: +; AVR: ; %bb.0: +; AVR-NEXT: push r0 +; AVR-NEXT: in r0, 63 +; AVR-NEXT: push r0 +; AVR-NEXT: pop r0 +; AVR-NEXT: out 63, r0 +; AVR-NEXT: pop r0 +; AVR-NEXT: reti +; +; TINY-LABEL: signal_handler: +; TINY: ; %bb.0: +; TINY-NEXT: push r0 +; TINY-NEXT: in r0, 63 +; TINY-NEXT: push r0 +; TINY-NEXT: pop r0 +; TINY-NEXT: out 63, r0 +; TINY-NEXT: pop r0 +; TINY-NEXT: reti ret void }