xref: /llvm-project/llvm/test/CodeGen/X86/imul.ll (revision 86eff6be686a1e41e13c08ebfc2db4dd4d58e7c6)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu | FileCheck %s --check-prefix=X64
3; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 | FileCheck %s --check-prefix=X64
4; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s --check-prefix=X86
5; At least one of the test cases in here crashed when linearizing the DAG.
6; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -pre-RA-sched=linearize | FileCheck %s --check-prefix=X64
7
8define i32 @mul4_32(i32 %A) {
9; X64-LABEL: mul4_32:
10; X64:       # %bb.0:
11; X64-NEXT:    # kill: def $edi killed $edi def $rdi
12; X64-NEXT:    leal (,%rdi,4), %eax
13; X64-NEXT:    retq
14;
15; X86-LABEL: mul4_32:
16; X86:       # %bb.0:
17; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
18; X86-NEXT:    shll $2, %eax
19; X86-NEXT:    retl
20    %mul = mul i32 %A, 4
21    ret i32 %mul
22}
23
24define i64 @mul4_64(i64 %A) {
25; X64-LABEL: mul4_64:
26; X64:       # %bb.0:
27; X64-NEXT:    leaq (,%rdi,4), %rax
28; X64-NEXT:    retq
29;
30; X86-LABEL: mul4_64:
31; X86:       # %bb.0:
32; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
33; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
34; X86-NEXT:    shldl $2, %eax, %edx
35; X86-NEXT:    shll $2, %eax
36; X86-NEXT:    retl
37    %mul = mul i64 %A, 4
38    ret i64 %mul
39}
40
41define i32 @mul4096_32(i32 %A) {
42; X64-LABEL: mul4096_32:
43; X64:       # %bb.0:
44; X64-NEXT:    movl %edi, %eax
45; X64-NEXT:    shll $12, %eax
46; X64-NEXT:    retq
47;
48; X86-LABEL: mul4096_32:
49; X86:       # %bb.0:
50; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
51; X86-NEXT:    shll $12, %eax
52; X86-NEXT:    retl
53    %mul = mul i32 %A, 4096
54    ret i32 %mul
55}
56
57define i64 @mul4096_64(i64 %A) {
58; X64-LABEL: mul4096_64:
59; X64:       # %bb.0:
60; X64-NEXT:    movq %rdi, %rax
61; X64-NEXT:    shlq $12, %rax
62; X64-NEXT:    retq
63;
64; X86-LABEL: mul4096_64:
65; X86:       # %bb.0:
66; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
67; X86-NEXT:    movl {{[0-9]+}}(%esp), %edx
68; X86-NEXT:    shldl $12, %eax, %edx
69; X86-NEXT:    shll $12, %eax
70; X86-NEXT:    retl
71    %mul = mul i64 %A, 4096
72    ret i64 %mul
73}
74
75define i32 @mulmin4096_32(i32 %A) {
76; X64-LABEL: mulmin4096_32:
77; X64:       # %bb.0:
78; X64-NEXT:    movl %edi, %eax
79; X64-NEXT:    shll $12, %eax
80; X64-NEXT:    negl %eax
81; X64-NEXT:    retq
82;
83; X86-LABEL: mulmin4096_32:
84; X86:       # %bb.0:
85; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
86; X86-NEXT:    shll $12, %eax
87; X86-NEXT:    negl %eax
88; X86-NEXT:    retl
89    %mul = mul i32 %A, -4096
90    ret i32 %mul
91}
92
93define i64 @mulmin4096_64(i64 %A) {
94; X64-LABEL: mulmin4096_64:
95; X64:       # %bb.0:
96; X64-NEXT:    movq %rdi, %rax
97; X64-NEXT:    shlq $12, %rax
98; X64-NEXT:    negq %rax
99; X64-NEXT:    retq
100;
101; X86-LABEL: mulmin4096_64:
102; X86:       # %bb.0:
103; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
104; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
105; X86-NEXT:    shldl $12, %eax, %ecx
106; X86-NEXT:    shll $12, %eax
107; X86-NEXT:    xorl %edx, %edx
108; X86-NEXT:    negl %eax
109; X86-NEXT:    sbbl %ecx, %edx
110; X86-NEXT:    retl
111    %mul = mul i64 %A, -4096
112    ret i64 %mul
113}
114
115define i32 @mul3_32(i32 %A) {
116; X64-LABEL: mul3_32:
117; X64:       # %bb.0:
118; X64-NEXT:    # kill: def $edi killed $edi def $rdi
119; X64-NEXT:    leal (%rdi,%rdi,2), %eax
120; X64-NEXT:    retq
121;
122; X86-LABEL: mul3_32:
123; X86:       # %bb.0:
124; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
125; X86-NEXT:    leal (%eax,%eax,2), %eax
126; X86-NEXT:    retl
127; But why?!
128    %mul = mul i32 %A, 3
129    ret i32 %mul
130}
131
132define i64 @mul3_64(i64 %A) {
133; X64-LABEL: mul3_64:
134; X64:       # %bb.0:
135; X64-NEXT:    leaq (%rdi,%rdi,2), %rax
136; X64-NEXT:    retq
137;
138; X86-LABEL: mul3_64:
139; X86:       # %bb.0:
140; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
141; X86-NEXT:    leal (%eax,%eax,2), %ecx
142; X86-NEXT:    movl $3, %eax
143; X86-NEXT:    mull {{[0-9]+}}(%esp)
144; X86-NEXT:    addl %ecx, %edx
145; X86-NEXT:    retl
146    %mul = mul i64 %A, 3
147    ret i64 %mul
148}
149
150define i32 @mul40_32(i32 %A) {
151; X64-LABEL: mul40_32:
152; X64:       # %bb.0:
153; X64-NEXT:    # kill: def $edi killed $edi def $rdi
154; X64-NEXT:    shll $3, %edi
155; X64-NEXT:    leal (%rdi,%rdi,4), %eax
156; X64-NEXT:    retq
157;
158; X86-LABEL: mul40_32:
159; X86:       # %bb.0:
160; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
161; X86-NEXT:    shll $3, %eax
162; X86-NEXT:    leal (%eax,%eax,4), %eax
163; X86-NEXT:    retl
164    %mul = mul i32 %A, 40
165    ret i32 %mul
166}
167
168define i64 @mul40_64(i64 %A) {
169; X64-LABEL: mul40_64:
170; X64:       # %bb.0:
171; X64-NEXT:    shlq $3, %rdi
172; X64-NEXT:    leaq (%rdi,%rdi,4), %rax
173; X64-NEXT:    retq
174;
175; X86-LABEL: mul40_64:
176; X86:       # %bb.0:
177; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
178; X86-NEXT:    leal (%eax,%eax,4), %ecx
179; X86-NEXT:    movl $40, %eax
180; X86-NEXT:    mull {{[0-9]+}}(%esp)
181; X86-NEXT:    leal (%edx,%ecx,8), %edx
182; X86-NEXT:    retl
183    %mul = mul i64 %A, 40
184    ret i64 %mul
185}
186
187define i32 @mul4_32_minsize(i32 %A) minsize {
188; X64-LABEL: mul4_32_minsize:
189; X64:       # %bb.0:
190; X64-NEXT:    # kill: def $edi killed $edi def $rdi
191; X64-NEXT:    leal (,%rdi,4), %eax
192; X64-NEXT:    retq
193;
194; X86-LABEL: mul4_32_minsize:
195; X86:       # %bb.0:
196; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
197; X86-NEXT:    shll $2, %eax
198; X86-NEXT:    retl
199    %mul = mul i32 %A, 4
200    ret i32 %mul
201}
202
203define i32 @mul40_32_minsize(i32 %A) minsize {
204; X64-LABEL: mul40_32_minsize:
205; X64:       # %bb.0:
206; X64-NEXT:    imull $40, %edi, %eax
207; X64-NEXT:    retq
208;
209; X86-LABEL: mul40_32_minsize:
210; X86:       # %bb.0:
211; X86-NEXT:    imull $40, {{[0-9]+}}(%esp), %eax
212; X86-NEXT:    retl
213    %mul = mul i32 %A, 40
214    ret i32 %mul
215}
216
217define i32 @mul33_32(i32 %A) {
218; X64-LABEL: mul33_32:
219; X64:       # %bb.0:
220; X64-NEXT:    movl %edi, %eax
221; X64-NEXT:    shll $5, %eax
222; X64-NEXT:    addl %edi, %eax
223; X64-NEXT:    retq
224;
225; X86-LABEL: mul33_32:
226; X86:       # %bb.0:
227; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
228; X86-NEXT:    movl %ecx, %eax
229; X86-NEXT:    shll $5, %eax
230; X86-NEXT:    addl %ecx, %eax
231; X86-NEXT:    retl
232    %mul = mul i32 %A, 33
233    ret i32 %mul
234}
235
236define i32 @mul31_32(i32 %A) {
237; X64-LABEL: mul31_32:
238; X64:       # %bb.0:
239; X64-NEXT:    movl %edi, %eax
240; X64-NEXT:    shll $5, %eax
241; X64-NEXT:    subl %edi, %eax
242; X64-NEXT:    retq
243;
244; X86-LABEL: mul31_32:
245; X86:       # %bb.0:
246; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
247; X86-NEXT:    movl %ecx, %eax
248; X86-NEXT:    shll $5, %eax
249; X86-NEXT:    subl %ecx, %eax
250; X86-NEXT:    retl
251    %mul = mul i32 %A, 31
252    ret i32 %mul
253}
254
255define i32 @mul0_32(i32 %A) {
256; X64-LABEL: mul0_32:
257; X64:       # %bb.0:
258; X64-NEXT:    xorl %eax, %eax
259; X64-NEXT:    retq
260;
261; X86-LABEL: mul0_32:
262; X86:       # %bb.0:
263; X86-NEXT:    xorl %eax, %eax
264; X86-NEXT:    retl
265    %mul = mul i32 %A, 0
266    ret i32 %mul
267}
268
269define i32 @mul4294967295_32(i32 %A) {
270; X64-LABEL: mul4294967295_32:
271; X64:       # %bb.0:
272; X64-NEXT:    movl %edi, %eax
273; X64-NEXT:    negl %eax
274; X64-NEXT:    retq
275;
276; X86-LABEL: mul4294967295_32:
277; X86:       # %bb.0:
278; X86-NEXT:    xorl %eax, %eax
279; X86-NEXT:    subl {{[0-9]+}}(%esp), %eax
280; X86-NEXT:    retl
281    %mul = mul i32 %A, 4294967295
282    ret i32 %mul
283}
284
285define i64 @mul18446744073709551615_64(i64 %A) {
286; X64-LABEL: mul18446744073709551615_64:
287; X64:       # %bb.0:
288; X64-NEXT:    movq %rdi, %rax
289; X64-NEXT:    negq %rax
290; X64-NEXT:    retq
291;
292; X86-LABEL: mul18446744073709551615_64:
293; X86:       # %bb.0:
294; X86-NEXT:    xorl %edx, %edx
295; X86-NEXT:    xorl %eax, %eax
296; X86-NEXT:    subl {{[0-9]+}}(%esp), %eax
297; X86-NEXT:    sbbl {{[0-9]+}}(%esp), %edx
298; X86-NEXT:    retl
299    %mul = mul i64 %A, 18446744073709551615
300    ret i64 %mul
301}
302
303define i32 @test(i32 %a) {
304; X64-LABEL: test:
305; X64:       # %bb.0: # %entry
306; X64-NEXT:    movl %edi, %eax
307; X64-NEXT:    shll $5, %eax
308; X64-NEXT:    subl %edi, %eax
309; X64-NEXT:    retq
310;
311; X86-LABEL: test:
312; X86:       # %bb.0: # %entry
313; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
314; X86-NEXT:    movl %ecx, %eax
315; X86-NEXT:    shll $5, %eax
316; X86-NEXT:    subl %ecx, %eax
317; X86-NEXT:    retl
318entry:
319	%tmp3 = mul i32 %a, 31
320	ret i32 %tmp3
321}
322
323define i32 @test1(i32 %a) {
324; X64-LABEL: test1:
325; X64:       # %bb.0: # %entry
326; X64-NEXT:    movl %edi, %eax
327; X64-NEXT:    movl %edi, %ecx
328; X64-NEXT:    shll $5, %ecx
329; X64-NEXT:    subl %ecx, %eax
330; X64-NEXT:    retq
331;
332; X86-LABEL: test1:
333; X86:       # %bb.0: # %entry
334; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
335; X86-NEXT:    movl %eax, %ecx
336; X86-NEXT:    shll $5, %ecx
337; X86-NEXT:    subl %ecx, %eax
338; X86-NEXT:    retl
339entry:
340	%tmp3 = mul i32 %a, -31
341	ret i32 %tmp3
342}
343
344
345define i32 @test2(i32 %a) {
346; X64-LABEL: test2:
347; X64:       # %bb.0: # %entry
348; X64-NEXT:    movl %edi, %eax
349; X64-NEXT:    shll $5, %eax
350; X64-NEXT:    addl %edi, %eax
351; X64-NEXT:    retq
352;
353; X86-LABEL: test2:
354; X86:       # %bb.0: # %entry
355; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
356; X86-NEXT:    movl %ecx, %eax
357; X86-NEXT:    shll $5, %eax
358; X86-NEXT:    addl %ecx, %eax
359; X86-NEXT:    retl
360entry:
361	%tmp3 = mul i32 %a, 33
362	ret i32 %tmp3
363}
364
365define i32 @test3(i32 %a) {
366; X64-LABEL: test3:
367; X64:       # %bb.0: # %entry
368; X64-NEXT:    movl %edi, %eax
369; X64-NEXT:    shll $5, %eax
370; X64-NEXT:    addl %edi, %eax
371; X64-NEXT:    negl %eax
372; X64-NEXT:    retq
373;
374; X86-LABEL: test3:
375; X86:       # %bb.0: # %entry
376; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
377; X86-NEXT:    movl %ecx, %eax
378; X86-NEXT:    shll $5, %eax
379; X86-NEXT:    addl %ecx, %eax
380; X86-NEXT:    negl %eax
381; X86-NEXT:    retl
382entry:
383	%tmp3 = mul i32 %a, -33
384	ret i32 %tmp3
385}
386
387define i64 @test4(i64 %a) {
388; X64-LABEL: test4:
389; X64:       # %bb.0: # %entry
390; X64-NEXT:    movq %rdi, %rax
391; X64-NEXT:    shlq $5, %rax
392; X64-NEXT:    subq %rdi, %rax
393; X64-NEXT:    retq
394;
395; X86-LABEL: test4:
396; X86:       # %bb.0: # %entry
397; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
398; X86-NEXT:    movl %eax, %ecx
399; X86-NEXT:    shll $5, %ecx
400; X86-NEXT:    subl %eax, %ecx
401; X86-NEXT:    movl $31, %eax
402; X86-NEXT:    mull {{[0-9]+}}(%esp)
403; X86-NEXT:    addl %ecx, %edx
404; X86-NEXT:    retl
405entry:
406	%tmp3 = mul i64 %a, 31
407	ret i64 %tmp3
408}
409
410define i64 @test5(i64 %a) {
411; X64-LABEL: test5:
412; X64:       # %bb.0: # %entry
413; X64-NEXT:    movq %rdi, %rax
414; X64-NEXT:    movq %rdi, %rcx
415; X64-NEXT:    shlq $5, %rcx
416; X64-NEXT:    subq %rcx, %rax
417; X64-NEXT:    retq
418;
419; X86-LABEL: test5:
420; X86:       # %bb.0: # %entry
421; X86-NEXT:    pushl %esi
422; X86-NEXT:    .cfi_def_cfa_offset 8
423; X86-NEXT:    .cfi_offset %esi, -8
424; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
425; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
426; X86-NEXT:    movl %esi, %eax
427; X86-NEXT:    shll $5, %eax
428; X86-NEXT:    subl %eax, %esi
429; X86-NEXT:    movl $-31, %edx
430; X86-NEXT:    movl %ecx, %eax
431; X86-NEXT:    mull %edx
432; X86-NEXT:    subl %ecx, %edx
433; X86-NEXT:    addl %esi, %edx
434; X86-NEXT:    popl %esi
435; X86-NEXT:    .cfi_def_cfa_offset 4
436; X86-NEXT:    retl
437entry:
438	%tmp3 = mul i64 %a, -31
439	ret i64 %tmp3
440}
441
442
443define i64 @test6(i64 %a) {
444; X64-LABEL: test6:
445; X64:       # %bb.0: # %entry
446; X64-NEXT:    movq %rdi, %rax
447; X64-NEXT:    shlq $5, %rax
448; X64-NEXT:    addq %rdi, %rax
449; X64-NEXT:    retq
450;
451; X86-LABEL: test6:
452; X86:       # %bb.0: # %entry
453; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
454; X86-NEXT:    movl %eax, %ecx
455; X86-NEXT:    shll $5, %ecx
456; X86-NEXT:    addl %eax, %ecx
457; X86-NEXT:    movl $33, %eax
458; X86-NEXT:    mull {{[0-9]+}}(%esp)
459; X86-NEXT:    addl %ecx, %edx
460; X86-NEXT:    retl
461entry:
462	%tmp3 = mul i64 %a, 33
463	ret i64 %tmp3
464}
465
466define i64 @test7(i64 %a) {
467; X64-LABEL: test7:
468; X64:       # %bb.0: # %entry
469; X64-NEXT:    movq %rdi, %rax
470; X64-NEXT:    shlq $5, %rax
471; X64-NEXT:    addq %rdi, %rax
472; X64-NEXT:    negq %rax
473; X64-NEXT:    retq
474;
475; X86-LABEL: test7:
476; X86:       # %bb.0: # %entry
477; X86-NEXT:    pushl %esi
478; X86-NEXT:    .cfi_def_cfa_offset 8
479; X86-NEXT:    .cfi_offset %esi, -8
480; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
481; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
482; X86-NEXT:    movl %eax, %esi
483; X86-NEXT:    shll $5, %esi
484; X86-NEXT:    addl %eax, %esi
485; X86-NEXT:    movl $-33, %edx
486; X86-NEXT:    movl %ecx, %eax
487; X86-NEXT:    mull %edx
488; X86-NEXT:    subl %ecx, %edx
489; X86-NEXT:    subl %esi, %edx
490; X86-NEXT:    popl %esi
491; X86-NEXT:    .cfi_def_cfa_offset 4
492; X86-NEXT:    retl
493entry:
494	%tmp3 = mul i64 %a, -33
495	ret i64 %tmp3
496}
497
498define i64 @testOverflow(i64 %a) {
499; X64-LABEL: testOverflow:
500; X64:       # %bb.0: # %entry
501; X64-NEXT:    movq %rdi, %rax
502; X64-NEXT:    shlq $63, %rax
503; X64-NEXT:    subq %rdi, %rax
504; X64-NEXT:    retq
505;
506; X86-LABEL: testOverflow:
507; X86:       # %bb.0: # %entry
508; X86-NEXT:    pushl %esi
509; X86-NEXT:    .cfi_def_cfa_offset 8
510; X86-NEXT:    .cfi_offset %esi, -8
511; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
512; X86-NEXT:    movl $-1, %edx
513; X86-NEXT:    movl %ecx, %eax
514; X86-NEXT:    mull %edx
515; X86-NEXT:    movl %ecx, %esi
516; X86-NEXT:    shll $31, %esi
517; X86-NEXT:    subl %ecx, %esi
518; X86-NEXT:    addl %esi, %edx
519; X86-NEXT:    subl {{[0-9]+}}(%esp), %edx
520; X86-NEXT:    popl %esi
521; X86-NEXT:    .cfi_def_cfa_offset 4
522; X86-NEXT:    retl
523entry:
524	%tmp3 = mul i64 %a, 9223372036854775807
525	ret i64 %tmp3
526}
527
528define i64 @testNegOverflow(i64 %a) {
529; X64-LABEL: testNegOverflow:
530; X64:       # %bb.0: # %entry
531; X64-NEXT:    movq %rdi, %rax
532; X64-NEXT:    shlq $63, %rax
533; X64-NEXT:    addq %rdi, %rax
534; X64-NEXT:    retq
535;
536; X86-LABEL: testNegOverflow:
537; X86:       # %bb.0: # %entry
538; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
539; X86-NEXT:    movl %eax, %edx
540; X86-NEXT:    shll $31, %edx
541; X86-NEXT:    addl {{[0-9]+}}(%esp), %edx
542; X86-NEXT:    retl
543entry:
544	%tmp3 = mul i64 %a, -9223372036854775807
545	ret i64 %tmp3
546}
547