Home | History | Annotate | Download | only in SystemZ
      1 ; Test 128-bit addition in which the second operand is a zero-extended i32.
      2 ;
      3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
      4 
      5 ; Check register additions.  The XOR ensures that we don't instead zero-extend
      6 ; %b into a register and use memory addition.
      7 define void @f1(i128 *%aptr, i32 %b) {
      8 ; CHECK-LABEL: f1:
      9 ; CHECK: slgfr {{%r[0-5]}}, %r3
     10 ; CHECK: slbgr
     11 ; CHECK: br %r14
     12   %a = load i128 *%aptr
     13   %xor = xor i128 %a, 127
     14   %bext = zext i32 %b to i128
     15   %sub = sub i128 %xor, %bext
     16   store i128 %sub, i128 *%aptr
     17   ret void
     18 }
     19 
     20 ; Like f1, but using an "in-register" extension.
     21 define void @f2(i128 *%aptr, i64 %b) {
     22 ; CHECK-LABEL: f2:
     23 ; CHECK: slgfr {{%r[0-5]}}, %r3
     24 ; CHECK: slbgr
     25 ; CHECK: br %r14
     26   %a = load i128 *%aptr
     27   %xor = xor i128 %a, 127
     28   %trunc = trunc i64 %b to i32
     29   %bext = zext i32 %trunc to i128
     30   %sub = sub i128 %xor, %bext
     31   store i128 %sub, i128 *%aptr
     32   ret void
     33 }
     34 
     35 ; Test register addition in cases where the second operand is zero extended
     36 ; from i64 rather than i32, but is later masked to i32 range.
     37 define void @f3(i128 *%aptr, i64 %b) {
     38 ; CHECK-LABEL: f3:
     39 ; CHECK: slgfr {{%r[0-5]}}, %r3
     40 ; CHECK: slbgr
     41 ; CHECK: br %r14
     42   %a = load i128 *%aptr
     43   %xor = xor i128 %a, 127
     44   %bext = zext i64 %b to i128
     45   %and = and i128 %bext, 4294967295
     46   %sub = sub i128 %xor, %and
     47   store i128 %sub, i128 *%aptr
     48   ret void
     49 }
     50 
     51 ; Test SLGF with no offset.
     52 define void @f4(i128 *%aptr, i32 *%bsrc) {
     53 ; CHECK-LABEL: f4:
     54 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
     55 ; CHECK: slbgr
     56 ; CHECK: br %r14
     57   %a = load i128 *%aptr
     58   %xor = xor i128 %a, 127
     59   %b = load i32 *%bsrc
     60   %bext = zext i32 %b to i128
     61   %sub = sub i128 %xor, %bext
     62   store i128 %sub, i128 *%aptr
     63   ret void
     64 }
     65 
     66 ; Check the high end of the SLGF range.
     67 define void @f5(i128 *%aptr, i32 *%bsrc) {
     68 ; CHECK-LABEL: f5:
     69 ; CHECK: slgf {{%r[0-5]}}, 524284(%r3)
     70 ; CHECK: slbgr
     71 ; CHECK: br %r14
     72   %a = load i128 *%aptr
     73   %xor = xor i128 %a, 127
     74   %ptr = getelementptr i32 *%bsrc, i64 131071
     75   %b = load i32 *%ptr
     76   %bext = zext i32 %b to i128
     77   %sub = sub i128 %xor, %bext
     78   store i128 %sub, i128 *%aptr
     79   ret void
     80 }
     81 
     82 ; Check the next word up, which must use separate address logic.
     83 ; Other sequences besides this one would be OK.
     84 define void @f6(i128 *%aptr, i32 *%bsrc) {
     85 ; CHECK-LABEL: f6:
     86 ; CHECK: agfi %r3, 524288
     87 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
     88 ; CHECK: slbgr
     89 ; CHECK: br %r14
     90   %a = load i128 *%aptr
     91   %xor = xor i128 %a, 127
     92   %ptr = getelementptr i32 *%bsrc, i64 131072
     93   %b = load i32 *%ptr
     94   %bext = zext i32 %b to i128
     95   %sub = sub i128 %xor, %bext
     96   store i128 %sub, i128 *%aptr
     97   ret void
     98 }
     99 
    100 ; Check the high end of the negative aligned SLGF range.
    101 define void @f7(i128 *%aptr, i32 *%bsrc) {
    102 ; CHECK-LABEL: f7:
    103 ; CHECK: slgf {{%r[0-5]}}, -4(%r3)
    104 ; CHECK: slbgr
    105 ; CHECK: br %r14
    106   %a = load i128 *%aptr
    107   %xor = xor i128 %a, 127
    108   %ptr = getelementptr i32 *%bsrc, i128 -1
    109   %b = load i32 *%ptr
    110   %bext = zext i32 %b to i128
    111   %sub = sub i128 %xor, %bext
    112   store i128 %sub, i128 *%aptr
    113   ret void
    114 }
    115 
    116 ; Check the low end of the SLGF range.
    117 define void @f8(i128 *%aptr, i32 *%bsrc) {
    118 ; CHECK-LABEL: f8:
    119 ; CHECK: slgf {{%r[0-5]}}, -524288(%r3)
    120 ; CHECK: slbgr
    121 ; CHECK: br %r14
    122   %a = load i128 *%aptr
    123   %xor = xor i128 %a, 127
    124   %ptr = getelementptr i32 *%bsrc, i128 -131072
    125   %b = load i32 *%ptr
    126   %bext = zext i32 %b to i128
    127   %sub = sub i128 %xor, %bext
    128   store i128 %sub, i128 *%aptr
    129   ret void
    130 }
    131 
    132 ; Check the next word down, which needs separate address logic.
    133 ; Other sequences besides this one would be OK.
    134 define void @f9(i128 *%aptr, i32 *%bsrc) {
    135 ; CHECK-LABEL: f9:
    136 ; CHECK: agfi %r3, -524292
    137 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
    138 ; CHECK: slbgr
    139 ; CHECK: br %r14
    140   %a = load i128 *%aptr
    141   %xor = xor i128 %a, 127
    142   %ptr = getelementptr i32 *%bsrc, i128 -131073
    143   %b = load i32 *%ptr
    144   %bext = zext i32 %b to i128
    145   %sub = sub i128 %xor, %bext
    146   store i128 %sub, i128 *%aptr
    147   ret void
    148 }
    149 
    150 ; Check that SLGF allows an index.
    151 define void @f10(i128 *%aptr, i64 %src, i64 %index) {
    152 ; CHECK-LABEL: f10:
    153 ; CHECK: slgf {{%r[0-5]}}, 524284({{%r4,%r3|%r3,%r4}})
    154 ; CHECK: br %r14
    155   %a = load i128 *%aptr
    156   %xor = xor i128 %a, 127
    157   %add1 = add i64 %src, %index
    158   %add2 = add i64 %add1, 524284
    159   %ptr = inttoptr i64 %add2 to i32 *
    160   %b = load i32 *%ptr
    161   %bext = zext i32 %b to i128
    162   %sub = sub i128 %xor, %bext
    163   store i128 %sub, i128 *%aptr
    164   ret void
    165 }
    166