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