Issue 108829
Summary Simple bit manipulation resulting in disjoint set could be tracked
Labels new issue
Assignees
Reporter Validark
    I just saw this scenario in my real code (simplified):

```zig
export fn foo(s: u64) u64 {
    const iter = s & ~(s << 1);
    return iter | (iter << 1);
}
```

For your convenience, here is a C version:

```c
#include <stdint.h>

uint64_t foo(uint64_t s) {
    uint64_t iter = s & ~(s << 1);
    return iter | (iter << 1);
}
```

Currently gives this assembly:

```asm
foo:
        lea     rax, [rdi + rdi]
 andn    rax, rax, rdi
        lea     rcx, [rax + rax]
        or rax, rcx
        ret
```

I realized that there is an optimization here, we can turn the `|` into a `+`, because `iter` is necessarily disjoint with `iter << 1`. [Z3 agrees](https://alive2.llvm.org/ce/z/ALEMHA). That means we can get this emit:

```asm
foo:
        lea     rax, [rdi + rdi]
 andn    rax, rax, rdi
        lea     rax, [rax + 2*rax]
 ret
```


_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to