xref: /llvm-project/llvm/test/CodeGen/CSKY/mul-imm.ll (revision 57c6fe273f237cca8c045a8c02266117c4ff72fb)
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
4
5;; This file shows if a multiplication can be simplified to an addition/subtraction
6;; of left shifts.
7
8define 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
13; CHECK-NEXT:    rts16
14;
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
23; GENERIC-NEXT:    rts16
24entry:
25  %y = mul nsw i32 %x, 4097
26  ret i32 %y
27}
28
29define 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
34; CHECK-NEXT:    rts16
35;
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
44; GENERIC-NEXT:    rts16
45entry:
46  %y = mul nsw i32 %x, 4095
47  ret i32 %y
48}
49
50define 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
55; CHECK-NEXT:    rts16
56;
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
65; GENERIC-NEXT:    rts16
66entry:
67  %y = mul nsw i32 %x, -4095
68  ret i32 %y
69}
70
71define 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
76; CHECK-NEXT:    rts16
77;
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
98; GENERIC-NEXT:    rts16
99entry:
100  %y = mul nsw i32 %x, 131074
101  ret i32 %y
102}
103
104define 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
109; CHECK-NEXT:    rts16
110;
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
128entry:
129  %y = mul nsw i32 %x, 131076
130  ret i32 %y
131}
132
133define 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
138; CHECK-NEXT:    rts16
139;
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
157entry:
158  %y = mul nsw i32 %x, 131080
159  ret i32 %y
160}
161
162define 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
167; CHECK-NEXT:    rts16
168;
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
178entry:
179  %y = mul nsw i16 %x, 4097
180  ret i16 %y
181}
182
183define 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
188; CHECK-NEXT:    rts16
189;
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
199entry:
200  %y = mul nsw i16 %x, 4095
201  ret i16 %y
202}
203
204define 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
209; CHECK-NEXT:    rts16
210;
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
220entry:
221  %y = mul nsw i16 %x, -4095
222  ret i16 %y
223}
224
225define 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
230; CHECK-NEXT:    rts16
231;
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
241entry:
242  %y = mul nsw i8 %x, 65
243  ret i8 %y
244}
245
246define 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
251; CHECK-NEXT:    rts16
252;
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
262entry:
263  %y = mul nsw i8 %x, 63
264  ret i8 %y
265}
266
267define 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
272; CHECK-NEXT:    rts16
273;
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
283entry:
284  %y = mul nsw i8 %x, -63
285  ret i8 %y
286}
287
288define 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
294; CHECK-NEXT:    rts16
295;
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
307entry:
308  %y = mul nsw i32 %x, -4097
309  ret i32 %y
310}
311
312define 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
318; CHECK-NEXT:    rts16
319;
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
331entry:
332  %y = mul nsw i16 %x, -4097
333  ret i16 %y
334}
335
336define 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
342; CHECK-NEXT:    rts16
343;
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
355entry:
356  %y = mul nsw i8 %x, -65
357  ret i8 %y
358}
359
360;; This case can not be optimized, due to the data type exceeds.
361define 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
374; CHECK-NEXT:    rts16
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
380;
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
413entry:
414  %y = mul nsw i64 %x, 4097
415  ret i64 %y
416}
417