293 lines · plain
1; Test the handling of base + 12-bit displacement addresses for large frames,2; in cases where no 20-bit form exists. The tests here assume z10 register3; pressure, without the high words being available.4;5; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | \6; RUN: FileCheck -check-prefix=CHECK-NOFP %s7; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -frame-pointer=all | \8; RUN: FileCheck -check-prefix=CHECK-FP %s9 10; This file tests what happens when a displacement is converted from11; being relative to the start of a frame object to being relative to12; the frame itself. In some cases the test is only possible if two13; objects are allocated.14;15; Rather than rely on a particular order for those objects, the tests16; instead allocate two objects of the same size and apply the test to17; both of them. For consistency, all tests follow this model, even if18; one object would actually be enough.19 20; First check the highest in-range offset after conversion, which is 409221; for word-addressing instructions like MVHI.22;23; The last in-range doubleword offset is 4088. Since the frame has two24; emergency spill slots at 160(%r15), the amount that we need to allocate25; in order to put another object at offset 4088 is (4088 - 176) / 4 = 97826; words.27define void @f1() {28; CHECK-NOFP-LABEL: f1:29; CHECK-NOFP: mvhi 4092(%r15), 4230; CHECK-NOFP: br %r1431;32; CHECK-FP-LABEL: f1:33; CHECK-FP: mvhi 4092(%r11), 4234; CHECK-FP: br %r1435 %region1 = alloca [978 x i32], align 836 %region2 = alloca [978 x i32], align 837 %ptr1 = getelementptr inbounds [978 x i32], ptr %region1, i64 0, i64 138 %ptr2 = getelementptr inbounds [978 x i32], ptr %region2, i64 0, i64 139 store volatile i32 42, ptr %ptr140 store volatile i32 42, ptr %ptr241 ret void42}43 44; Test the first out-of-range offset. We cannot use an index register here.45define void @f2() {46; CHECK-NOFP-LABEL: f2:47; CHECK-NOFP: lay %r1, 4096(%r15)48; CHECK-NOFP: mvhi 0(%r1), 4249; CHECK-NOFP: br %r1450;51; CHECK-FP-LABEL: f2:52; CHECK-FP: lay %r1, 4096(%r11)53; CHECK-FP: mvhi 0(%r1), 4254; CHECK-FP: br %r1455 %region1 = alloca [978 x i32], align 856 %region2 = alloca [978 x i32], align 857 %ptr1 = getelementptr inbounds [978 x i32], ptr %region1, i64 0, i64 258 %ptr2 = getelementptr inbounds [978 x i32], ptr %region2, i64 0, i64 259 store volatile i32 42, ptr %ptr160 store volatile i32 42, ptr %ptr261 ret void62}63 64; Test the next offset after that.65define void @f3() {66; CHECK-NOFP-LABEL: f3:67; CHECK-NOFP: lay %r1, 4096(%r15)68; CHECK-NOFP: mvhi 4(%r1), 4269; CHECK-NOFP: br %r1470;71; CHECK-FP-LABEL: f3:72; CHECK-FP: lay %r1, 4096(%r11)73; CHECK-FP: mvhi 4(%r1), 4274; CHECK-FP: br %r1475 %region1 = alloca [978 x i32], align 876 %region2 = alloca [978 x i32], align 877 %ptr1 = getelementptr inbounds [978 x i32], ptr %region1, i64 0, i64 378 %ptr2 = getelementptr inbounds [978 x i32], ptr %region2, i64 0, i64 379 store volatile i32 42, ptr %ptr180 store volatile i32 42, ptr %ptr281 ret void82}83 84; Add 4096 bytes (1024 words) to the size of each object and repeat.85define void @f4() {86; CHECK-NOFP-LABEL: f4:87; CHECK-NOFP: lay %r1, 4096(%r15)88; CHECK-NOFP: mvhi 4092(%r1), 4289; CHECK-NOFP: br %r1490;91; CHECK-FP-LABEL: f4:92; CHECK-FP: lay %r1, 4096(%r11)93; CHECK-FP: mvhi 4092(%r1), 4294; CHECK-FP: br %r1495 %region1 = alloca [2002 x i32], align 896 %region2 = alloca [2002 x i32], align 897 %ptr1 = getelementptr inbounds [2002 x i32], ptr %region1, i64 0, i64 198 %ptr2 = getelementptr inbounds [2002 x i32], ptr %region2, i64 0, i64 199 store volatile i32 42, ptr %ptr1100 store volatile i32 42, ptr %ptr2101 ret void102}103 104; ...as above.105define void @f5() {106; CHECK-NOFP-LABEL: f5:107; CHECK-NOFP: lay %r1, 8192(%r15)108; CHECK-NOFP: mvhi 0(%r1), 42109; CHECK-NOFP: br %r14110;111; CHECK-FP-LABEL: f5:112; CHECK-FP: lay %r1, 8192(%r11)113; CHECK-FP: mvhi 0(%r1), 42114; CHECK-FP: br %r14115 %region1 = alloca [2002 x i32], align 8116 %region2 = alloca [2002 x i32], align 8117 %ptr1 = getelementptr inbounds [2002 x i32], ptr %region1, i64 0, i64 2118 %ptr2 = getelementptr inbounds [2002 x i32], ptr %region2, i64 0, i64 2119 store volatile i32 42, ptr %ptr1120 store volatile i32 42, ptr %ptr2121 ret void122}123 124; ...as above.125define void @f6() {126; CHECK-NOFP-LABEL: f6:127; CHECK-NOFP: lay %r1, 8192(%r15)128; CHECK-NOFP: mvhi 4(%r1), 42129; CHECK-NOFP: br %r14130;131; CHECK-FP-LABEL: f6:132; CHECK-FP: lay %r1, 8192(%r11)133; CHECK-FP: mvhi 4(%r1), 42134; CHECK-FP: br %r14135 %region1 = alloca [2002 x i32], align 8136 %region2 = alloca [2002 x i32], align 8137 %ptr1 = getelementptr inbounds [2002 x i32], ptr %region1, i64 0, i64 3138 %ptr2 = getelementptr inbounds [2002 x i32], ptr %region2, i64 0, i64 3139 store volatile i32 42, ptr %ptr1140 store volatile i32 42, ptr %ptr2141 ret void142}143 144; Now try an offset of 4092 from the start of the object, with the object145; being at offset 8192. This time we need objects of (8192 - 176) / 4 = 2004146; words.147define void @f7() {148; CHECK-NOFP-LABEL: f7:149; CHECK-NOFP: lay %r1, 8192(%r15)150; CHECK-NOFP: mvhi 4092(%r1), 42151; CHECK-NOFP: br %r14152;153; CHECK-FP-LABEL: f7:154; CHECK-FP: lay %r1, 8192(%r11)155; CHECK-FP: mvhi 4092(%r1), 42156; CHECK-FP: br %r14157 %region1 = alloca [2004 x i32], align 8158 %region2 = alloca [2004 x i32], align 8159 %ptr1 = getelementptr inbounds [2004 x i32], ptr %region1, i64 0, i64 1023160 %ptr2 = getelementptr inbounds [2004 x i32], ptr %region2, i64 0, i64 1023161 store volatile i32 42, ptr %ptr1162 store volatile i32 42, ptr %ptr2163 ret void164}165 166; Keep the object-relative offset the same but bump the size of the167; objects by one doubleword.168define void @f8() {169; CHECK-NOFP-LABEL: f8:170; CHECK-NOFP: lay %r1, 12288(%r15)171; CHECK-NOFP: mvhi 4(%r1), 42172; CHECK-NOFP: br %r14173;174; CHECK-FP-LABEL: f8:175; CHECK-FP: lay %r1, 12288(%r11)176; CHECK-FP: mvhi 4(%r1), 42177; CHECK-FP: br %r14178 %region1 = alloca [2006 x i32], align 8179 %region2 = alloca [2006 x i32], align 8180 %ptr1 = getelementptr inbounds [2006 x i32], ptr %region1, i64 0, i64 1023181 %ptr2 = getelementptr inbounds [2006 x i32], ptr %region2, i64 0, i64 1023182 store volatile i32 42, ptr %ptr1183 store volatile i32 42, ptr %ptr2184 ret void185}186 187; Check a case where the original displacement is out of range. The backend188; should force STY to be used instead.189define void @f9() {190; CHECK-NOFP-LABEL: f9:191; CHECK-NOFP: lhi [[TMP:%r[0-5]]], 42192; CHECK-NOFP: sty [[TMP]], 12296(%r15)193; CHECK-NOFP: br %r14194;195; CHECK-FP-LABEL: f9:196; CHECK-FP: lhi [[TMP:%r[0-5]]], 42197; CHECK-FP: sty [[TMP]], 12296(%r11)198; CHECK-FP: br %r14199 %region1 = alloca [2006 x i32], align 8200 %region2 = alloca [2006 x i32], align 8201 %ptr1 = getelementptr inbounds [2006 x i32], ptr %region1, i64 0, i64 1024202 %ptr2 = getelementptr inbounds [2006 x i32], ptr %region2, i64 0, i64 1024203 store volatile i32 42, ptr %ptr1204 store volatile i32 42, ptr %ptr2205 ret void206}207 208; Repeat f2 in a case that needs the emergency spill slots (because all209; call-clobbered registers are live and no call-saved ones have been210; allocated).211define void @f10(ptr %vptr) {212; CHECK-NOFP-LABEL: f10:213; CHECK-NOFP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r15)214; CHECK-NOFP: lay [[REGISTER]], 4096(%r15)215; CHECK-NOFP: mvhi 0([[REGISTER]]), 42216; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15)217; CHECK-NOFP: br %r14218;219; CHECK-FP-LABEL: f10:220; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11)221; CHECK-FP: lay [[REGISTER]], 4096(%r11)222; CHECK-FP: mvhi 0([[REGISTER]]), 42223; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11)224; CHECK-FP: br %r14225 %i0 = load volatile i32, ptr %vptr226 %i1 = load volatile i32, ptr %vptr227 %i3 = load volatile i32, ptr %vptr228 %i4 = load volatile i32, ptr %vptr229 %i5 = load volatile i32, ptr %vptr230 %region1 = alloca [978 x i32], align 8231 %region2 = alloca [978 x i32], align 8232 %ptr1 = getelementptr inbounds [978 x i32], ptr %region1, i64 0, i64 2233 %ptr2 = getelementptr inbounds [978 x i32], ptr %region2, i64 0, i64 2234 store volatile i32 42, ptr %ptr1235 store volatile i32 42, ptr %ptr2236 store volatile i32 %i0, ptr %vptr237 store volatile i32 %i1, ptr %vptr238 store volatile i32 %i3, ptr %vptr239 store volatile i32 %i4, ptr %vptr240 store volatile i32 %i5, ptr %vptr241 ret void242}243 244; And again with maximum register pressure. The only spill slots that the245; NOFP case needs are the emergency ones, so the offsets are the same as for f2.246; The FP case needs to spill an extra register and is too dependent on247; register allocation heuristics for a stable test.248define void @f11(ptr %vptr) {249; CHECK-NOFP-LABEL: f11:250; CHECK-NOFP: stmg %r6, %r15,251; CHECK-NOFP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r15)252; CHECK-NOFP: lay [[REGISTER]], 4096(%r15)253; CHECK-NOFP: mvhi 0([[REGISTER]]), 42254; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15)255; CHECK-NOFP: lmg %r6, %r15,256; CHECK-NOFP: br %r14257 %i0 = load volatile i32, ptr %vptr258 %i1 = load volatile i32, ptr %vptr259 %i3 = load volatile i32, ptr %vptr260 %i4 = load volatile i32, ptr %vptr261 %i5 = load volatile i32, ptr %vptr262 %i6 = load volatile i32, ptr %vptr263 %i7 = load volatile i32, ptr %vptr264 %i8 = load volatile i32, ptr %vptr265 %i9 = load volatile i32, ptr %vptr266 %i10 = load volatile i32, ptr %vptr267 %i11 = load volatile i32, ptr %vptr268 %i12 = load volatile i32, ptr %vptr269 %i13 = load volatile i32, ptr %vptr270 %i14 = load volatile i32, ptr %vptr271 %region1 = alloca [978 x i32], align 8272 %region2 = alloca [978 x i32], align 8273 %ptr1 = getelementptr inbounds [978 x i32], ptr %region1, i64 0, i64 2274 %ptr2 = getelementptr inbounds [978 x i32], ptr %region2, i64 0, i64 2275 store volatile i32 42, ptr %ptr1276 store volatile i32 42, ptr %ptr2277 store volatile i32 %i0, ptr %vptr278 store volatile i32 %i1, ptr %vptr279 store volatile i32 %i3, ptr %vptr280 store volatile i32 %i4, ptr %vptr281 store volatile i32 %i5, ptr %vptr282 store volatile i32 %i6, ptr %vptr283 store volatile i32 %i7, ptr %vptr284 store volatile i32 %i8, ptr %vptr285 store volatile i32 %i9, ptr %vptr286 store volatile i32 %i10, ptr %vptr287 store volatile i32 %i11, ptr %vptr288 store volatile i32 %i12, ptr %vptr289 store volatile i32 %i13, ptr %vptr290 store volatile i32 %i14, ptr %vptr291 ret void292}293