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

            Bug ID: 119683
           Summary: [13/14 Regression] recalculating the return value
                    which was already in the register right before
                    function return
           Product: gcc
           Version: 13.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nikola at radojevic dot rs
  Target Milestone: ---

This C function demonstrates the regression, all of the examples are compiled
with just -O3:
unsigned ctoint(char c) {
        if (c >= '0' && c <= '9')
                return c - '0';

        if (c >= 'a' && c <= 'z')
                return c - 'a' + 10;

        if (c >= 'A' && c <= 'Z')
                return c - 'A' + 10;

        return -1;
}

gcc 13.1 on godbolt generates the following code:
  1 ctoint:
  2         leal    -48(%rdi), %eax
  3         cmpb    $9, %al
  4         jbe     .L7
  5         leal    -97(%rdi), %eax
  6         cmpb    $25, %al
  7         jbe     .L8
  8         leal    -65(%rdi), %edx
  9         movsbl  %dil, %eax
 10         subl    $55, %eax
 11         cmpb    $26, %dl
 12         movl    $-1, %edx
 13         cmovnb  %edx, %eax
 14         ret
 15 .L8:
 16         movsbl  %dil, %edi
 17         leal    -87(%rdi), %eax
 18         ret
 19 .L7:
 20         movsbl  %dil, %edi
 21         leal    -48(%rdi), %eax
 22         ret

It calculates and stores the return value in %eax on line 2, and after a
compare and a jump, it recalculates the same exactly value on line 21.

For reference, gcc 12.4 on godbolt.org generates the following code, note that
it reuses the value that's already in the register on line 20:
  1 ctoint:
  2         leal    -48(%rdi), %eax
  3         cmpb    $9, %al
  4         jbe     .L7
  5         leal    -97(%rdi), %eax
  6         cmpb    $25, %al
  7         jbe     .L8
  8         leal    -65(%rdi), %edx
  9         leal    -55(%rdi), %eax
 10         cmpb    $26, %dl
 11         movsbl  %al, %eax
 12         movl    $-1, %edx
 13         cmovnb  %edx, %eax
 14         ret
 15 .L8:
 16         subl    $87, %edi
 17         movsbl  %dil, %eax
 18         ret
 19 .L7:
 20         movsbl  %al, %eax
 21         ret

Here's the godbolt link: https://c.godbolt.org/z/MK6v6f5Kj
I first noticed this issue on my distro's gcc 14:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure
--enable-languages=ada,c,c++,d,fortran,go,lto,m2,objc,obj-c++,rust
--enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib
--mandir=/usr/share/man --infodir=/usr/share/info
--with-bugurl=https://gitea.artixlinux.org/packages/gcc/issues
--with-build-config=bootstrap-lto --with-linker-hash-style=gnu
--with-system-zlib --enable-__cxa_atexit --enable-cet=auto
--enable-checking=release --enable-clocale=gnu --enable-default-pie
--enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object
--enable-libstdcxx-backtrace --enable-link-serialization=1
--enable-linker-build-id --enable-lto --enable-multilib --enable-plugin
--enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch
--disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.1 20250207 (GCC)

Reply via email to