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