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.
7define 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.
21define 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.
37define 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.
52define 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.
67define 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.
84define 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.
101define 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.
117define 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.
134define 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.
151define 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