xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64-mul.ll (revision 61510b51c33464a6bc15e4cf5b1ee07e2e0ec1c9)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s --check-prefixes=CHECK,CHECK-SD
3; RUN: llc < %s -mtriple=arm64-eabi -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
4
5; rdar://9296808
6; rdar://9349137
7
8define i128 @t1(i64 %a, i64 %b) nounwind readnone ssp {
9; CHECK-LABEL: t1:
10; CHECK:       // %bb.0: // %entry
11; CHECK-NEXT:    mul x8, x0, x1
12; CHECK-NEXT:    umulh x1, x0, x1
13; CHECK-NEXT:    mov x0, x8
14; CHECK-NEXT:    ret
15entry:
16  %tmp1 = zext i64 %a to i128
17  %tmp2 = zext i64 %b to i128
18  %tmp3 = mul i128 %tmp1, %tmp2
19  ret i128 %tmp3
20}
21
22define i128 @t2(i64 %a, i64 %b) nounwind readnone ssp {
23; CHECK-SD-LABEL: t2:
24; CHECK-SD:       // %bb.0: // %entry
25; CHECK-SD-NEXT:    mul x8, x0, x1
26; CHECK-SD-NEXT:    smulh x1, x0, x1
27; CHECK-SD-NEXT:    mov x0, x8
28; CHECK-SD-NEXT:    ret
29;
30; CHECK-GI-LABEL: t2:
31; CHECK-GI:       // %bb.0: // %entry
32; CHECK-GI-NEXT:    asr x9, x1, #63
33; CHECK-GI-NEXT:    asr x10, x0, #63
34; CHECK-GI-NEXT:    mul x8, x0, x1
35; CHECK-GI-NEXT:    mul x9, x0, x9
36; CHECK-GI-NEXT:    umulh x11, x0, x1
37; CHECK-GI-NEXT:    mov x0, x8
38; CHECK-GI-NEXT:    madd x9, x10, x1, x9
39; CHECK-GI-NEXT:    add x1, x9, x11
40; CHECK-GI-NEXT:    ret
41entry:
42  %tmp1 = sext i64 %a to i128
43  %tmp2 = sext i64 %b to i128
44  %tmp3 = mul i128 %tmp1, %tmp2
45  ret i128 %tmp3
46}
47
48define i64 @t3(i32 %a, i32 %b) nounwind {
49; CHECK-LABEL: t3:
50; CHECK:       // %bb.0: // %entry
51; CHECK-NEXT:    umull x0, w0, w1
52; CHECK-NEXT:    ret
53entry:
54  %tmp1 = zext i32 %a to i64
55  %tmp2 = zext i32 %b to i64
56  %tmp3 = mul i64 %tmp1, %tmp2
57  ret i64 %tmp3
58}
59
60define i64 @t4(i32 %a, i32 %b) nounwind {
61; CHECK-LABEL: t4:
62; CHECK:       // %bb.0: // %entry
63; CHECK-NEXT:    smull x0, w0, w1
64; CHECK-NEXT:    ret
65entry:
66  %tmp1 = sext i32 %a to i64
67  %tmp2 = sext i32 %b to i64
68  %tmp3 = mul i64 %tmp1, %tmp2
69  ret i64 %tmp3
70}
71
72define i64 @t5(i32 %a, i32 %b, i64 %c) nounwind {
73; CHECK-LABEL: t5:
74; CHECK:       // %bb.0: // %entry
75; CHECK-NEXT:    umaddl x0, w0, w1, x2
76; CHECK-NEXT:    ret
77entry:
78  %tmp1 = zext i32 %a to i64
79  %tmp2 = zext i32 %b to i64
80  %tmp3 = mul i64 %tmp1, %tmp2
81  %tmp4 = add i64 %c, %tmp3
82  ret i64 %tmp4
83}
84
85define i64 @t6(i32 %a, i32 %b, i64 %c) nounwind {
86; CHECK-LABEL: t6:
87; CHECK:       // %bb.0: // %entry
88; CHECK-NEXT:    smsubl x0, w0, w1, x2
89; CHECK-NEXT:    ret
90entry:
91  %tmp1 = sext i32 %a to i64
92  %tmp2 = sext i32 %b to i64
93  %tmp3 = mul i64 %tmp1, %tmp2
94  %tmp4 = sub i64 %c, %tmp3
95  ret i64 %tmp4
96}
97
98define i64 @t7(i32 %a, i32 %b) nounwind {
99; CHECK-LABEL: t7:
100; CHECK:       // %bb.0: // %entry
101; CHECK-NEXT:    umnegl x0, w0, w1
102; CHECK-NEXT:    ret
103entry:
104  %tmp1 = zext i32 %a to i64
105  %tmp2 = zext i32 %b to i64
106  %tmp3 = mul i64 %tmp1, %tmp2
107  %tmp4 = sub i64 0, %tmp3
108  ret i64 %tmp4
109}
110
111define i64 @t8(i32 %a, i32 %b) nounwind {
112; CHECK-LABEL: t8:
113; CHECK:       // %bb.0: // %entry
114; CHECK-NEXT:    smnegl x0, w0, w1
115; CHECK-NEXT:    ret
116entry:
117  %tmp1 = sext i32 %a to i64
118  %tmp2 = sext i32 %b to i64
119  %tmp3 = mul i64 %tmp1, %tmp2
120  %tmp4 = sub i64 0, %tmp3
121  ret i64 %tmp4
122}
123
124define i64 @t9(i32 %a) nounwind {
125; CHECK-LABEL: t9:
126; CHECK:       // %bb.0: // %entry
127; CHECK-NEXT:    mov w8, #8896 // =0x22c0
128; CHECK-NEXT:    movk w8, #2, lsl #16
129; CHECK-NEXT:    umull x0, w0, w8
130; CHECK-NEXT:    ret
131entry:
132  %tmp1 = zext i32 %a to i64
133  %tmp2 = mul i64 %tmp1, 139968
134  ret i64 %tmp2
135}
136
137; Check 64-bit multiplication is used for constants > 32 bits.
138define i64 @t10(i32 %a) nounwind {
139; CHECK-LABEL: t10:
140; CHECK:       // %bb.0: // %entry
141; CHECK-NEXT:    // kill: def $w0 killed $w0 def $x0
142; CHECK-NEXT:    sxtw x8, w0
143; CHECK-NEXT:    mov w9, #2 // =0x2
144; CHECK-NEXT:    movk w9, #32768, lsl #16
145; CHECK-NEXT:    mul x0, x8, x9
146; CHECK-NEXT:    ret
147entry:
148  %tmp1 = sext i32 %a to i64
149  %tmp2 = mul i64 %tmp1, 2147483650 ; = 2^31 + 2
150  ret i64 %tmp2
151}
152
153; Check the sext_inreg case.
154define i64 @t11(i64 %a) nounwind {
155; CHECK-LABEL: t11:
156; CHECK:       // %bb.0: // %entry
157; CHECK-NEXT:    mov w8, #29594 // =0x739a
158; CHECK-NEXT:    movk w8, #65499, lsl #16
159; CHECK-NEXT:    smnegl x0, w0, w8
160; CHECK-NEXT:    ret
161entry:
162  %tmp1 = trunc i64 %a to i32
163  %tmp2 = sext i32 %tmp1 to i64
164  %tmp3 = mul i64 %tmp2, -2395238
165  %tmp4 = sub i64 0, %tmp3
166  ret i64 %tmp4
167}
168
169define i64 @t12(i64 %a, i64 %b) nounwind {
170; CHECK-LABEL: t12:
171; CHECK:       // %bb.0: // %entry
172; CHECK-NEXT:    mov w8, #35118 // =0x892e
173; CHECK-NEXT:    movk w8, #65008, lsl #16
174; CHECK-NEXT:    smaddl x0, w0, w8, x1
175; CHECK-NEXT:    ret
176entry:
177  %tmp1 = trunc i64 %a to i32
178  %tmp2 = sext i32 %tmp1 to i64
179  %tmp3 = mul i64 %tmp2, -34567890
180  %tmp4 = add i64 %b, %tmp3
181  ret i64 %tmp4
182}
183
184define i64 @t13(i32 %a, i64 %b) nounwind {
185; CHECK-LABEL: t13:
186; CHECK:       // %bb.0: // %entry
187; CHECK-NEXT:    mov w8, #24910 // =0x614e
188; CHECK-NEXT:    movk w8, #188, lsl #16
189; CHECK-NEXT:    umsubl x0, w0, w8, x1
190; CHECK-NEXT:    ret
191entry:
192  %tmp1 = zext i32 %a to i64
193  %tmp3 = mul i64 %tmp1, 12345678
194  %tmp4 = sub i64 %b, %tmp3
195  ret i64 %tmp4
196}
197
198define i64 @t14(i32 %a, i64 %b) nounwind {
199; CHECK-LABEL: t14:
200; CHECK:       // %bb.0: // %entry
201; CHECK-NEXT:    mov w8, #40626 // =0x9eb2
202; CHECK-NEXT:    movk w8, #65347, lsl #16
203; CHECK-NEXT:    smsubl x0, w0, w8, x1
204; CHECK-NEXT:    ret
205entry:
206  %tmp1 = sext i32 %a to i64
207  %tmp3 = mul i64 %tmp1, -12345678
208  %tmp4 = sub i64 %b, %tmp3
209  ret i64 %tmp4
210}
211