Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / div-rem-pair-recomposition-signed.ll
blob6e13ae6feb66b48c807ca312b31e2ede55d232cd
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s --check-prefix=ALL
4 ; If the target does not have a single div/rem operation,
5 ; -div-rem-pairs pass will decompose the remainder calculation as:
6 ;   X % Y --> X - ((X / Y) * Y)
7 ; But if the target does have a single div/rem operation,
8 ; the opposite transform is likely beneficial.
10 define i8 @scalar_i8(i8 %x, i8 %y, ptr %divdst) nounwind {
11 ; ALL-LABEL: scalar_i8:
12 ; ALL:       // %bb.0:
13 ; ALL-NEXT:    sxtb w8, w1
14 ; ALL-NEXT:    sxtb w9, w0
15 ; ALL-NEXT:    sdiv w8, w9, w8
16 ; ALL-NEXT:    msub w0, w8, w1, w0
17 ; ALL-NEXT:    strb w8, [x2]
18 ; ALL-NEXT:    ret
19   %div = sdiv i8 %x, %y
20   store i8 %div, ptr %divdst, align 4
21   %t1 = mul i8 %div, %y
22   %t2 = sub i8 %x, %t1
23   ret i8 %t2
26 define i16 @scalar_i16(i16 %x, i16 %y, ptr %divdst) nounwind {
27 ; ALL-LABEL: scalar_i16:
28 ; ALL:       // %bb.0:
29 ; ALL-NEXT:    sxth w8, w1
30 ; ALL-NEXT:    sxth w9, w0
31 ; ALL-NEXT:    sdiv w8, w9, w8
32 ; ALL-NEXT:    msub w0, w8, w1, w0
33 ; ALL-NEXT:    strh w8, [x2]
34 ; ALL-NEXT:    ret
35   %div = sdiv i16 %x, %y
36   store i16 %div, ptr %divdst, align 4
37   %t1 = mul i16 %div, %y
38   %t2 = sub i16 %x, %t1
39   ret i16 %t2
42 define i32 @scalar_i32(i32 %x, i32 %y, ptr %divdst) nounwind {
43 ; ALL-LABEL: scalar_i32:
44 ; ALL:       // %bb.0:
45 ; ALL-NEXT:    sdiv w8, w0, w1
46 ; ALL-NEXT:    msub w0, w8, w1, w0
47 ; ALL-NEXT:    str w8, [x2]
48 ; ALL-NEXT:    ret
49   %div = sdiv i32 %x, %y
50   store i32 %div, ptr %divdst, align 4
51   %t1 = mul i32 %div, %y
52   %t2 = sub i32 %x, %t1
53   ret i32 %t2
56 define i64 @scalar_i64(i64 %x, i64 %y, ptr %divdst) nounwind {
57 ; ALL-LABEL: scalar_i64:
58 ; ALL:       // %bb.0:
59 ; ALL-NEXT:    sdiv x8, x0, x1
60 ; ALL-NEXT:    msub x0, x8, x1, x0
61 ; ALL-NEXT:    str x8, [x2]
62 ; ALL-NEXT:    ret
63   %div = sdiv i64 %x, %y
64   store i64 %div, ptr %divdst, align 4
65   %t1 = mul i64 %div, %y
66   %t2 = sub i64 %x, %t1
67   ret i64 %t2
70 define <16 x i8> @vector_i128_i8(<16 x i8> %x, <16 x i8> %y, ptr %divdst) nounwind {
71 ; ALL-LABEL: vector_i128_i8:
72 ; ALL:       // %bb.0:
73 ; ALL-NEXT:    smov w8, v1.b[1]
74 ; ALL-NEXT:    smov w9, v0.b[1]
75 ; ALL-NEXT:    smov w10, v0.b[0]
76 ; ALL-NEXT:    smov w11, v0.b[2]
77 ; ALL-NEXT:    smov w12, v0.b[3]
78 ; ALL-NEXT:    smov w13, v0.b[4]
79 ; ALL-NEXT:    smov w14, v0.b[5]
80 ; ALL-NEXT:    smov w15, v0.b[6]
81 ; ALL-NEXT:    smov w16, v0.b[7]
82 ; ALL-NEXT:    smov w17, v0.b[8]
83 ; ALL-NEXT:    smov w18, v0.b[9]
84 ; ALL-NEXT:    sdiv w8, w9, w8
85 ; ALL-NEXT:    smov w9, v1.b[0]
86 ; ALL-NEXT:    sdiv w9, w10, w9
87 ; ALL-NEXT:    smov w10, v1.b[2]
88 ; ALL-NEXT:    sdiv w10, w11, w10
89 ; ALL-NEXT:    smov w11, v1.b[3]
90 ; ALL-NEXT:    fmov s2, w9
91 ; ALL-NEXT:    smov w9, v1.b[10]
92 ; ALL-NEXT:    mov v2.b[1], w8
93 ; ALL-NEXT:    sdiv w11, w12, w11
94 ; ALL-NEXT:    smov w12, v1.b[4]
95 ; ALL-NEXT:    mov v2.b[2], w10
96 ; ALL-NEXT:    smov w10, v0.b[10]
97 ; ALL-NEXT:    sdiv w12, w13, w12
98 ; ALL-NEXT:    smov w13, v1.b[5]
99 ; ALL-NEXT:    mov v2.b[3], w11
100 ; ALL-NEXT:    smov w11, v0.b[11]
101 ; ALL-NEXT:    sdiv w13, w14, w13
102 ; ALL-NEXT:    smov w14, v1.b[6]
103 ; ALL-NEXT:    mov v2.b[4], w12
104 ; ALL-NEXT:    smov w12, v0.b[12]
105 ; ALL-NEXT:    sdiv w14, w15, w14
106 ; ALL-NEXT:    smov w15, v1.b[7]
107 ; ALL-NEXT:    mov v2.b[5], w13
108 ; ALL-NEXT:    smov w13, v0.b[13]
109 ; ALL-NEXT:    sdiv w15, w16, w15
110 ; ALL-NEXT:    smov w16, v1.b[8]
111 ; ALL-NEXT:    mov v2.b[6], w14
112 ; ALL-NEXT:    sdiv w16, w17, w16
113 ; ALL-NEXT:    smov w17, v1.b[9]
114 ; ALL-NEXT:    mov v2.b[7], w15
115 ; ALL-NEXT:    sdiv w8, w18, w17
116 ; ALL-NEXT:    mov v2.b[8], w16
117 ; ALL-NEXT:    sdiv w9, w10, w9
118 ; ALL-NEXT:    smov w10, v1.b[11]
119 ; ALL-NEXT:    mov v2.b[9], w8
120 ; ALL-NEXT:    sdiv w10, w11, w10
121 ; ALL-NEXT:    smov w11, v1.b[12]
122 ; ALL-NEXT:    mov v2.b[10], w9
123 ; ALL-NEXT:    smov w9, v1.b[14]
124 ; ALL-NEXT:    sdiv w11, w12, w11
125 ; ALL-NEXT:    smov w12, v1.b[13]
126 ; ALL-NEXT:    mov v2.b[11], w10
127 ; ALL-NEXT:    smov w10, v1.b[15]
128 ; ALL-NEXT:    sdiv w8, w13, w12
129 ; ALL-NEXT:    smov w12, v0.b[14]
130 ; ALL-NEXT:    mov v2.b[12], w11
131 ; ALL-NEXT:    smov w11, v0.b[15]
132 ; ALL-NEXT:    sdiv w9, w12, w9
133 ; ALL-NEXT:    mov v2.b[13], w8
134 ; ALL-NEXT:    sdiv w8, w11, w10
135 ; ALL-NEXT:    mov v2.b[14], w9
136 ; ALL-NEXT:    mov v2.b[15], w8
137 ; ALL-NEXT:    mls v0.16b, v2.16b, v1.16b
138 ; ALL-NEXT:    str q2, [x0]
139 ; ALL-NEXT:    ret
140   %div = sdiv <16 x i8> %x, %y
141   store <16 x i8> %div, ptr %divdst, align 16
142   %t1 = mul <16 x i8> %div, %y
143   %t2 = sub <16 x i8> %x, %t1
144   ret <16 x i8> %t2
147 define <8 x i16> @vector_i128_i16(<8 x i16> %x, <8 x i16> %y, ptr %divdst) nounwind {
148 ; ALL-LABEL: vector_i128_i16:
149 ; ALL:       // %bb.0:
150 ; ALL-NEXT:    smov w8, v1.h[1]
151 ; ALL-NEXT:    smov w9, v0.h[1]
152 ; ALL-NEXT:    smov w10, v0.h[0]
153 ; ALL-NEXT:    smov w11, v0.h[2]
154 ; ALL-NEXT:    smov w12, v0.h[3]
155 ; ALL-NEXT:    smov w13, v0.h[4]
156 ; ALL-NEXT:    smov w14, v0.h[5]
157 ; ALL-NEXT:    sdiv w8, w9, w8
158 ; ALL-NEXT:    smov w9, v1.h[0]
159 ; ALL-NEXT:    sdiv w9, w10, w9
160 ; ALL-NEXT:    smov w10, v1.h[2]
161 ; ALL-NEXT:    sdiv w10, w11, w10
162 ; ALL-NEXT:    smov w11, v1.h[3]
163 ; ALL-NEXT:    fmov s2, w9
164 ; ALL-NEXT:    smov w9, v1.h[6]
165 ; ALL-NEXT:    mov v2.h[1], w8
166 ; ALL-NEXT:    sdiv w11, w12, w11
167 ; ALL-NEXT:    smov w12, v1.h[4]
168 ; ALL-NEXT:    mov v2.h[2], w10
169 ; ALL-NEXT:    smov w10, v0.h[6]
170 ; ALL-NEXT:    sdiv w12, w13, w12
171 ; ALL-NEXT:    smov w13, v1.h[5]
172 ; ALL-NEXT:    mov v2.h[3], w11
173 ; ALL-NEXT:    smov w11, v0.h[7]
174 ; ALL-NEXT:    sdiv w8, w14, w13
175 ; ALL-NEXT:    mov v2.h[4], w12
176 ; ALL-NEXT:    sdiv w9, w10, w9
177 ; ALL-NEXT:    smov w10, v1.h[7]
178 ; ALL-NEXT:    mov v2.h[5], w8
179 ; ALL-NEXT:    sdiv w8, w11, w10
180 ; ALL-NEXT:    mov v2.h[6], w9
181 ; ALL-NEXT:    mov v2.h[7], w8
182 ; ALL-NEXT:    mls v0.8h, v2.8h, v1.8h
183 ; ALL-NEXT:    str q2, [x0]
184 ; ALL-NEXT:    ret
185   %div = sdiv <8 x i16> %x, %y
186   store <8 x i16> %div, ptr %divdst, align 16
187   %t1 = mul <8 x i16> %div, %y
188   %t2 = sub <8 x i16> %x, %t1
189   ret <8 x i16> %t2
192 define <4 x i32> @vector_i128_i32(<4 x i32> %x, <4 x i32> %y, ptr %divdst) nounwind {
193 ; ALL-LABEL: vector_i128_i32:
194 ; ALL:       // %bb.0:
195 ; ALL-NEXT:    mov w8, v1.s[1]
196 ; ALL-NEXT:    mov w9, v0.s[1]
197 ; ALL-NEXT:    fmov w10, s0
198 ; ALL-NEXT:    mov w11, v0.s[2]
199 ; ALL-NEXT:    mov w12, v0.s[3]
200 ; ALL-NEXT:    sdiv w8, w9, w8
201 ; ALL-NEXT:    fmov w9, s1
202 ; ALL-NEXT:    sdiv w9, w10, w9
203 ; ALL-NEXT:    mov w10, v1.s[2]
204 ; ALL-NEXT:    sdiv w10, w11, w10
205 ; ALL-NEXT:    mov w11, v1.s[3]
206 ; ALL-NEXT:    fmov s2, w9
207 ; ALL-NEXT:    mov v2.s[1], w8
208 ; ALL-NEXT:    sdiv w8, w12, w11
209 ; ALL-NEXT:    mov v2.s[2], w10
210 ; ALL-NEXT:    mov v2.s[3], w8
211 ; ALL-NEXT:    mls v0.4s, v2.4s, v1.4s
212 ; ALL-NEXT:    str q2, [x0]
213 ; ALL-NEXT:    ret
214   %div = sdiv <4 x i32> %x, %y
215   store <4 x i32> %div, ptr %divdst, align 16
216   %t1 = mul <4 x i32> %div, %y
217   %t2 = sub <4 x i32> %x, %t1
218   ret <4 x i32> %t2
221 define <2 x i64> @vector_i128_i64(<2 x i64> %x, <2 x i64> %y, ptr %divdst) nounwind {
222 ; ALL-LABEL: vector_i128_i64:
223 ; ALL:       // %bb.0:
224 ; ALL-NEXT:    fmov x8, d1
225 ; ALL-NEXT:    fmov x9, d0
226 ; ALL-NEXT:    mov x10, v1.d[1]
227 ; ALL-NEXT:    mov x11, v0.d[1]
228 ; ALL-NEXT:    sdiv x9, x9, x8
229 ; ALL-NEXT:    sdiv x11, x11, x10
230 ; ALL-NEXT:    mul x8, x9, x8
231 ; ALL-NEXT:    fmov d2, x9
232 ; ALL-NEXT:    fmov d1, x8
233 ; ALL-NEXT:    mul x10, x11, x10
234 ; ALL-NEXT:    mov v2.d[1], x11
235 ; ALL-NEXT:    str q2, [x0]
236 ; ALL-NEXT:    mov v1.d[1], x10
237 ; ALL-NEXT:    sub v0.2d, v0.2d, v1.2d
238 ; ALL-NEXT:    ret
239   %div = sdiv <2 x i64> %x, %y
240   store <2 x i64> %div, ptr %divdst, align 16
241   %t1 = mul <2 x i64> %div, %y
242   %t2 = sub <2 x i64> %x, %t1
243   ret <2 x i64> %t2
246 ; Special tests.
248 define i32 @scalar_i32_commutative(i32 %x, ptr %ysrc, ptr %divdst) nounwind {
249 ; ALL-LABEL: scalar_i32_commutative:
250 ; ALL:       // %bb.0:
251 ; ALL-NEXT:    ldr w8, [x1]
252 ; ALL-NEXT:    sdiv w9, w0, w8
253 ; ALL-NEXT:    msub w0, w8, w9, w0
254 ; ALL-NEXT:    str w9, [x2]
255 ; ALL-NEXT:    ret
256   %y = load i32, ptr %ysrc, align 4
257   %div = sdiv i32 %x, %y
258   store i32 %div, ptr %divdst, align 4
259   %t1 = mul i32 %y, %div ; commutative
260   %t2 = sub i32 %x, %t1
261   ret i32 %t2
264 ; We do not care about extra uses.
265 define i32 @extrause(i32 %x, i32 %y, ptr %divdst, ptr %t1dst) nounwind {
266 ; ALL-LABEL: extrause:
267 ; ALL:       // %bb.0:
268 ; ALL-NEXT:    sdiv w8, w0, w1
269 ; ALL-NEXT:    mul w9, w8, w1
270 ; ALL-NEXT:    str w8, [x2]
271 ; ALL-NEXT:    sub w0, w0, w9
272 ; ALL-NEXT:    str w9, [x3]
273 ; ALL-NEXT:    ret
274   %div = sdiv i32 %x, %y
275   store i32 %div, ptr %divdst, align 4
276   %t1 = mul i32 %div, %y
277   store i32 %t1, ptr %t1dst, align 4
278   %t2 = sub i32 %x, %t1
279   ret i32 %t2
282 ; 'rem' should appear next to 'div'.
283 define i32 @multiple_bb(i32 %x, i32 %y, ptr %divdst, i1 zeroext %store_srem, ptr %sremdst) nounwind {
284 ; ALL-LABEL: multiple_bb:
285 ; ALL:       // %bb.0:
286 ; ALL-NEXT:    mov w8, w0
287 ; ALL-NEXT:    sdiv w0, w0, w1
288 ; ALL-NEXT:    str w0, [x2]
289 ; ALL-NEXT:    cbz w3, .LBB10_2
290 ; ALL-NEXT:  // %bb.1: // %do_srem
291 ; ALL-NEXT:    msub w8, w0, w1, w8
292 ; ALL-NEXT:    str w8, [x4]
293 ; ALL-NEXT:  .LBB10_2: // %end
294 ; ALL-NEXT:    ret
295   %div = sdiv i32 %x, %y
296   store i32 %div, ptr %divdst, align 4
297   br i1 %store_srem, label %do_srem, label %end
298 do_srem:
299   %t1 = mul i32 %div, %y
300   %t2 = sub i32 %x, %t1
301   store i32 %t2, ptr %sremdst, align 4
302   br label %end
303 end:
304   ret i32 %div
307 define i32 @negative_different_x(i32 %x0, i32 %x1, i32 %y, ptr %divdst) nounwind {
308 ; ALL-LABEL: negative_different_x:
309 ; ALL:       // %bb.0:
310 ; ALL-NEXT:    sdiv w8, w0, w2
311 ; ALL-NEXT:    msub w0, w8, w2, w1
312 ; ALL-NEXT:    str w8, [x3]
313 ; ALL-NEXT:    ret
314   %div = sdiv i32 %x0, %y ; not %x1
315   store i32 %div, ptr %divdst, align 4
316   %t1 = mul i32 %div, %y
317   %t2 = sub i32 %x1, %t1 ; not %x0
318   ret i32 %t2