220 lines · plain
1; Test saving and restoring of call-saved GPRs.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5; This function should require all GPRs, but no other spill slots. The caller6; allocates room for the GPR save slots, so we shouldn't need to allocate any7; extra space.8;9; The function only modifies the low 32 bits of each register, which in10; itself would allow STM and LM to be used instead of STMG and LMG.11; However, the ABI defines the offset of each register, so we always12; use the 64-bit form.13;14; Use a different address for the final store, so that we can check that15; %r15 isn't referenced again until after that.16define void @f1(ptr %ptr) {17; CHECK-LABEL: f1:18; CHECK: stmg %r6, %r15, 48(%r15)19; CHECK-NOT: %r1520; CHECK: .cfi_offset %r6, -11221; CHECK: .cfi_offset %r7, -10422; CHECK: .cfi_offset %r8, -9623; CHECK: .cfi_offset %r9, -8824; CHECK: .cfi_offset %r10, -8025; CHECK: .cfi_offset %r11, -7226; CHECK: .cfi_offset %r12, -6427; CHECK: .cfi_offset %r13, -5628; CHECK: .cfi_offset %r14, -4829; CHECK: .cfi_offset %r15, -4030; ...main function body...31; CHECK-NOT: %r1532; CHECK: st {{.*}}, 4(%r2)33; CHECK: lmg %r6, %r15, 48(%r15)34; CHECK: br %r1435 %l0 = load volatile i32, ptr %ptr36 %l1 = load volatile i32, ptr %ptr37 %l3 = load volatile i32, ptr %ptr38 %l4 = load volatile i32, ptr %ptr39 %l5 = load volatile i32, ptr %ptr40 %l6 = load volatile i32, ptr %ptr41 %l7 = load volatile i32, ptr %ptr42 %l8 = load volatile i32, ptr %ptr43 %l9 = load volatile i32, ptr %ptr44 %l10 = load volatile i32, ptr %ptr45 %l11 = load volatile i32, ptr %ptr46 %l12 = load volatile i32, ptr %ptr47 %l13 = load volatile i32, ptr %ptr48 %l14 = load volatile i32, ptr %ptr49 %add0 = add i32 %l0, %l050 %add1 = add i32 %l1, %add051 %add3 = add i32 %l3, %add152 %add4 = add i32 %l4, %add353 %add5 = add i32 %l5, %add454 %add6 = add i32 %l6, %add555 %add7 = add i32 %l7, %add656 %add8 = add i32 %l8, %add757 %add9 = add i32 %l9, %add858 %add10 = add i32 %l10, %add959 %add11 = add i32 %l11, %add1060 %add12 = add i32 %l12, %add1161 %add13 = add i32 %l13, %add1262 %add14 = add i32 %l14, %add1363 store volatile i32 %add0, ptr %ptr64 store volatile i32 %add1, ptr %ptr65 store volatile i32 %add3, ptr %ptr66 store volatile i32 %add4, ptr %ptr67 store volatile i32 %add5, ptr %ptr68 store volatile i32 %add6, ptr %ptr69 store volatile i32 %add7, ptr %ptr70 store volatile i32 %add8, ptr %ptr71 store volatile i32 %add9, ptr %ptr72 store volatile i32 %add10, ptr %ptr73 store volatile i32 %add11, ptr %ptr74 store volatile i32 %add12, ptr %ptr75 store volatile i32 %add13, ptr %ptr76 %final = getelementptr i32, ptr %ptr, i32 177 store volatile i32 %add14, ptr %final78 ret void79}80 81; Like f1, but requires one fewer GPR. We allocate the call-saved GPRs82; from %r14 down, so that the STMG/LMG sequences aren't any longer than83; they need to be.84define void @f2(ptr %ptr) {85; CHECK-LABEL: f2:86; CHECK: stmg %r7, %r15, 56(%r15)87; CHECK-NOT: %r1588; CHECK: .cfi_offset %r7, -10489; CHECK: .cfi_offset %r8, -9690; CHECK: .cfi_offset %r9, -8891; CHECK: .cfi_offset %r10, -8092; CHECK: .cfi_offset %r11, -7293; CHECK: .cfi_offset %r12, -6494; CHECK: .cfi_offset %r13, -5695; CHECK: .cfi_offset %r14, -4896; CHECK: .cfi_offset %r15, -4097; ...main function body...98; CHECK-NOT: %r1599; CHECK-NOT: %r6100; CHECK: st {{.*}}, 4(%r2)101; CHECK: lmg %r7, %r15, 56(%r15)102; CHECK: br %r14103 %l0 = load volatile i32, ptr %ptr104 %l1 = load volatile i32, ptr %ptr105 %l3 = load volatile i32, ptr %ptr106 %l4 = load volatile i32, ptr %ptr107 %l5 = load volatile i32, ptr %ptr108 %l7 = load volatile i32, ptr %ptr109 %l8 = load volatile i32, ptr %ptr110 %l9 = load volatile i32, ptr %ptr111 %l10 = load volatile i32, ptr %ptr112 %l11 = load volatile i32, ptr %ptr113 %l12 = load volatile i32, ptr %ptr114 %l13 = load volatile i32, ptr %ptr115 %l14 = load volatile i32, ptr %ptr116 %add0 = add i32 %l0, %l0117 %add1 = add i32 %l1, %add0118 %add3 = add i32 %l3, %add1119 %add4 = add i32 %l4, %add3120 %add5 = add i32 %l5, %add4121 %add7 = add i32 %l7, %add5122 %add8 = add i32 %l8, %add7123 %add9 = add i32 %l9, %add8124 %add10 = add i32 %l10, %add9125 %add11 = add i32 %l11, %add10126 %add12 = add i32 %l12, %add11127 %add13 = add i32 %l13, %add12128 %add14 = add i32 %l14, %add13129 store volatile i32 %add0, ptr %ptr130 store volatile i32 %add1, ptr %ptr131 store volatile i32 %add3, ptr %ptr132 store volatile i32 %add4, ptr %ptr133 store volatile i32 %add5, ptr %ptr134 store volatile i32 %add7, ptr %ptr135 store volatile i32 %add8, ptr %ptr136 store volatile i32 %add9, ptr %ptr137 store volatile i32 %add10, ptr %ptr138 store volatile i32 %add11, ptr %ptr139 store volatile i32 %add12, ptr %ptr140 store volatile i32 %add13, ptr %ptr141 %final = getelementptr i32, ptr %ptr, i32 1142 store volatile i32 %add14, ptr %final143 ret void144}145 146; Like f1, but only needs one call-saved GPR, which ought to be %r14.147define void @f3(ptr %ptr) {148; CHECK-LABEL: f3:149; CHECK: stmg %r14, %r15, 112(%r15)150; CHECK-NOT: %r15151; CHECK: .cfi_offset %r14, -48152; CHECK: .cfi_offset %r15, -40153; ...main function body...154; CHECK-NOT: %r15155; CHECK-NOT: %r6156; CHECK-NOT: %r7157; CHECK-NOT: %r8158; CHECK-NOT: %r9159; CHECK-NOT: %r10160; CHECK-NOT: %r11161; CHECK-NOT: %r12162; CHECK-NOT: %r13163; CHECK: st {{.*}}, 4(%r2)164; CHECK: lmg %r14, %r15, 112(%r15)165; CHECK: br %r14166 %l0 = load volatile i32, ptr %ptr167 %l1 = load volatile i32, ptr %ptr168 %l3 = load volatile i32, ptr %ptr169 %l4 = load volatile i32, ptr %ptr170 %l5 = load volatile i32, ptr %ptr171 %l14 = load volatile i32, ptr %ptr172 %add0 = add i32 %l0, %l0173 %add1 = add i32 %l1, %add0174 %add3 = add i32 %l3, %add1175 %add4 = add i32 %l4, %add3176 %add5 = add i32 %l5, %add4177 %add14 = add i32 %l14, %add5178 store volatile i32 %add0, ptr %ptr179 store volatile i32 %add1, ptr %ptr180 store volatile i32 %add3, ptr %ptr181 store volatile i32 %add4, ptr %ptr182 store volatile i32 %add5, ptr %ptr183 %final = getelementptr i32, ptr %ptr, i32 1184 store volatile i32 %add14, ptr %final185 ret void186}187 188; This function should use all call-clobbered GPRs but no call-saved ones.189; It shouldn't need to touch the stack at all.190define void @f4(ptr %ptr) {191; CHECK-LABEL: f4:192; CHECK-NOT: %r15193; CHECK-NOT: %r6194; CHECK-NOT: %r7195; CHECK-NOT: %r8196; CHECK-NOT: %r9197; CHECK-NOT: %r10198; CHECK-NOT: %r11199; CHECK-NOT: %r12200; CHECK-NOT: %r13201; CHECK: br %r14202 %l0 = load volatile i32, ptr %ptr203 %l1 = load volatile i32, ptr %ptr204 %l3 = load volatile i32, ptr %ptr205 %l4 = load volatile i32, ptr %ptr206 %l5 = load volatile i32, ptr %ptr207 %add0 = add i32 %l0, %l0208 %add1 = add i32 %l1, %add0209 %add3 = add i32 %l3, %add1210 %add4 = add i32 %l4, %add3211 %add5 = add i32 %l5, %add4212 store volatile i32 %add0, ptr %ptr213 store volatile i32 %add1, ptr %ptr214 store volatile i32 %add3, ptr %ptr215 store volatile i32 %add4, ptr %ptr216 %final = getelementptr i32, ptr %ptr, i32 1217 store volatile i32 %add5, ptr %final218 ret void219}220