1; Test the saving and restoring of GPRs in large frames. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5; This is the largest frame size that can use a plain LMG for %r6 and above. 6; It is big enough to require two emergency spill slots at 160(%r15), 7; so get a frame of size 524232 by allocating (524232 - 176) / 8 = 65507 8; extra doublewords. 9define void @f1(ptr %ptr, i64 %x) { 10; CHECK-LABEL: f1: 11; CHECK: stmg %r6, %r15, 48(%r15) 12; CHECK: .cfi_offset %r6, -112 13; CHECK: .cfi_offset %r7, -104 14; CHECK: .cfi_offset %r8, -96 15; CHECK: .cfi_offset %r9, -88 16; CHECK: .cfi_offset %r10, -80 17; CHECK: .cfi_offset %r11, -72 18; CHECK: .cfi_offset %r12, -64 19; CHECK: .cfi_offset %r13, -56 20; CHECK: .cfi_offset %r14, -48 21; CHECK: .cfi_offset %r15, -40 22; CHECK: agfi %r15, -524232 23; CHECK: .cfi_def_cfa_offset 524392 24; ...main function body... 25; CHECK-NOT: ag 26; CHECK: lmg %r6, %r15, 524280(%r15) 27; CHECK: br %r14 28 %l0 = load volatile i32, ptr %ptr 29 %l1 = load volatile i32, ptr %ptr 30 %l4 = load volatile i32, ptr %ptr 31 %l5 = load volatile i32, ptr %ptr 32 %l6 = load volatile i32, ptr %ptr 33 %l7 = load volatile i32, ptr %ptr 34 %l8 = load volatile i32, ptr %ptr 35 %l9 = load volatile i32, ptr %ptr 36 %l10 = load volatile i32, ptr %ptr 37 %l11 = load volatile i32, ptr %ptr 38 %l12 = load volatile i32, ptr %ptr 39 %l13 = load volatile i32, ptr %ptr 40 %l14 = load volatile i32, ptr %ptr 41 %add0 = add i32 %l0, %l0 42 %add1 = add i32 %l1, %add0 43 %add4 = add i32 %l4, %add1 44 %add5 = add i32 %l5, %add4 45 %add6 = add i32 %l6, %add5 46 %add7 = add i32 %l7, %add6 47 %add8 = add i32 %l8, %add7 48 %add9 = add i32 %l9, %add8 49 %add10 = add i32 %l10, %add9 50 %add11 = add i32 %l11, %add10 51 %add12 = add i32 %l12, %add11 52 %add13 = add i32 %l13, %add12 53 %add14 = add i32 %l14, %add13 54 store volatile i32 %add0, ptr %ptr 55 store volatile i32 %add1, ptr %ptr 56 store volatile i32 %add4, ptr %ptr 57 store volatile i32 %add5, ptr %ptr 58 store volatile i32 %add6, ptr %ptr 59 store volatile i32 %add7, ptr %ptr 60 store volatile i32 %add8, ptr %ptr 61 store volatile i32 %add9, ptr %ptr 62 store volatile i32 %add10, ptr %ptr 63 store volatile i32 %add11, ptr %ptr 64 store volatile i32 %add12, ptr %ptr 65 store volatile i32 %add13, ptr %ptr 66 store volatile i32 %add14, ptr %ptr 67 %y = alloca [65507 x i64], align 8 68 store volatile i64 %x, ptr %y 69 ret void 70} 71 72; This is the largest frame size that can use a plain LMG for %r14 and above 73; It is big enough to require two emergency spill slots at 160(%r15), 74; so get a frame of size 524168 by allocating (524168 - 176) / 8 = 65499 75; extra doublewords. 76define void @f2(ptr %ptr, i64 %x) { 77; CHECK-LABEL: f2: 78; CHECK: stmg %r14, %r15, 112(%r15) 79; CHECK: .cfi_offset %r14, -48 80; CHECK: .cfi_offset %r15, -40 81; CHECK: agfi %r15, -524168 82; CHECK: .cfi_def_cfa_offset 524328 83; ...main function body... 84; CHECK-NOT: ag 85; CHECK: lmg %r14, %r15, 524280(%r15) 86; CHECK: br %r14 87 %l0 = load volatile i32, ptr %ptr 88 %l1 = load volatile i32, ptr %ptr 89 %l4 = load volatile i32, ptr %ptr 90 %l5 = load volatile i32, ptr %ptr 91 %l14 = load volatile i32, ptr %ptr 92 %add0 = add i32 %l0, %l0 93 %add1 = add i32 %l1, %add0 94 %add4 = add i32 %l4, %add1 95 %add5 = add i32 %l5, %add4 96 %add14 = add i32 %l14, %add5 97 store volatile i32 %add0, ptr %ptr 98 store volatile i32 %add1, ptr %ptr 99 store volatile i32 %add4, ptr %ptr 100 store volatile i32 %add5, ptr %ptr 101 store volatile i32 %add14, ptr %ptr 102 %y = alloca [65499 x i64], align 8 103 store volatile i64 %x, ptr %y 104 ret void 105} 106 107; Like f1 but with a frame that is 8 bytes bigger. This is the smallest 108; frame size that needs two instructions to perform the final LMG for 109; %r6 and above. 110define void @f3(ptr %ptr, i64 %x) { 111; CHECK-LABEL: f3: 112; CHECK: stmg %r6, %r15, 48(%r15) 113; CHECK: .cfi_offset %r6, -112 114; CHECK: .cfi_offset %r7, -104 115; CHECK: .cfi_offset %r8, -96 116; CHECK: .cfi_offset %r9, -88 117; CHECK: .cfi_offset %r10, -80 118; CHECK: .cfi_offset %r11, -72 119; CHECK: .cfi_offset %r12, -64 120; CHECK: .cfi_offset %r13, -56 121; CHECK: .cfi_offset %r14, -48 122; CHECK: .cfi_offset %r15, -40 123; CHECK: agfi %r15, -524240 124; CHECK: .cfi_def_cfa_offset 524400 125; ...main function body... 126; CHECK: aghi %r15, 8 127; CHECK: lmg %r6, %r15, 524280(%r15) 128; CHECK: br %r14 129 %l0 = load volatile i32, ptr %ptr 130 %l1 = load volatile i32, ptr %ptr 131 %l4 = load volatile i32, ptr %ptr 132 %l5 = load volatile i32, ptr %ptr 133 %l6 = load volatile i32, ptr %ptr 134 %l7 = load volatile i32, ptr %ptr 135 %l8 = load volatile i32, ptr %ptr 136 %l9 = load volatile i32, ptr %ptr 137 %l10 = load volatile i32, ptr %ptr 138 %l11 = load volatile i32, ptr %ptr 139 %l12 = load volatile i32, ptr %ptr 140 %l13 = load volatile i32, ptr %ptr 141 %l14 = load volatile i32, ptr %ptr 142 %add0 = add i32 %l0, %l0 143 %add1 = add i32 %l1, %add0 144 %add4 = add i32 %l4, %add1 145 %add5 = add i32 %l5, %add4 146 %add6 = add i32 %l6, %add5 147 %add7 = add i32 %l7, %add6 148 %add8 = add i32 %l8, %add7 149 %add9 = add i32 %l9, %add8 150 %add10 = add i32 %l10, %add9 151 %add11 = add i32 %l11, %add10 152 %add12 = add i32 %l12, %add11 153 %add13 = add i32 %l13, %add12 154 %add14 = add i32 %l14, %add13 155 store volatile i32 %add0, ptr %ptr 156 store volatile i32 %add1, ptr %ptr 157 store volatile i32 %add4, ptr %ptr 158 store volatile i32 %add5, ptr %ptr 159 store volatile i32 %add6, ptr %ptr 160 store volatile i32 %add7, ptr %ptr 161 store volatile i32 %add8, ptr %ptr 162 store volatile i32 %add9, ptr %ptr 163 store volatile i32 %add10, ptr %ptr 164 store volatile i32 %add11, ptr %ptr 165 store volatile i32 %add12, ptr %ptr 166 store volatile i32 %add13, ptr %ptr 167 store volatile i32 %add14, ptr %ptr 168 %y = alloca [65508 x i64], align 8 169 store volatile i64 %x, ptr %y 170 ret void 171} 172 173; Like f2 but with a frame that is 8 bytes bigger. This is the smallest 174; frame size that needs two instructions to perform the final LMG for 175; %r14 and %r15. 176define void @f4(ptr %ptr, i64 %x) { 177; CHECK-LABEL: f4: 178; CHECK: stmg %r14, %r15, 112(%r15) 179; CHECK: .cfi_offset %r14, -48 180; CHECK: .cfi_offset %r15, -40 181; CHECK: agfi %r15, -524176 182; CHECK: .cfi_def_cfa_offset 524336 183; ...main function body... 184; CHECK: aghi %r15, 8 185; CHECK: lmg %r14, %r15, 524280(%r15) 186; CHECK: br %r14 187 %l0 = load volatile i32, ptr %ptr 188 %l1 = load volatile i32, ptr %ptr 189 %l4 = load volatile i32, ptr %ptr 190 %l5 = load volatile i32, ptr %ptr 191 %l14 = load volatile i32, ptr %ptr 192 %add0 = add i32 %l0, %l0 193 %add1 = add i32 %l1, %add0 194 %add4 = add i32 %l4, %add1 195 %add5 = add i32 %l5, %add4 196 %add14 = add i32 %l14, %add5 197 store volatile i32 %add0, ptr %ptr 198 store volatile i32 %add1, ptr %ptr 199 store volatile i32 %add4, ptr %ptr 200 store volatile i32 %add5, ptr %ptr 201 store volatile i32 %add14, ptr %ptr 202 %y = alloca [65500 x i64], align 8 203 store volatile i64 %x, ptr %y 204 ret void 205} 206 207; This is the largest frame size for which the preparatory increment for 208; "lmg %r14, %r15, ..." can be done using AGHI. 209define void @f5(ptr %ptr, i64 %x) { 210; CHECK-LABEL: f5: 211; CHECK: stmg %r14, %r15, 112(%r15) 212; CHECK: .cfi_offset %r14, -48 213; CHECK: .cfi_offset %r15, -40 214; CHECK: agfi %r15, -556928 215; CHECK: .cfi_def_cfa_offset 557088 216; ...main function body... 217; CHECK: aghi %r15, 32760 218; CHECK: lmg %r14, %r15, 524280(%r15) 219; CHECK: br %r14 220 %l0 = load volatile i32, ptr %ptr 221 %l1 = load volatile i32, ptr %ptr 222 %l4 = load volatile i32, ptr %ptr 223 %l5 = load volatile i32, ptr %ptr 224 %l14 = load volatile i32, ptr %ptr 225 %add0 = add i32 %l0, %l0 226 %add1 = add i32 %l1, %add0 227 %add4 = add i32 %l4, %add1 228 %add5 = add i32 %l5, %add4 229 %add14 = add i32 %l14, %add5 230 store volatile i32 %add0, ptr %ptr 231 store volatile i32 %add1, ptr %ptr 232 store volatile i32 %add4, ptr %ptr 233 store volatile i32 %add5, ptr %ptr 234 store volatile i32 %add14, ptr %ptr 235 %y = alloca [69594 x i64], align 8 236 store volatile i64 %x, ptr %y 237 ret void 238} 239 240; This is the smallest frame size for which the preparatory increment for 241; "lmg %r14, %r15, ..." needs to be done using AGFI. 242define void @f6(ptr %ptr, i64 %x) { 243; CHECK-LABEL: f6: 244; CHECK: stmg %r14, %r15, 112(%r15) 245; CHECK: .cfi_offset %r14, -48 246; CHECK: .cfi_offset %r15, -40 247; CHECK: agfi %r15, -556936 248; CHECK: .cfi_def_cfa_offset 557096 249; ...main function body... 250; CHECK: agfi %r15, 32768 251; CHECK: lmg %r14, %r15, 524280(%r15) 252; CHECK: br %r14 253 %l0 = load volatile i32, ptr %ptr 254 %l1 = load volatile i32, ptr %ptr 255 %l4 = load volatile i32, ptr %ptr 256 %l5 = load volatile i32, ptr %ptr 257 %l14 = load volatile i32, ptr %ptr 258 %add0 = add i32 %l0, %l0 259 %add1 = add i32 %l1, %add0 260 %add4 = add i32 %l4, %add1 261 %add5 = add i32 %l5, %add4 262 %add14 = add i32 %l14, %add5 263 store volatile i32 %add0, ptr %ptr 264 store volatile i32 %add1, ptr %ptr 265 store volatile i32 %add4, ptr %ptr 266 store volatile i32 %add5, ptr %ptr 267 store volatile i32 %add14, ptr %ptr 268 %y = alloca [69595 x i64], align 8 269 store volatile i64 %x, ptr %y 270 ret void 271} 272