- This c function demonstrates the regression, all of the examples are compiled with just -O3:
- 1 unsigned ctoint(char c) {
- 2 if (c >= '0' && c <= '9')
- 3 return c - '0';
- 4
- 5 if (c >= 'a' && c <= 'z')
- 6 return c - 'a' + 10;
- 7
- 8 if (c >= 'A' && c <= 'Z')
- 9 return c - 'A' + 10;
- 10
- 11 return -1;
- 12 }
- 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 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:
- 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= --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)