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
5declare i64 @foo()
6
7; Check AGH with no displacement.
8define 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.
25define 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.
44define 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.
63define 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.
81define 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.
100define 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.
119define 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.
139define 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
153call:
154  tail call i64 @foo()
155  br label %exit
156
157exit:
158  ret void
159}
160
161; ... and the same with the inverted direction.
162define 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
176call:
177  tail call i64 @foo()
178  br label %exit
179
180exit:
181  ret void
182}
183
184
185declare {i64, i1} @llvm.sadd.with.overflow.i64(i64, i64) nounwind readnone
186
187