334 lines · plain
1; Test the handling of base + index + 12-bit displacement addresses for2; large frames, in cases where no 20-bit form exists. The tests here3; assume z10 register 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 10declare void @foo(ptr %ptr1, ptr %ptr2)11 12; This file tests what happens when a displacement is converted from13; being relative to the start of a frame object to being relative to14; the frame itself. In some cases the test is only possible if two15; objects are allocated.16;17; Rather than rely on a particular order for those objects, the tests18; instead allocate two objects of the same size and apply the test to19; both of them. For consistency, all tests follow this model, even if20; one object would actually be enough.21 22; First check the highest in-range offset after conversion, which is 409223; for word-addressing instructions like LDEB.24;25; The last in-range doubleword offset is 4088. Since the frame has two26; emergency spill slots at 160(%r15), the amount that we need to allocate27; in order to put another object at offset 4088 is (4088 - 176) / 4 = 97828; words.29define void @f1(ptr %dst) {30; CHECK-NOFP-LABEL: f1:31; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r15)32; CHECK-NOFP: br %r1433;34; CHECK-FP-LABEL: f1:35; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r11)36; CHECK-FP: br %r1437 %region1 = alloca [978 x float], align 838 %region2 = alloca [978 x float], align 839 call void @foo(ptr %region1, ptr %region2)40 %ptr1 = getelementptr inbounds [978 x float], ptr %region1, i64 0, i64 141 %ptr2 = getelementptr inbounds [978 x float], ptr %region2, i64 0, i64 142 %float1 = load float, ptr %ptr143 %float2 = load float, ptr %ptr244 %double1 = fpext float %float1 to double45 %double2 = fpext float %float2 to double46 store volatile double %double1, ptr %dst47 store volatile double %double2, ptr %dst48 ret void49}50 51; Test the first out-of-range offset.52define void @f2(ptr %dst) {53; CHECK-NOFP-LABEL: f2:54; CHECK-NOFP: lghi %r1, 409655; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)56; CHECK-NOFP: br %r1457;58; CHECK-FP-LABEL: f2:59; CHECK-FP: lghi %r1, 409660; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)61; CHECK-FP: br %r1462 %region1 = alloca [978 x float], align 863 %region2 = alloca [978 x float], align 864 call void @foo(ptr %region1, ptr %region2)65 %ptr1 = getelementptr inbounds [978 x float], ptr %region1, i64 0, i64 266 %ptr2 = getelementptr inbounds [978 x float], ptr %region2, i64 0, i64 267 %float1 = load float, ptr %ptr168 %float2 = load float, ptr %ptr269 %double1 = fpext float %float1 to double70 %double2 = fpext float %float2 to double71 store volatile double %double1, ptr %dst72 store volatile double %double2, ptr %dst73 ret void74}75 76; Test the next offset after that.77define void @f3(ptr %dst) {78; CHECK-NOFP-LABEL: f3:79; CHECK-NOFP: lghi %r1, 409680; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)81; CHECK-NOFP: br %r1482;83; CHECK-FP-LABEL: f3:84; CHECK-FP: lghi %r1, 409685; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)86; CHECK-FP: br %r1487 %region1 = alloca [978 x float], align 888 %region2 = alloca [978 x float], align 889 call void @foo(ptr %region1, ptr %region2)90 %ptr1 = getelementptr inbounds [978 x float], ptr %region1, i64 0, i64 391 %ptr2 = getelementptr inbounds [978 x float], ptr %region2, i64 0, i64 392 %float1 = load float, ptr %ptr193 %float2 = load float, ptr %ptr294 %double1 = fpext float %float1 to double95 %double2 = fpext float %float2 to double96 store volatile double %double1, ptr %dst97 store volatile double %double2, ptr %dst98 ret void99}100 101; Add 4096 bytes (1024 words) to the size of each object and repeat.102define void @f4(ptr %dst) {103; CHECK-NOFP-LABEL: f4:104; CHECK-NOFP: lghi %r1, 4096105; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)106; CHECK-NOFP: br %r14107;108; CHECK-FP-LABEL: f4:109; CHECK-FP: lghi %r1, 4096110; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)111; CHECK-FP: br %r14112 %region1 = alloca [2002 x float], align 8113 %region2 = alloca [2002 x float], align 8114 call void @foo(ptr %region1, ptr %region2)115 %ptr1 = getelementptr inbounds [2002 x float], ptr %region1, i64 0, i64 1116 %ptr2 = getelementptr inbounds [2002 x float], ptr %region2, i64 0, i64 1117 %float1 = load float, ptr %ptr1118 %float2 = load float, ptr %ptr2119 %double1 = fpext float %float1 to double120 %double2 = fpext float %float2 to double121 store volatile double %double1, ptr %dst122 store volatile double %double2, ptr %dst123 ret void124}125 126; ...as above.127define void @f5(ptr %dst) {128; CHECK-NOFP-LABEL: f5:129; CHECK-NOFP: lghi %r1, 8192130; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)131; CHECK-NOFP: br %r14132;133; CHECK-FP-LABEL: f5:134; CHECK-FP: lghi %r1, 8192135; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)136; CHECK-FP: br %r14137 %region1 = alloca [2002 x float], align 8138 %region2 = alloca [2002 x float], align 8139 call void @foo(ptr %region1, ptr %region2)140 %ptr1 = getelementptr inbounds [2002 x float], ptr %region1, i64 0, i64 2141 %ptr2 = getelementptr inbounds [2002 x float], ptr %region2, i64 0, i64 2142 %float1 = load float, ptr %ptr1143 %float2 = load float, ptr %ptr2144 %double1 = fpext float %float1 to double145 %double2 = fpext float %float2 to double146 store volatile double %double1, ptr %dst147 store volatile double %double2, ptr %dst148 ret void149}150 151; ...as above.152define void @f6(ptr %dst) {153; CHECK-NOFP-LABEL: f6:154; CHECK-NOFP: lghi %r1, 8192155; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)156; CHECK-NOFP: br %r14157;158; CHECK-FP-LABEL: f6:159; CHECK-FP: lghi %r1, 8192160; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)161; CHECK-FP: br %r14162 %region1 = alloca [2002 x float], align 8163 %region2 = alloca [2002 x float], align 8164 call void @foo(ptr %region1, ptr %region2)165 %ptr1 = getelementptr inbounds [2002 x float], ptr %region1, i64 0, i64 3166 %ptr2 = getelementptr inbounds [2002 x float], ptr %region2, i64 0, i64 3167 %float1 = load float, ptr %ptr1168 %float2 = load float, ptr %ptr2169 %double1 = fpext float %float1 to double170 %double2 = fpext float %float2 to double171 store volatile double %double1, ptr %dst172 store volatile double %double2, ptr %dst173 ret void174}175 176; Now try an offset of 4092 from the start of the object, with the object177; being at offset 8192. This time we need objects of (8192 - 168) / 4 = 2004178; words.179define void @f7(ptr %dst) {180; CHECK-NOFP-LABEL: f7:181; CHECK-NOFP: lghi %r1, 8192182; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)183; CHECK-NOFP: br %r14184;185; CHECK-FP-LABEL: f7:186; CHECK-FP: lghi %r1, 8192187; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)188; CHECK-FP: br %r14189 %region1 = alloca [2004 x float], align 8190 %region2 = alloca [2004 x float], align 8191 call void @foo(ptr %region1, ptr %region2)192 %ptr1 = getelementptr inbounds [2004 x float], ptr %region1, i64 0, i64 1023193 %ptr2 = getelementptr inbounds [2004 x float], ptr %region2, i64 0, i64 1023194 %float1 = load float, ptr %ptr1195 %float2 = load float, ptr %ptr2196 %double1 = fpext float %float1 to double197 %double2 = fpext float %float2 to double198 store volatile double %double1, ptr %dst199 store volatile double %double2, ptr %dst200 ret void201}202 203; Keep the object-relative offset the same but bump the size of the204; objects by one doubleword.205define void @f8(ptr %dst) {206; CHECK-NOFP-LABEL: f8:207; CHECK-NOFP: lghi %r1, 12288208; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)209; CHECK-NOFP: br %r14210;211; CHECK-FP-LABEL: f8:212; CHECK-FP: lghi %r1, 12288213; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)214; CHECK-FP: br %r14215 %region1 = alloca [2006 x float], align 8216 %region2 = alloca [2006 x float], align 8217 call void @foo(ptr %region1, ptr %region2)218 %ptr1 = getelementptr inbounds [2006 x float], ptr %region1, i64 0, i64 1023219 %ptr2 = getelementptr inbounds [2006 x float], ptr %region2, i64 0, i64 1023220 %float1 = load float, ptr %ptr1221 %float2 = load float, ptr %ptr2222 %double1 = fpext float %float1 to double223 %double2 = fpext float %float2 to double224 store volatile double %double1, ptr %dst225 store volatile double %double2, ptr %dst226 ret void227}228 229; Check a case where the original displacement is out of range. The backend230; should force an LAY from the outset. We don't yet do any kind of anchor231; optimization, so there should be no offset on the LDEB itself.232define void @f9(ptr %dst) {233; CHECK-NOFP-LABEL: f9:234; CHECK-NOFP: lay %r1, 12296(%r15)235; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1)236; CHECK-NOFP: br %r14237;238; CHECK-FP-LABEL: f9:239; CHECK-FP: lay %r1, 12296(%r11)240; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1)241; CHECK-FP: br %r14242 %region1 = alloca [2006 x float], align 8243 %region2 = alloca [2006 x float], align 8244 call void @foo(ptr %region1, ptr %region2)245 %ptr1 = getelementptr inbounds [2006 x float], ptr %region1, i64 0, i64 1024246 %ptr2 = getelementptr inbounds [2006 x float], ptr %region2, i64 0, i64 1024247 %float1 = load float, ptr %ptr1248 %float2 = load float, ptr %ptr2249 %double1 = fpext float %float1 to double250 %double2 = fpext float %float2 to double251 store volatile double %double1, ptr %dst252 store volatile double %double2, ptr %dst253 ret void254}255 256; Repeat f2 in a case that needs the emergency spill slots, because all257; call-clobbered and allocated call-saved registers are live. Note that258; %vptr and %dst are copied to call-saved registers, freeing up %r2 and259; %r3 during the main test.260define void @f10(ptr %vptr, ptr %dst) {261; CHECK-NOFP-LABEL: f10:262; CHECK-NOFP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r15)263; CHECK-NOFP: lghi [[REGISTER]], 4096264; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r15)265; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15)266; CHECK-NOFP: br %r14267;268; CHECK-FP-LABEL: f10:269; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11)270; CHECK-FP: lghi [[REGISTER]], 4096271; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r11)272; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11)273; CHECK-FP: br %r14274 %region1 = alloca [978 x float], align 8275 %region2 = alloca [978 x float], align 8276 call void @foo(ptr %region1, ptr %region2)277 %ptr1 = getelementptr inbounds [978 x float], ptr %region1, i64 0, i64 2278 %ptr2 = getelementptr inbounds [978 x float], ptr %region2, i64 0, i64 2279 %i0 = load volatile i32, ptr %vptr280 %i1 = load volatile i32, ptr %vptr281 %i2 = load volatile i32, ptr %vptr282 %i3 = load volatile i32, ptr %vptr283 %i4 = load volatile i32, ptr %vptr284 %i5 = load volatile i32, ptr %vptr285 %i14 = load volatile i32, ptr %vptr286 %float1 = load float, ptr %ptr1287 %float2 = load float, ptr %ptr2288 %double1 = fpext float %float1 to double289 %double2 = fpext float %float2 to double290 store volatile double %double1, ptr %dst291 store volatile double %double2, ptr %dst292 store volatile i32 %i0, ptr %vptr293 store volatile i32 %i1, ptr %vptr294 store volatile i32 %i2, ptr %vptr295 store volatile i32 %i3, ptr %vptr296 store volatile i32 %i4, ptr %vptr297 store volatile i32 %i5, ptr %vptr298 store volatile i32 %i14, ptr %vptr299 ret void300}301 302; Repeat f2 in a case where the index register is already occupied.303define void @f11(ptr %dst, i64 %index) {304; CHECK-NOFP-LABEL: f11:305; CHECK-NOFP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3306; CHECK-NOFP: lay %r1, 4096(%r15)307; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)308; CHECK-NOFP: br %r14309;310; CHECK-FP-LABEL: f11:311; CHECK-FP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3312; CHECK-FP: lay %r1, 4096(%r11)313; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)314; CHECK-FP: br %r14315 %region1 = alloca [978 x float], align 8316 %region2 = alloca [978 x float], align 8317 call void @foo(ptr %region1, ptr %region2)318 %elem1 = getelementptr inbounds [978 x float], ptr %region1, i64 0, i64 2319 %elem2 = getelementptr inbounds [978 x float], ptr %region2, i64 0, i64 2320 %base1 = ptrtoint ptr %elem1 to i64321 %base2 = ptrtoint ptr %elem2 to i64322 %addr1 = add i64 %base1, %index323 %addr2 = add i64 %base2, %index324 %ptr1 = inttoptr i64 %addr1 to ptr325 %ptr2 = inttoptr i64 %addr2 to ptr326 %float1 = load float, ptr %ptr1327 %float2 = load float, ptr %ptr2328 %double1 = fpext float %float1 to double329 %double2 = fpext float %float2 to double330 store volatile double %double1, ptr %dst331 store volatile double %double2, ptr %dst332 ret void333}334