1; RUN: llc < %s -mtriple=xcore | FileCheck %s 2; RUN: llc < %s -mtriple=xcore -frame-pointer=all | 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 22define void @f1() nounwind { 23entry: 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 54declare void @f2() 55define i32 @f3(i32 %i) nounwind { 56entry: 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: .cfi_def_cfa_offset 262140 66; CHECKFP-NEXT: .cfi_offset 15, 0 67; CHECKFP-NEXT: extsp 34467 68; CHECKFP-NEXT: .cfi_def_cfa_offset 400008 69; CHECKFP-NEXT: stw r10, sp[1] 70; CHECKFP-NEXT: .cfi_offset 10, -400004 71; CHECKFP-NEXT: ldaw r10, sp[0] 72; CHECKFP-NEXT: .cfi_def_cfa_register 10 73; CHECKFP-NEXT: set sp, r10 74; CHECKFP-NEXT: ldw r10, sp[1] 75; CHECKFP-NEXT: ldaw sp, sp[65535] 76; CHECKFP-NEXT: retsp 34467 77; 78; !FP + large frame: spill SR+SR = entsp 2 + 100000 79; CHECK-LABEL: f4: 80; CHECK: entsp 65535 81; CHECK-NEXT: .cfi_def_cfa_offset 262140 82; CHECK-NEXT: .cfi_offset 15, 0 83; CHECK-NEXT: extsp 34467 84; CHECK-NEXT: .cfi_def_cfa_offset 400008 85; CHECK-NEXT: ldaw sp, sp[65535] 86; CHECK-NEXT: retsp 34467 87define void @f4() { 88entry: 89 %0 = alloca [100000 x i32] 90 ret void 91} 92 93 94; FP + large frame: spill FP+SR+R4+LR = entsp 3 + 200000 + extsp 1 95; CHECKFP: .section .cp.rodata.cst4,"aMc",@progbits,4 96; CHECKFP-NEXT: .p2align 2 97; CHECKFP-NEXT: .LCPI[[CNST0:[0-9_]+]]: 98; CHECKFP-NEXT: .long 200002 99; CHECKFP-NEXT: .LCPI[[CNST1:[0-9_]+]]: 100; CHECKFP-NEXT: .long 200001 101; CHECKFP-NEXT: .text 102; CHECKFP-LABEL: f6: 103; CHECKFP: entsp 65535 104; CHECKFP-NEXT: .cfi_def_cfa_offset 262140 105; CHECKFP-NEXT: .cfi_offset 15, 0 106; CHECKFP-NEXT: extsp 65535 107; CHECKFP-NEXT: .cfi_def_cfa_offset 524280 108; CHECKFP-NEXT: extsp 65535 109; CHECKFP-NEXT: .cfi_def_cfa_offset 786420 110; CHECKFP-NEXT: extsp 3398 111; CHECKFP-NEXT: .cfi_def_cfa_offset 800012 112; CHECKFP-NEXT: stw r10, sp[1] 113; CHECKFP-NEXT: .cfi_offset 10, -800008 114; CHECKFP-NEXT: ldaw r10, sp[0] 115; CHECKFP-NEXT: .cfi_def_cfa_register 10 116; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 117; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[r1] 118; CHECKFP-NEXT: .cfi_offset 4, -4 119; CHECKFP-NEXT: mov [[REG]], r0 120; CHECKFP-NEXT: extsp 1 121; CHECKFP-NEXT: ldaw r0, r10[2] 122; CHECKFP-NEXT: bl f5 123; CHECKFP-NEXT: ldaw sp, sp[1] 124; CHECKFP-NEXT: ldw r1, cp[.LCPI3_1] 125; CHECKFP-NEXT: ldaw r0, r10[r1] 126; CHECKFP-NEXT: extsp 1 127; CHECKFP-NEXT: bl f5 128; CHECKFP-NEXT: ldaw sp, sp[1] 129; CHECKFP-NEXT: mov r0, [[REG]] 130; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 131; CHECKFP-NEXT: ldw [[REG]], r10[r1] 132; CHECKFP-NEXT: set sp, r10 133; CHECKFP-NEXT: ldw r10, sp[1] 134; CHECKFP-NEXT: ldaw sp, sp[65535] 135; CHECKFP-NEXT: ldaw sp, sp[65535] 136; CHECKFP-NEXT: ldaw sp, sp[65535] 137; CHECKFP-NEXT: retsp 3398 138; 139; !FP + large frame: spill SR+SR+R4+LR = entsp 4 + 200000 140; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 141; CHECK-NEXT: .p2align 2 142; CHECK-NEXT: .LCPI[[CNST0:[0-9_]+]]: 143; CHECK-NEXT: .long 200003 144; CHECK-NEXT: .LCPI[[CNST1:[0-9_]+]]: 145; CHECK-NEXT: .long 200002 146; CHECK-NEXT: .text 147; CHECK-LABEL: f6: 148; CHECK: entsp 65535 149; CHECK-NEXT: .cfi_def_cfa_offset 262140 150; CHECK-NEXT: .cfi_offset 15, 0 151; CHECK-NEXT: extsp 65535 152; CHECK-NEXT: .cfi_def_cfa_offset 524280 153; CHECK-NEXT: extsp 65535 154; CHECK-NEXT: .cfi_def_cfa_offset 786420 155; CHECK-NEXT: extsp 3399 156; CHECK-NEXT: .cfi_def_cfa_offset 800016 157; CHECK-NEXT: ldaw r1, sp[0] 158; CHECK-NEXT: ldw r2, cp[.LCPI[[CNST0]]] 159; CHECK-NEXT: stw [[REG:r[4-9]+]], r1[r2] 160; CHECK-NEXT: .cfi_offset 4, -4 161; CHECK-NEXT: mov [[REG]], r0 162; CHECK-NEXT: ldaw r0, sp[3] 163; CHECK-NEXT: bl f5 164; CHECK-NEXT: ldaw r0, sp[0] 165; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST1]]] 166; CHECK-NEXT: ldaw r0, r0[r1] 167; CHECK-NEXT: bl f5 168; CHECK-NEXT: mov r0, [[REG]] 169; CHECK-NEXT: ldaw [[REG]], sp[0] 170; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST0]]] 171; CHECK-NEXT: ldw [[REG]], [[REG]][r1] 172; CHECK-NEXT: ldaw sp, sp[65535] 173; CHECK-NEXT: ldaw sp, sp[65535] 174; CHECK-NEXT: ldaw sp, sp[65535] 175; CHECK-NEXT: retsp 3399 176declare void @f5(ptr) 177define i32 @f6(i32 %i) { 178entry: 179 %0 = alloca [200000 x i32] 180 call void @f5(ptr %0) 181 %1 = getelementptr inbounds [200000 x i32], ptr %0, i32 0, i32 199999 182 call void @f5(ptr %1) 183 ret i32 %i 184} 185 186; FP + large frame: spill FP+SR+LR = entsp 2 + 256 + extsp 1 187; CHECKFP-LABEL: f8: 188; CHECKFP: entsp 258 189; CHECKFP-NEXT: stw r10, sp[1] 190; CHECKFP-NEXT: ldaw r10, sp[0] 191; CHECKFP-NEXT: mkmsk [[REG:r[0-9]+]], 8 192; CHECKFP-NEXT: ldaw r0, r10[[[REG]]] 193; CHECKFP-NEXT: extsp 1 194; CHECKFP-NEXT: bl f5 195; CHECKFP-NEXT: ldaw sp, sp[1] 196; CHECKFP-NEXT: set sp, r10 197; CHECKFP-NEXT: ldw r10, sp[1] 198; CHECKFP-NEXT: retsp 258 199; 200; !FP + large frame: spill SR+SR+LR = entsp 3 + 256 201; CHECK-LABEL: f8: 202; CHECK: entsp 257 203; CHECK-NEXT: ldaw r0, sp[254] 204; CHECK-NEXT: bl f5 205; CHECK-NEXT: retsp 257 206define void @f8() nounwind { 207entry: 208 %0 = alloca [256 x i32] 209 %1 = getelementptr inbounds [256 x i32], ptr %0, i32 0, i32 253 210 call void @f5(ptr %1) 211 ret void 212} 213 214; FP + large frame: spill FP+SR+LR = entsp 2 + 32768 + extsp 1 215; CHECKFP-LABEL: f9: 216; CHECKFP: entsp 32770 217; CHECKFP-NEXT: stw r10, sp[1] 218; CHECKFP-NEXT: ldaw r10, sp[0] 219; CHECKFP-NEXT: ldc [[REG:r[0-9]+]], 32767 220; CHECKFP-NEXT: ldaw r0, r10[[[REG]]] 221; CHECKFP-NEXT: extsp 1 222; CHECKFP-NEXT: bl f5 223; CHECKFP-NEXT: ldaw sp, sp[1] 224; CHECKFP-NEXT: set sp, r10 225; CHECKFP-NEXT: ldw r10, sp[1] 226; CHECKFP-NEXT: retsp 32770 227; 228; !FP + large frame: spill SR+SR+LR = entsp 3 + 32768 229; CHECK-LABEL: f9: 230; CHECK: entsp 32771 231; CHECK-NEXT: ldaw r0, sp[32768] 232; CHECK-NEXT: bl f5 233; CHECK-NEXT: retsp 32771 234define void @f9() nounwind { 235entry: 236 %0 = alloca [32768 x i32] 237 %1 = getelementptr inbounds [32768 x i32], ptr %0, i32 0, i32 32765 238 call void @f5(ptr %1) 239 ret void 240} 241