xref: /llvm-project/llvm/test/CodeGen/X86/ctlo.ll (revision 90e9895a9373b3d83eefe15b34d2dc83c7bcc88f)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86,X86-NOCMOV
3; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+cmov | FileCheck %s --check-prefixes=X86,X86-CMOV
4; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
5; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X86-CLZ
6; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt | FileCheck %s --check-prefix=X64-CLZ
7; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi,+lzcnt,+fast-lzcnt | FileCheck %s --check-prefix=X86-CLZ
8; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi,+lzcnt,+fast-lzcnt | FileCheck %s --check-prefix=X64-CLZ
9
10declare i8 @llvm.ctlz.i8(i8, i1)
11declare i16 @llvm.ctlz.i16(i16, i1)
12declare i32 @llvm.ctlz.i32(i32, i1)
13declare i64 @llvm.ctlz.i64(i64, i1)
14
15define i8 @ctlo_i8(i8 %x) {
16; X86-NOCMOV-LABEL: ctlo_i8:
17; X86-NOCMOV:       # %bb.0:
18; X86-NOCMOV-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
19; X86-NOCMOV-NEXT:    xorb $-1, %al
20; X86-NOCMOV-NEXT:    je .LBB0_1
21; X86-NOCMOV-NEXT:  # %bb.2: # %cond.false
22; X86-NOCMOV-NEXT:    movzbl %al, %eax
23; X86-NOCMOV-NEXT:    bsrl %eax, %eax
24; X86-NOCMOV-NEXT:    xorl $7, %eax
25; X86-NOCMOV-NEXT:    # kill: def $al killed $al killed $eax
26; X86-NOCMOV-NEXT:    retl
27; X86-NOCMOV-NEXT:  .LBB0_1:
28; X86-NOCMOV-NEXT:    movb $8, %al
29; X86-NOCMOV-NEXT:    # kill: def $al killed $al killed $eax
30; X86-NOCMOV-NEXT:    retl
31;
32; X86-CMOV-LABEL: ctlo_i8:
33; X86-CMOV:       # %bb.0:
34; X86-CMOV-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
35; X86-CMOV-NEXT:    notb %al
36; X86-CMOV-NEXT:    movzbl %al, %eax
37; X86-CMOV-NEXT:    bsrl %eax, %ecx
38; X86-CMOV-NEXT:    movl $15, %eax
39; X86-CMOV-NEXT:    cmovnel %ecx, %eax
40; X86-CMOV-NEXT:    xorl $7, %eax
41; X86-CMOV-NEXT:    # kill: def $al killed $al killed $eax
42; X86-CMOV-NEXT:    retl
43;
44; X64-LABEL: ctlo_i8:
45; X64:       # %bb.0:
46; X64-NEXT:    notb %dil
47; X64-NEXT:    movzbl %dil, %ecx
48; X64-NEXT:    movl $15, %eax
49; X64-NEXT:    bsrl %ecx, %eax
50; X64-NEXT:    xorl $7, %eax
51; X64-NEXT:    # kill: def $al killed $al killed $eax
52; X64-NEXT:    retq
53;
54; X86-CLZ-LABEL: ctlo_i8:
55; X86-CLZ:       # %bb.0:
56; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
57; X86-CLZ-NEXT:    shll $24, %eax
58; X86-CLZ-NEXT:    notl %eax
59; X86-CLZ-NEXT:    lzcntl %eax, %eax
60; X86-CLZ-NEXT:    # kill: def $al killed $al killed $eax
61; X86-CLZ-NEXT:    retl
62;
63; X64-CLZ-LABEL: ctlo_i8:
64; X64-CLZ:       # %bb.0:
65; X64-CLZ-NEXT:    shll $24, %edi
66; X64-CLZ-NEXT:    notl %edi
67; X64-CLZ-NEXT:    lzcntl %edi, %eax
68; X64-CLZ-NEXT:    # kill: def $al killed $al killed $eax
69; X64-CLZ-NEXT:    retq
70  %tmp1 = xor i8 %x, -1
71  %tmp2 = call i8 @llvm.ctlz.i8( i8 %tmp1, i1 false )
72  ret i8 %tmp2
73}
74
75define i8 @ctlo_i8_undef(i8 %x) {
76; X86-LABEL: ctlo_i8_undef:
77; X86:       # %bb.0:
78; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
79; X86-NEXT:    notb %al
80; X86-NEXT:    movzbl %al, %eax
81; X86-NEXT:    bsrl %eax, %eax
82; X86-NEXT:    xorl $7, %eax
83; X86-NEXT:    # kill: def $al killed $al killed $eax
84; X86-NEXT:    retl
85;
86; X64-LABEL: ctlo_i8_undef:
87; X64:       # %bb.0:
88; X64-NEXT:    notb %dil
89; X64-NEXT:    movzbl %dil, %eax
90; X64-NEXT:    bsrl %eax, %eax
91; X64-NEXT:    xorl $7, %eax
92; X64-NEXT:    # kill: def $al killed $al killed $eax
93; X64-NEXT:    retq
94;
95; X86-CLZ-LABEL: ctlo_i8_undef:
96; X86-CLZ:       # %bb.0:
97; X86-CLZ-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
98; X86-CLZ-NEXT:    notb %al
99; X86-CLZ-NEXT:    movzbl %al, %eax
100; X86-CLZ-NEXT:    shll $24, %eax
101; X86-CLZ-NEXT:    lzcntl %eax, %eax
102; X86-CLZ-NEXT:    # kill: def $al killed $al killed $eax
103; X86-CLZ-NEXT:    retl
104;
105; X64-CLZ-LABEL: ctlo_i8_undef:
106; X64-CLZ:       # %bb.0:
107; X64-CLZ-NEXT:    notb %dil
108; X64-CLZ-NEXT:    movzbl %dil, %eax
109; X64-CLZ-NEXT:    shll $24, %eax
110; X64-CLZ-NEXT:    lzcntl %eax, %eax
111; X64-CLZ-NEXT:    # kill: def $al killed $al killed $eax
112; X64-CLZ-NEXT:    retq
113  %tmp1 = xor i8 %x, -1
114  %tmp2 = call i8 @llvm.ctlz.i8( i8 %tmp1, i1 true )
115  ret i8 %tmp2
116}
117
118define i16 @ctlo_i16(i16 %x) {
119; X86-NOCMOV-LABEL: ctlo_i16:
120; X86-NOCMOV:       # %bb.0:
121; X86-NOCMOV-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
122; X86-NOCMOV-NEXT:    xorw $-1, %ax
123; X86-NOCMOV-NEXT:    je .LBB2_1
124; X86-NOCMOV-NEXT:  # %bb.2: # %cond.false
125; X86-NOCMOV-NEXT:    bsrw %ax, %ax
126; X86-NOCMOV-NEXT:    xorl $15, %eax
127; X86-NOCMOV-NEXT:    # kill: def $ax killed $ax killed $eax
128; X86-NOCMOV-NEXT:    retl
129; X86-NOCMOV-NEXT:  .LBB2_1:
130; X86-NOCMOV-NEXT:    movw $16, %ax
131; X86-NOCMOV-NEXT:    # kill: def $ax killed $ax killed $eax
132; X86-NOCMOV-NEXT:    retl
133;
134; X86-CMOV-LABEL: ctlo_i16:
135; X86-CMOV:       # %bb.0:
136; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
137; X86-CMOV-NEXT:    notl %eax
138; X86-CMOV-NEXT:    bsrw %ax, %cx
139; X86-CMOV-NEXT:    movw $31, %ax
140; X86-CMOV-NEXT:    cmovnew %cx, %ax
141; X86-CMOV-NEXT:    xorl $15, %eax
142; X86-CMOV-NEXT:    # kill: def $ax killed $ax killed $eax
143; X86-CMOV-NEXT:    retl
144;
145; X64-LABEL: ctlo_i16:
146; X64:       # %bb.0:
147; X64-NEXT:    notl %edi
148; X64-NEXT:    movw $31, %ax
149; X64-NEXT:    bsrw %di, %ax
150; X64-NEXT:    xorl $15, %eax
151; X64-NEXT:    # kill: def $ax killed $ax killed $eax
152; X64-NEXT:    retq
153;
154; X86-CLZ-LABEL: ctlo_i16:
155; X86-CLZ:       # %bb.0:
156; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
157; X86-CLZ-NEXT:    notl %eax
158; X86-CLZ-NEXT:    lzcntw %ax, %ax
159; X86-CLZ-NEXT:    retl
160;
161; X64-CLZ-LABEL: ctlo_i16:
162; X64-CLZ:       # %bb.0:
163; X64-CLZ-NEXT:    notl %edi
164; X64-CLZ-NEXT:    lzcntw %di, %ax
165; X64-CLZ-NEXT:    retq
166  %tmp1 = xor i16 %x, -1
167  %tmp2 = call i16 @llvm.ctlz.i16( i16 %tmp1, i1 false )
168  ret i16 %tmp2
169}
170
171define i16 @ctlo_i16_undef(i16 %x) {
172; X86-LABEL: ctlo_i16_undef:
173; X86:       # %bb.0:
174; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
175; X86-NEXT:    notl %eax
176; X86-NEXT:    bsrw %ax, %ax
177; X86-NEXT:    xorl $15, %eax
178; X86-NEXT:    # kill: def $ax killed $ax killed $eax
179; X86-NEXT:    retl
180;
181; X64-LABEL: ctlo_i16_undef:
182; X64:       # %bb.0:
183; X64-NEXT:    notl %edi
184; X64-NEXT:    bsrw %di, %ax
185; X64-NEXT:    xorl $15, %eax
186; X64-NEXT:    # kill: def $ax killed $ax killed $eax
187; X64-NEXT:    retq
188;
189; X86-CLZ-LABEL: ctlo_i16_undef:
190; X86-CLZ:       # %bb.0:
191; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
192; X86-CLZ-NEXT:    notl %eax
193; X86-CLZ-NEXT:    lzcntw %ax, %ax
194; X86-CLZ-NEXT:    retl
195;
196; X64-CLZ-LABEL: ctlo_i16_undef:
197; X64-CLZ:       # %bb.0:
198; X64-CLZ-NEXT:    notl %edi
199; X64-CLZ-NEXT:    lzcntw %di, %ax
200; X64-CLZ-NEXT:    retq
201  %tmp1 = xor i16 %x, -1
202  %tmp2 = call i16 @llvm.ctlz.i16( i16 %tmp1, i1 true )
203  ret i16 %tmp2
204}
205
206define i32 @ctlo_i32(i32 %x) {
207; X86-NOCMOV-LABEL: ctlo_i32:
208; X86-NOCMOV:       # %bb.0:
209; X86-NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
210; X86-NOCMOV-NEXT:    xorl $-1, %eax
211; X86-NOCMOV-NEXT:    je .LBB4_1
212; X86-NOCMOV-NEXT:  # %bb.2: # %cond.false
213; X86-NOCMOV-NEXT:    bsrl %eax, %eax
214; X86-NOCMOV-NEXT:    xorl $31, %eax
215; X86-NOCMOV-NEXT:    retl
216; X86-NOCMOV-NEXT:  .LBB4_1:
217; X86-NOCMOV-NEXT:    movl $32, %eax
218; X86-NOCMOV-NEXT:    retl
219;
220; X86-CMOV-LABEL: ctlo_i32:
221; X86-CMOV:       # %bb.0:
222; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
223; X86-CMOV-NEXT:    notl %eax
224; X86-CMOV-NEXT:    bsrl %eax, %ecx
225; X86-CMOV-NEXT:    movl $63, %eax
226; X86-CMOV-NEXT:    cmovnel %ecx, %eax
227; X86-CMOV-NEXT:    xorl $31, %eax
228; X86-CMOV-NEXT:    retl
229;
230; X64-LABEL: ctlo_i32:
231; X64:       # %bb.0:
232; X64-NEXT:    notl %edi
233; X64-NEXT:    movl $63, %eax
234; X64-NEXT:    bsrl %edi, %eax
235; X64-NEXT:    xorl $31, %eax
236; X64-NEXT:    retq
237;
238; X86-CLZ-LABEL: ctlo_i32:
239; X86-CLZ:       # %bb.0:
240; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
241; X86-CLZ-NEXT:    notl %eax
242; X86-CLZ-NEXT:    lzcntl %eax, %eax
243; X86-CLZ-NEXT:    retl
244;
245; X64-CLZ-LABEL: ctlo_i32:
246; X64-CLZ:       # %bb.0:
247; X64-CLZ-NEXT:    notl %edi
248; X64-CLZ-NEXT:    lzcntl %edi, %eax
249; X64-CLZ-NEXT:    retq
250  %tmp1 = xor i32 %x, -1
251  %tmp2 = call i32 @llvm.ctlz.i32( i32 %tmp1, i1 false )
252  ret i32 %tmp2
253}
254
255define i32 @ctlo_i32_undef(i32 %x) {
256; X86-LABEL: ctlo_i32_undef:
257; X86:       # %bb.0:
258; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
259; X86-NEXT:    notl %eax
260; X86-NEXT:    bsrl %eax, %eax
261; X86-NEXT:    xorl $31, %eax
262; X86-NEXT:    retl
263;
264; X64-LABEL: ctlo_i32_undef:
265; X64:       # %bb.0:
266; X64-NEXT:    notl %edi
267; X64-NEXT:    bsrl %edi, %eax
268; X64-NEXT:    xorl $31, %eax
269; X64-NEXT:    retq
270;
271; X86-CLZ-LABEL: ctlo_i32_undef:
272; X86-CLZ:       # %bb.0:
273; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
274; X86-CLZ-NEXT:    notl %eax
275; X86-CLZ-NEXT:    lzcntl %eax, %eax
276; X86-CLZ-NEXT:    retl
277;
278; X64-CLZ-LABEL: ctlo_i32_undef:
279; X64-CLZ:       # %bb.0:
280; X64-CLZ-NEXT:    notl %edi
281; X64-CLZ-NEXT:    lzcntl %edi, %eax
282; X64-CLZ-NEXT:    retq
283  %tmp1 = xor i32 %x, -1
284  %tmp2 = call i32 @llvm.ctlz.i32( i32 %tmp1, i1 true )
285  ret i32 %tmp2
286}
287
288define i64 @ctlo_i64(i64 %x) {
289; X86-NOCMOV-LABEL: ctlo_i64:
290; X86-NOCMOV:       # %bb.0:
291; X86-NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
292; X86-NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %ecx
293; X86-NOCMOV-NEXT:    notl %ecx
294; X86-NOCMOV-NEXT:    notl %eax
295; X86-NOCMOV-NEXT:    bsrl %eax, %edx
296; X86-NOCMOV-NEXT:    movl $63, %eax
297; X86-NOCMOV-NEXT:    je .LBB6_2
298; X86-NOCMOV-NEXT:  # %bb.1:
299; X86-NOCMOV-NEXT:    movl %edx, %eax
300; X86-NOCMOV-NEXT:  .LBB6_2:
301; X86-NOCMOV-NEXT:    testl %ecx, %ecx
302; X86-NOCMOV-NEXT:    jne .LBB6_3
303; X86-NOCMOV-NEXT:  # %bb.4:
304; X86-NOCMOV-NEXT:    xorl $31, %eax
305; X86-NOCMOV-NEXT:    addl $32, %eax
306; X86-NOCMOV-NEXT:    xorl %edx, %edx
307; X86-NOCMOV-NEXT:    retl
308; X86-NOCMOV-NEXT:  .LBB6_3:
309; X86-NOCMOV-NEXT:    bsrl %ecx, %eax
310; X86-NOCMOV-NEXT:    xorl $31, %eax
311; X86-NOCMOV-NEXT:    xorl %edx, %edx
312; X86-NOCMOV-NEXT:    retl
313;
314; X86-CMOV-LABEL: ctlo_i64:
315; X86-CMOV:       # %bb.0:
316; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
317; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %ecx
318; X86-CMOV-NEXT:    notl %ecx
319; X86-CMOV-NEXT:    notl %eax
320; X86-CMOV-NEXT:    bsrl %eax, %eax
321; X86-CMOV-NEXT:    movl $63, %edx
322; X86-CMOV-NEXT:    cmovnel %eax, %edx
323; X86-CMOV-NEXT:    xorl $31, %edx
324; X86-CMOV-NEXT:    addl $32, %edx
325; X86-CMOV-NEXT:    bsrl %ecx, %eax
326; X86-CMOV-NEXT:    xorl $31, %eax
327; X86-CMOV-NEXT:    testl %ecx, %ecx
328; X86-CMOV-NEXT:    cmovel %edx, %eax
329; X86-CMOV-NEXT:    xorl %edx, %edx
330; X86-CMOV-NEXT:    retl
331;
332; X64-LABEL: ctlo_i64:
333; X64:       # %bb.0:
334; X64-NEXT:    notq %rdi
335; X64-NEXT:    movl $127, %eax
336; X64-NEXT:    bsrq %rdi, %rax
337; X64-NEXT:    xorq $63, %rax
338; X64-NEXT:    retq
339;
340; X86-CLZ-LABEL: ctlo_i64:
341; X86-CLZ:       # %bb.0:
342; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
343; X86-CLZ-NEXT:    notl %eax
344; X86-CLZ-NEXT:    testl %eax, %eax
345; X86-CLZ-NEXT:    jne .LBB6_1
346; X86-CLZ-NEXT:  # %bb.2:
347; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
348; X86-CLZ-NEXT:    notl %eax
349; X86-CLZ-NEXT:    lzcntl %eax, %eax
350; X86-CLZ-NEXT:    addl $32, %eax
351; X86-CLZ-NEXT:    xorl %edx, %edx
352; X86-CLZ-NEXT:    retl
353; X86-CLZ-NEXT:  .LBB6_1:
354; X86-CLZ-NEXT:    lzcntl %eax, %eax
355; X86-CLZ-NEXT:    xorl %edx, %edx
356; X86-CLZ-NEXT:    retl
357;
358; X64-CLZ-LABEL: ctlo_i64:
359; X64-CLZ:       # %bb.0:
360; X64-CLZ-NEXT:    notq %rdi
361; X64-CLZ-NEXT:    lzcntq %rdi, %rax
362; X64-CLZ-NEXT:    retq
363  %tmp1 = xor i64 %x, -1
364  %tmp2 = call i64 @llvm.ctlz.i64( i64 %tmp1, i1 false )
365  ret i64 %tmp2
366}
367
368define i64 @ctlo_i64_undef(i64 %x) {
369; X86-NOCMOV-LABEL: ctlo_i64_undef:
370; X86-NOCMOV:       # %bb.0:
371; X86-NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
372; X86-NOCMOV-NEXT:    notl %eax
373; X86-NOCMOV-NEXT:    testl %eax, %eax
374; X86-NOCMOV-NEXT:    jne .LBB7_1
375; X86-NOCMOV-NEXT:  # %bb.2:
376; X86-NOCMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
377; X86-NOCMOV-NEXT:    notl %eax
378; X86-NOCMOV-NEXT:    bsrl %eax, %eax
379; X86-NOCMOV-NEXT:    xorl $31, %eax
380; X86-NOCMOV-NEXT:    orl $32, %eax
381; X86-NOCMOV-NEXT:    xorl %edx, %edx
382; X86-NOCMOV-NEXT:    retl
383; X86-NOCMOV-NEXT:  .LBB7_1:
384; X86-NOCMOV-NEXT:    bsrl %eax, %eax
385; X86-NOCMOV-NEXT:    xorl $31, %eax
386; X86-NOCMOV-NEXT:    xorl %edx, %edx
387; X86-NOCMOV-NEXT:    retl
388;
389; X86-CMOV-LABEL: ctlo_i64_undef:
390; X86-CMOV:       # %bb.0:
391; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %eax
392; X86-CMOV-NEXT:    movl {{[0-9]+}}(%esp), %ecx
393; X86-CMOV-NEXT:    notl %eax
394; X86-CMOV-NEXT:    notl %ecx
395; X86-CMOV-NEXT:    bsrl %ecx, %edx
396; X86-CMOV-NEXT:    xorl $31, %edx
397; X86-CMOV-NEXT:    bsrl %eax, %eax
398; X86-CMOV-NEXT:    xorl $31, %eax
399; X86-CMOV-NEXT:    orl $32, %eax
400; X86-CMOV-NEXT:    testl %ecx, %ecx
401; X86-CMOV-NEXT:    cmovnel %edx, %eax
402; X86-CMOV-NEXT:    xorl %edx, %edx
403; X86-CMOV-NEXT:    retl
404;
405; X64-LABEL: ctlo_i64_undef:
406; X64:       # %bb.0:
407; X64-NEXT:    notq %rdi
408; X64-NEXT:    bsrq %rdi, %rax
409; X64-NEXT:    xorq $63, %rax
410; X64-NEXT:    retq
411;
412; X86-CLZ-LABEL: ctlo_i64_undef:
413; X86-CLZ:       # %bb.0:
414; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
415; X86-CLZ-NEXT:    notl %eax
416; X86-CLZ-NEXT:    testl %eax, %eax
417; X86-CLZ-NEXT:    jne .LBB7_1
418; X86-CLZ-NEXT:  # %bb.2:
419; X86-CLZ-NEXT:    movl {{[0-9]+}}(%esp), %eax
420; X86-CLZ-NEXT:    notl %eax
421; X86-CLZ-NEXT:    lzcntl %eax, %eax
422; X86-CLZ-NEXT:    addl $32, %eax
423; X86-CLZ-NEXT:    xorl %edx, %edx
424; X86-CLZ-NEXT:    retl
425; X86-CLZ-NEXT:  .LBB7_1:
426; X86-CLZ-NEXT:    lzcntl %eax, %eax
427; X86-CLZ-NEXT:    xorl %edx, %edx
428; X86-CLZ-NEXT:    retl
429;
430; X64-CLZ-LABEL: ctlo_i64_undef:
431; X64-CLZ:       # %bb.0:
432; X64-CLZ-NEXT:    notq %rdi
433; X64-CLZ-NEXT:    lzcntq %rdi, %rax
434; X64-CLZ-NEXT:    retq
435  %tmp1 = xor i64 %x, -1
436  %tmp2 = call i64 @llvm.ctlz.i64( i64 %tmp1, i1 true )
437  ret i64 %tmp2
438}
439