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