1 ; RUN: llc < %s -march=xcore | FileCheck %s 2 ; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP 3 4 ; When using SP for small frames, we don't need any scratch registers (SR). 5 ; When using SP for large frames, we may need two scratch registers. 6 ; When using FP, for large or small frames, we may need one scratch register. 7 8 ; FP + small frame: spill FP+SR = entsp 2 9 ; CHECKFP-LABEL: f1 10 ; CHECKFP: entsp 2 11 ; CHECKFP-NEXT: stw r10, sp[1] 12 ; CHECKFP-NEXT: ldaw r10, sp[0] 13 ; CHECKFP: set sp, r10 14 ; CHECKFP-NEXT: ldw r10, sp[1] 15 ; CHECKFP-NEXT: retsp 2 16 ; 17 ; !FP + small frame: no spills = no stack adjustment needed 18 ; CHECK-LABEL: f1 19 ; CHECK: stw lr, sp[0] 20 ; CHECK: ldw lr, sp[0] 21 ; CHECK-NEXT: retsp 0 22 define void @f1() nounwind { 23 entry: 24 tail call void asm sideeffect "", "~{lr}"() nounwind 25 ret void 26 } 27 28 29 ; FP + small frame: spill FP+SR+R0+LR = entsp 3 + extsp 1 30 ; CHECKFP-LABEL:f3 31 ; CHECKFP: entsp 3 32 ; CHECKFP-NEXT: stw r10, sp[1] 33 ; CHECKFP-NEXT: ldaw r10, sp[0] 34 ; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[2] 35 ; CHECKFP-NEXT: mov [[REG]], r0 36 ; CHECKFP-NEXT: extsp 1 37 ; CHECKFP-NEXT: bl f2 38 ; CHECKFP-NEXT: ldaw sp, sp[1] 39 ; CHECKFP-NEXT: mov r0, [[REG]] 40 ; CHECKFP-NEXT: ldw [[REG]], r10[2] 41 ; CHECKFP-NEXT: set sp, r10 42 ; CHECKFP-NEXT: ldw r10, sp[1] 43 ; CHECKFP-NEXT: retsp 3 44 ; 45 ; !FP + small frame: spill R0+LR = entsp 2 46 ; CHECK-LABEL: f3 47 ; CHECK: entsp 2 48 ; CHECK-NEXT: stw [[REG:r[4-9]+]], sp[1] 49 ; CHECK-NEXT: mov [[REG]], r0 50 ; CHECK-NEXT: bl f2 51 ; CHECK-NEXT: mov r0, [[REG]] 52 ; CHECK-NEXT: ldw [[REG]], sp[1] 53 ; CHECK-NEXT: retsp 2 54 declare void @f2() 55 define i32 @f3(i32 %i) nounwind { 56 entry: 57 call void @f2() 58 ret i32 %i 59 } 60 61 62 ; FP + large frame: spill FP+SR = entsp 2 + 100000 63 ; CHECKFP-LABEL: f4 64 ; CHECKFP: entsp 65535 65 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 66 ; CHECKFP-NEXT: .cfi_def_cfa_offset 262140 67 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 68 ; CHECKFP-NEXT: .cfi_offset 15, 0 69 ; CHECKFP-NEXT: extsp 34467 70 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 71 ; CHECKFP-NEXT: .cfi_def_cfa_offset 400008 72 ; CHECKFP-NEXT: stw r10, sp[1] 73 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 74 ; CHECKFP-NEXT: .cfi_offset 10, -400004 75 ; CHECKFP-NEXT: ldaw r10, sp[0] 76 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 77 ; CHECKFP-NEXT: .cfi_def_cfa_register 10 78 ; CHECKFP-NEXT: set sp, r10 79 ; CHECKFP-NEXT: ldw r10, sp[1] 80 ; CHECKFP-NEXT: ldaw sp, sp[65535] 81 ; CHECKFP-NEXT: retsp 34467 82 ; 83 ; !FP + large frame: spill SR+SR = entsp 2 + 100000 84 ; CHECK-LABEL: f4 85 ; CHECK: entsp 65535 86 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 87 ; CHECK-NEXT: .cfi_def_cfa_offset 262140 88 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 89 ; CHECK-NEXT: .cfi_offset 15, 0 90 ; CHECK-NEXT: extsp 34467 91 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 92 ; CHECK-NEXT: .cfi_def_cfa_offset 400008 93 ; CHECK-NEXT: ldaw sp, sp[65535] 94 ; CHECK-NEXT: retsp 34467 95 define void @f4() { 96 entry: 97 %0 = alloca [100000 x i32] 98 ret void 99 } 100 101 102 ; FP + large frame: spill FP+SR+R4+LR = entsp 3 + 200000 + extsp 1 103 ; CHECKFP: .section .cp.rodata.cst4,"aMc",@progbits,4 104 ; CHECKFP-NEXT: .p2align 2 105 ; CHECKFP-NEXT: .LCPI[[CNST0:[0-9_]+]]: 106 ; CHECKFP-NEXT: .long 200002 107 ; CHECKFP-NEXT: .LCPI[[CNST1:[0-9_]+]]: 108 ; CHECKFP-NEXT: .long 200001 109 ; CHECKFP-NEXT: .text 110 ; CHECKFP-LABEL: f6 111 ; CHECKFP: entsp 65535 112 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 113 ; CHECKFP-NEXT: .cfi_def_cfa_offset 262140 114 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 115 ; CHECKFP-NEXT: .cfi_offset 15, 0 116 ; CHECKFP-NEXT: extsp 65535 117 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 118 ; CHECKFP-NEXT: .cfi_def_cfa_offset 524280 119 ; CHECKFP-NEXT: extsp 65535 120 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 121 ; CHECKFP-NEXT: .cfi_def_cfa_offset 786420 122 ; CHECKFP-NEXT: extsp 3398 123 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 124 ; CHECKFP-NEXT: .cfi_def_cfa_offset 800012 125 ; CHECKFP-NEXT: stw r10, sp[1] 126 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 127 ; CHECKFP-NEXT: .cfi_offset 10, -800008 128 ; CHECKFP-NEXT: ldaw r10, sp[0] 129 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 130 ; CHECKFP-NEXT: .cfi_def_cfa_register 10 131 ; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 132 ; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[r1] 133 ; CHECKFP-NEXT: .Ltmp{{[0-9]+}} 134 ; CHECKFP-NEXT: .cfi_offset 4, -4 135 ; CHECKFP-NEXT: mov [[REG]], r0 136 ; CHECKFP-NEXT: extsp 1 137 ; CHECKFP-NEXT: ldaw r0, r10[2] 138 ; CHECKFP-NEXT: bl f5 139 ; CHECKFP-NEXT: ldaw sp, sp[1] 140 ; CHECKFP-NEXT: ldw r1, cp[.LCPI3_1] 141 ; CHECKFP-NEXT: ldaw r0, r10[r1] 142 ; CHECKFP-NEXT: extsp 1 143 ; CHECKFP-NEXT: bl f5 144 ; CHECKFP-NEXT: ldaw sp, sp[1] 145 ; CHECKFP-NEXT: mov r0, [[REG]] 146 ; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 147 ; CHECKFP-NEXT: ldw [[REG]], r10[r1] 148 ; CHECKFP-NEXT: set sp, r10 149 ; CHECKFP-NEXT: ldw r10, sp[1] 150 ; CHECKFP-NEXT: ldaw sp, sp[65535] 151 ; CHECKFP-NEXT: ldaw sp, sp[65535] 152 ; CHECKFP-NEXT: ldaw sp, sp[65535] 153 ; CHECKFP-NEXT: retsp 3398 154 ; 155 ; !FP + large frame: spill SR+SR+R4+LR = entsp 4 + 200000 156 ; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 157 ; CHECK-NEXT: .p2align 2 158 ; CHECK-NEXT: .LCPI[[CNST0:[0-9_]+]]: 159 ; CHECK-NEXT: .long 200003 160 ; CHECK-NEXT: .LCPI[[CNST1:[0-9_]+]]: 161 ; CHECK-NEXT: .long 200002 162 ; CHECK-NEXT: .text 163 ; CHECK-LABEL: f6 164 ; CHECK: entsp 65535 165 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 166 ; CHECK-NEXT: .cfi_def_cfa_offset 262140 167 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 168 ; CHECK-NEXT: .cfi_offset 15, 0 169 ; CHECK-NEXT: extsp 65535 170 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 171 ; CHECK-NEXT: .cfi_def_cfa_offset 524280 172 ; CHECK-NEXT: extsp 65535 173 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 174 ; CHECK-NEXT: .cfi_def_cfa_offset 786420 175 ; CHECK-NEXT: extsp 3399 176 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 177 ; CHECK-NEXT: .cfi_def_cfa_offset 800016 178 ; CHECK-NEXT: ldaw r1, sp[0] 179 ; CHECK-NEXT: ldw r2, cp[.LCPI[[CNST0]]] 180 ; CHECK-NEXT: stw [[REG:r[4-9]+]], r1[r2] 181 ; CHECK-NEXT: .Ltmp{{[0-9]+}} 182 ; CHECK-NEXT: .cfi_offset 4, -4 183 ; CHECK-NEXT: mov [[REG]], r0 184 ; CHECK-NEXT: ldaw r0, sp[3] 185 ; CHECK-NEXT: bl f5 186 ; CHECK-NEXT: ldaw r0, sp[0] 187 ; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST1]]] 188 ; CHECK-NEXT: ldaw r0, r0[r1] 189 ; CHECK-NEXT: bl f5 190 ; CHECK-NEXT: mov r0, [[REG]] 191 ; CHECK-NEXT: ldaw [[REG]], sp[0] 192 ; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 193 ; CHECK-NEXT: ldw [[REG]], [[REG]][r1] 194 ; CHECK-NEXT: ldaw sp, sp[65535] 195 ; CHECK-NEXT: ldaw sp, sp[65535] 196 ; CHECK-NEXT: ldaw sp, sp[65535] 197 ; CHECK-NEXT: retsp 3399 198 declare void @f5(i32*) 199 define i32 @f6(i32 %i) { 200 entry: 201 %0 = alloca [200000 x i32] 202 %1 = getelementptr inbounds [200000 x i32], [200000 x i32]* %0, i32 0, i32 0 203 call void @f5(i32* %1) 204 %2 = getelementptr inbounds [200000 x i32], [200000 x i32]* %0, i32 0, i32 199999 205 call void @f5(i32* %2) 206 ret i32 %i 207 } 208 209 ; FP + large frame: spill FP+SR+LR = entsp 2 + 256 + extsp 1 210 ; CHECKFP-LABEL:f8 211 ; CHECKFP: entsp 258 212 ; CHECKFP-NEXT: stw r10, sp[1] 213 ; CHECKFP-NEXT: ldaw r10, sp[0] 214 ; CHECKFP-NEXT: mkmsk [[REG:r[0-9]+]], 8 215 ; CHECKFP-NEXT: ldaw r0, r10{{\[}}[[REG]]{{\]}} 216 ; CHECKFP-NEXT: extsp 1 217 ; CHECKFP-NEXT: bl f5 218 ; CHECKFP-NEXT: ldaw sp, sp[1] 219 ; CHECKFP-NEXT: set sp, r10 220 ; CHECKFP-NEXT: ldw r10, sp[1] 221 ; CHECKFP-NEXT: retsp 258 222 ; 223 ; !FP + large frame: spill SR+SR+LR = entsp 3 + 256 224 ; CHECK-LABEL:f8 225 ; CHECK: entsp 257 226 ; CHECK-NEXT: ldaw r0, sp[254] 227 ; CHECK-NEXT: bl f5 228 ; CHECK-NEXT: retsp 257 229 define void @f8() nounwind { 230 entry: 231 %0 = alloca [256 x i32] 232 %1 = getelementptr inbounds [256 x i32], [256 x i32]* %0, i32 0, i32 253 233 call void @f5(i32* %1) 234 ret void 235 } 236 237 ; FP + large frame: spill FP+SR+LR = entsp 2 + 32768 + extsp 1 238 ; CHECKFP-LABEL:f9 239 ; CHECKFP: entsp 32770 240 ; CHECKFP-NEXT: stw r10, sp[1] 241 ; CHECKFP-NEXT: ldaw r10, sp[0] 242 ; CHECKFP-NEXT: ldc [[REG:r[0-9]+]], 32767 243 ; CHECKFP-NEXT: ldaw r0, r10{{\[}}[[REG]]{{\]}} 244 ; CHECKFP-NEXT: extsp 1 245 ; CHECKFP-NEXT: bl f5 246 ; CHECKFP-NEXT: ldaw sp, sp[1] 247 ; CHECKFP-NEXT: set sp, r10 248 ; CHECKFP-NEXT: ldw r10, sp[1] 249 ; CHECKFP-NEXT: retsp 32770 250 ; 251 ; !FP + large frame: spill SR+SR+LR = entsp 3 + 32768 252 ; CHECK-LABEL:f9 253 ; CHECK: entsp 32771 254 ; CHECK-NEXT: ldaw r0, sp[32768] 255 ; CHECK-NEXT: bl f5 256 ; CHECK-NEXT: retsp 32771 257 define void @f9() nounwind { 258 entry: 259 %0 = alloca [32768 x i32] 260 %1 = getelementptr inbounds [32768 x i32], [32768 x i32]* %0, i32 0, i32 32765 261 call void @f5(i32* %1) 262 ret void 263 } 264