1; RUN: llc < %s -mtriple=aarch64-eabi | FileCheck %s
2
3; Convert mul x, pow2 to shift.
4; Convert mul x, pow2 +/- 1 to shift + add/sub.
5; Convert mul x, (pow2 + 1) * pow2 to shift + add + shift.
6; Lowering other positive constants are not supported yet.
7
8define i32 @test2(i32 %x) {
9; CHECK-LABEL: test2
10; CHECK: lsl w0, w0, #1
11
12  %mul = shl nsw i32 %x, 1
13  ret i32 %mul
14}
15
16define i32 @test3(i32 %x) {
17; CHECK-LABEL: test3
18; CHECK: add w0, w0, w0, lsl #1
19
20  %mul = mul nsw i32 %x, 3
21  ret i32 %mul
22}
23
24define i32 @test4(i32 %x) {
25; CHECK-LABEL: test4
26; CHECK: lsl w0, w0, #2
27
28  %mul = shl nsw i32 %x, 2
29  ret i32 %mul
30}
31
32define i32 @test5(i32 %x) {
33; CHECK-LABEL: test5
34; CHECK: add w0, w0, w0, lsl #2
35
36
37  %mul = mul nsw i32 %x, 5
38  ret i32 %mul
39}
40
41define i32 @test6_32b(i32 %x) {
42; CHECK-LABEL: test6
43; CHECK: add {{w[0-9]+}}, w0, w0, lsl #1
44; CHECK: lsl w0, {{w[0-9]+}}, #1
45
46  %mul = mul nsw i32 %x, 6
47  ret i32 %mul
48}
49
50define i64 @test6_64b(i64 %x) {
51; CHECK-LABEL: test6_64b
52; CHECK: add {{x[0-9]+}}, x0, x0, lsl #1
53; CHECK: lsl x0, {{x[0-9]+}}, #1
54
55  %mul = mul nsw i64 %x, 6
56  ret i64 %mul
57}
58
59; mul that appears together with add, sub, s(z)ext is not supported to be
60; converted to the combination of lsl, add/sub yet.
61define i64 @test6_umull(i32 %x) {
62; CHECK-LABEL: test6_umull
63; CHECK: umull x0, w0, {{w[0-9]+}}
64
65  %ext = zext i32 %x to i64
66  %mul = mul nsw i64 %ext, 6
67  ret i64 %mul
68}
69
70define i64 @test6_smull(i32 %x) {
71; CHECK-LABEL: test6_smull
72; CHECK: smull x0, w0, {{w[0-9]+}}
73
74  %ext = sext i32 %x to i64
75  %mul = mul nsw i64 %ext, 6
76  ret i64 %mul
77}
78
79define i32 @test6_madd(i32 %x, i32 %y) {
80; CHECK-LABEL: test6_madd
81; CHECK: madd w0, w0, {{w[0-9]+}}, w1
82
83  %mul = mul nsw i32 %x, 6
84  %add = add i32 %mul, %y
85  ret i32 %add
86}
87
88define i32 @test6_msub(i32 %x, i32 %y) {
89; CHECK-LABEL: test6_msub
90; CHECK: msub w0, w0, {{w[0-9]+}}, w1
91
92  %mul = mul nsw i32 %x, 6
93  %sub = sub i32 %y, %mul
94  ret i32 %sub
95}
96
97define i64 @test6_umaddl(i32 %x, i64 %y) {
98; CHECK-LABEL: test6_umaddl
99; CHECK: umaddl x0, w0, {{w[0-9]+}}, x1
100
101  %ext = zext i32 %x to i64
102  %mul = mul nsw i64 %ext, 6
103  %add = add i64 %mul, %y
104  ret i64 %add
105}
106
107define i64 @test6_smaddl(i32 %x, i64 %y) {
108; CHECK-LABEL: test6_smaddl
109; CHECK: smaddl x0, w0, {{w[0-9]+}}, x1
110
111  %ext = sext i32 %x to i64
112  %mul = mul nsw i64 %ext, 6
113  %add = add i64 %mul, %y
114  ret i64 %add
115}
116
117define i64 @test6_umsubl(i32 %x, i64 %y) {
118; CHECK-LABEL: test6_umsubl
119; CHECK: umsubl x0, w0, {{w[0-9]+}}, x1
120
121  %ext = zext i32 %x to i64
122  %mul = mul nsw i64 %ext, 6
123  %sub = sub i64 %y, %mul
124  ret i64 %sub
125}
126
127define i64 @test6_smsubl(i32 %x, i64 %y) {
128; CHECK-LABEL: test6_smsubl
129; CHECK: smsubl x0, w0, {{w[0-9]+}}, x1
130
131  %ext = sext i32 %x to i64
132  %mul = mul nsw i64 %ext, 6
133  %sub = sub i64 %y, %mul
134  ret i64 %sub
135}
136
137define i64 @test6_umnegl(i32 %x) {
138; CHECK-LABEL: test6_umnegl
139; CHECK: umnegl x0, w0, {{w[0-9]+}}
140
141  %ext = zext i32 %x to i64
142  %mul = mul nsw i64 %ext, 6
143  %sub = sub i64 0, %mul
144  ret i64 %sub
145}
146
147define i64 @test6_smnegl(i32 %x) {
148; CHECK-LABEL: test6_smnegl
149; CHECK: smnegl x0, w0, {{w[0-9]+}}
150
151  %ext = sext i32 %x to i64
152  %mul = mul nsw i64 %ext, 6
153  %sub = sub i64 0, %mul
154  ret i64 %sub
155}
156
157define i32 @test7(i32 %x) {
158; CHECK-LABEL: test7
159; CHECK: lsl {{w[0-9]+}}, w0, #3
160; CHECK: sub w0, {{w[0-9]+}}, w0
161
162  %mul = mul nsw i32 %x, 7
163  ret i32 %mul
164}
165
166define i32 @test8(i32 %x) {
167; CHECK-LABEL: test8
168; CHECK: lsl w0, w0, #3
169
170  %mul = shl nsw i32 %x, 3
171  ret i32 %mul
172}
173
174define i32 @test9(i32 %x) {
175; CHECK-LABEL: test9
176; CHECK: add w0, w0, w0, lsl #3
177
178  %mul = mul nsw i32 %x, 9
179  ret i32 %mul
180}
181
182define i32 @test10(i32 %x) {
183; CHECK-LABEL: test10
184; CHECK: add {{w[0-9]+}}, w0, w0, lsl #2
185; CHECK: lsl w0, {{w[0-9]+}}, #1
186
187  %mul = mul nsw i32 %x, 10
188  ret i32 %mul
189}
190
191define i32 @test11(i32 %x) {
192; CHECK-LABEL: test11
193; CHECK: mul w0, w0, {{w[0-9]+}}
194
195  %mul = mul nsw i32 %x, 11
196  ret i32 %mul
197}
198
199define i32 @test12(i32 %x) {
200; CHECK-LABEL: test12
201; CHECK: add {{w[0-9]+}}, w0, w0, lsl #1
202; CHECK: lsl w0, {{w[0-9]+}}, #2
203
204  %mul = mul nsw i32 %x, 12
205  ret i32 %mul
206}
207
208define i32 @test13(i32 %x) {
209; CHECK-LABEL: test13
210; CHECK: mul w0, w0, {{w[0-9]+}}
211
212  %mul = mul nsw i32 %x, 13
213  ret i32 %mul
214}
215
216define i32 @test14(i32 %x) {
217; CHECK-LABEL: test14
218; CHECK: mul w0, w0, {{w[0-9]+}}
219
220  %mul = mul nsw i32 %x, 14
221  ret i32 %mul
222}
223
224define i32 @test15(i32 %x) {
225; CHECK-LABEL: test15
226; CHECK: lsl {{w[0-9]+}}, w0, #4
227; CHECK: sub w0, {{w[0-9]+}}, w0
228
229  %mul = mul nsw i32 %x, 15
230  ret i32 %mul
231}
232
233define i32 @test16(i32 %x) {
234; CHECK-LABEL: test16
235; CHECK: lsl w0, w0, #4
236
237  %mul = mul nsw i32 %x, 16
238  ret i32 %mul
239}
240
241; Convert mul x, -pow2 to shift.
242; Convert mul x, -(pow2 +/- 1) to shift + add/sub.
243; Lowering other negative constants are not supported yet.
244
245define i32 @ntest2(i32 %x) {
246; CHECK-LABEL: ntest2
247; CHECK: neg w0, w0, lsl #1
248
249  %mul = mul nsw i32 %x, -2
250  ret i32 %mul
251}
252
253define i32 @ntest3(i32 %x) {
254; CHECK-LABEL: ntest3
255; CHECK: sub w0, w0, w0, lsl #2
256
257  %mul = mul nsw i32 %x, -3
258  ret i32 %mul
259}
260
261define i32 @ntest4(i32 %x) {
262; CHECK-LABEL: ntest4
263; CHECK:neg w0, w0, lsl #2
264
265  %mul = mul nsw i32 %x, -4
266  ret i32 %mul
267}
268
269define i32 @ntest5(i32 %x) {
270; CHECK-LABEL: ntest5
271; CHECK: add {{w[0-9]+}}, w0, w0, lsl #2
272; CHECK: neg w0, {{w[0-9]+}}
273  %mul = mul nsw i32 %x, -5
274  ret i32 %mul
275}
276
277define i32 @ntest6(i32 %x) {
278; CHECK-LABEL: ntest6
279; CHECK: mul w0, w0, {{w[0-9]+}}
280
281  %mul = mul nsw i32 %x, -6
282  ret i32 %mul
283}
284
285define i32 @ntest7(i32 %x) {
286; CHECK-LABEL: ntest7
287; CHECK: sub w0, w0, w0, lsl #3
288
289  %mul = mul nsw i32 %x, -7
290  ret i32 %mul
291}
292
293define i32 @ntest8(i32 %x) {
294; CHECK-LABEL: ntest8
295; CHECK: neg w0, w0, lsl #3
296
297  %mul = mul nsw i32 %x, -8
298  ret i32 %mul
299}
300
301define i32 @ntest9(i32 %x) {
302; CHECK-LABEL: ntest9
303; CHECK: add {{w[0-9]+}}, w0, w0, lsl #3
304; CHECK: neg w0, {{w[0-9]+}}
305
306  %mul = mul nsw i32 %x, -9
307  ret i32 %mul
308}
309
310define i32 @ntest10(i32 %x) {
311; CHECK-LABEL: ntest10
312; CHECK: mul w0, w0, {{w[0-9]+}}
313
314  %mul = mul nsw i32 %x, -10
315  ret i32 %mul
316}
317
318define i32 @ntest11(i32 %x) {
319; CHECK-LABEL: ntest11
320; CHECK: mul w0, w0, {{w[0-9]+}}
321
322  %mul = mul nsw i32 %x, -11
323  ret i32 %mul
324}
325
326define i32 @ntest12(i32 %x) {
327; CHECK-LABEL: ntest12
328; CHECK: mul w0, w0, {{w[0-9]+}}
329
330  %mul = mul nsw i32 %x, -12
331  ret i32 %mul
332}
333
334define i32 @ntest13(i32 %x) {
335; CHECK-LABEL: ntest13
336; CHECK: mul w0, w0, {{w[0-9]+}}
337  %mul = mul nsw i32 %x, -13
338  ret i32 %mul
339}
340
341define i32 @ntest14(i32 %x) {
342; CHECK-LABEL: ntest14
343; CHECK: mul w0, w0, {{w[0-9]+}}
344
345  %mul = mul nsw i32 %x, -14
346  ret i32 %mul
347}
348
349define i32 @ntest15(i32 %x) {
350; CHECK-LABEL: ntest15
351; CHECK: sub w0, w0, w0, lsl #4
352
353  %mul = mul nsw i32 %x, -15
354  ret i32 %mul
355}
356
357define i32 @ntest16(i32 %x) {
358; CHECK-LABEL: ntest16
359; CHECK: neg w0, w0, lsl #4
360
361  %mul = mul nsw i32 %x, -16
362  ret i32 %mul
363}
364