Issue 208989
Summary [AggressiveInstCombine] suboptimal debruijin clz pattern codegen
Labels llvm:instcombine, missed-optimization
Assignees
Reporter Andarwinux
    after https://github.com/llvm/llvm-project/issues/207571
```c
typedef unsigned long long uint64_t;

void
get_msb_index (unsigned long *result, uint64_t value)
{
  static const unsigned long deBruijnTable64[64] = {
    63, 0, 58, 1,  59, 47, 53, 2,  60, 39, 48, 27, 54,
    33, 42, 3,  61, 51, 37, 40, 49, 18, 28, 20, 55, 30,
    34, 11, 43, 14, 22, 4,  62, 57, 46, 52, 38, 26, 32,
    41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31,
    35, 16, 9, 12, 44, 24, 15, 8,  23, 7,  6,  5
  };

  value |= value >> 1;
  value |= value >> 2;
  value |= value >> 4;
  value |= value >> 8;
  value |= value >> 16;
  value |= value >> 32;

  *result = deBruijnTable64[((value - (value >> 1))
			     * (uint64_t) 0x07EDD5E59A4E28C2ULL) >> 58];
}
```
https://godbolt.org/z/znP3eYshv
clang:
```asm
get_msb_index:
 test    rsi, rsi
        je      .LBB0_1
        lzcnt   rax, rsi
 xor     rax, 63
        mov     qword ptr [rdi], rax
 ret
.LBB0_1:
        mov     eax, 63
        mov     qword ptr [rdi], rax
        ret
```
gcc:
```asm
"get_msb_index":
        lzcnt   rsi, rsi
        not     esi
        and     esi, 63
        mov     eax, esi
 mov     QWORD PTR [rdi], rax
        ret
```

LLVM generated a strange select:

```llvm
define dso_local void @get_msb_index(ptr nofree noundef writeonly captures(none) initializes((0, 8)) %result, i64 noundef %value) local_unnamed_addr {
entry:
  %0 = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %value, i1 true)
  %1 = xor i64 %0, 63
  %2 = icmp eq i64 %value, 0
  %3 = select i1 %2, i64 63, i64 %1
  store i64 %3, ptr %result, align 8
  ret void
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to