Home | History | Annotate | Download | only in SystemZ
      1 ; Test 64-bit conditional stores that are presented as selects.
      2 ;
      3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
      4 
      5 declare void @foo(i64 *)
      6 
      7 ; Test with the loaded value first.
      8 define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
      9 ; CHECK-LABEL: f1:
     10 ; CHECK-NOT: %r2
     11 ; CHECK: blr %r14
     12 ; CHECK-NOT: %r2
     13 ; CHECK: stg %r3, 0(%r2)
     14 ; CHECK: br %r14
     15   %cond = icmp ult i32 %limit, 420
     16   %orig = load i64 , i64 *%ptr
     17   %res = select i1 %cond, i64 %orig, i64 %alt
     18   store i64 %res, i64 *%ptr
     19   ret void
     20 }
     21 
     22 ; ...and with the loaded value second
     23 define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
     24 ; CHECK-LABEL: f2:
     25 ; CHECK-NOT: %r2
     26 ; CHECK: bher %r14
     27 ; CHECK-NOT: %r2
     28 ; CHECK: stg %r3, 0(%r2)
     29 ; CHECK: br %r14
     30   %cond = icmp ult i32 %limit, 420
     31   %orig = load i64 , i64 *%ptr
     32   %res = select i1 %cond, i64 %alt, i64 %orig
     33   store i64 %res, i64 *%ptr
     34   ret void
     35 }
     36 
     37 ; Check the high end of the aligned STG range.
     38 define void @f3(i64 *%base, i64 %alt, i32 %limit) {
     39 ; CHECK-LABEL: f3:
     40 ; CHECK-NOT: %r2
     41 ; CHECK: blr %r14
     42 ; CHECK-NOT: %r2
     43 ; CHECK: stg %r3, 524280(%r2)
     44 ; CHECK: br %r14
     45   %ptr = getelementptr i64, i64 *%base, i64 65535
     46   %cond = icmp ult i32 %limit, 420
     47   %orig = load i64 , i64 *%ptr
     48   %res = select i1 %cond, i64 %orig, i64 %alt
     49   store i64 %res, i64 *%ptr
     50   ret void
     51 }
     52 
     53 ; Check the next doubleword up, which needs separate address logic.
     54 ; Other sequences besides this one would be OK.
     55 define void @f4(i64 *%base, i64 %alt, i32 %limit) {
     56 ; CHECK-LABEL: f4:
     57 ; CHECK-NOT: %r2
     58 ; CHECK: blr %r14
     59 ; CHECK-NOT: %r2
     60 ; CHECK: agfi %r2, 524288
     61 ; CHECK: stg %r3, 0(%r2)
     62 ; CHECK: br %r14
     63   %ptr = getelementptr i64, i64 *%base, i64 65536
     64   %cond = icmp ult i32 %limit, 420
     65   %orig = load i64 , i64 *%ptr
     66   %res = select i1 %cond, i64 %orig, i64 %alt
     67   store i64 %res, i64 *%ptr
     68   ret void
     69 }
     70 
     71 ; Check the low end of the STG range.
     72 define void @f5(i64 *%base, i64 %alt, i32 %limit) {
     73 ; CHECK-LABEL: f5:
     74 ; CHECK-NOT: %r2
     75 ; CHECK: blr %r14
     76 ; CHECK-NOT: %r2
     77 ; CHECK: stg %r3, -524288(%r2)
     78 ; CHECK: br %r14
     79   %ptr = getelementptr i64, i64 *%base, i64 -65536
     80   %cond = icmp ult i32 %limit, 420
     81   %orig = load i64 , i64 *%ptr
     82   %res = select i1 %cond, i64 %orig, i64 %alt
     83   store i64 %res, i64 *%ptr
     84   ret void
     85 }
     86 
     87 ; Check the next doubleword down, which needs separate address logic.
     88 ; Other sequences besides this one would be OK.
     89 define void @f6(i64 *%base, i64 %alt, i32 %limit) {
     90 ; CHECK-LABEL: f6:
     91 ; CHECK-NOT: %r2
     92 ; CHECK: blr %r14
     93 ; CHECK-NOT: %r2
     94 ; CHECK: agfi %r2, -524296
     95 ; CHECK: stg %r3, 0(%r2)
     96 ; CHECK: br %r14
     97   %ptr = getelementptr i64, i64 *%base, i64 -65537
     98   %cond = icmp ult i32 %limit, 420
     99   %orig = load i64 , i64 *%ptr
    100   %res = select i1 %cond, i64 %orig, i64 %alt
    101   store i64 %res, i64 *%ptr
    102   ret void
    103 }
    104 
    105 ; Check that STG allows an index.
    106 define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {
    107 ; CHECK-LABEL: f7:
    108 ; CHECK-NOT: %r2
    109 ; CHECK: blr %r14
    110 ; CHECK-NOT: %r2
    111 ; CHECK: stg %r4, 524287(%r3,%r2)
    112 ; CHECK: br %r14
    113   %add1 = add i64 %base, %index
    114   %add2 = add i64 %add1, 524287
    115   %ptr = inttoptr i64 %add2 to i64 *
    116   %cond = icmp ult i32 %limit, 420
    117   %orig = load i64 , i64 *%ptr
    118   %res = select i1 %cond, i64 %orig, i64 %alt
    119   store i64 %res, i64 *%ptr
    120   ret void
    121 }
    122 
    123 ; Check that volatile loads are not matched.
    124 define void @f8(i64 *%ptr, i64 %alt, i32 %limit) {
    125 ; CHECK-LABEL: f8:
    126 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
    127 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
    128 ; CHECK: [[LABEL]]:
    129 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
    130 ; CHECK: br %r14
    131   %cond = icmp ult i32 %limit, 420
    132   %orig = load volatile i64 , i64 *%ptr
    133   %res = select i1 %cond, i64 %orig, i64 %alt
    134   store i64 %res, i64 *%ptr
    135   ret void
    136 }
    137 
    138 ; ...likewise stores.  In this case we should have a conditional load into %r3.
    139 define void @f9(i64 *%ptr, i64 %alt, i32 %limit) {
    140 ; CHECK-LABEL: f9:
    141 ; CHECK: jhe [[LABEL:[^ ]*]]
    142 ; CHECK: lg %r3, 0(%r2)
    143 ; CHECK: [[LABEL]]:
    144 ; CHECK: stg %r3, 0(%r2)
    145 ; CHECK: br %r14
    146   %cond = icmp ult i32 %limit, 420
    147   %orig = load i64 , i64 *%ptr
    148   %res = select i1 %cond, i64 %orig, i64 %alt
    149   store volatile i64 %res, i64 *%ptr
    150   ret void
    151 }
    152 
    153 ; Check that atomic loads are not matched.  The transformation is OK for
    154 ; the "unordered" case tested here, but since we don't try to handle atomic
    155 ; operations at all in this context, it seems better to assert that than
    156 ; to restrict the test to a stronger ordering.
    157 define void @f10(i64 *%ptr, i64 %alt, i32 %limit) {
    158 ; FIXME: should use a normal load instead of CSG.
    159 ; CHECK-LABEL: f10:
    160 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
    161 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
    162 ; CHECK: [[LABEL]]:
    163 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
    164 ; CHECK: br %r14
    165   %cond = icmp ult i32 %limit, 420
    166   %orig = load atomic i64 , i64 *%ptr unordered, align 8
    167   %res = select i1 %cond, i64 %orig, i64 %alt
    168   store i64 %res, i64 *%ptr
    169   ret void
    170 }
    171 
    172 ; ...likewise stores.
    173 define void @f11(i64 *%ptr, i64 %alt, i32 %limit) {
    174 ; FIXME: should use a normal store instead of CSG.
    175 ; CHECK-LABEL: f11:
    176 ; CHECK: jhe [[LABEL:[^ ]*]]
    177 ; CHECK: lg %r3, 0(%r2)
    178 ; CHECK: [[LABEL]]:
    179 ; CHECK: stg %r3, 0(%r2)
    180 ; CHECK: br %r14
    181   %cond = icmp ult i32 %limit, 420
    182   %orig = load i64 , i64 *%ptr
    183   %res = select i1 %cond, i64 %orig, i64 %alt
    184   store atomic i64 %res, i64 *%ptr unordered, align 8
    185   ret void
    186 }
    187 
    188 ; Try a frame index base.
    189 define void @f12(i64 %alt, i32 %limit) {
    190 ; CHECK-LABEL: f12:
    191 ; CHECK: brasl %r14, foo@PLT
    192 ; CHECK-NOT: %r15
    193 ; CHECK: jl [[LABEL:[^ ]*]]
    194 ; CHECK-NOT: %r15
    195 ; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)
    196 ; CHECK: [[LABEL]]:
    197 ; CHECK: brasl %r14, foo@PLT
    198 ; CHECK: br %r14
    199   %ptr = alloca i64
    200   call void @foo(i64 *%ptr)
    201   %cond = icmp ult i32 %limit, 420
    202   %orig = load i64 , i64 *%ptr
    203   %res = select i1 %cond, i64 %orig, i64 %alt
    204   store i64 %res, i64 *%ptr
    205   call void @foo(i64 *%ptr)
    206   ret void
    207 }
    208