1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2 ; RUN: llc -verify-machineinstrs -csky-no-aliases -mattr=+2e3 < %s -mtriple=csky | FileCheck %s
3 ; RUN: llc -verify-machineinstrs -csky-no-aliases < %s -mtriple=csky | FileCheck %s --check-prefix=GENERIC
5 ;; This file shows if a multiplication can be simplified to an addition/subtraction
8 define i32 @mul_i32_4097(i32 %x) {
9 ; CHECK-LABEL: mul_i32_4097:
10 ; CHECK: # %bb.0: # %entry
11 ; CHECK-NEXT: lsli16 a1, a0, 12
12 ; CHECK-NEXT: addu16 a0, a1
15 ; GENERIC-LABEL: mul_i32_4097:
16 ; GENERIC: # %bb.0: # %entry
17 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
18 ; GENERIC-NEXT: subi16 sp, sp, 4
19 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
20 ; GENERIC-NEXT: lsli16 a1, a0, 12
21 ; GENERIC-NEXT: addu16 a0, a1, a0
22 ; GENERIC-NEXT: addi16 sp, sp, 4
25 %y = mul nsw i32 %x, 4097
29 define i32 @mul_i32_4095(i32 %x) {
30 ; CHECK-LABEL: mul_i32_4095:
31 ; CHECK: # %bb.0: # %entry
32 ; CHECK-NEXT: lsli16 a1, a0, 12
33 ; CHECK-NEXT: subu16 a0, a1, a0
36 ; GENERIC-LABEL: mul_i32_4095:
37 ; GENERIC: # %bb.0: # %entry
38 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
39 ; GENERIC-NEXT: subi16 sp, sp, 4
40 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
41 ; GENERIC-NEXT: lsli16 a1, a0, 12
42 ; GENERIC-NEXT: subu16 a0, a1, a0
43 ; GENERIC-NEXT: addi16 sp, sp, 4
46 %y = mul nsw i32 %x, 4095
50 define i32 @mul_i32_minus_4095(i32 %x) {
51 ; CHECK-LABEL: mul_i32_minus_4095:
52 ; CHECK: # %bb.0: # %entry
53 ; CHECK-NEXT: lsli16 a1, a0, 12
54 ; CHECK-NEXT: subu16 a0, a1
57 ; GENERIC-LABEL: mul_i32_minus_4095:
58 ; GENERIC: # %bb.0: # %entry
59 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
60 ; GENERIC-NEXT: subi16 sp, sp, 4
61 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
62 ; GENERIC-NEXT: lsli16 a1, a0, 12
63 ; GENERIC-NEXT: subu16 a0, a0, a1
64 ; GENERIC-NEXT: addi16 sp, sp, 4
67 %y = mul nsw i32 %x, -4095
71 define i32 @mul_i32_131074(i32 %x) {
72 ; CHECK-LABEL: mul_i32_131074:
73 ; CHECK: # %bb.0: # %entry
74 ; CHECK-NEXT: lsli16 a1, a0, 17
75 ; CHECK-NEXT: ixh32 a0, a1, a0
78 ; GENERIC-LABEL: mul_i32_131074:
79 ; GENERIC: # %bb.0: # %entry
80 ; GENERIC-NEXT: subi16 sp, sp, 4
81 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
82 ; GENERIC-NEXT: st16.w l0, (sp, 0) # 4-byte Folded Spill
83 ; GENERIC-NEXT: .cfi_offset l0, -4
84 ; GENERIC-NEXT: subi16 sp, sp, 4
85 ; GENERIC-NEXT: .cfi_def_cfa_offset 8
86 ; GENERIC-NEXT: movi16 a1, 0
87 ; GENERIC-NEXT: lsli16 a2, a1, 24
88 ; GENERIC-NEXT: movi16 a3, 2
89 ; GENERIC-NEXT: lsli16 l0, a3, 16
90 ; GENERIC-NEXT: or16 l0, a2
91 ; GENERIC-NEXT: lsli16 a1, a1, 8
92 ; GENERIC-NEXT: or16 a1, l0
93 ; GENERIC-NEXT: or16 a1, a3
94 ; GENERIC-NEXT: mult16 a0, a1
95 ; GENERIC-NEXT: addi16 sp, sp, 4
96 ; GENERIC-NEXT: ld16.w l0, (sp, 0) # 4-byte Folded Reload
97 ; GENERIC-NEXT: addi16 sp, sp, 4
100 %y = mul nsw i32 %x, 131074
104 define i32 @mul_i32_131076(i32 %x) {
105 ; CHECK-LABEL: mul_i32_131076:
106 ; CHECK: # %bb.0: # %entry
107 ; CHECK-NEXT: lsli16 a1, a0, 17
108 ; CHECK-NEXT: ixw32 a0, a1, a0
111 ; GENERIC-LABEL: mul_i32_131076:
112 ; GENERIC: # %bb.0: # %entry
113 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
114 ; GENERIC-NEXT: subi16 sp, sp, 4
115 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
116 ; GENERIC-NEXT: movi16 a1, 0
117 ; GENERIC-NEXT: lsli16 a2, a1, 24
118 ; GENERIC-NEXT: movi16 a3, 2
119 ; GENERIC-NEXT: lsli16 a3, a3, 16
120 ; GENERIC-NEXT: or16 a3, a2
121 ; GENERIC-NEXT: lsli16 a1, a1, 8
122 ; GENERIC-NEXT: or16 a1, a3
123 ; GENERIC-NEXT: movi16 a2, 4
124 ; GENERIC-NEXT: or16 a2, a1
125 ; GENERIC-NEXT: mult16 a0, a2
126 ; GENERIC-NEXT: addi16 sp, sp, 4
127 ; GENERIC-NEXT: rts16
129 %y = mul nsw i32 %x, 131076
133 define i32 @mul_i32_131080(i32 %x) {
134 ; CHECK-LABEL: mul_i32_131080:
135 ; CHECK: # %bb.0: # %entry
136 ; CHECK-NEXT: lsli16 a1, a0, 17
137 ; CHECK-NEXT: ixd32 a0, a1, a0
140 ; GENERIC-LABEL: mul_i32_131080:
141 ; GENERIC: # %bb.0: # %entry
142 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
143 ; GENERIC-NEXT: subi16 sp, sp, 4
144 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
145 ; GENERIC-NEXT: movi16 a1, 0
146 ; GENERIC-NEXT: lsli16 a2, a1, 24
147 ; GENERIC-NEXT: movi16 a3, 2
148 ; GENERIC-NEXT: lsli16 a3, a3, 16
149 ; GENERIC-NEXT: or16 a3, a2
150 ; GENERIC-NEXT: lsli16 a1, a1, 8
151 ; GENERIC-NEXT: or16 a1, a3
152 ; GENERIC-NEXT: movi16 a2, 8
153 ; GENERIC-NEXT: or16 a2, a1
154 ; GENERIC-NEXT: mult16 a0, a2
155 ; GENERIC-NEXT: addi16 sp, sp, 4
156 ; GENERIC-NEXT: rts16
158 %y = mul nsw i32 %x, 131080
162 define i16 @mul_i16_4097(i16 %x) {
163 ; CHECK-LABEL: mul_i16_4097:
164 ; CHECK: # %bb.0: # %entry
165 ; CHECK-NEXT: lsli16 a1, a0, 12
166 ; CHECK-NEXT: addu16 a0, a1
169 ; GENERIC-LABEL: mul_i16_4097:
170 ; GENERIC: # %bb.0: # %entry
171 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
172 ; GENERIC-NEXT: subi16 sp, sp, 4
173 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
174 ; GENERIC-NEXT: lsli16 a1, a0, 12
175 ; GENERIC-NEXT: addu16 a0, a1, a0
176 ; GENERIC-NEXT: addi16 sp, sp, 4
177 ; GENERIC-NEXT: rts16
179 %y = mul nsw i16 %x, 4097
183 define i16 @mul_i16_4095(i16 %x) {
184 ; CHECK-LABEL: mul_i16_4095:
185 ; CHECK: # %bb.0: # %entry
186 ; CHECK-NEXT: lsli16 a1, a0, 12
187 ; CHECK-NEXT: subu16 a0, a1, a0
190 ; GENERIC-LABEL: mul_i16_4095:
191 ; GENERIC: # %bb.0: # %entry
192 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
193 ; GENERIC-NEXT: subi16 sp, sp, 4
194 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
195 ; GENERIC-NEXT: lsli16 a1, a0, 12
196 ; GENERIC-NEXT: subu16 a0, a1, a0
197 ; GENERIC-NEXT: addi16 sp, sp, 4
198 ; GENERIC-NEXT: rts16
200 %y = mul nsw i16 %x, 4095
204 define i16 @mul_i16_minus_4095(i16 %x) {
205 ; CHECK-LABEL: mul_i16_minus_4095:
206 ; CHECK: # %bb.0: # %entry
207 ; CHECK-NEXT: lsli16 a1, a0, 12
208 ; CHECK-NEXT: subu16 a0, a1
211 ; GENERIC-LABEL: mul_i16_minus_4095:
212 ; GENERIC: # %bb.0: # %entry
213 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
214 ; GENERIC-NEXT: subi16 sp, sp, 4
215 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
216 ; GENERIC-NEXT: lsli16 a1, a0, 12
217 ; GENERIC-NEXT: subu16 a0, a0, a1
218 ; GENERIC-NEXT: addi16 sp, sp, 4
219 ; GENERIC-NEXT: rts16
221 %y = mul nsw i16 %x, -4095
225 define i8 @mul_i8_65(i8 %x) {
226 ; CHECK-LABEL: mul_i8_65:
227 ; CHECK: # %bb.0: # %entry
228 ; CHECK-NEXT: lsli16 a1, a0, 6
229 ; CHECK-NEXT: addu16 a0, a1
232 ; GENERIC-LABEL: mul_i8_65:
233 ; GENERIC: # %bb.0: # %entry
234 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
235 ; GENERIC-NEXT: subi16 sp, sp, 4
236 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
237 ; GENERIC-NEXT: lsli16 a1, a0, 6
238 ; GENERIC-NEXT: addu16 a0, a1, a0
239 ; GENERIC-NEXT: addi16 sp, sp, 4
240 ; GENERIC-NEXT: rts16
242 %y = mul nsw i8 %x, 65
246 define i8 @mul_i8_63(i8 %x) {
247 ; CHECK-LABEL: mul_i8_63:
248 ; CHECK: # %bb.0: # %entry
249 ; CHECK-NEXT: lsli16 a1, a0, 6
250 ; CHECK-NEXT: subu16 a0, a1, a0
253 ; GENERIC-LABEL: mul_i8_63:
254 ; GENERIC: # %bb.0: # %entry
255 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
256 ; GENERIC-NEXT: subi16 sp, sp, 4
257 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
258 ; GENERIC-NEXT: lsli16 a1, a0, 6
259 ; GENERIC-NEXT: subu16 a0, a1, a0
260 ; GENERIC-NEXT: addi16 sp, sp, 4
261 ; GENERIC-NEXT: rts16
263 %y = mul nsw i8 %x, 63
267 define i8 @mul_i8_minus_63(i8 %x) {
268 ; CHECK-LABEL: mul_i8_minus_63:
269 ; CHECK: # %bb.0: # %entry
270 ; CHECK-NEXT: lsli16 a1, a0, 6
271 ; CHECK-NEXT: subu16 a0, a1
274 ; GENERIC-LABEL: mul_i8_minus_63:
275 ; GENERIC: # %bb.0: # %entry
276 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
277 ; GENERIC-NEXT: subi16 sp, sp, 4
278 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
279 ; GENERIC-NEXT: lsli16 a1, a0, 6
280 ; GENERIC-NEXT: subu16 a0, a0, a1
281 ; GENERIC-NEXT: addi16 sp, sp, 4
282 ; GENERIC-NEXT: rts16
284 %y = mul nsw i8 %x, -63
288 define i32 @mul_i32_minus_4097(i32 %x) {
289 ; CHECK-LABEL: mul_i32_minus_4097:
290 ; CHECK: # %bb.0: # %entry
291 ; CHECK-NEXT: movih32 a1, 65535
292 ; CHECK-NEXT: ori32 a1, a1, 61439
293 ; CHECK-NEXT: mult16 a0, a1
296 ; GENERIC-LABEL: mul_i32_minus_4097:
297 ; GENERIC: # %bb.0: # %entry
298 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
299 ; GENERIC-NEXT: subi16 sp, sp, 4
300 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
301 ; GENERIC-NEXT: lsli16 a1, a0, 12
302 ; GENERIC-NEXT: addu16 a0, a1, a0
303 ; GENERIC-NEXT: movi16 a1, 0
304 ; GENERIC-NEXT: subu16 a0, a1, a0
305 ; GENERIC-NEXT: addi16 sp, sp, 4
306 ; GENERIC-NEXT: rts16
308 %y = mul nsw i32 %x, -4097
312 define i16 @mul_i16_minus_4097(i16 %x) {
313 ; CHECK-LABEL: mul_i16_minus_4097:
314 ; CHECK: # %bb.0: # %entry
315 ; CHECK-NEXT: movih32 a1, 65535
316 ; CHECK-NEXT: ori32 a1, a1, 61439
317 ; CHECK-NEXT: mult16 a0, a1
320 ; GENERIC-LABEL: mul_i16_minus_4097:
321 ; GENERIC: # %bb.0: # %entry
322 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
323 ; GENERIC-NEXT: subi16 sp, sp, 4
324 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
325 ; GENERIC-NEXT: lsli16 a1, a0, 12
326 ; GENERIC-NEXT: addu16 a0, a1, a0
327 ; GENERIC-NEXT: movi16 a1, 0
328 ; GENERIC-NEXT: subu16 a0, a1, a0
329 ; GENERIC-NEXT: addi16 sp, sp, 4
330 ; GENERIC-NEXT: rts16
332 %y = mul nsw i16 %x, -4097
336 define i8 @mul_i8_minus_65(i8 %x) {
337 ; CHECK-LABEL: mul_i8_minus_65:
338 ; CHECK: # %bb.0: # %entry
339 ; CHECK-NEXT: movih32 a1, 65535
340 ; CHECK-NEXT: ori32 a1, a1, 65471
341 ; CHECK-NEXT: mult16 a0, a1
344 ; GENERIC-LABEL: mul_i8_minus_65:
345 ; GENERIC: # %bb.0: # %entry
346 ; GENERIC-NEXT: .cfi_def_cfa_offset 0
347 ; GENERIC-NEXT: subi16 sp, sp, 4
348 ; GENERIC-NEXT: .cfi_def_cfa_offset 4
349 ; GENERIC-NEXT: lsli16 a1, a0, 6
350 ; GENERIC-NEXT: addu16 a0, a1, a0
351 ; GENERIC-NEXT: movi16 a1, 0
352 ; GENERIC-NEXT: subu16 a0, a1, a0
353 ; GENERIC-NEXT: addi16 sp, sp, 4
354 ; GENERIC-NEXT: rts16
356 %y = mul nsw i8 %x, -65
360 ;; This case can not be optimized, due to the data type exceeds.
361 define i64 @mul_i64_4097(i64 %x) {
362 ; CHECK-LABEL: mul_i64_4097:
363 ; CHECK: # %bb.0: # %entry
364 ; CHECK-NEXT: subi16 sp, sp, 4
365 ; CHECK-NEXT: .cfi_def_cfa_offset 4
366 ; CHECK-NEXT: st32.w lr, (sp, 0) # 4-byte Folded Spill
367 ; CHECK-NEXT: .cfi_offset lr, -4
368 ; CHECK-NEXT: .cfi_def_cfa_offset 4
369 ; CHECK-NEXT: movi32 a2, 4097
370 ; CHECK-NEXT: movi16 a3, 0
371 ; CHECK-NEXT: jsri32 [.LCPI15_0]
372 ; CHECK-NEXT: ld32.w lr, (sp, 0) # 4-byte Folded Reload
373 ; CHECK-NEXT: addi16 sp, sp, 4
375 ; CHECK-NEXT: .p2align 1
376 ; CHECK-NEXT: # %bb.1:
377 ; CHECK-NEXT: .p2align 2, 0x0
378 ; CHECK-NEXT: .LCPI15_0:
379 ; CHECK-NEXT: .long __muldi3
381 ; GENERIC-LABEL: mul_i64_4097:
382 ; GENERIC: # %bb.0: # %entry
383 ; GENERIC-NEXT: subi16 sp, sp, 8
384 ; GENERIC-NEXT: .cfi_def_cfa_offset 8
385 ; GENERIC-NEXT: st16.w l0, (sp, 4) # 4-byte Folded Spill
386 ; GENERIC-NEXT: st32.w lr, (sp, 0) # 4-byte Folded Spill
387 ; GENERIC-NEXT: .cfi_offset l0, -4
388 ; GENERIC-NEXT: .cfi_offset lr, -8
389 ; GENERIC-NEXT: subi16 sp, sp, 4
390 ; GENERIC-NEXT: .cfi_def_cfa_offset 12
391 ; GENERIC-NEXT: movi16 a2, 0
392 ; GENERIC-NEXT: lsli16 a3, a2, 24
393 ; GENERIC-NEXT: lsli16 a2, a2, 16
394 ; GENERIC-NEXT: or16 a2, a3
395 ; GENERIC-NEXT: movi16 a3, 16
396 ; GENERIC-NEXT: lsli16 a3, a3, 8
397 ; GENERIC-NEXT: or16 a3, a2
398 ; GENERIC-NEXT: movi16 a2, 1
399 ; GENERIC-NEXT: or16 a2, a3
400 ; GENERIC-NEXT: lrw32 l0, [.LCPI15_0]
401 ; GENERIC-NEXT: movi16 a3, 0
402 ; GENERIC-NEXT: jsr16 l0
403 ; GENERIC-NEXT: addi16 sp, sp, 4
404 ; GENERIC-NEXT: ld32.w lr, (sp, 0) # 4-byte Folded Reload
405 ; GENERIC-NEXT: ld16.w l0, (sp, 4) # 4-byte Folded Reload
406 ; GENERIC-NEXT: addi16 sp, sp, 8
407 ; GENERIC-NEXT: rts16
408 ; GENERIC-NEXT: .p2align 1
409 ; GENERIC-NEXT: # %bb.1:
410 ; GENERIC-NEXT: .p2align 2, 0x0
411 ; GENERIC-NEXT: .LCPI15_0:
412 ; GENERIC-NEXT: .long __muldi3
414 %y = mul nsw i64 %x, 4097