Home | History | Annotate | Download | only in SystemZ
      1 ; Test 64-bit subtractions of constants from memory.
      2 ;
      3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
      4 
      5 declare i64 @foo()
      6 
      7 ; Check subtraction of 1.
      8 define zeroext i1 @f1(i64 *%ptr) {
      9 ; CHECK-LABEL: f1:
     10 ; CHECK: algsi 0(%r2), -1
     11 ; CHECK: ipm [[REG:%r[0-5]]]
     12 ; CHECK: afi [[REG]], -536870912
     13 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
     14 ; CHECK: br %r14
     15   %a = load i64, i64 *%ptr
     16   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
     17   %val = extractvalue {i64, i1} %t, 0
     18   %obit = extractvalue {i64, i1} %t, 1
     19   store i64 %val, i64 *%ptr
     20   ret i1 %obit
     21 }
     22 
     23 ; Check the high end of the constant range.
     24 define zeroext i1 @f2(i64 *%ptr) {
     25 ; CHECK-LABEL: f2:
     26 ; CHECK: algsi 0(%r2), -128
     27 ; CHECK: ipm [[REG:%r[0-5]]]
     28 ; CHECK: afi [[REG]], -536870912
     29 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
     30 ; CHECK: br %r14
     31   %a = load i64, i64 *%ptr
     32   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 128)
     33   %val = extractvalue {i64, i1} %t, 0
     34   %obit = extractvalue {i64, i1} %t, 1
     35   store i64 %val, i64 *%ptr
     36   ret i1 %obit
     37 }
     38 
     39 ; Check the next constant up, which must use an addition and a store.
     40 define zeroext i1 @f3(i64 %dummy, i64 *%ptr) {
     41 ; CHECK-LABEL: f3:
     42 ; CHECK: lg [[VAL:%r[0-5]]], 0(%r3)
     43 ; CHECK: slgfi [[VAL]], 129
     44 ; CHECK-DAG: stg [[VAL]], 0(%r3)
     45 ; CHECK-DAG: ipm [[REG:%r[0-5]]]
     46 ; CHECK-DAG: afi [[REG]], -536870912
     47 ; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
     48 ; CHECK: br %r14
     49   %a = load i64, i64 *%ptr
     50   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 129)
     51   %val = extractvalue {i64, i1} %t, 0
     52   %obit = extractvalue {i64, i1} %t, 1
     53   store i64 %val, i64 *%ptr
     54   ret i1 %obit
     55 }
     56 
     57 ; Check the low end of the constant range.
     58 define zeroext i1 @f4(i64 *%ptr) {
     59 ; CHECK-LABEL: f4:
     60 ; CHECK: algsi 0(%r2), 127
     61 ; CHECK: ipm [[REG:%r[0-5]]]
     62 ; CHECK: afi [[REG]], -536870912
     63 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
     64 ; CHECK: br %r14
     65   %a = load i64, i64 *%ptr
     66   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 -127)
     67   %val = extractvalue {i64, i1} %t, 0
     68   %obit = extractvalue {i64, i1} %t, 1
     69   store i64 %val, i64 *%ptr
     70   ret i1 %obit
     71 }
     72 
     73 ; Check the next value down, with the same comment as f3.
     74 define zeroext i1 @f5(i64 %dummy, i64 *%ptr) {
     75 ; CHECK-LABEL: f5:
     76 ; CHECK: lg [[VAL1:%r[0-5]]], 0(%r3)
     77 ; CHECK: lghi [[VAL2:%r[0-9]+]], -128
     78 ; CHECK: slgr [[VAL1]], [[VAL2]]
     79 ; CHECK-DAG: stg [[VAL1]], 0(%r3)
     80 ; CHECK-DAG: ipm [[REG:%r[0-5]]]
     81 ; CHECK-DAG: afi [[REG]], -536870912
     82 ; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
     83 ; CHECK: br %r14
     84   %a = load i64, i64 *%ptr
     85   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 -128)
     86   %val = extractvalue {i64, i1} %t, 0
     87   %obit = extractvalue {i64, i1} %t, 1
     88   store i64 %val, i64 *%ptr
     89   ret i1 %obit
     90 }
     91 
     92 ; Check the high end of the aligned ALGSI range.
     93 define zeroext i1 @f6(i64 *%base) {
     94 ; CHECK-LABEL: f6:
     95 ; CHECK: algsi 524280(%r2), -1
     96 ; CHECK: ipm [[REG:%r[0-5]]]
     97 ; CHECK: afi [[REG]], -536870912
     98 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
     99 ; CHECK: br %r14
    100   %ptr = getelementptr i64, i64 *%base, i64 65535
    101   %a = load i64, i64 *%ptr
    102   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    103   %val = extractvalue {i64, i1} %t, 0
    104   %obit = extractvalue {i64, i1} %t, 1
    105   store i64 %val, i64 *%ptr
    106   ret i1 %obit
    107 }
    108 
    109 ; Check the next word up, which must use separate address logic.
    110 ; Other sequences besides this one would be OK.
    111 define zeroext i1 @f7(i64 *%base) {
    112 ; CHECK-LABEL: f7:
    113 ; CHECK: agfi %r2, 524288
    114 ; CHECK: algsi 0(%r2), -1
    115 ; CHECK: ipm [[REG:%r[0-5]]]
    116 ; CHECK: afi [[REG]], -536870912
    117 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
    118 ; CHECK: br %r14
    119   %ptr = getelementptr i64, i64 *%base, i64 65536
    120   %a = load i64, i64 *%ptr
    121   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    122   %val = extractvalue {i64, i1} %t, 0
    123   %obit = extractvalue {i64, i1} %t, 1
    124   store i64 %val, i64 *%ptr
    125   ret i1 %obit
    126 }
    127 
    128 ; Check the low end of the ALGSI range.
    129 define zeroext i1 @f8(i64 *%base) {
    130 ; CHECK-LABEL: f8:
    131 ; CHECK: algsi -524288(%r2), -1
    132 ; CHECK: ipm [[REG:%r[0-5]]]
    133 ; CHECK: afi [[REG]], -536870912
    134 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
    135 ; CHECK: br %r14
    136   %ptr = getelementptr i64, i64 *%base, i64 -65536
    137   %a = load i64, i64 *%ptr
    138   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    139   %val = extractvalue {i64, i1} %t, 0
    140   %obit = extractvalue {i64, i1} %t, 1
    141   store i64 %val, i64 *%ptr
    142   ret i1 %obit
    143 }
    144 
    145 ; Check the next word down, which must use separate address logic.
    146 ; Other sequences besides this one would be OK.
    147 define zeroext i1 @f9(i64 *%base) {
    148 ; CHECK-LABEL: f9:
    149 ; CHECK: agfi %r2, -524296
    150 ; CHECK: algsi 0(%r2), -1
    151 ; CHECK: ipm [[REG:%r[0-5]]]
    152 ; CHECK: afi [[REG]], -536870912
    153 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
    154 ; CHECK: br %r14
    155   %ptr = getelementptr i64, i64 *%base, i64 -65537
    156   %a = load i64, i64 *%ptr
    157   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    158   %val = extractvalue {i64, i1} %t, 0
    159   %obit = extractvalue {i64, i1} %t, 1
    160   store i64 %val, i64 *%ptr
    161   ret i1 %obit
    162 }
    163 
    164 ; Check that ALGSI does not allow indices.
    165 define zeroext i1 @f10(i64 %base, i64 %index) {
    166 ; CHECK-LABEL: f10:
    167 ; CHECK: agr %r2, %r3
    168 ; CHECK: algsi 8(%r2), -1
    169 ; CHECK: ipm [[REG:%r[0-5]]]
    170 ; CHECK: afi [[REG]], -536870912
    171 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
    172 ; CHECK: br %r14
    173   %add1 = add i64 %base, %index
    174   %add2 = add i64 %add1, 8
    175   %ptr = inttoptr i64 %add2 to i64 *
    176   %a = load i64, i64 *%ptr
    177   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    178   %val = extractvalue {i64, i1} %t, 0
    179   %obit = extractvalue {i64, i1} %t, 1
    180   store i64 %val, i64 *%ptr
    181   ret i1 %obit
    182 }
    183 
    184 ; Check that subtracting 128 from a spilled value can use ALGSI.
    185 define zeroext i1 @f11(i64 *%ptr, i64 %sel) {
    186 ; CHECK-LABEL: f11:
    187 ; CHECK: algsi {{[0-9]+}}(%r15), -128
    188 ; CHECK: br %r14
    189 entry:
    190   %val0 = load volatile i64, i64 *%ptr
    191   %val1 = load volatile i64, i64 *%ptr
    192   %val2 = load volatile i64, i64 *%ptr
    193   %val3 = load volatile i64, i64 *%ptr
    194   %val4 = load volatile i64, i64 *%ptr
    195   %val5 = load volatile i64, i64 *%ptr
    196   %val6 = load volatile i64, i64 *%ptr
    197   %val7 = load volatile i64, i64 *%ptr
    198   %val8 = load volatile i64, i64 *%ptr
    199   %val9 = load volatile i64, i64 *%ptr
    200   %val10 = load volatile i64, i64 *%ptr
    201   %val11 = load volatile i64, i64 *%ptr
    202   %val12 = load volatile i64, i64 *%ptr
    203   %val13 = load volatile i64, i64 *%ptr
    204   %val14 = load volatile i64, i64 *%ptr
    205   %val15 = load volatile i64, i64 *%ptr
    206 
    207   %test = icmp ne i64 %sel, 0
    208   br i1 %test, label %add, label %store
    209 
    210 add:
    211   %t0 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 128)
    212   %add0 = extractvalue {i64, i1} %t0, 0
    213   %obit0 = extractvalue {i64, i1} %t0, 1
    214   %t1 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val1, i64 128)
    215   %add1 = extractvalue {i64, i1} %t1, 0
    216   %obit1 = extractvalue {i64, i1} %t1, 1
    217   %res1 = or i1 %obit0, %obit1
    218   %t2 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val2, i64 128)
    219   %add2 = extractvalue {i64, i1} %t2, 0
    220   %obit2 = extractvalue {i64, i1} %t2, 1
    221   %res2 = or i1 %res1, %obit2
    222   %t3 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val3, i64 128)
    223   %add3 = extractvalue {i64, i1} %t3, 0
    224   %obit3 = extractvalue {i64, i1} %t3, 1
    225   %res3 = or i1 %res2, %obit3
    226   %t4 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val4, i64 128)
    227   %add4 = extractvalue {i64, i1} %t4, 0
    228   %obit4 = extractvalue {i64, i1} %t4, 1
    229   %res4 = or i1 %res3, %obit4
    230   %t5 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val5, i64 128)
    231   %add5 = extractvalue {i64, i1} %t5, 0
    232   %obit5 = extractvalue {i64, i1} %t5, 1
    233   %res5 = or i1 %res4, %obit5
    234   %t6 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val6, i64 128)
    235   %add6 = extractvalue {i64, i1} %t6, 0
    236   %obit6 = extractvalue {i64, i1} %t6, 1
    237   %res6 = or i1 %res5, %obit6
    238   %t7 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val7, i64 128)
    239   %add7 = extractvalue {i64, i1} %t7, 0
    240   %obit7 = extractvalue {i64, i1} %t7, 1
    241   %res7 = or i1 %res6, %obit7
    242   %t8 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val8, i64 128)
    243   %add8 = extractvalue {i64, i1} %t8, 0
    244   %obit8 = extractvalue {i64, i1} %t8, 1
    245   %res8 = or i1 %res7, %obit8
    246   %t9 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val9, i64 128)
    247   %add9 = extractvalue {i64, i1} %t9, 0
    248   %obit9 = extractvalue {i64, i1} %t9, 1
    249   %res9 = or i1 %res8, %obit9
    250   %t10 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val10, i64 128)
    251   %add10 = extractvalue {i64, i1} %t10, 0
    252   %obit10 = extractvalue {i64, i1} %t10, 1
    253   %res10 = or i1 %res9, %obit10
    254   %t11 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val11, i64 128)
    255   %add11 = extractvalue {i64, i1} %t11, 0
    256   %obit11 = extractvalue {i64, i1} %t11, 1
    257   %res11 = or i1 %res10, %obit11
    258   %t12 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val12, i64 128)
    259   %add12 = extractvalue {i64, i1} %t12, 0
    260   %obit12 = extractvalue {i64, i1} %t12, 1
    261   %res12 = or i1 %res11, %obit12
    262   %t13 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val13, i64 128)
    263   %add13 = extractvalue {i64, i1} %t13, 0
    264   %obit13 = extractvalue {i64, i1} %t13, 1
    265   %res13 = or i1 %res12, %obit13
    266   %t14 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val14, i64 128)
    267   %add14 = extractvalue {i64, i1} %t14, 0
    268   %obit14 = extractvalue {i64, i1} %t14, 1
    269   %res14 = or i1 %res13, %obit14
    270   %t15 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val15, i64 128)
    271   %add15 = extractvalue {i64, i1} %t15, 0
    272   %obit15 = extractvalue {i64, i1} %t15, 1
    273   %res15 = or i1 %res14, %obit15
    274 
    275   br label %store
    276 
    277 store:
    278   %new0 = phi i64 [ %val0, %entry ], [ %add0, %add ]
    279   %new1 = phi i64 [ %val1, %entry ], [ %add1, %add ]
    280   %new2 = phi i64 [ %val2, %entry ], [ %add2, %add ]
    281   %new3 = phi i64 [ %val3, %entry ], [ %add3, %add ]
    282   %new4 = phi i64 [ %val4, %entry ], [ %add4, %add ]
    283   %new5 = phi i64 [ %val5, %entry ], [ %add5, %add ]
    284   %new6 = phi i64 [ %val6, %entry ], [ %add6, %add ]
    285   %new7 = phi i64 [ %val7, %entry ], [ %add7, %add ]
    286   %new8 = phi i64 [ %val8, %entry ], [ %add8, %add ]
    287   %new9 = phi i64 [ %val9, %entry ], [ %add9, %add ]
    288   %new10 = phi i64 [ %val10, %entry ], [ %add10, %add ]
    289   %new11 = phi i64 [ %val11, %entry ], [ %add11, %add ]
    290   %new12 = phi i64 [ %val12, %entry ], [ %add12, %add ]
    291   %new13 = phi i64 [ %val13, %entry ], [ %add13, %add ]
    292   %new14 = phi i64 [ %val14, %entry ], [ %add14, %add ]
    293   %new15 = phi i64 [ %val15, %entry ], [ %add15, %add ]
    294   %res = phi i1 [ 0, %entry ], [ %res15, %add ]
    295 
    296   store volatile i64 %new0, i64 *%ptr
    297   store volatile i64 %new1, i64 *%ptr
    298   store volatile i64 %new2, i64 *%ptr
    299   store volatile i64 %new3, i64 *%ptr
    300   store volatile i64 %new4, i64 *%ptr
    301   store volatile i64 %new5, i64 *%ptr
    302   store volatile i64 %new6, i64 *%ptr
    303   store volatile i64 %new7, i64 *%ptr
    304   store volatile i64 %new8, i64 *%ptr
    305   store volatile i64 %new9, i64 *%ptr
    306   store volatile i64 %new10, i64 *%ptr
    307   store volatile i64 %new11, i64 *%ptr
    308   store volatile i64 %new12, i64 *%ptr
    309   store volatile i64 %new13, i64 *%ptr
    310   store volatile i64 %new14, i64 *%ptr
    311   store volatile i64 %new15, i64 *%ptr
    312 
    313   ret i1 %res
    314 }
    315 
    316 ; Check using the overflow result for a branch.
    317 define void @f12(i64 *%ptr) {
    318 ; CHECK-LABEL: f12:
    319 ; CHECK: algsi 0(%r2), -1
    320 ; CHECK: jgle foo@PLT
    321 ; CHECK: br %r14
    322   %a = load i64, i64 *%ptr
    323   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    324   %val = extractvalue {i64, i1} %t, 0
    325   %obit = extractvalue {i64, i1} %t, 1
    326   store i64 %val, i64 *%ptr
    327   br i1 %obit, label %call, label %exit
    328 
    329 call:
    330   tail call i64 @foo()
    331   br label %exit
    332 
    333 exit:
    334   ret void
    335 }
    336 
    337 ; ... and the same with the inverted direction.
    338 define void @f13(i64 *%ptr) {
    339 ; CHECK-LABEL: f13:
    340 ; CHECK: algsi 0(%r2), -1
    341 ; CHECK: jgnle foo@PLT
    342 ; CHECK: br %r14
    343   %a = load i64, i64 *%ptr
    344   %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
    345   %val = extractvalue {i64, i1} %t, 0
    346   %obit = extractvalue {i64, i1} %t, 1
    347   store i64 %val, i64 *%ptr
    348   br i1 %obit, label %exit, label %call
    349 
    350 call:
    351   tail call i64 @foo()
    352   br label %exit
    353 
    354 exit:
    355   ret void
    356 }
    357 
    358 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone
    359 
    360