[SystemZ] Fold more spills
[oota-llvm.git] / test / CodeGen / SystemZ / int-mul-08.ll
1 ; Test high-part i64->i128 multiplications.
2 ;
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
4
5 declare i64 @foo()
6
7 ; Check zero-extended multiplication in which only the high part is used.
8 define i64 @f1(i64 %dummy, i64 %a, i64 %b) {
9 ; CHECK: f1:
10 ; CHECK-NOT: {{%r[234]}}
11 ; CHECK: mlgr %r2, %r4
12 ; CHECK: br %r14
13   %ax = zext i64 %a to i128
14   %bx = zext i64 %b to i128
15   %mulx = mul i128 %ax, %bx
16   %highx = lshr i128 %mulx, 64
17   %high = trunc i128 %highx to i64
18   ret i64 %high
19 }
20
21 ; Check sign-extended multiplication in which only the high part is used.
22 ; This needs a rather convoluted sequence.
23 define i64 @f2(i64 %dummy, i64 %a, i64 %b) {
24 ; CHECK: f2:
25 ; CHECK: mlgr
26 ; CHECK: agr
27 ; CHECK: agr
28 ; CHECK: br %r14
29   %ax = sext i64 %a to i128
30   %bx = sext i64 %b to i128
31   %mulx = mul i128 %ax, %bx
32   %highx = lshr i128 %mulx, 64
33   %high = trunc i128 %highx to i64
34   ret i64 %high
35 }
36
37 ; Check zero-extended multiplication in which only part of the high half
38 ; is used.
39 define i64 @f3(i64 %dummy, i64 %a, i64 %b) {
40 ; CHECK: f3:
41 ; CHECK-NOT: {{%r[234]}}
42 ; CHECK: mlgr %r2, %r4
43 ; CHECK: srlg %r2, %r2, 3
44 ; CHECK: br %r14
45   %ax = zext i64 %a to i128
46   %bx = zext i64 %b to i128
47   %mulx = mul i128 %ax, %bx
48   %highx = lshr i128 %mulx, 67
49   %high = trunc i128 %highx to i64
50   ret i64 %high
51 }
52
53 ; Check zero-extended multiplication in which the result is split into
54 ; high and low halves.
55 define i64 @f4(i64 %dummy, i64 %a, i64 %b) {
56 ; CHECK: f4:
57 ; CHECK-NOT: {{%r[234]}}
58 ; CHECK: mlgr %r2, %r4
59 ; CHECK: ogr %r2, %r3
60 ; CHECK: br %r14
61   %ax = zext i64 %a to i128
62   %bx = zext i64 %b to i128
63   %mulx = mul i128 %ax, %bx
64   %highx = lshr i128 %mulx, 64
65   %high = trunc i128 %highx to i64
66   %low = trunc i128 %mulx to i64
67   %or = or i64 %high, %low
68   ret i64 %or
69 }
70
71 ; Check division by a constant, which should use multiplication instead.
72 define i64 @f5(i64 %dummy, i64 %a) {
73 ; CHECK: f5:
74 ; CHECK: mlgr %r2,
75 ; CHECK: srlg %r2, %r2,
76 ; CHECK: br %r14
77   %res = udiv i64 %a, 1234
78   ret i64 %res
79 }
80
81 ; Check MLG with no displacement.
82 define i64 @f6(i64 %dummy, i64 %a, i64 *%src) {
83 ; CHECK: f6:
84 ; CHECK-NOT: {{%r[234]}}
85 ; CHECK: mlg %r2, 0(%r4)
86 ; CHECK: br %r14
87   %b = load i64 *%src
88   %ax = zext i64 %a to i128
89   %bx = zext i64 %b to i128
90   %mulx = mul i128 %ax, %bx
91   %highx = lshr i128 %mulx, 64
92   %high = trunc i128 %highx to i64
93   ret i64 %high
94 }
95
96 ; Check the high end of the aligned MLG range.
97 define i64 @f7(i64 %dummy, i64 %a, i64 *%src) {
98 ; CHECK: f7:
99 ; CHECK: mlg %r2, 524280(%r4)
100 ; CHECK: br %r14
101   %ptr = getelementptr i64 *%src, i64 65535
102   %b = load i64 *%ptr
103   %ax = zext i64 %a to i128
104   %bx = zext i64 %b to i128
105   %mulx = mul i128 %ax, %bx
106   %highx = lshr i128 %mulx, 64
107   %high = trunc i128 %highx to i64
108   ret i64 %high
109 }
110
111 ; Check the next doubleword up, which requires separate address logic.
112 ; Other sequences besides this one would be OK.
113 define i64 @f8(i64 %dummy, i64 %a, i64 *%src) {
114 ; CHECK: f8:
115 ; CHECK: agfi %r4, 524288
116 ; CHECK: mlg %r2, 0(%r4)
117 ; CHECK: br %r14
118   %ptr = getelementptr i64 *%src, i64 65536
119   %b = load i64 *%ptr
120   %ax = zext i64 %a to i128
121   %bx = zext i64 %b to i128
122   %mulx = mul i128 %ax, %bx
123   %highx = lshr i128 %mulx, 64
124   %high = trunc i128 %highx to i64
125   ret i64 %high
126 }
127
128 ; Check the high end of the negative aligned MLG range.
129 define i64 @f9(i64 %dummy, i64 %a, i64 *%src) {
130 ; CHECK: f9:
131 ; CHECK: mlg %r2, -8(%r4)
132 ; CHECK: br %r14
133   %ptr = getelementptr i64 *%src, i64 -1
134   %b = load i64 *%ptr
135   %ax = zext i64 %a to i128
136   %bx = zext i64 %b to i128
137   %mulx = mul i128 %ax, %bx
138   %highx = lshr i128 %mulx, 64
139   %high = trunc i128 %highx to i64
140   ret i64 %high
141 }
142
143 ; Check the low end of the MLG range.
144 define i64 @f10(i64 %dummy, i64 %a, i64 *%src) {
145 ; CHECK: f10:
146 ; CHECK: mlg %r2, -524288(%r4)
147 ; CHECK: br %r14
148   %ptr = getelementptr i64 *%src, i64 -65536
149   %b = load i64 *%ptr
150   %ax = zext i64 %a to i128
151   %bx = zext i64 %b to i128
152   %mulx = mul i128 %ax, %bx
153   %highx = lshr i128 %mulx, 64
154   %high = trunc i128 %highx to i64
155   ret i64 %high
156 }
157
158 ; Check the next doubleword down, which needs separate address logic.
159 ; Other sequences besides this one would be OK.
160 define i64 @f11(i64 *%dest, i64 %a, i64 *%src) {
161 ; CHECK: f11:
162 ; CHECK: agfi %r4, -524296
163 ; CHECK: mlg %r2, 0(%r4)
164 ; CHECK: br %r14
165   %ptr = getelementptr i64 *%src, i64 -65537
166   %b = load i64 *%ptr
167   %ax = zext i64 %a to i128
168   %bx = zext i64 %b to i128
169   %mulx = mul i128 %ax, %bx
170   %highx = lshr i128 %mulx, 64
171   %high = trunc i128 %highx to i64
172   ret i64 %high
173 }
174
175 ; Check that MLG allows an index.
176 define i64 @f12(i64 *%dest, i64 %a, i64 %src, i64 %index) {
177 ; CHECK: f12:
178 ; CHECK: mlg %r2, 524287(%r5,%r4)
179 ; CHECK: br %r14
180   %add1 = add i64 %src, %index
181   %add2 = add i64 %add1, 524287
182   %ptr = inttoptr i64 %add2 to i64 *
183   %b = load i64 *%ptr
184   %ax = zext i64 %a to i128
185   %bx = zext i64 %b to i128
186   %mulx = mul i128 %ax, %bx
187   %highx = lshr i128 %mulx, 64
188   %high = trunc i128 %highx to i64
189   ret i64 %high
190 }
191
192 ; Check that multiplications of spilled values can use MLG rather than MLGR.
193 define i64 @f13(i64 *%ptr0) {
194 ; CHECK: f13:
195 ; CHECK: brasl %r14, foo@PLT
196 ; CHECK: mlg {{%r[0-9]+}}, 160(%r15)
197 ; CHECK: br %r14
198   %ptr1 = getelementptr i64 *%ptr0, i64 2
199   %ptr2 = getelementptr i64 *%ptr0, i64 4
200   %ptr3 = getelementptr i64 *%ptr0, i64 6
201   %ptr4 = getelementptr i64 *%ptr0, i64 8
202   %ptr5 = getelementptr i64 *%ptr0, i64 10
203   %ptr6 = getelementptr i64 *%ptr0, i64 12
204   %ptr7 = getelementptr i64 *%ptr0, i64 14
205   %ptr8 = getelementptr i64 *%ptr0, i64 16
206   %ptr9 = getelementptr i64 *%ptr0, i64 18
207
208   %val0 = load i64 *%ptr0
209   %val1 = load i64 *%ptr1
210   %val2 = load i64 *%ptr2
211   %val3 = load i64 *%ptr3
212   %val4 = load i64 *%ptr4
213   %val5 = load i64 *%ptr5
214   %val6 = load i64 *%ptr6
215   %val7 = load i64 *%ptr7
216   %val8 = load i64 *%ptr8
217   %val9 = load i64 *%ptr9
218
219   %ret = call i64 @foo()
220
221   %retx = zext i64 %ret to i128
222   %val0x = zext i64 %val0 to i128
223   %mul0d = mul i128 %retx, %val0x
224   %mul0x = lshr i128 %mul0d, 64
225
226   %val1x = zext i64 %val1 to i128
227   %mul1d = mul i128 %mul0x, %val1x
228   %mul1x = lshr i128 %mul1d, 64
229
230   %val2x = zext i64 %val2 to i128
231   %mul2d = mul i128 %mul1x, %val2x
232   %mul2x = lshr i128 %mul2d, 64
233
234   %val3x = zext i64 %val3 to i128
235   %mul3d = mul i128 %mul2x, %val3x
236   %mul3x = lshr i128 %mul3d, 64
237
238   %val4x = zext i64 %val4 to i128
239   %mul4d = mul i128 %mul3x, %val4x
240   %mul4x = lshr i128 %mul4d, 64
241
242   %val5x = zext i64 %val5 to i128
243   %mul5d = mul i128 %mul4x, %val5x
244   %mul5x = lshr i128 %mul5d, 64
245
246   %val6x = zext i64 %val6 to i128
247   %mul6d = mul i128 %mul5x, %val6x
248   %mul6x = lshr i128 %mul6d, 64
249
250   %val7x = zext i64 %val7 to i128
251   %mul7d = mul i128 %mul6x, %val7x
252   %mul7x = lshr i128 %mul7d, 64
253
254   %val8x = zext i64 %val8 to i128
255   %mul8d = mul i128 %mul7x, %val8x
256   %mul8x = lshr i128 %mul8d, 64
257
258   %val9x = zext i64 %val9 to i128
259   %mul9d = mul i128 %mul8x, %val9x
260   %mul9x = lshr i128 %mul9d, 64
261
262   %mul9 = trunc i128 %mul9x to i64
263   ret i64 %mul9
264 }