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 register 3 ; 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 %s 7 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -disable-fp-elim | \ 8 ; RUN: FileCheck -check-prefix=CHECK-FP %s 9 10 ; This file tests what happens when a displacement is converted from 11 ; being relative to the start of a frame object to being relative to 12 ; the frame itself. In some cases the test is only possible if two 13 ; objects are allocated. 14 ; 15 ; Rather than rely on a particular order for those objects, the tests 16 ; instead allocate two objects of the same size and apply the test to 17 ; both of them. For consistency, all tests follow this model, even if 18 ; one object would actually be enough. 19 20 ; First check the highest in-range offset after conversion, which is 4092 21 ; for word-addressing instructions like MVHI. 22 ; 23 ; The last in-range doubleword offset is 4088. Since the frame has two 24 ; emergency spill slots at 160(%r15), the amount that we need to allocate 25 ; in order to put another object at offset 4088 is (4088 - 176) / 4 = 978 26 ; words. 27 define void @f1() { 28 ; CHECK-NOFP-LABEL: f1: 29 ; CHECK-NOFP: mvhi 4092(%r15), 42 30 ; CHECK-NOFP: br %r14 31 ; 32 ; CHECK-FP-LABEL: f1: 33 ; CHECK-FP: mvhi 4092(%r11), 42 34 ; CHECK-FP: br %r14 35 %region1 = alloca [978 x i32], align 8 36 %region2 = alloca [978 x i32], align 8 37 %ptr1 = getelementptr inbounds [978 x i32]* %region1, i64 0, i64 1 38 %ptr2 = getelementptr inbounds [978 x i32]* %region2, i64 0, i64 1 39 store volatile i32 42, i32 *%ptr1 40 store volatile i32 42, i32 *%ptr2 41 ret void 42 } 43 44 ; Test the first out-of-range offset. We cannot use an index register here. 45 define void @f2() { 46 ; CHECK-NOFP-LABEL: f2: 47 ; CHECK-NOFP: lay %r1, 4096(%r15) 48 ; CHECK-NOFP: mvhi 0(%r1), 42 49 ; CHECK-NOFP: br %r14 50 ; 51 ; CHECK-FP-LABEL: f2: 52 ; CHECK-FP: lay %r1, 4096(%r11) 53 ; CHECK-FP: mvhi 0(%r1), 42 54 ; CHECK-FP: br %r14 55 %region1 = alloca [978 x i32], align 8 56 %region2 = alloca [978 x i32], align 8 57 %ptr1 = getelementptr inbounds [978 x i32]* %region1, i64 0, i64 2 58 %ptr2 = getelementptr inbounds [978 x i32]* %region2, i64 0, i64 2 59 store volatile i32 42, i32 *%ptr1 60 store volatile i32 42, i32 *%ptr2 61 ret void 62 } 63 64 ; Test the next offset after that. 65 define void @f3() { 66 ; CHECK-NOFP-LABEL: f3: 67 ; CHECK-NOFP: lay %r1, 4096(%r15) 68 ; CHECK-NOFP: mvhi 4(%r1), 42 69 ; CHECK-NOFP: br %r14 70 ; 71 ; CHECK-FP-LABEL: f3: 72 ; CHECK-FP: lay %r1, 4096(%r11) 73 ; CHECK-FP: mvhi 4(%r1), 42 74 ; CHECK-FP: br %r14 75 %region1 = alloca [978 x i32], align 8 76 %region2 = alloca [978 x i32], align 8 77 %ptr1 = getelementptr inbounds [978 x i32]* %region1, i64 0, i64 3 78 %ptr2 = getelementptr inbounds [978 x i32]* %region2, i64 0, i64 3 79 store volatile i32 42, i32 *%ptr1 80 store volatile i32 42, i32 *%ptr2 81 ret void 82 } 83 84 ; Add 4096 bytes (1024 words) to the size of each object and repeat. 85 define void @f4() { 86 ; CHECK-NOFP-LABEL: f4: 87 ; CHECK-NOFP: lay %r1, 4096(%r15) 88 ; CHECK-NOFP: mvhi 4092(%r1), 42 89 ; CHECK-NOFP: br %r14 90 ; 91 ; CHECK-FP-LABEL: f4: 92 ; CHECK-FP: lay %r1, 4096(%r11) 93 ; CHECK-FP: mvhi 4092(%r1), 42 94 ; CHECK-FP: br %r14 95 %region1 = alloca [2002 x i32], align 8 96 %region2 = alloca [2002 x i32], align 8 97 %ptr1 = getelementptr inbounds [2002 x i32]* %region1, i64 0, i64 1 98 %ptr2 = getelementptr inbounds [2002 x i32]* %region2, i64 0, i64 1 99 store volatile i32 42, i32 *%ptr1 100 store volatile i32 42, i32 *%ptr2 101 ret void 102 } 103 104 ; ...as above. 105 define void @f5() { 106 ; CHECK-NOFP-LABEL: f5: 107 ; CHECK-NOFP: lay %r1, 8192(%r15) 108 ; CHECK-NOFP: mvhi 0(%r1), 42 109 ; CHECK-NOFP: br %r14 110 ; 111 ; CHECK-FP-LABEL: f5: 112 ; CHECK-FP: lay %r1, 8192(%r11) 113 ; CHECK-FP: mvhi 0(%r1), 42 114 ; CHECK-FP: br %r14 115 %region1 = alloca [2002 x i32], align 8 116 %region2 = alloca [2002 x i32], align 8 117 %ptr1 = getelementptr inbounds [2002 x i32]* %region1, i64 0, i64 2 118 %ptr2 = getelementptr inbounds [2002 x i32]* %region2, i64 0, i64 2 119 store volatile i32 42, i32 *%ptr1 120 store volatile i32 42, i32 *%ptr2 121 ret void 122 } 123 124 ; ...as above. 125 define void @f6() { 126 ; CHECK-NOFP-LABEL: f6: 127 ; CHECK-NOFP: lay %r1, 8192(%r15) 128 ; CHECK-NOFP: mvhi 4(%r1), 42 129 ; CHECK-NOFP: br %r14 130 ; 131 ; CHECK-FP-LABEL: f6: 132 ; CHECK-FP: lay %r1, 8192(%r11) 133 ; CHECK-FP: mvhi 4(%r1), 42 134 ; CHECK-FP: br %r14 135 %region1 = alloca [2002 x i32], align 8 136 %region2 = alloca [2002 x i32], align 8 137 %ptr1 = getelementptr inbounds [2002 x i32]* %region1, i64 0, i64 3 138 %ptr2 = getelementptr inbounds [2002 x i32]* %region2, i64 0, i64 3 139 store volatile i32 42, i32 *%ptr1 140 store volatile i32 42, i32 *%ptr2 141 ret void 142 } 143 144 ; Now try an offset of 4092 from the start of the object, with the object 145 ; being at offset 8192. This time we need objects of (8192 - 176) / 4 = 2004 146 ; words. 147 define void @f7() { 148 ; CHECK-NOFP-LABEL: f7: 149 ; CHECK-NOFP: lay %r1, 8192(%r15) 150 ; CHECK-NOFP: mvhi 4092(%r1), 42 151 ; CHECK-NOFP: br %r14 152 ; 153 ; CHECK-FP-LABEL: f7: 154 ; CHECK-FP: lay %r1, 8192(%r11) 155 ; CHECK-FP: mvhi 4092(%r1), 42 156 ; CHECK-FP: br %r14 157 %region1 = alloca [2004 x i32], align 8 158 %region2 = alloca [2004 x i32], align 8 159 %ptr1 = getelementptr inbounds [2004 x i32]* %region1, i64 0, i64 1023 160 %ptr2 = getelementptr inbounds [2004 x i32]* %region2, i64 0, i64 1023 161 store volatile i32 42, i32 *%ptr1 162 store volatile i32 42, i32 *%ptr2 163 ret void 164 } 165 166 ; Keep the object-relative offset the same but bump the size of the 167 ; objects by one doubleword. 168 define void @f8() { 169 ; CHECK-NOFP-LABEL: f8: 170 ; CHECK-NOFP: lay %r1, 12288(%r15) 171 ; CHECK-NOFP: mvhi 4(%r1), 42 172 ; CHECK-NOFP: br %r14 173 ; 174 ; CHECK-FP-LABEL: f8: 175 ; CHECK-FP: lay %r1, 12288(%r11) 176 ; CHECK-FP: mvhi 4(%r1), 42 177 ; CHECK-FP: br %r14 178 %region1 = alloca [2006 x i32], align 8 179 %region2 = alloca [2006 x i32], align 8 180 %ptr1 = getelementptr inbounds [2006 x i32]* %region1, i64 0, i64 1023 181 %ptr2 = getelementptr inbounds [2006 x i32]* %region2, i64 0, i64 1023 182 store volatile i32 42, i32 *%ptr1 183 store volatile i32 42, i32 *%ptr2 184 ret void 185 } 186 187 ; Check a case where the original displacement is out of range. The backend 188 ; should force STY to be used instead. 189 define void @f9() { 190 ; CHECK-NOFP-LABEL: f9: 191 ; CHECK-NOFP: lhi [[TMP:%r[0-5]]], 42 192 ; CHECK-NOFP: sty [[TMP]], 12296(%r15) 193 ; CHECK-NOFP: br %r14 194 ; 195 ; CHECK-FP-LABEL: f9: 196 ; CHECK-FP: lhi [[TMP:%r[0-5]]], 42 197 ; CHECK-FP: sty [[TMP]], 12296(%r11) 198 ; CHECK-FP: br %r14 199 %region1 = alloca [2006 x i32], align 8 200 %region2 = alloca [2006 x i32], align 8 201 %ptr1 = getelementptr inbounds [2006 x i32]* %region1, i64 0, i64 1024 202 %ptr2 = getelementptr inbounds [2006 x i32]* %region2, i64 0, i64 1024 203 store volatile i32 42, i32 *%ptr1 204 store volatile i32 42, i32 *%ptr2 205 ret void 206 } 207 208 ; Repeat f2 in a case that needs the emergency spill slots (because all 209 ; call-clobbered registers are live and no call-saved ones have been 210 ; allocated). 211 define void @f10(i32 *%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]]), 42 216 ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15) 217 ; CHECK-NOFP: br %r14 218 ; 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]]), 42 223 ; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11) 224 ; CHECK-FP: br %r14 225 %i0 = load volatile i32 *%vptr 226 %i1 = load volatile i32 *%vptr 227 %i3 = load volatile i32 *%vptr 228 %i4 = load volatile i32 *%vptr 229 %i5 = load volatile i32 *%vptr 230 %region1 = alloca [978 x i32], align 8 231 %region2 = alloca [978 x i32], align 8 232 %ptr1 = getelementptr inbounds [978 x i32]* %region1, i64 0, i64 2 233 %ptr2 = getelementptr inbounds [978 x i32]* %region2, i64 0, i64 2 234 store volatile i32 42, i32 *%ptr1 235 store volatile i32 42, i32 *%ptr2 236 store volatile i32 %i0, i32 *%vptr 237 store volatile i32 %i1, i32 *%vptr 238 store volatile i32 %i3, i32 *%vptr 239 store volatile i32 %i4, i32 *%vptr 240 store volatile i32 %i5, i32 *%vptr 241 ret void 242 } 243 244 ; And again with maximum register pressure. The only spill slots that the 245 ; 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 on 247 ; register allocation heuristics for a stable test. 248 define void @f11(i32 *%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]]), 42 254 ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15) 255 ; CHECK-NOFP: lmg %r6, %r15, 256 ; CHECK-NOFP: br %r14 257 %i0 = load volatile i32 *%vptr 258 %i1 = load volatile i32 *%vptr 259 %i3 = load volatile i32 *%vptr 260 %i4 = load volatile i32 *%vptr 261 %i5 = load volatile i32 *%vptr 262 %i6 = load volatile i32 *%vptr 263 %i7 = load volatile i32 *%vptr 264 %i8 = load volatile i32 *%vptr 265 %i9 = load volatile i32 *%vptr 266 %i10 = load volatile i32 *%vptr 267 %i11 = load volatile i32 *%vptr 268 %i12 = load volatile i32 *%vptr 269 %i13 = load volatile i32 *%vptr 270 %i14 = load volatile i32 *%vptr 271 %region1 = alloca [978 x i32], align 8 272 %region2 = alloca [978 x i32], align 8 273 %ptr1 = getelementptr inbounds [978 x i32]* %region1, i64 0, i64 2 274 %ptr2 = getelementptr inbounds [978 x i32]* %region2, i64 0, i64 2 275 store volatile i32 42, i32 *%ptr1 276 store volatile i32 42, i32 *%ptr2 277 store volatile i32 %i0, i32 *%vptr 278 store volatile i32 %i1, i32 *%vptr 279 store volatile i32 %i3, i32 *%vptr 280 store volatile i32 %i4, i32 *%vptr 281 store volatile i32 %i5, i32 *%vptr 282 store volatile i32 %i6, i32 *%vptr 283 store volatile i32 %i7, i32 *%vptr 284 store volatile i32 %i8, i32 *%vptr 285 store volatile i32 %i9, i32 *%vptr 286 store volatile i32 %i10, i32 *%vptr 287 store volatile i32 %i11, i32 *%vptr 288 store volatile i32 %i12, i32 *%vptr 289 store volatile i32 %i13, i32 *%vptr 290 store volatile i32 %i14, i32 *%vptr 291 ret void 292 } 293