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