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