1 ; Check that 64-bit division is bypassed correctly.
2 ; RUN: llc < %s -mtriple=x86_64-- -mattr=-idivq-to-divl | FileCheck %s --check-prefixes=CHECK,FAST-DIVQ
3 ; RUN: llc < %s -mtriple=x86_64-- -mattr=+idivq-to-divl | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
4 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
5 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
6 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
7 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
9 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=nehalem | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
10 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=sandybridge | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
11 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=haswell | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
12 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=skylake | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
13 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=alderlake | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
15 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=barcelona | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
16 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=btver1 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
17 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=btver2 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
18 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=bdver1 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
19 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=bdver2 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
20 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=bdver3 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
21 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=bdver4 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
22 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver1 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
23 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver2 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
24 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver3 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
25 ; RUN: llc < %s -mtriple=x86_64-- -mcpu=znver4 | FileCheck %s --check-prefixes=CHECK,SLOW-DIVQ
27 ; Additional tests for 64-bit divide bypass
33 define i64 @sdiv_quotient(i64 %a, i64 %b) nounwind {
34 ; FAST-DIVQ-LABEL: sdiv_quotient:
36 ; FAST-DIVQ-NEXT: movq %rdi, %rax
37 ; FAST-DIVQ-NEXT: cqto
38 ; FAST-DIVQ-NEXT: idivq %rsi
39 ; FAST-DIVQ-NEXT: retq
41 ; SLOW-DIVQ-LABEL: sdiv_quotient:
43 ; SLOW-DIVQ-DAG: movq %rdi, %rax
44 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
45 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
46 ; SLOW-DIVQ-DAG: shrq $32, %rcx
47 ; SLOW-DIVQ-NEXT: je .LBB0_1
48 ; SLOW-DIVQ-NEXT: # %bb.2:
49 ; SLOW-DIVQ-NEXT: cqto
50 ; SLOW-DIVQ-NEXT: idivq %rsi
51 ; SLOW-DIVQ-NEXT: retq
52 ; SLOW-DIVQ-NEXT: .LBB0_1:
53 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
54 ; SLOW-DIVQ-DAG: xorl %edx, %edx
55 ; SLOW-DIVQ-NEXT: divl %esi
56 ; SLOW-DIVQ-NEXT: # kill: def $eax killed $eax def $rax
57 ; SLOW-DIVQ-NEXT: retq
58 %result = sdiv i64 %a, %b
62 define i64 @sdiv_quotient_optsize(i64 %a, i64 %b) nounwind optsize {
63 ; CHECK-LABEL: sdiv_quotient_optsize:
65 ; CHECK-NEXT: movq %rdi, %rax
67 ; CHECK-NEXT: idivq %rsi
69 %result = sdiv i64 %a, %b
73 define i64 @sdiv_quotient_minsize(i64 %a, i64 %b) nounwind minsize {
74 ; CHECK-LABEL: sdiv_quotient_minsize:
76 ; CHECK-NEXT: movq %rdi, %rax
78 ; CHECK-NEXT: idivq %rsi
80 %result = sdiv i64 %a, %b
84 define i64 @sdiv_remainder(i64 %a, i64 %b) nounwind {
85 ; FAST-DIVQ-LABEL: sdiv_remainder:
87 ; FAST-DIVQ-NEXT: movq %rdi, %rax
88 ; FAST-DIVQ-NEXT: cqto
89 ; FAST-DIVQ-NEXT: idivq %rsi
90 ; FAST-DIVQ-NEXT: movq %rdx, %rax
91 ; FAST-DIVQ-NEXT: retq
93 ; SLOW-DIVQ-LABEL: sdiv_remainder:
95 ; SLOW-DIVQ-DAG: movq %rdi, %rax
96 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
97 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
98 ; SLOW-DIVQ-DAG: shrq $32, %rcx
99 ; SLOW-DIVQ-NEXT: je .LBB3_1
100 ; SLOW-DIVQ-NEXT: # %bb.2:
101 ; SLOW-DIVQ-NEXT: cqto
102 ; SLOW-DIVQ-NEXT: idivq %rsi
103 ; SLOW-DIVQ-NEXT: movq %rdx, %rax
104 ; SLOW-DIVQ-NEXT: retq
105 ; SLOW-DIVQ-NEXT: .LBB3_1:
106 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
107 ; SLOW-DIVQ-DAG: xorl %edx, %edx
108 ; SLOW-DIVQ-NEXT: divl %esi
109 ; SLOW-DIVQ-NEXT: movl %edx, %eax
110 ; SLOW-DIVQ-NEXT: retq
111 %result = srem i64 %a, %b
115 define i64 @sdiv_remainder_optsize(i64 %a, i64 %b) nounwind optsize {
116 ; CHECK-LABEL: sdiv_remainder_optsize:
118 ; CHECK-NEXT: movq %rdi, %rax
120 ; CHECK-NEXT: idivq %rsi
121 ; CHECK-NEXT: movq %rdx, %rax
123 %result = srem i64 %a, %b
127 define i64 @sdiv_remainder_minsize(i64 %a, i64 %b) nounwind minsize {
128 ; CHECK-LABEL: sdiv_remainder_minsize:
130 ; CHECK-NEXT: movq %rdi, %rax
132 ; CHECK-NEXT: idivq %rsi
133 ; CHECK-NEXT: movq %rdx, %rax
135 %result = srem i64 %a, %b
139 define i64 @sdiv_quotient_and_remainder(i64 %a, i64 %b) nounwind {
140 ; FAST-DIVQ-LABEL: sdiv_quotient_and_remainder:
141 ; FAST-DIVQ: # %bb.0:
142 ; FAST-DIVQ-NEXT: movq %rdi, %rax
143 ; FAST-DIVQ-NEXT: cqto
144 ; FAST-DIVQ-NEXT: idivq %rsi
145 ; FAST-DIVQ-NEXT: addq %rdx, %rax
146 ; FAST-DIVQ-NEXT: retq
148 ; SLOW-DIVQ-LABEL: sdiv_quotient_and_remainder:
149 ; SLOW-DIVQ: # %bb.0:
150 ; SLOW-DIVQ-DAG: movq %rdi, %rax
151 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
152 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
153 ; SLOW-DIVQ-DAG: shrq $32, %rcx
154 ; SLOW-DIVQ-NEXT: je .LBB6_1
155 ; SLOW-DIVQ-NEXT: # %bb.2:
156 ; SLOW-DIVQ-NEXT: cqto
157 ; SLOW-DIVQ-NEXT: idivq %rsi
158 ; SLOW-DIVQ-NEXT: addq %rdx, %rax
159 ; SLOW-DIVQ-NEXT: retq
160 ; SLOW-DIVQ-NEXT: .LBB6_1:
161 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
162 ; SLOW-DIVQ-DAG: xorl %edx, %edx
163 ; SLOW-DIVQ-NEXT: divl %esi
164 ; SLOW-DIVQ-NEXT: # kill: def $edx killed $edx def $rdx
165 ; SLOW-DIVQ-NEXT: # kill: def $eax killed $eax def $rax
166 ; SLOW-DIVQ-NEXT: addq %rdx, %rax
167 ; SLOW-DIVQ-NEXT: retq
168 %resultdiv = sdiv i64 %a, %b
169 %resultrem = srem i64 %a, %b
170 %result = add i64 %resultdiv, %resultrem
174 define i64 @sdiv_quotient_and_remainder_optsize(i64 %a, i64 %b) nounwind optsize {
175 ; CHECK-LABEL: sdiv_quotient_and_remainder_optsize:
177 ; CHECK-NEXT: movq %rdi, %rax
179 ; CHECK-NEXT: idivq %rsi
180 ; CHECK-NEXT: addq %rdx, %rax
182 %resultdiv = sdiv i64 %a, %b
183 %resultrem = srem i64 %a, %b
184 %result = add i64 %resultdiv, %resultrem
188 define i64 @sdiv_quotient_and_remainder_minsize(i64 %a, i64 %b) nounwind minsize {
189 ; CHECK-LABEL: sdiv_quotient_and_remainder_minsize:
191 ; CHECK-NEXT: movq %rdi, %rax
193 ; CHECK-NEXT: idivq %rsi
194 ; CHECK-NEXT: addq %rdx, %rax
196 %resultdiv = sdiv i64 %a, %b
197 %resultrem = srem i64 %a, %b
198 %result = add i64 %resultdiv, %resultrem
206 define i64 @udiv_quotient(i64 %a, i64 %b) nounwind {
207 ; FAST-DIVQ-LABEL: udiv_quotient:
208 ; FAST-DIVQ: # %bb.0:
209 ; FAST-DIVQ-NEXT: movq %rdi, %rax
210 ; FAST-DIVQ-NEXT: xorl %edx, %edx
211 ; FAST-DIVQ-NEXT: divq %rsi
212 ; FAST-DIVQ-NEXT: retq
214 ; SLOW-DIVQ-LABEL: udiv_quotient:
215 ; SLOW-DIVQ: # %bb.0:
216 ; SLOW-DIVQ-DAG: movq %rdi, %rax
217 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
218 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
219 ; SLOW-DIVQ-DAG: shrq $32, %rcx
220 ; SLOW-DIVQ-NEXT: je .LBB9_1
221 ; SLOW-DIVQ-NEXT: # %bb.2:
222 ; SLOW-DIVQ-NEXT: xorl %edx, %edx
223 ; SLOW-DIVQ-NEXT: divq %rsi
224 ; SLOW-DIVQ-NEXT: retq
225 ; SLOW-DIVQ-NEXT: .LBB9_1:
226 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
227 ; SLOW-DIVQ-DAG: xorl %edx, %edx
228 ; SLOW-DIVQ-NEXT: divl %esi
229 ; SLOW-DIVQ-NEXT: # kill: def $eax killed $eax def $rax
230 ; SLOW-DIVQ-NEXT: retq
231 %result = udiv i64 %a, %b
235 define i64 @udiv_quotient_optsize(i64 %a, i64 %b) nounwind optsize {
236 ; CHECK-LABEL: udiv_quotient_optsize:
238 ; CHECK-NEXT: movq %rdi, %rax
239 ; CHECK-NEXT: xorl %edx, %edx
240 ; CHECK-NEXT: divq %rsi
242 %result = udiv i64 %a, %b
246 define i64 @udiv_quotient_minsize(i64 %a, i64 %b) nounwind minsize {
247 ; CHECK-LABEL: udiv_quotient_minsize:
249 ; CHECK-NEXT: movq %rdi, %rax
250 ; CHECK-NEXT: xorl %edx, %edx
251 ; CHECK-NEXT: divq %rsi
253 %result = udiv i64 %a, %b
257 define i64 @udiv_remainder(i64 %a, i64 %b) nounwind {
258 ; FAST-DIVQ-LABEL: udiv_remainder:
259 ; FAST-DIVQ: # %bb.0:
260 ; FAST-DIVQ-NEXT: movq %rdi, %rax
261 ; FAST-DIVQ-NEXT: xorl %edx, %edx
262 ; FAST-DIVQ-NEXT: divq %rsi
263 ; FAST-DIVQ-NEXT: movq %rdx, %rax
264 ; FAST-DIVQ-NEXT: retq
266 ; SLOW-DIVQ-LABEL: udiv_remainder:
267 ; SLOW-DIVQ: # %bb.0:
268 ; SLOW-DIVQ-DAG: movq %rdi, %rax
269 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
270 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
271 ; SLOW-DIVQ-DAG: shrq $32, %rcx
272 ; SLOW-DIVQ-NEXT: je .LBB12_1
273 ; SLOW-DIVQ-NEXT: # %bb.2:
274 ; SLOW-DIVQ-NEXT: xorl %edx, %edx
275 ; SLOW-DIVQ-NEXT: divq %rsi
276 ; SLOW-DIVQ-NEXT: movq %rdx, %rax
277 ; SLOW-DIVQ-NEXT: retq
278 ; SLOW-DIVQ-NEXT: .LBB12_1:
279 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
280 ; SLOW-DIVQ-DAG: xorl %edx, %edx
281 ; SLOW-DIVQ-NEXT: divl %esi
282 ; SLOW-DIVQ-NEXT: movl %edx, %eax
283 ; SLOW-DIVQ-NEXT: retq
284 %result = urem i64 %a, %b
288 define i64 @udiv_remainder_optsize(i64 %a, i64 %b) nounwind optsize {
289 ; CHECK-LABEL: udiv_remainder_optsize:
291 ; CHECK-NEXT: movq %rdi, %rax
292 ; CHECK-NEXT: xorl %edx, %edx
293 ; CHECK-NEXT: divq %rsi
294 ; CHECK-NEXT: movq %rdx, %rax
296 %result = urem i64 %a, %b
300 define i64 @udiv_remainder_minsize(i64 %a, i64 %b) nounwind minsize {
301 ; CHECK-LABEL: udiv_remainder_minsize:
303 ; CHECK-NEXT: movq %rdi, %rax
304 ; CHECK-NEXT: xorl %edx, %edx
305 ; CHECK-NEXT: divq %rsi
306 ; CHECK-NEXT: movq %rdx, %rax
308 %result = urem i64 %a, %b
312 define i64 @udiv_quotient_and_remainder(i64 %a, i64 %b) nounwind {
313 ; FAST-DIVQ-LABEL: udiv_quotient_and_remainder:
314 ; FAST-DIVQ: # %bb.0:
315 ; FAST-DIVQ-NEXT: movq %rdi, %rax
316 ; FAST-DIVQ-NEXT: xorl %edx, %edx
317 ; FAST-DIVQ-NEXT: divq %rsi
318 ; FAST-DIVQ-NEXT: addq %rdx, %rax
319 ; FAST-DIVQ-NEXT: retq
321 ; SLOW-DIVQ-LABEL: udiv_quotient_and_remainder:
322 ; SLOW-DIVQ: # %bb.0:
323 ; SLOW-DIVQ-DAG: movq %rdi, %rax
324 ; SLOW-DIVQ-DAG: movq %rdi, %rcx
325 ; SLOW-DIVQ-DAG: orq %rsi, %rcx
326 ; SLOW-DIVQ-DAG: shrq $32, %rcx
327 ; SLOW-DIVQ-NEXT: je .LBB15_1
328 ; SLOW-DIVQ-NEXT: # %bb.2:
329 ; SLOW-DIVQ-NEXT: xorl %edx, %edx
330 ; SLOW-DIVQ-NEXT: divq %rsi
331 ; SLOW-DIVQ-NEXT: addq %rdx, %rax
332 ; SLOW-DIVQ-NEXT: retq
333 ; SLOW-DIVQ-NEXT: .LBB15_1:
334 ; SLOW-DIVQ-DAG: # kill: def $eax killed $eax killed $rax
335 ; SLOW-DIVQ-DAG: xorl %edx, %edx
336 ; SLOW-DIVQ-NEXT: divl %esi
337 ; SLOW-DIVQ-NEXT: # kill: def $edx killed $edx def $rdx
338 ; SLOW-DIVQ-NEXT: # kill: def $eax killed $eax def $rax
339 ; SLOW-DIVQ-NEXT: addq %rdx, %rax
340 ; SLOW-DIVQ-NEXT: retq
341 %resultdiv = udiv i64 %a, %b
342 %resultrem = urem i64 %a, %b
343 %result = add i64 %resultdiv, %resultrem
347 define i64 @udiv_quotient_and_remainder_optsize(i64 %a, i64 %b) nounwind optsize {
348 ; CHECK-LABEL: udiv_quotient_and_remainder_optsize:
350 ; CHECK-NEXT: movq %rdi, %rax
351 ; CHECK-NEXT: xorl %edx, %edx
352 ; CHECK-NEXT: divq %rsi
353 ; CHECK-NEXT: addq %rdx, %rax
355 %resultdiv = udiv i64 %a, %b
356 %resultrem = urem i64 %a, %b
357 %result = add i64 %resultdiv, %resultrem
361 define i64 @udiv_quotient_and_remainder_minsize(i64 %a, i64 %b) nounwind minsize {
362 ; CHECK-LABEL: udiv_quotient_and_remainder_minsize:
364 ; CHECK-NEXT: movq %rdi, %rax
365 ; CHECK-NEXT: xorl %edx, %edx
366 ; CHECK-NEXT: divq %rsi
367 ; CHECK-NEXT: addq %rdx, %rax
369 %resultdiv = udiv i64 %a, %b
370 %resultrem = urem i64 %a, %b
371 %result = add i64 %resultdiv, %resultrem
375 define void @PR43514(i32 %x, i32 %y) {
376 ; CHECK-LABEL: PR43514:
379 %z1 = zext i32 %x to i64
380 %z2 = zext i32 %y to i64
381 %s = srem i64 %z1, %z2