1; RUN: llc -mtriple=avr < %s | FileCheck %s 2 3; CHECK-LABEL: ret_void_args_i64_i64_i32 4define void @ret_void_args_i64_i64_i32(i64 %a, i64 %b, i32 %c) { 5 ; We're goign to clobber PTRREG Y 6 ; CHECK: push r28 7 ; CHECK-NEXT: push r29 8 9 ; Load the stack pointer into Y. 10 ; CHECK-NEXT: in r28, 61 11 ; CHECK-NEXT: in r29, 62 12 13 ; Load the top two bytes from the 32-bit int. 14 ; CHECK-NEXT: ldd r24, Y+7 15 ; CHECK-NEXT: ldd r25, Y+8 16 ; Store the top two bytes of the 32-bit int to memory. 17 ; CHECK-NEXT: sts 7, r25 18 ; CHECK-NEXT: sts 6, r24 19 20 ; Load the bottom two bytes from the 32-bit int. 21 ; CHECK-NEXT: ldd r24, Y+5 22 ; CHECK-NEXT: ldd r25, Y+6 23 ; Store the bottom two bytes of the 32-bit int to memory. 24 ; CHECK-NEXT: sts 5, r25 25 ; CHECK-NEXT: sts 4, r24 26 27 ; Restore PTRREG Y 28 ; CHECK-NEXT: pop r29 29 ; CHECK-NEXT: pop r28 30 store volatile i32 %c, ptr inttoptr (i64 4 to ptr) 31 ret void 32} 33 34; NOTE: All arguments are passed via the stack for varargs functions. 35; NOTE: Both %a & %b occupy a 1-byte stack slot. 36define i8 @foo0(i8 %a, i8 %b, ...) { 37; CHECK-LABEL: foo0: 38; CHECK: ; %bb.0: 39; CHECK-NEXT: push r28 40; CHECK-NEXT: push r29 41; CHECK-NEXT: in r28, 61 42; CHECK-NEXT: in r29, 62 43; CHECK-NEXT: ldd r25, Y+6 44; CHECK-NEXT: ldd r24, Y+5 45; CHECK-NEXT: sub r24, r25 46; CHECK-NEXT: pop r29 47; CHECK-NEXT: pop r28 48; CHECK-NEXT: ret 49 %c = sub i8 %a, %b 50 ret i8 %c 51} 52 53; NOTE: All arguments are passed via the stack since the argument %a is too large. 54define i8 @foo1([19 x i8] %a, i8 %b) { 55; CHECK-LABEL: foo1: 56; CHECK: ; %bb.0: 57; CHECK-NEXT: push r28 58; CHECK-NEXT: push r29 59; CHECK-NEXT: in r28, 61 60; CHECK-NEXT: in r29, 62 61; CHECK-NEXT: ldd r25, Y+24 62; CHECK-NEXT: ldd r24, Y+5 63; CHECK-NEXT: sub r24, r25 64; CHECK-NEXT: pop r29 65; CHECK-NEXT: pop r28 66; CHECK-NEXT: ret 67 %c = extractvalue [19 x i8] %a, 0 68 %d = sub i8 %c, %b 69 ret i8 %d 70} 71 72; NOTE: The argument %b is passed via the stack, since the argument %a costs 73; NOTE: total 18 registers though it is a 17-byte array. 74define i8 @foo2([17 x i8] %a, i8 %b) { 75; CHECK-LABEL: foo2: 76; CHECK: ; %bb.0: 77; CHECK-NEXT: push r8 78; CHECK-NEXT: push r28 79; CHECK-NEXT: push r29 80; CHECK-NEXT: in r28, 61 81; CHECK-NEXT: in r29, 62 82; CHECK-NEXT: ldd r24, Y+6 83; CHECK-NEXT: sub r8, r24 84; CHECK-NEXT: mov r24, r8 85; CHECK-NEXT: pop r29 86; CHECK-NEXT: pop r28 87; CHECK-NEXT: pop r8 88; CHECK-NEXT: ret 89 %c = extractvalue [17 x i8] %a, 0 90 %d = sub i8 %c, %b 91 ret i8 %d 92} 93 94; NOTE: Though %a costs 16 registers and 2 registers are vacant, the 4-byte 95; NOTE: %b has to be dropped to the stack. 96; NOTE: total 18 registers. 97define i32 @foo3([4 x i32] %a, i32 %b) { 98; CHECK-LABEL: foo3: 99; CHECK: ; %bb.0: 100; CHECK-NEXT: push r28 101; CHECK-NEXT: push r29 102; CHECK-NEXT: in r28, 61 103; CHECK-NEXT: in r29, 62 104; CHECK-NEXT: ldd r22, Y+5 105; CHECK-NEXT: ldd r23, Y+6 106; CHECK-NEXT: ldd r24, Y+7 107; CHECK-NEXT: ldd r25, Y+8 108; CHECK-NEXT: sub r22, r10 109; CHECK-NEXT: sbc r23, r11 110; CHECK-NEXT: sbc r24, r12 111; CHECK-NEXT: sbc r25, r13 112; CHECK-NEXT: pop r29 113; CHECK-NEXT: pop r28 114; CHECK-NEXT: ret 115 %c = extractvalue [4 x i32] %a, 0 116 %d = sub nsw i32 %b, %c 117 ret i32 %d 118} 119 120; NOTE: Both %1 and %2 are passed via stack, and each has a 1-byte slot. 121define i8 @foo4([17 x i8] %0, i8 %1, i8 %2) { 122; CHECK-LABEL: foo4: 123; CHECK: ; %bb.0: 124; CHECK-NEXT: push r8 125; CHECK-NEXT: push r28 126; CHECK-NEXT: push r29 127; CHECK-NEXT: in r28, 61 128; CHECK-NEXT: in r29, 62 129; CHECK-NEXT: ldd r24, Y+6 130; CHECK-NEXT: sub r8, r24 131; CHECK-NEXT: ldd r24, Y+7 132; CHECK-NEXT: add r24, r8 133; CHECK-NEXT: pop r29 134; CHECK-NEXT: pop r28 135; CHECK-NEXT: pop r8 136; CHECK-NEXT: ret 137 %4 = extractvalue [17 x i8] %0, 0 138 %5 = sub i8 %4, %1 139 %6 = add i8 %5, %2 140 ret i8 %6 141} 142