1 ; Test load/store pairs that act as memcpys. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 @g1src = global i8 1 6 @g1dst = global i8 1 7 @g2src = global i16 2 8 @g2dst = global i16 2 9 @g3 = global i32 3 10 @g4 = global i64 4 11 @g5src = external global fp128, align 16 12 @g5dst = external global fp128, align 16 13 14 ; Test the simple i8 case. 15 define void @f1(i8 *%ptr1) { 16 ; CHECK-LABEL: f1: 17 ; CHECK: mvc 1(1,%r2), 0(%r2) 18 ; CHECK: br %r14 19 %ptr2 = getelementptr i8 *%ptr1, i64 1 20 %val = load i8 *%ptr1 21 store i8 %val, i8 *%ptr2 22 ret void 23 } 24 25 ; Test i8 cases where the value is zero-extended to 32 bits. 26 define void @f2(i8 *%ptr1) { 27 ; CHECK-LABEL: f2: 28 ; CHECK: mvc 1(1,%r2), 0(%r2) 29 ; CHECK: br %r14 30 %ptr2 = getelementptr i8 *%ptr1, i64 1 31 %val = load i8 *%ptr1 32 %ext = zext i8 %val to i32 33 %trunc = trunc i32 %ext to i8 34 store i8 %trunc, i8 *%ptr2 35 ret void 36 } 37 38 ; Test i8 cases where the value is zero-extended to 64 bits. 39 define void @f3(i8 *%ptr1) { 40 ; CHECK-LABEL: f3: 41 ; CHECK: mvc 1(1,%r2), 0(%r2) 42 ; CHECK: br %r14 43 %ptr2 = getelementptr i8 *%ptr1, i64 1 44 %val = load i8 *%ptr1 45 %ext = zext i8 %val to i64 46 %trunc = trunc i64 %ext to i8 47 store i8 %trunc, i8 *%ptr2 48 ret void 49 } 50 51 ; Test i8 cases where the value is sign-extended to 32 bits. 52 define void @f4(i8 *%ptr1) { 53 ; CHECK-LABEL: f4: 54 ; CHECK: mvc 1(1,%r2), 0(%r2) 55 ; CHECK: br %r14 56 %ptr2 = getelementptr i8 *%ptr1, i64 1 57 %val = load i8 *%ptr1 58 %ext = sext i8 %val to i32 59 %trunc = trunc i32 %ext to i8 60 store i8 %trunc, i8 *%ptr2 61 ret void 62 } 63 64 ; Test i8 cases where the value is sign-extended to 64 bits. 65 define void @f5(i8 *%ptr1) { 66 ; CHECK-LABEL: f5: 67 ; CHECK: mvc 1(1,%r2), 0(%r2) 68 ; CHECK: br %r14 69 %ptr2 = getelementptr i8 *%ptr1, i64 1 70 %val = load i8 *%ptr1 71 %ext = sext i8 %val to i64 72 %trunc = trunc i64 %ext to i8 73 store i8 %trunc, i8 *%ptr2 74 ret void 75 } 76 77 ; Test the simple i16 case. 78 define void @f6(i16 *%ptr1) { 79 ; CHECK-LABEL: f6: 80 ; CHECK: mvc 2(2,%r2), 0(%r2) 81 ; CHECK: br %r14 82 %ptr2 = getelementptr i16 *%ptr1, i64 1 83 %val = load i16 *%ptr1 84 store i16 %val, i16 *%ptr2 85 ret void 86 } 87 88 ; Test i16 cases where the value is zero-extended to 32 bits. 89 define void @f7(i16 *%ptr1) { 90 ; CHECK-LABEL: f7: 91 ; CHECK: mvc 2(2,%r2), 0(%r2) 92 ; CHECK: br %r14 93 %ptr2 = getelementptr i16 *%ptr1, i64 1 94 %val = load i16 *%ptr1 95 %ext = zext i16 %val to i32 96 %trunc = trunc i32 %ext to i16 97 store i16 %trunc, i16 *%ptr2 98 ret void 99 } 100 101 ; Test i16 cases where the value is zero-extended to 64 bits. 102 define void @f8(i16 *%ptr1) { 103 ; CHECK-LABEL: f8: 104 ; CHECK: mvc 2(2,%r2), 0(%r2) 105 ; CHECK: br %r14 106 %ptr2 = getelementptr i16 *%ptr1, i64 1 107 %val = load i16 *%ptr1 108 %ext = zext i16 %val to i64 109 %trunc = trunc i64 %ext to i16 110 store i16 %trunc, i16 *%ptr2 111 ret void 112 } 113 114 ; Test i16 cases where the value is sign-extended to 32 bits. 115 define void @f9(i16 *%ptr1) { 116 ; CHECK-LABEL: f9: 117 ; CHECK: mvc 2(2,%r2), 0(%r2) 118 ; CHECK: br %r14 119 %ptr2 = getelementptr i16 *%ptr1, i64 1 120 %val = load i16 *%ptr1 121 %ext = sext i16 %val to i32 122 %trunc = trunc i32 %ext to i16 123 store i16 %trunc, i16 *%ptr2 124 ret void 125 } 126 127 ; Test i16 cases where the value is sign-extended to 64 bits. 128 define void @f10(i16 *%ptr1) { 129 ; CHECK-LABEL: f10: 130 ; CHECK: mvc 2(2,%r2), 0(%r2) 131 ; CHECK: br %r14 132 %ptr2 = getelementptr i16 *%ptr1, i64 1 133 %val = load i16 *%ptr1 134 %ext = sext i16 %val to i64 135 %trunc = trunc i64 %ext to i16 136 store i16 %trunc, i16 *%ptr2 137 ret void 138 } 139 140 ; Test the simple i32 case. 141 define void @f11(i32 *%ptr1) { 142 ; CHECK-LABEL: f11: 143 ; CHECK: mvc 4(4,%r2), 0(%r2) 144 ; CHECK: br %r14 145 %ptr2 = getelementptr i32 *%ptr1, i64 1 146 %val = load i32 *%ptr1 147 store i32 %val, i32 *%ptr2 148 ret void 149 } 150 151 ; Test i32 cases where the value is zero-extended to 64 bits. 152 define void @f12(i32 *%ptr1) { 153 ; CHECK-LABEL: f12: 154 ; CHECK: mvc 4(4,%r2), 0(%r2) 155 ; CHECK: br %r14 156 %ptr2 = getelementptr i32 *%ptr1, i64 1 157 %val = load i32 *%ptr1 158 %ext = zext i32 %val to i64 159 %trunc = trunc i64 %ext to i32 160 store i32 %trunc, i32 *%ptr2 161 ret void 162 } 163 164 ; Test i32 cases where the value is sign-extended to 64 bits. 165 define void @f13(i32 *%ptr1) { 166 ; CHECK-LABEL: f13: 167 ; CHECK: mvc 4(4,%r2), 0(%r2) 168 ; CHECK: br %r14 169 %ptr2 = getelementptr i32 *%ptr1, i64 1 170 %val = load i32 *%ptr1 171 %ext = sext i32 %val to i64 172 %trunc = trunc i64 %ext to i32 173 store i32 %trunc, i32 *%ptr2 174 ret void 175 } 176 177 ; Test the i64 case. 178 define void @f14(i64 *%ptr1) { 179 ; CHECK-LABEL: f14: 180 ; CHECK: mvc 8(8,%r2), 0(%r2) 181 ; CHECK: br %r14 182 %ptr2 = getelementptr i64 *%ptr1, i64 1 183 %val = load i64 *%ptr1 184 store i64 %val, i64 *%ptr2 185 ret void 186 } 187 188 ; Test the f32 case. 189 define void @f15(float *%ptr1) { 190 ; CHECK-LABEL: f15: 191 ; CHECK: mvc 4(4,%r2), 0(%r2) 192 ; CHECK: br %r14 193 %ptr2 = getelementptr float *%ptr1, i64 1 194 %val = load float *%ptr1 195 store float %val, float *%ptr2 196 ret void 197 } 198 199 ; Test the f64 case. 200 define void @f16(double *%ptr1) { 201 ; CHECK-LABEL: f16: 202 ; CHECK: mvc 8(8,%r2), 0(%r2) 203 ; CHECK: br %r14 204 %ptr2 = getelementptr double *%ptr1, i64 1 205 %val = load double *%ptr1 206 store double %val, double *%ptr2 207 ret void 208 } 209 210 ; Test the f128 case. 211 define void @f17(fp128 *%ptr1) { 212 ; CHECK-LABEL: f17: 213 ; CHECK: mvc 16(16,%r2), 0(%r2) 214 ; CHECK: br %r14 215 %ptr2 = getelementptr fp128 *%ptr1, i64 1 216 %val = load fp128 *%ptr1 217 store fp128 %val, fp128 *%ptr2 218 ret void 219 } 220 221 ; Make sure that we don't use MVC if the load is volatile. 222 define void @f18(i64 *%ptr1) { 223 ; CHECK-LABEL: f18: 224 ; CHECK-NOT: mvc 225 ; CHECK: br %r14 226 %ptr2 = getelementptr i64 *%ptr1, i64 1 227 %val = load volatile i64 *%ptr1 228 store i64 %val, i64 *%ptr2 229 ret void 230 } 231 232 ; ...likewise the store. 233 define void @f19(i64 *%ptr1) { 234 ; CHECK-LABEL: f19: 235 ; CHECK-NOT: mvc 236 ; CHECK: br %r14 237 %ptr2 = getelementptr i64 *%ptr1, i64 1 238 %val = load i64 *%ptr1 239 store volatile i64 %val, i64 *%ptr2 240 ret void 241 } 242 243 ; Test that MVC is not used for aligned loads and stores if there is 244 ; no way of telling whether they alias. We don't want to use MVC in 245 ; cases where the addresses could be equal. 246 define void @f20(i64 *%ptr1, i64 *%ptr2) { 247 ; CHECK-LABEL: f20: 248 ; CHECK-NOT: mvc 249 ; CHECK: br %r14 250 %val = load i64 *%ptr1 251 store i64 %val, i64 *%ptr2 252 ret void 253 } 254 255 ; ...and again for unaligned loads and stores. 256 define void @f21(i64 *%ptr1, i64 *%ptr2) { 257 ; CHECK-LABEL: f21: 258 ; CHECK-NOT: mvc 259 ; CHECK: br %r14 260 %val = load i64 *%ptr1, align 2 261 store i64 %val, i64 *%ptr2, align 2 262 ret void 263 } 264 265 ; Test a case where there is definite overlap. 266 define void @f22(i64 %base) { 267 ; CHECK-LABEL: f22: 268 ; CHECK-NOT: mvc 269 ; CHECK: br %r14 270 %add = add i64 %base, 1 271 %ptr1 = inttoptr i64 %base to i64 * 272 %ptr2 = inttoptr i64 %add to i64 * 273 %val = load i64 *%ptr1, align 1 274 store i64 %val, i64 *%ptr2, align 1 275 ret void 276 } 277 278 ; Test that we can use MVC for global addresses for i8. 279 define void @f23(i8 *%ptr) { 280 ; CHECK-LABEL: f23: 281 ; CHECK-DAG: larl [[SRC:%r[0-5]]], g1src 282 ; CHECK-DAG: larl [[DST:%r[0-5]]], g1dst 283 ; CHECK: mvc 0(1,[[DST]]), 0([[SRC]]) 284 ; CHECK: br %r14 285 %val = load i8 *@g1src 286 store i8 %val, i8 *@g1dst 287 ret void 288 } 289 290 ; Test that we use LHRL and STHRL for i16. 291 define void @f24(i16 *%ptr) { 292 ; CHECK-LABEL: f24: 293 ; CHECK: lhrl [[REG:%r[0-5]]], g2src 294 ; CHECK: sthrl [[REG]], g2dst 295 ; CHECK: br %r14 296 %val = load i16 *@g2src 297 store i16 %val, i16 *@g2dst 298 ret void 299 } 300 301 ; Test that we use LRL for i32. 302 define void @f25(i32 *%ptr) { 303 ; CHECK-LABEL: f25: 304 ; CHECK: lrl [[REG:%r[0-5]]], g3 305 ; CHECK: st [[REG]], 0(%r2) 306 ; CHECK: br %r14 307 %val = load i32 *@g3 308 store i32 %val, i32 *%ptr 309 ret void 310 } 311 312 ; ...likewise STRL. 313 define void @f26(i32 *%ptr) { 314 ; CHECK-LABEL: f26: 315 ; CHECK: l [[REG:%r[0-5]]], 0(%r2) 316 ; CHECK: strl [[REG]], g3 317 ; CHECK: br %r14 318 %val = load i32 *%ptr 319 store i32 %val, i32 *@g3 320 ret void 321 } 322 323 ; Test that we use LGRL for i64. 324 define void @f27(i64 *%ptr) { 325 ; CHECK-LABEL: f27: 326 ; CHECK: lgrl [[REG:%r[0-5]]], g4 327 ; CHECK: stg [[REG]], 0(%r2) 328 ; CHECK: br %r14 329 %val = load i64 *@g4 330 store i64 %val, i64 *%ptr 331 ret void 332 } 333 334 ; ...likewise STGRL. 335 define void @f28(i64 *%ptr) { 336 ; CHECK-LABEL: f28: 337 ; CHECK: lg [[REG:%r[0-5]]], 0(%r2) 338 ; CHECK: stgrl [[REG]], g4 339 ; CHECK: br %r14 340 %val = load i64 *%ptr 341 store i64 %val, i64 *@g4 342 ret void 343 } 344 345 ; Test that we can use MVC for global addresses for fp128. 346 define void @f29(fp128 *%ptr) { 347 ; CHECK-LABEL: f29: 348 ; CHECK-DAG: larl [[SRC:%r[0-5]]], g5src 349 ; CHECK-DAG: larl [[DST:%r[0-5]]], g5dst 350 ; CHECK: mvc 0(16,[[DST]]), 0([[SRC]]) 351 ; CHECK: br %r14 352 %val = load fp128 *@g5src, align 16 353 store fp128 %val, fp128 *@g5dst, align 16 354 ret void 355 } 356 357 ; Test a case where offset disambiguation is enough. 358 define void @f30(i64 *%ptr1) { 359 ; CHECK-LABEL: f30: 360 ; CHECK: mvc 8(8,%r2), 0(%r2) 361 ; CHECK: br %r14 362 %ptr2 = getelementptr i64 *%ptr1, i64 1 363 %val = load i64 *%ptr1, align 1 364 store i64 %val, i64 *%ptr2, align 1 365 ret void 366 } 367 368 ; Test f21 in cases where TBAA tells us there is no alias. 369 define void @f31(i64 *%ptr1, i64 *%ptr2) { 370 ; CHECK-LABEL: f31: 371 ; CHECK: mvc 0(8,%r3), 0(%r2) 372 ; CHECK: br %r14 373 %val = load i64 *%ptr1, align 2, !tbaa !1 374 store i64 %val, i64 *%ptr2, align 2, !tbaa !2 375 ret void 376 } 377 378 ; Test f21 in cases where TBAA is present but doesn't help. 379 define void @f32(i64 *%ptr1, i64 *%ptr2) { 380 ; CHECK-LABEL: f32: 381 ; CHECK-NOT: mvc 382 ; CHECK: br %r14 383 %val = load i64 *%ptr1, align 2, !tbaa !1 384 store i64 %val, i64 *%ptr2, align 2, !tbaa !1 385 ret void 386 } 387 388 !0 = metadata !{ metadata !"root" } 389 !1 = metadata !{ metadata !3, metadata !3, i64 0 } 390 !2 = metadata !{ metadata !4, metadata !4, i64 0 } 391 !3 = metadata !{ metadata !"set1", metadata !0 } 392 !4 = metadata !{ metadata !"set2", metadata !0 } 393