Home | History | Annotate | Download | only in SystemZ
      1 ; Test that floating-point compares are omitted if CC already has the
      2 ; right value.
      3 ;
      4 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as | FileCheck %s
      5 
      6 declare float @llvm.fabs.f32(float %f)
      7 
      8 ; Test addition followed by EQ, which can use the CC result of the addition.
      9 define float @f1(float %a, float %b, float *%dest) {
     10 ; CHECK-LABEL: f1:
     11 ; CHECK: aebr %f0, %f2
     12 ; CHECK-NEXT: ber %r14
     13 ; CHECK: br %r14
     14 entry:
     15   %res = fadd float %a, %b
     16   %cmp = fcmp oeq float %res, 0.0
     17   br i1 %cmp, label %exit, label %store
     18 
     19 store:
     20   store float %b, float *%dest
     21   br label %exit
     22 
     23 exit:
     24   ret float %res
     25 }
     26 
     27 ; ...and again with LT.
     28 define float @f2(float %a, float %b, float *%dest) {
     29 ; CHECK-LABEL: f2:
     30 ; CHECK: aebr %f0, %f2
     31 ; CHECK-NEXT: blr %r14
     32 ; CHECK: br %r14
     33 entry:
     34   %res = fadd float %a, %b
     35   %cmp = fcmp olt float %res, 0.0
     36   br i1 %cmp, label %exit, label %store
     37 
     38 store:
     39   store float %b, float *%dest
     40   br label %exit
     41 
     42 exit:
     43   ret float %res
     44 }
     45 
     46 ; ...and again with GT.
     47 define float @f3(float %a, float %b, float *%dest) {
     48 ; CHECK-LABEL: f3:
     49 ; CHECK: aebr %f0, %f2
     50 ; CHECK-NEXT: bhr %r14
     51 ; CHECK: br %r14
     52 entry:
     53   %res = fadd float %a, %b
     54   %cmp = fcmp ogt float %res, 0.0
     55   br i1 %cmp, label %exit, label %store
     56 
     57 store:
     58   store float %b, float *%dest
     59   br label %exit
     60 
     61 exit:
     62   ret float %res
     63 }
     64 
     65 ; ...and again with UEQ.
     66 define float @f4(float %a, float %b, float *%dest) {
     67 ; CHECK-LABEL: f4:
     68 ; CHECK: aebr %f0, %f2
     69 ; CHECK-NEXT: bnlhr %r14
     70 ; CHECK: br %r14
     71 entry:
     72   %res = fadd float %a, %b
     73   %cmp = fcmp ueq float %res, 0.0
     74   br i1 %cmp, label %exit, label %store
     75 
     76 store:
     77   store float %b, float *%dest
     78   br label %exit
     79 
     80 exit:
     81   ret float %res
     82 }
     83 
     84 ; Subtraction also provides a zero-based CC value.
     85 define float @f5(float %a, float %b, float *%dest) {
     86 ; CHECK-LABEL: f5:
     87 ; CHECK: seb %f0, 0(%r2)
     88 ; CHECK-NEXT: bnher %r14
     89 ; CHECK: br %r14
     90 entry:
     91   %cur = load float , float *%dest
     92   %res = fsub float %a, %cur
     93   %cmp = fcmp ult float %res, 0.0
     94   br i1 %cmp, label %exit, label %store
     95 
     96 store:
     97   store float %b, float *%dest
     98   br label %exit
     99 
    100 exit:
    101   ret float %res
    102 }
    103 
    104 ; Test the result of LOAD POSITIVE.
    105 define float @f6(float %dummy, float %a, float *%dest) {
    106 ; CHECK-LABEL: f6:
    107 ; CHECK: lpebr %f0, %f2
    108 ; CHECK-NEXT: bhr %r14
    109 ; CHECK: br %r14
    110 entry:
    111   %res = call float @llvm.fabs.f32(float %a)
    112   %cmp = fcmp ogt float %res, 0.0
    113   br i1 %cmp, label %exit, label %store
    114 
    115 store:
    116   store float %res, float *%dest
    117   br label %exit
    118 
    119 exit:
    120   ret float %res
    121 }
    122 
    123 ; Test the result of LOAD NEGATIVE.
    124 define float @f7(float %dummy, float %a, float *%dest) {
    125 ; CHECK-LABEL: f7:
    126 ; CHECK: lnebr %f0, %f2
    127 ; CHECK-NEXT: blr %r14
    128 ; CHECK: br %r14
    129 entry:
    130   %abs = call float @llvm.fabs.f32(float %a)
    131   %res = fsub float -0.0, %abs
    132   %cmp = fcmp olt float %res, 0.0
    133   br i1 %cmp, label %exit, label %store
    134 
    135 store:
    136   store float %res, float *%dest
    137   br label %exit
    138 
    139 exit:
    140   ret float %res
    141 }
    142 
    143 ; Test the result of LOAD COMPLEMENT.
    144 define float @f8(float %dummy, float %a, float *%dest) {
    145 ; CHECK-LABEL: f8:
    146 ; CHECK: lcebr %f0, %f2
    147 ; CHECK-NEXT: bler %r14
    148 ; CHECK: br %r14
    149 entry:
    150   %res = fsub float -0.0, %a
    151   %cmp = fcmp ole float %res, 0.0
    152   br i1 %cmp, label %exit, label %store
    153 
    154 store:
    155   store float %res, float *%dest
    156   br label %exit
    157 
    158 exit:
    159   ret float %res
    160 }
    161 
    162 ; Multiplication (for example) does not modify CC.
    163 define float @f9(float %a, float %b, float *%dest) {
    164 ; CHECK-LABEL: f9:
    165 ; CHECK: meebr %f0, %f2
    166 ; CHECK-NEXT: ltebr %f0, %f0
    167 ; CHECK-NEXT: blhr %r14
    168 ; CHECK: br %r14
    169 entry:
    170   %res = fmul float %a, %b
    171   %cmp = fcmp one float %res, 0.0
    172   br i1 %cmp, label %exit, label %store
    173 
    174 store:
    175   store float %b, float *%dest
    176   br label %exit
    177 
    178 exit:
    179   ret float %res
    180 }
    181 
    182 ; Test a combination involving a CC-setting instruction followed by
    183 ; a non-CC-setting instruction.
    184 define float @f10(float %a, float %b, float %c, float *%dest) {
    185 ; CHECK-LABEL: f10:
    186 ; CHECK: aebr %f0, %f2
    187 ; CHECK-NEXT: debr %f0, %f4
    188 ; CHECK-NEXT: ltebr %f0, %f0
    189 ; CHECK-NEXT: bner %r14
    190 ; CHECK: br %r14
    191 entry:
    192   %add = fadd float %a, %b
    193   %res = fdiv float %add, %c
    194   %cmp = fcmp une float %res, 0.0
    195   br i1 %cmp, label %exit, label %store
    196 
    197 store:
    198   store float %b, float *%dest
    199   br label %exit
    200 
    201 exit:
    202   ret float %res
    203 }
    204 
    205 ; Test a case where CC is set based on a different register from the
    206 ; compare input.
    207 define float @f11(float %a, float %b, float %c, float *%dest1, float *%dest2) {
    208 ; CHECK-LABEL: f11:
    209 ; CHECK: aebr %f0, %f2
    210 ; CHECK-NEXT: sebr %f4, %f0
    211 ; CHECK-NEXT: ste %f4, 0(%r2)
    212 ; CHECK-NEXT: ltebr %f0, %f0
    213 ; CHECK-NEXT: ber %r14
    214 ; CHECK: br %r14
    215 entry:
    216   %add = fadd float %a, %b
    217   %sub = fsub float %c, %add
    218   store float %sub, float *%dest1
    219   %cmp = fcmp oeq float %add, 0.0
    220   br i1 %cmp, label %exit, label %store
    221 
    222 store:
    223   store float %sub, float *%dest2
    224   br label %exit
    225 
    226 exit:
    227   ret float %add
    228 }
    229 
    230 ; Test that LER gets converted to LTEBR where useful.
    231 define float @f12(float %dummy, float %val, float *%dest) {
    232 ; CHECK-LABEL: f12:
    233 ; CHECK: ltebr %f0, %f2
    234 ; CHECK-NEXT: #APP
    235 ; CHECK-NEXT: blah %f0
    236 ; CHECK-NEXT: #NO_APP
    237 ; CHECK-NEXT: blr %r14
    238 ; CHECK: br %r14
    239 entry:
    240   call void asm sideeffect "blah $0", "{f0}"(float %val)
    241   %cmp = fcmp olt float %val, 0.0
    242   br i1 %cmp, label %exit, label %store
    243 
    244 store:
    245   store float %val, float *%dest
    246   br label %exit
    247 
    248 exit:
    249   ret float %val
    250 }
    251 
    252 ; Test that LDR gets converted to LTDBR where useful.
    253 define double @f13(double %dummy, double %val, double *%dest) {
    254 ; CHECK-LABEL: f13:
    255 ; CHECK: ltdbr %f0, %f2
    256 ; CHECK-NEXT: #APP
    257 ; CHECK-NEXT: blah %f0
    258 ; CHECK-NEXT: #NO_APP
    259 ; CHECK-NEXT: blr %r14
    260 ; CHECK: br %r14
    261 entry:
    262   call void asm sideeffect "blah $0", "{f0}"(double %val)
    263   %cmp = fcmp olt double %val, 0.0
    264   br i1 %cmp, label %exit, label %store
    265 
    266 store:
    267   store double %val, double *%dest
    268   br label %exit
    269 
    270 exit:
    271   ret double %val
    272 }
    273 
    274 ; Test that LXR gets converted to LTXBR where useful.
    275 define void @f14(fp128 *%ptr1, fp128 *%ptr2) {
    276 ; CHECK-LABEL: f14:
    277 ; CHECK: ltxbr
    278 ; CHECK-NEXT: dxbr
    279 ; CHECK-NEXT: std
    280 ; CHECK-NEXT: std
    281 ; CHECK-NEXT: mxbr
    282 ; CHECK-NEXT: std
    283 ; CHECK-NEXT: std
    284 ; CHECK-NEXT: blr %r14
    285 ; CHECK: br %r14
    286 entry:
    287   %val1 = load fp128 , fp128 *%ptr1
    288   %val2 = load fp128 , fp128 *%ptr2
    289   %div = fdiv fp128 %val1, %val2
    290   store fp128 %div, fp128 *%ptr1
    291   %mul = fmul fp128 %val1, %val2
    292   store fp128 %mul, fp128 *%ptr2
    293   %cmp = fcmp olt fp128 %val1, 0xL00000000000000000000000000000000
    294   br i1 %cmp, label %exit, label %store
    295 
    296 store:
    297   call void asm sideeffect "blah", ""()
    298   br label %exit
    299 
    300 exit:
    301   ret void
    302 }
    303 
    304 ; Test a case where it is the source rather than destination of LER that
    305 ; we need.
    306 define float @f15(float %val, float %dummy, float *%dest) {
    307 ; CHECK-LABEL: f15:
    308 ; CHECK: ltebr %f2, %f0
    309 ; CHECK-NEXT: #APP
    310 ; CHECK-NEXT: blah %f2
    311 ; CHECK-NEXT: #NO_APP
    312 ; CHECK-NEXT: blr %r14
    313 ; CHECK: br %r14
    314 entry:
    315   call void asm sideeffect "blah $0", "{f2}"(float %val)
    316   %cmp = fcmp olt float %val, 0.0
    317   br i1 %cmp, label %exit, label %store
    318 
    319 store:
    320   store float %val, float *%dest
    321   br label %exit
    322 
    323 exit:
    324   ret float %val
    325 }
    326 
    327 ; Test a case where it is the source rather than destination of LDR that
    328 ; we need.
    329 define double @f16(double %val, double %dummy, double *%dest) {
    330 ; CHECK-LABEL: f16:
    331 ; CHECK: ltdbr %f2, %f0
    332 ; CHECK-NEXT: #APP
    333 ; CHECK-NEXT: blah %f2
    334 ; CHECK-NEXT: #NO_APP
    335 ; CHECK-NEXT: blr %r14
    336 ; CHECK: br %r14
    337 entry:
    338   call void asm sideeffect "blah $0", "{f2}"(double %val)
    339   %cmp = fcmp olt double %val, 0.0
    340   br i1 %cmp, label %exit, label %store
    341 
    342 store:
    343   store double %val, double *%dest
    344   br label %exit
    345 
    346 exit:
    347   ret double %val
    348 }
    349 
    350 ; Repeat f2 with a comparison against -0.
    351 define float @f17(float %a, float %b, float *%dest) {
    352 ; CHECK-LABEL: f17:
    353 ; CHECK: aebr %f0, %f2
    354 ; CHECK-NEXT: blr %r14
    355 ; CHECK: br %r14
    356 entry:
    357   %res = fadd float %a, %b
    358   %cmp = fcmp olt float %res, -0.0
    359   br i1 %cmp, label %exit, label %store
    360 
    361 store:
    362   store float %b, float *%dest
    363   br label %exit
    364 
    365 exit:
    366   ret float %res
    367 }
    368 
    369 ; Test another form of f7 in which the condition is based on the unnegated
    370 ; result.  This is what InstCombine would produce.
    371 define float @f18(float %dummy, float %a, float *%dest) {
    372 ; CHECK-LABEL: f18:
    373 ; CHECK: lnebr %f0, %f2
    374 ; CHECK-NEXT: blr %r14
    375 ; CHECK: br %r14
    376 entry:
    377   %abs = call float @llvm.fabs.f32(float %a)
    378   %res = fsub float -0.0, %abs
    379   %cmp = fcmp ogt float %abs, 0.0
    380   br i1 %cmp, label %exit, label %store
    381 
    382 store:
    383   store float %res, float *%dest
    384   br label %exit
    385 
    386 exit:
    387   ret float %res
    388 }
    389 
    390 ; Similarly for f8.
    391 define float @f19(float %dummy, float %a, float *%dest) {
    392 ; CHECK-LABEL: f19:
    393 ; CHECK: lcebr %f0, %f2
    394 ; CHECK-NEXT: bler %r14
    395 ; CHECK: br %r14
    396 entry:
    397   %res = fsub float -0.0, %a
    398   %cmp = fcmp oge float %a, 0.0
    399   br i1 %cmp, label %exit, label %store
    400 
    401 store:
    402   store float %res, float *%dest
    403   br label %exit
    404 
    405 exit:
    406   ret float %res
    407 }
    408