https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121136

            Bug ID: 121136
           Summary: Missed optimization: (x <= 0xFFFFF) in '-Os' mode can
                    convert to ((x >> 20) == 0)
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Explorer09 at gmail dot com
  Target Milestone: ---

Test code

```c
#include <stdbool.h>
#include <stdint.h>

bool func1(uint32_t x) {
    return x < 0x100000U;
}

bool func2(uint32_t x) {
    return ((x >> 20) == 0);
}

bool func3(uint32_t x) {
    return ((x / 0x100000U) == 0);
}
```

The three functions are equivalent. Specifically the threshold constant to be
compared with is a power-of-two. If there is no shortage of temporary
registers, then the right shift version (that is, func2) will likely make the
smallest code.

The actual result I tested in gcc is:

gcc can recognize func3 and func1 are equivalent (it optimizes func3 to func1),
but missed func2. Also it doesn't realize func2 can make the smallest code (at
least in x86-64 and RISC-V targets; it likely misses for ARM too but I didn't
test it thoroughly and so can't tell for sure). I assume `-Os` optimization
mode here.

This is the assembly I expected for x86-64:

```
        shrl    $20, %edi
        sete    %al
        ret
```

And for RV64:

```
        srliw   a0,a0,20
        seqz    a0,a0
        ret
```

(This issue report is related to bug 115529 - maybe I can consider this a
sub-issue of it.)

Reply via email to