1 ; Test 128-bit addition in which the second operand is a zero-extended i32.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
5 ; Check register additions. The XOR ensures that we don't instead zero-extend
6 ; %b into a register and use memory addition.
7 define void @f1(ptr %aptr, i32 %b) {
9 ; CHECK: slgfr {{%r[0-5]}}, %r3
12 %a = load i128, ptr %aptr
13 %xor = xor i128 %a, 127
14 %bext = zext i32 %b to i128
15 %sub = sub i128 %xor, %bext
16 store i128 %sub, ptr %aptr
20 ; Like f1, but using an "in-register" extension.
21 define void @f2(ptr %aptr, i64 %b) {
23 ; CHECK: slgfr {{%r[0-5]}}, %r3
26 %a = load i128, ptr %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, ptr %aptr
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.
37 define void @f3(ptr %aptr, i64 %b) {
39 ; CHECK: slgfr {{%r[0-5]}}, %r3
42 %a = load i128, ptr %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, ptr %aptr
51 ; Test SLGF with no offset.
52 define void @f4(ptr %aptr, ptr %bsrc) {
54 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
57 %a = load i128, ptr %aptr
58 %xor = xor i128 %a, 127
59 %b = load i32, ptr %bsrc
60 %bext = zext i32 %b to i128
61 %sub = sub i128 %xor, %bext
62 store i128 %sub, ptr %aptr
66 ; Check the high end of the SLGF range.
67 define void @f5(ptr %aptr, ptr %bsrc) {
69 ; CHECK: slgf {{%r[0-5]}}, 524284(%r3)
72 %a = load i128, ptr %aptr
73 %xor = xor i128 %a, 127
74 %ptr = getelementptr i32, ptr %bsrc, i64 131071
75 %b = load i32, ptr %ptr
76 %bext = zext i32 %b to i128
77 %sub = sub i128 %xor, %bext
78 store i128 %sub, ptr %aptr
82 ; Check the next word up, which must use separate address logic.
83 ; Other sequences besides this one would be OK.
84 define void @f6(ptr %aptr, ptr %bsrc) {
86 ; CHECK: agfi %r3, 524288
87 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
90 %a = load i128, ptr %aptr
91 %xor = xor i128 %a, 127
92 %ptr = getelementptr i32, ptr %bsrc, i64 131072
93 %b = load i32, ptr %ptr
94 %bext = zext i32 %b to i128
95 %sub = sub i128 %xor, %bext
96 store i128 %sub, ptr %aptr
100 ; Check the high end of the negative aligned SLGF range.
101 define void @f7(ptr %aptr, ptr %bsrc) {
103 ; CHECK: slgf {{%r[0-5]}}, -4(%r3)
106 %a = load i128, ptr %aptr
107 %xor = xor i128 %a, 127
108 %ptr = getelementptr i32, ptr %bsrc, i128 -1
109 %b = load i32, ptr %ptr
110 %bext = zext i32 %b to i128
111 %sub = sub i128 %xor, %bext
112 store i128 %sub, ptr %aptr
116 ; Check the low end of the SLGF range.
117 define void @f8(ptr %aptr, ptr %bsrc) {
119 ; CHECK: slgf {{%r[0-5]}}, -524288(%r3)
122 %a = load i128, ptr %aptr
123 %xor = xor i128 %a, 127
124 %ptr = getelementptr i32, ptr %bsrc, i128 -131072
125 %b = load i32, ptr %ptr
126 %bext = zext i32 %b to i128
127 %sub = sub i128 %xor, %bext
128 store i128 %sub, ptr %aptr
132 ; Check the next word down, which needs separate address logic.
133 ; Other sequences besides this one would be OK.
134 define void @f9(ptr %aptr, ptr %bsrc) {
136 ; CHECK: agfi %r3, -524292
137 ; CHECK: slgf {{%r[0-5]}}, 0(%r3)
140 %a = load i128, ptr %aptr
141 %xor = xor i128 %a, 127
142 %ptr = getelementptr i32, ptr %bsrc, i128 -131073
143 %b = load i32, ptr %ptr
144 %bext = zext i32 %b to i128
145 %sub = sub i128 %xor, %bext
146 store i128 %sub, ptr %aptr
150 ; Check that SLGF allows an index.
151 define void @f10(ptr %aptr, i64 %src, i64 %index) {
153 ; CHECK: slgf {{%r[0-5]}}, 524284({{%r4,%r3|%r3,%r4}})
155 %a = load i128, ptr %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 ptr
160 %b = load i32, ptr %ptr
161 %bext = zext i32 %b to i128
162 %sub = sub i128 %xor, %bext
163 store i128 %sub, ptr %aptr