1; RUN: llc < %s -march=xcore | FileCheck %s 2; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP 3 4declare i8* @llvm.frameaddress(i32) nounwind readnone 5declare i8* @llvm.returnaddress(i32) nounwind 6declare i8* @llvm.eh.dwarf.cfa(i32) nounwind 7declare void @llvm.eh.return.i32(i32, i8*) nounwind 8declare void @llvm.eh.unwind.init() nounwind 9 10define i8* @FA0() nounwind { 11entry: 12; CHECK-LABEL: FA0 13; CHECK: ldaw r0, sp[0] 14; CHECK-NEXT: retsp 0 15 %0 = call i8* @llvm.frameaddress(i32 0) 16 ret i8* %0 17} 18 19define i8* @FA1() nounwind { 20entry: 21; CHECK-LABEL: FA1 22; CHECK: entsp 100 23; CHECK-NEXT: ldaw r0, sp[0] 24; CHECK-NEXT: retsp 100 25 %0 = alloca [100 x i32] 26 %1 = call i8* @llvm.frameaddress(i32 0) 27 ret i8* %1 28} 29 30define i8* @RA0() nounwind { 31entry: 32; CHECK-LABEL: RA0 33; CHECK: stw lr, sp[0] 34; CHECK-NEXT: ldw r0, sp[0] 35; CHECK-NEXT: ldw lr, sp[0] 36; CHECK-NEXT: retsp 0 37 %0 = call i8* @llvm.returnaddress(i32 0) 38 ret i8* %0 39} 40 41define i8* @RA1() nounwind { 42entry: 43; CHECK-LABEL: RA1 44; CHECK: entsp 100 45; CHECK-NEXT: ldw r0, sp[100] 46; CHECK-NEXT: retsp 100 47 %0 = alloca [100 x i32] 48 %1 = call i8* @llvm.returnaddress(i32 0) 49 ret i8* %1 50} 51 52; test FRAME_TO_ARGS_OFFSET lowering 53define i8* @FTAO0() nounwind { 54entry: 55; CHECK-LABEL: FTAO0 56; CHECK: ldc r0, 0 57; CHECK-NEXT: ldaw r1, sp[0] 58; CHECK-NEXT: add r0, r1, r0 59; CHECK-NEXT: retsp 0 60 %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) 61 ret i8* %0 62} 63 64define i8* @FTAO1() nounwind { 65entry: 66; CHECK-LABEL: FTAO1 67; CHECK: entsp 100 68; CHECK-NEXT: ldc r0, 400 69; CHECK-NEXT: ldaw r1, sp[0] 70; CHECK-NEXT: add r0, r1, r0 71; CHECK-NEXT: retsp 100 72 %0 = alloca [100 x i32] 73 %1 = call i8* @llvm.eh.dwarf.cfa(i32 0) 74 ret i8* %1 75} 76 77define i8* @EH0(i32 %offset, i8* %handler) { 78entry: 79; CHECK-LABEL: EH0 80; CHECK: entsp 2 81; CHECK: .cfi_def_cfa_offset 8 82; CHECK: .cfi_offset 15, 0 83; CHECK: .cfi_offset 1, -8 84; CHECK: .cfi_offset 0, -4 85; CHECK: ldc r2, 8 86; CHECK-NEXT: ldaw r3, sp[0] 87; CHECK-NEXT: add r2, r3, r2 88; CHECK-NEXT: add r2, r2, r0 89; CHECK-NEXT: mov r3, r1 90; CHECK-NEXT: ldw r1, sp[0] 91; CHECK-NEXT: ldw r0, sp[1] 92; CHECK-NEXT: set sp, r2 93; CHECK-NEXT: bau r3 94 call void @llvm.eh.return.i32(i32 %offset, i8* %handler) 95 unreachable 96} 97 98declare void @foo(...) 99define i8* @EH1(i32 %offset, i8* %handler) { 100entry: 101; CHECK-LABEL: EH1 102; CHECK: entsp 5 103; CHECK: .cfi_def_cfa_offset 20 104; CHECK: .cfi_offset 15, 0 105; CHECK: .cfi_offset 1, -16 106; CHECK: .cfi_offset 0, -12 107; CHECK: stw r4, sp[4] 108; CHECK: .cfi_offset 4, -4 109; CHECK: stw r5, sp[3] 110; CHECK: .cfi_offset 5, -8 111; CHECK: mov r4, r1 112; CHECK-NEXT: mov r5, r0 113; CHECK-NEXT: bl foo 114; CHECK-NEXT: ldc r0, 20 115; CHECK-NEXT: ldaw r1, sp[0] 116; CHECK-NEXT: add r0, r1, r0 117; CHECK-NEXT: add r2, r0, r5 118; CHECK-NEXT: mov r3, r4 119; CHECK-NEXT: ldw r5, sp[3] 120; CHECK-NEXT: ldw r4, sp[4] 121; CHECK-NEXT: ldw r1, sp[1] 122; CHECK-NEXT: ldw r0, sp[2] 123; CHECK-NEXT: set sp, r2 124; CHECK-NEXT: bau r3 125 call void (...) @foo() 126 call void @llvm.eh.return.i32(i32 %offset, i8* %handler) 127 unreachable 128} 129 130@offset = external constant i32 131@handler = external constant i8 132define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) { 133entry: 134; CHECK-LABEL: EH2 135; CHECK: entsp 3 136; CHECK: bl foo 137; CHECK-NEXT: ldw r0, dp[offset] 138; CHECK-NEXT: ldc r1, 12 139; CHECK-NEXT: ldaw r2, sp[0] 140; CHECK-NEXT: add r1, r2, r1 141; CHECK-NEXT: add r2, r1, r0 142; CHECK-NEXT: ldaw r3, dp[handler] 143; CHECK-NEXT: ldw r1, sp[1] 144; CHECK-NEXT: ldw r0, sp[2] 145; CHECK-NEXT: set sp, r2 146; CHECK-NEXT: bau r3 147 call void (...) @foo() 148 %0 = load i32, i32* @offset 149 call void @llvm.eh.return.i32(i32 %0, i8* @handler) 150 unreachable 151} 152 153 154; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 155; But we dont actually spill or restore R0:1 156; CHECKFP-LABEL: Unwind0: 157; CHECKFP: entsp 10 158; CHECKFP: stw r10, sp[1] 159; CHECKFP: ldaw r10, sp[0] 160; CHECKFP: stw r4, r10[9] 161; CHECKFP: stw r5, r10[8] 162; CHECKFP: stw r6, r10[7] 163; CHECKFP: stw r7, r10[6] 164; CHECKFP: stw r8, r10[5] 165; CHECKFP: stw r9, r10[4] 166; CHECKFP: ldw r9, r10[4] 167; CHECKFP: ldw r8, r10[5] 168; CHECKFP: ldw r7, r10[6] 169; CHECKFP: ldw r6, r10[7] 170; CHECKFP: ldw r5, r10[8] 171; CHECKFP: ldw r4, r10[9] 172; CHECKFP: set sp, r10 173; CHECKFP: ldw r10, sp[1] 174; CHECKFP: retsp 10 175; 176; !FP: spill R0:1+R4:10 = entsp 2+7 177; But we dont actually spill or restore R0:1 178; CHECK-LABEL: Unwind0: 179; CHECK: entsp 9 180; CHECK: stw r4, sp[8] 181; CHECK: stw r5, sp[7] 182; CHECK: stw r6, sp[6] 183; CHECK: stw r7, sp[5] 184; CHECK: stw r8, sp[4] 185; CHECK: stw r9, sp[3] 186; CHECK: stw r10, sp[2] 187; CHECK: ldw r10, sp[2] 188; CHECK: ldw r9, sp[3] 189; CHECK: ldw r8, sp[4] 190; CHECK: ldw r7, sp[5] 191; CHECK: ldw r6, sp[6] 192; CHECK: ldw r5, sp[7] 193; CHECK: ldw r4, sp[8] 194; CHECK: retsp 9 195define void @Unwind0() { 196 call void @llvm.eh.unwind.init() 197 ret void 198} 199 200 201; FP: spill FP+SR+R0:1+R4:9+LR = entsp 2+2+6 + extsp 1 202; But we dont actually spill or restore R0:1 203; CHECKFP-LABEL: Unwind1: 204; CHECKFP: entsp 10 205; CHECKFP: stw r10, sp[1] 206; CHECKFP: ldaw r10, sp[0] 207; CHECKFP: stw r4, r10[9] 208; CHECKFP: stw r5, r10[8] 209; CHECKFP: stw r6, r10[7] 210; CHECKFP: stw r7, r10[6] 211; CHECKFP: stw r8, r10[5] 212; CHECKFP: stw r9, r10[4] 213; CHECKFP: extsp 1 214; CHECKFP: bl foo 215; CHECKFP: ldaw sp, sp[1] 216; CHECKFP: ldw r9, r10[4] 217; CHECKFP: ldw r8, r10[5] 218; CHECKFP: ldw r7, r10[6] 219; CHECKFP: ldw r6, r10[7] 220; CHECKFP: ldw r5, r10[8] 221; CHECKFP: ldw r4, r10[9] 222; CHECKFP: set sp, r10 223; CHECKFP: ldw r10, sp[1] 224; CHECKFP: retsp 10 225; 226; !FP: spill R0:1+R4:10+LR = entsp 2+7+1 227; But we dont actually spill or restore R0:1 228; CHECK-LABEL: Unwind1: 229; CHECK: entsp 10 230; CHECK: stw r4, sp[9] 231; CHECK: stw r5, sp[8] 232; CHECK: stw r6, sp[7] 233; CHECK: stw r7, sp[6] 234; CHECK: stw r8, sp[5] 235; CHECK: stw r9, sp[4] 236; CHECK: stw r10, sp[3] 237; CHECK: bl foo 238; CHECK: ldw r10, sp[3] 239; CHECK: ldw r9, sp[4] 240; CHECK: ldw r8, sp[5] 241; CHECK: ldw r7, sp[6] 242; CHECK: ldw r6, sp[7] 243; CHECK: ldw r5, sp[8] 244; CHECK: ldw r4, sp[9] 245; CHECK: retsp 10 246define void @Unwind1() { 247 call void (...) @foo() 248 call void @llvm.eh.unwind.init() 249 ret void 250} 251 252; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 253; We dont spill R0:1 254; We only restore R0:1 during eh.return 255; CHECKFP-LABEL: UnwindEH: 256; CHECKFP: entsp 10 257; CHECKFP: .cfi_def_cfa_offset 40 258; CHECKFP: .cfi_offset 15, 0 259; CHECKFP: stw r10, sp[1] 260; CHECKFP: .cfi_offset 10, -36 261; CHECKFP: ldaw r10, sp[0] 262; CHECKFP: .cfi_def_cfa_register 10 263; CHECKFP: .cfi_offset 1, -32 264; CHECKFP: .cfi_offset 0, -28 265; CHECKFP: stw r4, r10[9] 266; CHECKFP: .cfi_offset 4, -4 267; CHECKFP: stw r5, r10[8] 268; CHECKFP: .cfi_offset 5, -8 269; CHECKFP: stw r6, r10[7] 270; CHECKFP: .cfi_offset 6, -12 271; CHECKFP: stw r7, r10[6] 272; CHECKFP: .cfi_offset 7, -16 273; CHECKFP: stw r8, r10[5] 274; CHECKFP: .cfi_offset 8, -20 275; CHECKFP: stw r9, r10[4] 276; CHECKFP: .cfi_offset 9, -24 277; CHECKFP: bt r0, .LBB{{[0-9_]+}} 278; CHECKFP: ldw r9, r10[4] 279; CHECKFP-NEXT: ldw r8, r10[5] 280; CHECKFP-NEXT: ldw r7, r10[6] 281; CHECKFP-NEXT: ldw r6, r10[7] 282; CHECKFP-NEXT: ldw r5, r10[8] 283; CHECKFP-NEXT: ldw r4, r10[9] 284; CHECKFP-NEXT: set sp, r10 285; CHECKFP-NEXT: ldw r10, sp[1] 286; CHECKFP-NEXT: retsp 10 287; CHECKFP: .LBB{{[0-9_]+}} 288; CHECKFP-NEXT: ldc r2, 40 289; CHECKFP-NEXT: add r2, r10, r2 290; CHECKFP-NEXT: add r2, r2, r0 291; CHECKFP-NEXT: mov r3, r1 292; CHECKFP-NEXT: ldw r9, r10[4] 293; CHECKFP-NEXT: ldw r8, r10[5] 294; CHECKFP-NEXT: ldw r7, r10[6] 295; CHECKFP-NEXT: ldw r6, r10[7] 296; CHECKFP-NEXT: ldw r5, r10[8] 297; CHECKFP-NEXT: ldw r4, r10[9] 298; CHECKFP-NEXT: ldw r1, sp[2] 299; CHECKFP-NEXT: ldw r0, sp[3] 300; CHECKFP-NEXT: set sp, r2 301; CHECKFP-NEXT: bau r3 302; 303; !FP: spill R0:1+R4:10 = entsp 2+7 304; We dont spill R0:1 305; We only restore R0:1 during eh.return 306; CHECK-LABEL: UnwindEH: 307; CHECK: entsp 9 308; CHECK: .cfi_def_cfa_offset 36 309; CHECK: .cfi_offset 15, 0 310; CHECK: .cfi_offset 1, -36 311; CHECK: .cfi_offset 0, -32 312; CHECK: stw r4, sp[8] 313; CHECK: .cfi_offset 4, -4 314; CHECK: stw r5, sp[7] 315; CHECK: .cfi_offset 5, -8 316; CHECK: stw r6, sp[6] 317; CHECK: .cfi_offset 6, -12 318; CHECK: stw r7, sp[5] 319; CHECK: .cfi_offset 7, -16 320; CHECK: stw r8, sp[4] 321; CHECK: .cfi_offset 8, -20 322; CHECK: stw r9, sp[3] 323; CHECK: .cfi_offset 9, -24 324; CHECK: stw r10, sp[2] 325; CHECK: .cfi_offset 10, -28 326; CHECK: bt r0, .LBB{{[0-9_]+}} 327; CHECK: ldw r10, sp[2] 328; CHECK-NEXT: ldw r9, sp[3] 329; CHECK-NEXT: ldw r8, sp[4] 330; CHECK-NEXT: ldw r7, sp[5] 331; CHECK-NEXT: ldw r6, sp[6] 332; CHECK-NEXT: ldw r5, sp[7] 333; CHECK-NEXT: ldw r4, sp[8] 334; CHECK-NEXT: retsp 9 335; CHECK: .LBB{{[0-9_]+}} 336; CHECK-NEXT: ldc r2, 36 337; CHECK-NEXT: ldaw r3, sp[0] 338; CHECK-NEXT: add r2, r3, r2 339; CHECK-NEXT: add r2, r2, r0 340; CHECK-NEXT: mov r3, r1 341; CHECK-NEXT: ldw r10, sp[2] 342; CHECK-NEXT: ldw r9, sp[3] 343; CHECK-NEXT: ldw r8, sp[4] 344; CHECK-NEXT: ldw r7, sp[5] 345; CHECK-NEXT: ldw r6, sp[6] 346; CHECK-NEXT: ldw r5, sp[7] 347; CHECK-NEXT: ldw r4, sp[8] 348; CHECK-NEXT: ldw r1, sp[0] 349; CHECK-NEXT: ldw r0, sp[1] 350; CHECK-NEXT: set sp, r2 351; CHECK-NEXT: bau r3 352define void @UnwindEH(i32 %offset, i8* %handler) { 353 call void @llvm.eh.unwind.init() 354 %cmp = icmp eq i32 %offset, 0 355 br i1 %cmp, label %normal, label %eh 356eh: 357 call void @llvm.eh.return.i32(i32 %offset, i8* %handler) 358 unreachable 359normal: 360 ret void 361} 362