Home | History | Annotate | Download | only in SystemZ
      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