xref: /llvm-project/llvm/test/CodeGen/SystemZ/int-div-03.ll (revision a1710eb3cd5823c5d14899112ca3086acbdbe9cb)
1; Test 64-bit signed division and remainder when the divisor is
2; a signed-extended i32.
3;
4; RUN: llc < %s -mtriple=s390x-linux-gnu -asm-verbose=0 | FileCheck %s
5
6declare i64 @foo()
7
8; Test register division.  The result is in the second of the two registers.
9define void @f1(i64 %dummy, i64 %a, i32 %b, ptr %dest) {
10; CHECK-LABEL: f1:
11; CHECK-NOT: {{%r[234]}}
12; CHECK: dsgfr %r2, %r4
13; CHECK: stg %r3, 0(%r5)
14; CHECK: br %r14
15  %bext = sext i32 %b to i64
16  %div = sdiv i64 %a, %bext
17  store i64 %div, ptr %dest
18  ret void
19}
20
21; Test register remainder.  The result is in the first of the two registers.
22define void @f2(i64 %dummy, i64 %a, i32 %b, ptr %dest) {
23; CHECK-LABEL: f2:
24; CHECK-NOT: {{%r[234]}}
25; CHECK: dsgfr %r2, %r4
26; CHECK: stg %r2, 0(%r5)
27; CHECK: br %r14
28  %bext = sext i32 %b to i64
29  %rem = srem i64 %a, %bext
30  store i64 %rem, ptr %dest
31  ret void
32}
33
34; Test that division and remainder use a single instruction.
35define i64 @f3(i64 %dummy, i64 %a, i32 %b) {
36; CHECK-LABEL: f3:
37; CHECK-NOT: {{%r[234]}}
38; CHECK: dsgfr %r2, %r4
39; CHECK: ogr %r3, %r2
40; CHECK: lgr %r2, %r3
41; CHECK: br %r14
42  %bext = sext i32 %b to i64
43  %div = sdiv i64 %a, %bext
44  %rem = srem i64 %a, %bext
45  %or = or i64 %rem, %div
46  ret i64 %or
47}
48
49; Test register division when the dividend is zero rather than sign extended.
50; We can't use dsgfr here
51define void @f4(i64 %dummy, i64 %a, i32 %b, ptr %dest) {
52; CHECK-LABEL: f4:
53; CHECK-NOT: dsgfr
54; CHECK: br %r14
55  %bext = zext i32 %b to i64
56  %div = sdiv i64 %a, %bext
57  store i64 %div, ptr %dest
58  ret void
59}
60
61; ...likewise remainder.
62define void @f5(i64 %dummy, i64 %a, i32 %b, ptr %dest) {
63; CHECK-LABEL: f5:
64; CHECK-NOT: dsgfr
65; CHECK: br %r14
66  %bext = zext i32 %b to i64
67  %rem = srem i64 %a, %bext
68  store i64 %rem, ptr %dest
69  ret void
70}
71
72; Test memory division with no displacement.
73define void @f6(i64 %dummy, i64 %a, ptr %src, ptr %dest) {
74; CHECK-LABEL: f6:
75; CHECK-NOT: {{%r[234]}}
76; CHECK: dsgf %r2, 0(%r4)
77; CHECK: stg %r3, 0(%r5)
78; CHECK: br %r14
79  %b = load i32, ptr %src
80  %bext = sext i32 %b to i64
81  %div = sdiv i64 %a, %bext
82  store i64 %div, ptr %dest
83  ret void
84}
85
86; Test memory remainder with no displacement.
87define void @f7(i64 %dummy, i64 %a, ptr %src, ptr %dest) {
88; CHECK-LABEL: f7:
89; CHECK-NOT: {{%r[234]}}
90; CHECK: dsgf %r2, 0(%r4)
91; CHECK: stg %r2, 0(%r5)
92; CHECK: br %r14
93  %b = load i32, ptr %src
94  %bext = sext i32 %b to i64
95  %rem = srem i64 %a, %bext
96  store i64 %rem, ptr %dest
97  ret void
98}
99
100; Test both memory division and memory remainder.
101define i64 @f8(i64 %dummy, i64 %a, ptr %src) {
102; CHECK-LABEL: f8:
103; CHECK-NOT: {{%r[234]}}
104; CHECK: dsgf %r2, 0(%r4)
105; CHECK-NOT: {{dsgf|dsgfr}}
106; CHECK: ogr %r3, %r2
107; CHECK: lgr %r2, %r3
108; CHECK: br %r14
109  %b = load i32, ptr %src
110  %bext = sext i32 %b to i64
111  %div = sdiv i64 %a, %bext
112  %rem = srem i64 %a, %bext
113  %or = or i64 %rem, %div
114  ret i64 %or
115}
116
117; Check the high end of the DSGF range.
118define i64 @f9(i64 %dummy, i64 %a, ptr %src) {
119; CHECK-LABEL: f9:
120; CHECK: dsgf %r2, 524284(%r4)
121; CHECK: br %r14
122  %ptr = getelementptr i32, ptr %src, i64 131071
123  %b = load i32, ptr %ptr
124  %bext = sext i32 %b to i64
125  %rem = srem i64 %a, %bext
126  ret i64 %rem
127}
128
129; Check the next word up, which needs separate address logic.
130; Other sequences besides this one would be OK.
131define i64 @f10(i64 %dummy, i64 %a, ptr %src) {
132; CHECK-LABEL: f10:
133; CHECK: agfi %r4, 524288
134; CHECK: dsgf %r2, 0(%r4)
135; CHECK: br %r14
136  %ptr = getelementptr i32, ptr %src, i64 131072
137  %b = load i32, ptr %ptr
138  %bext = sext i32 %b to i64
139  %rem = srem i64 %a, %bext
140  ret i64 %rem
141}
142
143; Check the high end of the negative aligned DSGF range.
144define i64 @f11(i64 %dummy, i64 %a, ptr %src) {
145; CHECK-LABEL: f11:
146; CHECK: dsgf %r2, -4(%r4)
147; CHECK: br %r14
148  %ptr = getelementptr i32, ptr %src, i64 -1
149  %b = load i32, ptr %ptr
150  %bext = sext i32 %b to i64
151  %rem = srem i64 %a, %bext
152  ret i64 %rem
153}
154
155; Check the low end of the DSGF range.
156define i64 @f12(i64 %dummy, i64 %a, ptr %src) {
157; CHECK-LABEL: f12:
158; CHECK: dsgf %r2, -524288(%r4)
159; CHECK: br %r14
160  %ptr = getelementptr i32, ptr %src, i64 -131072
161  %b = load i32, ptr %ptr
162  %bext = sext i32 %b to i64
163  %rem = srem i64 %a, %bext
164  ret i64 %rem
165}
166
167; Check the next word down, which needs separate address logic.
168; Other sequences besides this one would be OK.
169define i64 @f13(i64 %dummy, i64 %a, ptr %src) {
170; CHECK-LABEL: f13:
171; CHECK: agfi %r4, -524292
172; CHECK: dsgf %r2, 0(%r4)
173; CHECK: br %r14
174  %ptr = getelementptr i32, ptr %src, i64 -131073
175  %b = load i32, ptr %ptr
176  %bext = sext i32 %b to i64
177  %rem = srem i64 %a, %bext
178  ret i64 %rem
179}
180
181; Check that DSGF allows an index.
182define i64 @f14(i64 %dummy, i64 %a, i64 %src, i64 %index) {
183; CHECK-LABEL: f14:
184; CHECK: dsgf %r2, 524287(%r5,%r4)
185; CHECK: br %r14
186  %add1 = add i64 %src, %index
187  %add2 = add i64 %add1, 524287
188  %ptr = inttoptr i64 %add2 to ptr
189  %b = load i32, ptr %ptr
190  %bext = sext i32 %b to i64
191  %rem = srem i64 %a, %bext
192  ret i64 %rem
193}
194
195; Make sure that we still use DSGFR rather than DSGR in cases where
196; a load and division cannot be combined.
197define void @f15(ptr %dest, ptr %src) {
198; CHECK-LABEL: f15:
199; CHECK: l [[B:%r[0-9]+]], 0(%r3)
200; CHECK: brasl %r14, foo@PLT
201; CHECK: lgr %r1, %r2
202; CHECK: dsgfr %r0, [[B]]
203; CHECK: br %r14
204  %b = load i32, ptr %src
205  %a = call i64 @foo()
206  %ext = sext i32 %b to i64
207  %div = sdiv i64 %a, %ext
208  store i64 %div, ptr %dest
209  ret void
210}
211