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

            Bug ID: 122943
           Summary: [14/15 Regression] Wrong code for switch on int64_t on
                    32-bit ARM at -O2
           Product: gcc
           Version: 14.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: baltth at gmail dot com
  Target Milestone: ---

Created attachment 62960
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=62960&action=edit
Preprocessed source of a function generating incorrect code with -O2

When compiling a switch statement on int64_t for 32-bit ARM with -O2,
GCC 14.2.0 may generate incorrect code that only compares the low 32 bits
(r0), ignoring the high 32 bits (r1).

Sample code:

```
unsigned char arm_switch_o2_bug(long long val) {
    unsigned char result = 0;
    switch (val) {
        case 0: result = 1; break;  /* val == INT64_MIN passes this label */
        case 1: result = 2; break;
        case 2: result = 3; break;
        default: break;
    }
    return result;
}
```

Compiled with arm-linux-gnueabi-gcc-14 -march=armv7ve -mthumb -O2 -S
./arm_switch_o2_bug.c

The generated assembly is
```
arm_switch_o2_bug:
        cmp     r0, #2
        itte    ls
        addls   r0, r0, #1
        uxtbls  r0, r0
        movhi   r0, #0
        bx      lr
```

Here r1 is ignored completely, causing all input values with
lower word value 0-2 mapped incorrectly.

arm-gcc 14.x and 15.x versions generate wrong code
(https://godbolt.org/z/do6bzsf6x)

arm-gcc version 13.x generates correct code,
adding an sbcs r1, r1, #0 instruction after cmp r0, #2
(https://godbolt.org/z/obrrcKv7a)


Conditions to trigger wrong code generation:
- use Thumb instructions on a 32 bit architecture
- use -O2
- create a switch
  - with condition type long long (or an enumeration with
    the same underlying type),
  - mapping sequence-to-sequence (e.g. 1,2,3 to 5,6,7),
  - having three or more case labels


Output of arm-linux-gnueabi-gcc-14 -v:
```
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabi-gcc-14
COLLECT_LTO_WRAPPER=/usr/libexec/gcc-cross/arm-linux-gnueabi/14/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Ubuntu
14.2.0-4ubuntu2~24.04' --with-bugurl=file:///usr/share/doc/gcc-14/README.Bugs
--enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr
--with-gcc-major-version-only --program-suffix=-14 --enable-shared
--enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext
--enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/
--enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace
--enable-gnu-unique-object --disable-libitm --disable-libquadmath
--disable-libquadmath-support --enable-plugin --with-system-zlib
--enable-libphobos-checking=release --without-target-system-zlib
--enable-multiarch --disable-sjlj-exceptions
--with-specs='%{mfloat-abi=hard:-march=armv7-a -mcpu=generic-armv7-a
-mfloat-abi=hard}' --with-arch=armv5t --with-float=soft --disable-werror
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=arm-linux-gnueabi --program-prefix=arm-linux-gnueabi-
--includedir=/usr/arm-linux-gnueabi/include
--with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.0 (Ubuntu 14.2.0-4ubuntu2~24.04)
```

Reply via email to