Issue 129676
Summary Clang emits not the smallest code with `-Os` for `(unsigned)x >> C1 == C2`
Labels
Assignees
Reporter Explorer09
    ```c
unsigned int pred2_rshift(unsigned int x) {
    return (x >> 11) == 0x1B;
    // 0x1B == (0xD800 >> 11);
}
unsigned int pred2_bitand(unsigned int x) {
 return (x &= ~0x7FF) == 0xD800;
}
```

When tested on Compiler Explorer, x86-64 clang 19.1.0, with `-Os` option, `pred2_rshift` translates to `pred2_bitand` which is slightly larger code.

My expected result is the right shift should be used, as I specify `-Os` I expect smallest code size.

Note: The example code is part of [a report I reported to GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115529). When checking whether an integer is in a specified range, and the range happens to be aligned to a power of two, then all of these comparisons can do the same thing:

```c
unsigned int pred2(unsigned int x) {
    return x >= 0xD800 && x <= 0xDFFF;
}
unsigned int pred2_sub(unsigned int x) {
    return (x - 0xD800) <= (0xDFFF - 0xD800);
}
unsigned int pred2_bitand(unsigned int x) {
    return (x &= ~0x7FF) == 0xD800;
}
unsigned int pred2_bitor(unsigned int x) {
    return (x |= 0x7FF) == 0xDFFF;
}
unsigned int pred2_rshift(unsigned int x) {
    return (x >>= 11) == (0xD800 >> 11);
}
unsigned int pred2_div(unsigned int x) {
    return (x / 0x800) == (0xD800 / 0x800);
}
```

While Clang can recognize _all_ of these as equivalent (good job, by the way), it made a strange decision on which code to emit. While I can't tell which one is best for speed (performance), I can figure out which one is the smallest size.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to