• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; Test 32-bit addition in which the second operand is a sign-extended
2; i16 memory value.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5
6declare i32 @foo()
7
8; Check the low end of the AH range.
9define zeroext i1 @f1(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
10; CHECK-LABEL: f1:
11; CHECK: ah %r3, 0(%r4)
12; CHECK-DAG: st %r3, 0(%r5)
13; CHECK-DAG: ipm [[REG:%r[0-5]]]
14; CHECK-DAG: afi [[REG]], 1342177280
15; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
16; CHECK: br %r14
17  %half = load i16, i16 *%src
18  %b = sext i16 %half to i32
19  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
20  %val = extractvalue {i32, i1} %t, 0
21  %obit = extractvalue {i32, i1} %t, 1
22  store i32 %val, i32 *%res
23  ret i1 %obit
24}
25
26; Check the high end of the aligned AH range.
27define zeroext i1 @f2(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
28; CHECK-LABEL: f2:
29; CHECK: ah %r3, 4094(%r4)
30; CHECK-DAG: st %r3, 0(%r5)
31; CHECK-DAG: ipm [[REG:%r[0-5]]]
32; CHECK-DAG: afi [[REG]], 1342177280
33; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
34; CHECK: br %r14
35  %ptr = getelementptr i16, i16 *%src, i64 2047
36  %half = load i16, i16 *%ptr
37  %b = sext i16 %half to i32
38  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
39  %val = extractvalue {i32, i1} %t, 0
40  %obit = extractvalue {i32, i1} %t, 1
41  store i32 %val, i32 *%res
42  ret i1 %obit
43}
44
45; Check the next halfword up, which should use AHY instead of AH.
46define zeroext i1 @f3(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
47; CHECK-LABEL: f3:
48; CHECK: ahy %r3, 4096(%r4)
49; CHECK-DAG: st %r3, 0(%r5)
50; CHECK-DAG: ipm [[REG:%r[0-5]]]
51; CHECK-DAG: afi [[REG]], 1342177280
52; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
53; CHECK: br %r14
54  %ptr = getelementptr i16, i16 *%src, i64 2048
55  %half = load i16, i16 *%ptr
56  %b = sext i16 %half to i32
57  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
58  %val = extractvalue {i32, i1} %t, 0
59  %obit = extractvalue {i32, i1} %t, 1
60  store i32 %val, i32 *%res
61  ret i1 %obit
62}
63
64; Check the high end of the aligned AHY range.
65define zeroext i1 @f4(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
66; CHECK-LABEL: f4:
67; CHECK: ahy %r3, 524286(%r4)
68; CHECK-DAG: st %r3, 0(%r5)
69; CHECK-DAG: ipm [[REG:%r[0-5]]]
70; CHECK-DAG: afi [[REG]], 1342177280
71; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
72; CHECK: br %r14
73  %ptr = getelementptr i16, i16 *%src, i64 262143
74  %half = load i16, i16 *%ptr
75  %b = sext i16 %half to i32
76  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
77  %val = extractvalue {i32, i1} %t, 0
78  %obit = extractvalue {i32, i1} %t, 1
79  store i32 %val, i32 *%res
80  ret i1 %obit
81}
82
83; Check the next halfword up, which needs separate address logic.
84; Other sequences besides this one would be OK.
85define zeroext i1 @f5(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
86; CHECK-LABEL: f5:
87; CHECK: agfi %r4, 524288
88; CHECK: ah %r3, 0(%r4)
89; CHECK-DAG: st %r3, 0(%r5)
90; CHECK-DAG: ipm [[REG:%r[0-5]]]
91; CHECK-DAG: afi [[REG]], 1342177280
92; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
93; CHECK: br %r14
94  %ptr = getelementptr i16, i16 *%src, i64 262144
95  %half = load i16, i16 *%ptr
96  %b = sext i16 %half to i32
97  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
98  %val = extractvalue {i32, i1} %t, 0
99  %obit = extractvalue {i32, i1} %t, 1
100  store i32 %val, i32 *%res
101  ret i1 %obit
102}
103
104; Check the high end of the negative aligned AHY range.
105define zeroext i1 @f6(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
106; CHECK-LABEL: f6:
107; CHECK: ahy %r3, -2(%r4)
108; CHECK-DAG: st %r3, 0(%r5)
109; CHECK-DAG: ipm [[REG:%r[0-5]]]
110; CHECK-DAG: afi [[REG]], 1342177280
111; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
112; CHECK: br %r14
113  %ptr = getelementptr i16, i16 *%src, i64 -1
114  %half = load i16, i16 *%ptr
115  %b = sext i16 %half to i32
116  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
117  %val = extractvalue {i32, i1} %t, 0
118  %obit = extractvalue {i32, i1} %t, 1
119  store i32 %val, i32 *%res
120  ret i1 %obit
121}
122
123; Check the low end of the AHY range.
124define zeroext i1 @f7(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
125; CHECK-LABEL: f7:
126; CHECK: ahy %r3, -524288(%r4)
127; CHECK-DAG: st %r3, 0(%r5)
128; CHECK-DAG: ipm [[REG:%r[0-5]]]
129; CHECK-DAG: afi [[REG]], 1342177280
130; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
131; CHECK: br %r14
132  %ptr = getelementptr i16, i16 *%src, i64 -262144
133  %half = load i16, i16 *%ptr
134  %b = sext i16 %half to i32
135  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
136  %val = extractvalue {i32, i1} %t, 0
137  %obit = extractvalue {i32, i1} %t, 1
138  store i32 %val, i32 *%res
139  ret i1 %obit
140}
141
142; Check the next halfword down, which needs separate address logic.
143; Other sequences besides this one would be OK.
144define zeroext i1 @f8(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
145; CHECK-LABEL: f8:
146; CHECK: agfi %r4, -524290
147; CHECK: ah %r3, 0(%r4)
148; CHECK-DAG: st %r3, 0(%r5)
149; CHECK-DAG: ipm [[REG:%r[0-5]]]
150; CHECK-DAG: afi [[REG]], 1342177280
151; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
152; CHECK: br %r14
153  %ptr = getelementptr i16, i16 *%src, i64 -262145
154  %half = load i16, i16 *%ptr
155  %b = sext i16 %half to i32
156  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
157  %val = extractvalue {i32, i1} %t, 0
158  %obit = extractvalue {i32, i1} %t, 1
159  store i32 %val, i32 *%res
160  ret i1 %obit
161}
162
163; Check that AH allows an index.
164define zeroext i1 @f9(i64 %src, i64 %index, i32 %a, i32 *%res) {
165; CHECK-LABEL: f9:
166; CHECK: ah %r4, 4094({{%r3,%r2|%r2,%r3}})
167; CHECK-DAG: st %r4, 0(%r5)
168; CHECK-DAG: ipm [[REG:%r[0-5]]]
169; CHECK-DAG: afi [[REG]], 1342177280
170; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
171; CHECK: br %r14
172  %add1 = add i64 %src, %index
173  %add2 = add i64 %add1, 4094
174  %ptr = inttoptr i64 %add2 to i16 *
175  %half = load i16, i16 *%ptr
176  %b = sext i16 %half to i32
177  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
178  %val = extractvalue {i32, i1} %t, 0
179  %obit = extractvalue {i32, i1} %t, 1
180  store i32 %val, i32 *%res
181  ret i1 %obit
182}
183
184; Check that AHY allows an index.
185define zeroext i1 @f10(i64 %src, i64 %index, i32 %a, i32 *%res) {
186; CHECK-LABEL: f10:
187; CHECK: ahy %r4, 4096({{%r3,%r2|%r2,%r3}})
188; CHECK-DAG: st %r4, 0(%r5)
189; CHECK-DAG: ipm [[REG:%r[0-5]]]
190; CHECK-DAG: afi [[REG]], 1342177280
191; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
192; CHECK: br %r14
193  %add1 = add i64 %src, %index
194  %add2 = add i64 %add1, 4096
195  %ptr = inttoptr i64 %add2 to i16 *
196  %half = load i16, i16 *%ptr
197  %b = sext i16 %half to i32
198  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
199  %val = extractvalue {i32, i1} %t, 0
200  %obit = extractvalue {i32, i1} %t, 1
201  store i32 %val, i32 *%res
202  ret i1 %obit
203}
204
205; Check using the overflow result for a branch.
206define void @f11(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
207; CHECK-LABEL: f11:
208; CHECK: ah %r3, 0(%r4)
209; CHECK: st %r3, 0(%r5)
210; CHECK: jgo foo@PLT
211; CHECK: br %r14
212  %half = load i16, i16 *%src
213  %b = sext i16 %half to i32
214  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
215  %val = extractvalue {i32, i1} %t, 0
216  %obit = extractvalue {i32, i1} %t, 1
217  store i32 %val, i32 *%res
218  br i1 %obit, label %call, label %exit
219
220call:
221  tail call i32 @foo()
222  br label %exit
223
224exit:
225  ret void
226}
227
228; ... and the same with the inverted direction.
229define void @f12(i32 %dummy, i32 %a, i16 *%src, i32 *%res) {
230; CHECK-LABEL: f12:
231; CHECK: ah %r3, 0(%r4)
232; CHECK: st %r3, 0(%r5)
233; CHECK: jgno foo@PLT
234; CHECK: br %r14
235  %half = load i16, i16 *%src
236  %b = sext i16 %half to i32
237  %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
238  %val = extractvalue {i32, i1} %t, 0
239  %obit = extractvalue {i32, i1} %t, 1
240  store i32 %val, i32 *%res
241  br i1 %obit, label %exit, label %call
242
243call:
244  tail call i32 @foo()
245  br label %exit
246
247exit:
248  ret void
249}
250
251
252declare {i32, i1} @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone
253
254