1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
; RUN: llc -mtriple=avr < %s | FileCheck %s
; CHECK-LABEL: ret_void_args_i8
define void @ret_void_args_i8(i8 %a) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i8_i32
define void @ret_void_args_i8_i32(i8 %a, i32 %b) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
; CHECK-NEXT: sts 8, r23
; CHECK-NEXT: sts 7, r22
; CHECK-NEXT: sts 6, r21
; CHECK-NEXT: sts 5, r20
store volatile i32 %b, i32* inttoptr (i64 5 to i32*)
ret void
}
; CHECK-LABEL: ret_void_args_i8_i8_i8_i8
define void @ret_void_args_i8_i8_i8_i8(i8 %a, i8 %b, i8 %c, i8 %d) {
; CHECK: sts 4, r24
store volatile i8 %a, i8* inttoptr (i64 4 to i8*)
; CHECK-NEXT: sts 5, r22
store volatile i8 %b, i8* inttoptr (i64 5 to i8*)
; CHECK-NEXT: sts 6, r20
store volatile i8 %c, i8* inttoptr (i64 6 to i8*)
; CHECK-NEXT: sts 7, r18
store volatile i8 %d, i8* inttoptr (i64 7 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i32_16_i8
define void @ret_void_args_i32_16_i8(i32 %a, i16 %b, i8 %c) {
; CHECK: sts 7, r25
; CHECK-NEXT: sts 6, r24
; CHECK-NEXT: sts 5, r23
; CHECK-NEXT: sts 4, r22
store volatile i32 %a, i32* inttoptr (i64 4 to i32*)
; CHECK-NEXT: sts 5, r21
; CHECK-NEXT: sts 4, r20
store volatile i16 %b, i16* inttoptr (i64 4 to i16*)
; CHECK-NEXT: sts 4, r18
store volatile i8 %c, i8* inttoptr (i64 4 to i8*)
ret void
}
; CHECK-LABEL: ret_void_args_i64
define void @ret_void_args_i64(i64 %a) {
; CHECK: sts 11, r25
; CHECK-NEXT: sts 10, r24
; CHECK-NEXT: sts 9, r23
; CHECK-NEXT: sts 8, r22
; CHECK-NEXT: sts 7, r21
; CHECK-NEXT: sts 6, r20
; CHECK-NEXT: sts 5, r19
; CHECK-NEXT: sts 4, r18
store volatile i64 %a, i64* inttoptr (i64 4 to i64*)
ret void
}
; CHECK-LABEL: ret_void_args_i64_i64
define void @ret_void_args_i64_i64(i64 %a, i64 %b) {
; CHECK-DAG: sts 11, r25
; CHECK-DAG: sts 10, r24
; CHECK-DAG: sts 9, r23
; CHECK-DAG: sts 8, r22
; CHECK-DAG: sts 7, r21
; CHECK-DAG: sts 6, r20
; CHECK-DAG: sts 5, r19
; CHECK-DAG: sts 4, r18
store volatile i64 %a, i64* inttoptr (i64 4 to i64*)
; CHECK-DAG: sts 11, r17
; CHECK-DAG: sts 10, r16
; CHECK-DAG: sts 9, r15
; CHECK-DAG: sts 8, r14
; CHECK-DAG: sts 7, r13
; CHECK-DAG: sts 6, r12
; CHECK-DAG: sts 5, r11
; CHECK-DAG: sts 4, r10
store volatile i64 %b, i64* inttoptr (i64 4 to i64*)
ret void
}
; This is exactly enough to hit the limit of what can be passed
; completely in registers.
; CHECK-LABEL: ret_void_args_i64_i64_i16
define void @ret_void_args_i64_i64_i16(i64 %a, i64 %b, i16 %c) {
; CHECK: sts 5, r9
; CHECK-NEXT: sts 4, r8
store volatile i16 %c, i16* inttoptr (i64 4 to i16*)
ret void
}
; 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: Both %a (i32) and %b (i32) cost four registers.
define i32 @foo2(i32 %a, i32 %b) {
; CHECK-LABEL: foo2:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub r22, r18
; CHECK-NEXT: sbc r23, r19
; CHECK-NEXT: sbc r24, r20
; CHECK-NEXT: sbc r25, r21
; CHECK-NEXT: ret
%c = sub i32 %a, %b
ret i32 %c
}
; NOTE: Each argument costs four registers, and total 16 registers are used.
define i32 @foo3(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-LABEL: foo3:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub r22, r10
; CHECK-NEXT: sbc r23, r11
; CHECK-NEXT: sbc r24, r12
; CHECK-NEXT: sbc r25, r13
; CHECK-NEXT: ret
%e = sub nsw i32 %a, %d
ret i32 %e
}
; NOTE: Each argument (except %e) cost four registers, and total 16 registers
; NOTE: are used. Though there are still 2 registers are vacant, the %e has
; NOTE: to be dropped to the stack.
define i32 @foo4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
; CHECK-LABEL: foo4:
; CHECK: ; %bb.0:
; CHECK-NEXT: push r28
; CHECK-NEXT: push r29
; CHECK-NEXT: in r28, 61
; CHECK-NEXT: in r29, 62
; CHECK-NEXT: ldd r18, Y+5
; CHECK-NEXT: ldd r19, Y+6
; CHECK-NEXT: ldd r20, Y+7
; CHECK-NEXT: ldd r21, Y+8
; CHECK-NEXT: sub r22, r18
; CHECK-NEXT: sbc r23, r19
; CHECK-NEXT: sbc r24, r20
; CHECK-NEXT: sbc r25, r21
; CHECK-NEXT: pop r29
; CHECK-NEXT: pop r28
; CHECK-NEXT: ret
%f = sub nsw i32 %a, %e
ret i32 %f
}
|