xref: /llvm-project/llvm/test/CodeGen/X86/bit_ceil.ll (revision 90e9895a9373b3d83eefe15b34d2dc83c7bcc88f)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-bmi2,-lzcnt | FileCheck %s --check-prefix=NOBMI
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi2,+lzcnt | FileCheck %s --check-prefix=BMI
4
5; Check the assembly sequence generated for std::bit_ceil.
6
7; std::bit_ceil<uint32_t>(x)
8define i32 @bit_ceil_i32(i32 %x) {
9; NOBMI-LABEL: bit_ceil_i32:
10; NOBMI:       # %bb.0:
11; NOBMI-NEXT:    # kill: def $edi killed $edi def $rdi
12; NOBMI-NEXT:    leal -1(%rdi), %eax
13; NOBMI-NEXT:    movl $63, %ecx
14; NOBMI-NEXT:    bsrl %eax, %ecx
15; NOBMI-NEXT:    xorl $31, %ecx
16; NOBMI-NEXT:    negb %cl
17; NOBMI-NEXT:    movl $1, %edx
18; NOBMI-NEXT:    movl $1, %eax
19; NOBMI-NEXT:    # kill: def $cl killed $cl killed $ecx
20; NOBMI-NEXT:    shll %cl, %eax
21; NOBMI-NEXT:    cmpl $2, %edi
22; NOBMI-NEXT:    cmovbl %edx, %eax
23; NOBMI-NEXT:    retq
24;
25; BMI-LABEL: bit_ceil_i32:
26; BMI:       # %bb.0:
27; BMI-NEXT:    # kill: def $edi killed $edi def $rdi
28; BMI-NEXT:    leal -1(%rdi), %eax
29; BMI-NEXT:    lzcntl %eax, %eax
30; BMI-NEXT:    negb %al
31; BMI-NEXT:    movl $1, %ecx
32; BMI-NEXT:    shlxl %eax, %ecx, %eax
33; BMI-NEXT:    cmpl $2, %edi
34; BMI-NEXT:    cmovbl %ecx, %eax
35; BMI-NEXT:    retq
36  %dec = add i32 %x, -1
37  %lz = tail call i32 @llvm.ctlz.i32(i32 %dec, i1 false)
38  %cnt = sub i32 32, %lz
39  %res = shl i32 1, %cnt
40  %ugt = icmp ugt i32 %x, 1
41  %sel = select i1 %ugt, i32 %res, i32 1
42  ret i32 %sel
43}
44
45; std::bit_ceil<uint32_t>(x + 1)
46define i32 @bit_ceil_i32_plus1(i32 noundef %x) {
47; NOBMI-LABEL: bit_ceil_i32_plus1:
48; NOBMI:       # %bb.0: # %entry
49; NOBMI-NEXT:    movl $63, %ecx
50; NOBMI-NEXT:    bsrl %edi, %ecx
51; NOBMI-NEXT:    xorl $31, %ecx
52; NOBMI-NEXT:    negb %cl
53; NOBMI-NEXT:    movl $1, %edx
54; NOBMI-NEXT:    movl $1, %eax
55; NOBMI-NEXT:    # kill: def $cl killed $cl killed $ecx
56; NOBMI-NEXT:    shll %cl, %eax
57; NOBMI-NEXT:    decl %edi
58; NOBMI-NEXT:    cmpl $-2, %edi
59; NOBMI-NEXT:    cmovael %edx, %eax
60; NOBMI-NEXT:    retq
61;
62; BMI-LABEL: bit_ceil_i32_plus1:
63; BMI:       # %bb.0: # %entry
64; BMI-NEXT:    lzcntl %edi, %eax
65; BMI-NEXT:    negb %al
66; BMI-NEXT:    movl $1, %ecx
67; BMI-NEXT:    shlxl %eax, %ecx, %eax
68; BMI-NEXT:    decl %edi
69; BMI-NEXT:    cmpl $-2, %edi
70; BMI-NEXT:    cmovael %ecx, %eax
71; BMI-NEXT:    retq
72entry:
73  %ctlz = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
74  %cnt = sub i32 32, %ctlz
75  %shl = shl i32 1, %cnt
76  %dec = add i32 %x, -1
77  %ult = icmp ult i32 %dec, -2
78  %sel = select i1 %ult, i32 %shl, i32 1
79  ret i32 %sel
80}
81
82; std::bit_ceil<uint64_t>(x)
83define i64 @bit_ceil_i64(i64 %x) {
84; NOBMI-LABEL: bit_ceil_i64:
85; NOBMI:       # %bb.0:
86; NOBMI-NEXT:    leaq -1(%rdi), %rax
87; NOBMI-NEXT:    movl $127, %ecx
88; NOBMI-NEXT:    bsrq %rax, %rcx
89; NOBMI-NEXT:    xorl $63, %ecx
90; NOBMI-NEXT:    negb %cl
91; NOBMI-NEXT:    movl $1, %edx
92; NOBMI-NEXT:    movl $1, %eax
93; NOBMI-NEXT:    # kill: def $cl killed $cl killed $rcx
94; NOBMI-NEXT:    shlq %cl, %rax
95; NOBMI-NEXT:    cmpq $2, %rdi
96; NOBMI-NEXT:    cmovbq %rdx, %rax
97; NOBMI-NEXT:    retq
98;
99; BMI-LABEL: bit_ceil_i64:
100; BMI:       # %bb.0:
101; BMI-NEXT:    leaq -1(%rdi), %rax
102; BMI-NEXT:    lzcntq %rax, %rax
103; BMI-NEXT:    negb %al
104; BMI-NEXT:    movl $1, %ecx
105; BMI-NEXT:    shlxq %rax, %rcx, %rax
106; BMI-NEXT:    cmpq $2, %rdi
107; BMI-NEXT:    cmovbq %rcx, %rax
108; BMI-NEXT:    retq
109  %dec = add i64 %x, -1
110  %lz = tail call i64 @llvm.ctlz.i64(i64 %dec, i1 false)
111  %cnt = sub i64 64, %lz
112  %res = shl i64 1, %cnt
113  %ugt = icmp ugt i64 %x, 1
114  %sel = select i1 %ugt, i64 %res, i64 1
115  ret i64 %sel
116}
117
118; std::bit_ceil<uint64_t>(x + 1)
119define i64 @bit_ceil_i64_plus1(i64 noundef %x) {
120; NOBMI-LABEL: bit_ceil_i64_plus1:
121; NOBMI:       # %bb.0: # %entry
122; NOBMI-NEXT:    movl $127, %ecx
123; NOBMI-NEXT:    bsrq %rdi, %rcx
124; NOBMI-NEXT:    xorl $63, %ecx
125; NOBMI-NEXT:    negb %cl
126; NOBMI-NEXT:    movl $1, %edx
127; NOBMI-NEXT:    movl $1, %eax
128; NOBMI-NEXT:    # kill: def $cl killed $cl killed $rcx
129; NOBMI-NEXT:    shlq %cl, %rax
130; NOBMI-NEXT:    decq %rdi
131; NOBMI-NEXT:    cmpq $-2, %rdi
132; NOBMI-NEXT:    cmovaeq %rdx, %rax
133; NOBMI-NEXT:    retq
134;
135; BMI-LABEL: bit_ceil_i64_plus1:
136; BMI:       # %bb.0: # %entry
137; BMI-NEXT:    lzcntq %rdi, %rax
138; BMI-NEXT:    negb %al
139; BMI-NEXT:    movl $1, %ecx
140; BMI-NEXT:    shlxq %rax, %rcx, %rax
141; BMI-NEXT:    decq %rdi
142; BMI-NEXT:    cmpq $-2, %rdi
143; BMI-NEXT:    cmovaeq %rcx, %rax
144; BMI-NEXT:    retq
145entry:
146  %ctlz = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
147  %cnt = sub i64 64, %ctlz
148  %shl = shl i64 1, %cnt
149  %dec = add i64 %x, -1
150  %ult = icmp ult i64 %dec, -2
151  %sel = select i1 %ult, i64 %shl, i64 1
152  ret i64 %sel
153}
154
155declare i32 @llvm.ctlz.i32(i32, i1 immarg)
156declare i64 @llvm.ctlz.i64(i64, i1 immarg)
157