Home | History | Annotate | Download | only in SystemZ
      1 ; Test additions between an i64 and a sign-extended i16 on z14.
      2 ;
      3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s
      4 
      5 declare i64 @foo()
      6 
      7 ; Check AGH with no displacement.
      8 define zeroext i1 @f1(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
      9 ; CHECK-LABEL: f1:
     10 ; CHECK: agh %r3, 0(%r4)
     11 ; CHECK-DAG: stg %r3, 0(%r5)
     12 ; CHECK-DAG: lghi %r2, 0
     13 ; CHECK-DAG: locghio %r2, 1
     14 ; CHECK: br %r14
     15   %half = load i16, i16 *%src
     16   %b = sext i16 %half to i64
     17   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
     18   %val = extractvalue {i64, i1} %t, 0
     19   %obit = extractvalue {i64, i1} %t, 1
     20   store i64 %val, i64 *%res
     21   ret i1 %obit
     22 }
     23 
     24 ; Check the high end of the aligned AGH range.
     25 define zeroext i1 @f4(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
     26 ; CHECK-LABEL: f4:
     27 ; CHECK: agh %r3, 524286(%r4)
     28 ; CHECK-DAG: stg %r3, 0(%r5)
     29 ; CHECK-DAG: lghi %r2, 0
     30 ; CHECK-DAG: locghio %r2, 1
     31 ; CHECK: br %r14
     32   %ptr = getelementptr i16, i16 *%src, i64 262143
     33   %half = load i16, i16 *%ptr
     34   %b = sext i16 %half to i64
     35   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
     36   %val = extractvalue {i64, i1} %t, 0
     37   %obit = extractvalue {i64, i1} %t, 1
     38   store i64 %val, i64 *%res
     39   ret i1 %obit
     40 }
     41 
     42 ; Check the next halfword up, which needs separate address logic.
     43 ; Other sequences besides this one would be OK.
     44 define zeroext i1 @f5(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
     45 ; CHECK-LABEL: f5:
     46 ; CHECK: agfi %r4, 524288
     47 ; CHECK: agh %r3, 0(%r4)
     48 ; CHECK-DAG: stg %r3, 0(%r5)
     49 ; CHECK-DAG: lghi %r2, 0
     50 ; CHECK-DAG: locghio %r2, 1
     51 ; CHECK: br %r14
     52   %ptr = getelementptr i16, i16 *%src, i64 262144
     53   %half = load i16, i16 *%ptr
     54   %b = sext i16 %half to i64
     55   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
     56   %val = extractvalue {i64, i1} %t, 0
     57   %obit = extractvalue {i64, i1} %t, 1
     58   store i64 %val, i64 *%res
     59   ret i1 %obit
     60 }
     61 
     62 ; Check the high end of the negative aligned AGH range.
     63 define zeroext i1 @f6(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
     64 ; CHECK-LABEL: f6:
     65 ; CHECK: agh %r3, -2(%r4)
     66 ; CHECK-DAG: stg %r3, 0(%r5)
     67 ; CHECK-DAG: lghi %r2, 0
     68 ; CHECK-DAG: locghio %r2, 1
     69 ; CHECK: br %r14
     70   %ptr = getelementptr i16, i16 *%src, i64 -1
     71   %half = load i16, i16 *%ptr
     72   %b = sext i16 %half to i64
     73   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
     74   %val = extractvalue {i64, i1} %t, 0
     75   %obit = extractvalue {i64, i1} %t, 1
     76   store i64 %val, i64 *%res
     77   ret i1 %obit
     78 }
     79 
     80 ; Check the low end of the AGH range.
     81 define zeroext i1 @f7(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
     82 ; CHECK-LABEL: f7:
     83 ; CHECK: agh %r3, -524288(%r4)
     84 ; CHECK-DAG: stg %r3, 0(%r5)
     85 ; CHECK-DAG: lghi %r2, 0
     86 ; CHECK-DAG: locghio %r2, 1
     87 ; CHECK: br %r14
     88   %ptr = getelementptr i16, i16 *%src, i64 -262144
     89   %half = load i16, i16 *%ptr
     90   %b = sext i16 %half to i64
     91   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
     92   %val = extractvalue {i64, i1} %t, 0
     93   %obit = extractvalue {i64, i1} %t, 1
     94   store i64 %val, i64 *%res
     95   ret i1 %obit
     96 }
     97 
     98 ; Check the next halfword down, which needs separate address logic.
     99 ; Other sequences besides this one would be OK.
    100 define zeroext i1 @f8(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
    101 ; CHECK-LABEL: f8:
    102 ; CHECK: agfi %r4, -524290
    103 ; CHECK: agh %r3, 0(%r4)
    104 ; CHECK-DAG: stg %r3, 0(%r5)
    105 ; CHECK-DAG: lghi %r2, 0
    106 ; CHECK-DAG: locghio %r2, 1
    107 ; CHECK: br %r14
    108   %ptr = getelementptr i16, i16 *%src, i64 -262145
    109   %half = load i16, i16 *%ptr
    110   %b = sext i16 %half to i64
    111   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
    112   %val = extractvalue {i64, i1} %t, 0
    113   %obit = extractvalue {i64, i1} %t, 1
    114   store i64 %val, i64 *%res
    115   ret i1 %obit
    116 }
    117 
    118 ; Check that AGH allows an index.
    119 define zeroext i1 @f9(i64 %src, i64 %index, i64 %a, i64 *%res) {
    120 ; CHECK-LABEL: f9:
    121 ; CHECK: agh %r4, 524284({{%r3,%r2|%r2,%r3}})
    122 ; CHECK-DAG: stg %r4, 0(%r5)
    123 ; CHECK-DAG: lghi %r2, 0
    124 ; CHECK-DAG: locghio %r2, 1
    125 ; CHECK: br %r14
    126   %add1 = add i64 %src, %index
    127   %add2 = add i64 %add1, 524284
    128   %ptr = inttoptr i64 %add2 to i16 *
    129   %half = load i16, i16 *%ptr
    130   %b = sext i16 %half to i64
    131   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
    132   %val = extractvalue {i64, i1} %t, 0
    133   %obit = extractvalue {i64, i1} %t, 1
    134   store i64 %val, i64 *%res
    135   ret i1 %obit
    136 }
    137 
    138 ; Check using the overflow result for a branch.
    139 define void @f11(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
    140 ; CHECK-LABEL: f11:
    141 ; CHECK: agh %r3, 0(%r4)
    142 ; CHECK: stg %r3, 0(%r5)
    143 ; CHECK: jgo foo@PLT
    144 ; CHECK: br %r14
    145   %half = load i16, i16 *%src
    146   %b = sext i16 %half to i64
    147   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
    148   %val = extractvalue {i64, i1} %t, 0
    149   %obit = extractvalue {i64, i1} %t, 1
    150   store i64 %val, i64 *%res
    151   br i1 %obit, label %call, label %exit
    152 
    153 call:
    154   tail call i64 @foo()
    155   br label %exit
    156 
    157 exit:
    158   ret void
    159 }
    160 
    161 ; ... and the same with the inverted direction.
    162 define void @f12(i64 %dummy, i64 %a, i16 *%src, i64 *%res) {
    163 ; CHECK-LABEL: f12:
    164 ; CHECK: agh %r3, 0(%r4)
    165 ; CHECK: stg %r3, 0(%r5)
    166 ; CHECK: jgno foo@PLT
    167 ; CHECK: br %r14
    168   %half = load i16, i16 *%src
    169   %b = sext i16 %half to i64
    170   %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
    171   %val = extractvalue {i64, i1} %t, 0
    172   %obit = extractvalue {i64, i1} %t, 1
    173   store i64 %val, i64 *%res
    174   br i1 %obit, label %exit, label %call
    175 
    176 call:
    177   tail call i64 @foo()
    178   br label %exit
    179 
    180 exit:
    181   ret void
    182 }
    183 
    184 
    185 declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
    186 
    187