https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127810
Bug ID: 127810
Summary: RV32 Incorrect inlining of struct field access on
union
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: [email protected]
Target Milestone: ---
GCC 16.2.0 from the extra/riscv64-elf-newlib Arch package.
Test case:
---------------------------------------
#define DIVISOR 30000000U
typedef union
{
struct
{
unsigned char pad0;
unsigned char target;
unsigned char pad1;
} s;
unsigned int w;
} my_union;
volatile unsigned int data = 0xff01ff;
unsigned char extract_field()
{
my_union cs = {.w = data};
return cs.s.target;
}
unsigned int convert_val(unsigned int val)
{
unsigned long long tmp = ((unsigned long long)val << 33) / (unsigned long
long)DIVISOR;
return (unsigned int)(tmp / 2);
}
int main() {
// Expected result: extract_field() == 0x01 -> u == 143 & 0xff =
exit code 143
// Unexpected result: extract_field() == 0xff01 -> u == 9345992 & 0xff =
exit code 200
unsigned int u =
convert_val(extract_field());
return u;
}
---------------------------------------
Command line and output:
---------------------------------------
riscv64-elf-gcc -v -save-temps -Wall -Wextra -march=rv32imac -mabi=ilp32 -O2
mwe.c -o mwe
Using built-in specs.
COLLECT_GCC=riscv64-elf-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/riscv64-elf/16.2.0/lto-wrapper
Target: riscv64-elf
Configured with: /build/riscv64-elf-gcc/src/gcc-16.2.0/configure
--target=riscv64-elf --prefix=/usr --with-sysroot=/usr/riscv64-elf
--with-native-system-header-dir=/include --libexecdir=/usr/lib
--enable-languages=c,c++ --enable-threads=single --enable-plugins
--enable-multilib --enable-libgcc --disable-libgomp --disable-libquadmath
--disable-libffi --disable-libssp --disable-libmudflap --disable-decimal-float
--disable-libstdcxx-pch --disable-nls --disable-shared --disable-tls
--with-newlib --with-gnu-as --with-gnu-ld --with-system-zlib
--with-headers=/usr/riscv64-elf/include --with-python-dir=share/gcc-riscv64-elf
--with-gmp --with-mpfr --with-mpc --with-isl --with-libelf
--enable-gnu-indirect-function --with-pkgversion='Arch Linux Repositories'
--with-bugurl=https://gitlab.archlinux.org/archlinux/packaging/packages/riscv64-elf-gcc/-/issues
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 16.2.0 (Arch Linux Repositories)
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-march=rv32imac'
'-mabi=ilp32' '-O2' '-o' 'mwe' '-misa-spec=20191213'
'-march=rv32imac_zmmul_zaamo_zalrsc_zca'
/usr/lib/gcc/riscv64-elf/16.2.0/cc1 -E -quiet -v -imultilib rv32imac/ilp32
mwe.c -march=rv32imac -mabi=ilp32 -misa-spec=20191213
-march=rv32imac_zmmul_zaamo_zalrsc_zca -Wall -Wextra -O2 -fpch-preprocess -o
mwe.i
ignoring nonexistent directory "/usr/riscv64-elf/usr/local/include"
ignoring duplicate directory "/usr/riscv64-elf/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/riscv64-elf/16.2.0/include
/usr/lib/gcc/riscv64-elf/16.2.0/include-fixed
/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-march=rv32imac'
'-mabi=ilp32' '-O2' '-o' 'mwe' '-misa-spec=20191213'
'-march=rv32imac_zmmul_zaamo_zalrsc_zca'
/usr/lib/gcc/riscv64-elf/16.2.0/cc1 -fpreprocessed mwe.i -quiet -dumpbase
mwe.c -dumpbase-ext .c -march=rv32imac -mabi=ilp32 -misa-spec=20191213
-march=rv32imac_zmmul_zaamo_zalrsc_zca -O2 -Wall -Wextra -version -o mwe.s
GNU C23 (Arch Linux Repositories) version 16.2.0 (riscv64-elf)
compiled by GNU C version 16.2.1 20260810, GMP version 6.3.0, MPFR
version 4.2.2, MPC version 1.4.1, isl version isl-0.28-GMP
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 124f6cb1a76ad5a7e253787b2e4451b5
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-march=rv32imac'
'-mabi=ilp32' '-O2' '-o' 'mwe' '-misa-spec=20191213'
'-march=rv32imac_zmmul_zaamo_zalrsc_zca'
/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/bin/as -v
--traditional-format -march=rv32imac -march=rv32imac_zmmul_zaamo_zalrsc_zca
-mabi=ilp32 -misa-spec=20191213 -o mwe.o mwe.s
GNU assembler version 2.47 (riscv64-elf) using BFD version (GNU Binutils)
2.47.20260726
COMPILER_PATH=/usr/lib/gcc/riscv64-elf/16.2.0/:/usr/lib/gcc/riscv64-elf/16.2.0/:/usr/lib/gcc/riscv64-elf/:/usr/lib/gcc/riscv64-elf/16.2.0/:/usr/lib/gcc/riscv64-elf/:/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/bin/
LIBRARY_PATH=/usr/lib/gcc/riscv64-elf/16.2.0/rv32imac/ilp32/:/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/lib/rv32imac/ilp32/:/usr/riscv64-elf/lib/rv32imac/ilp32/:/usr/lib/gcc/riscv64-elf/16.2.0/:/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/lib/:/usr/riscv64-elf/lib/
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-march=rv32imac'
'-mabi=ilp32' '-O2' '-o' 'mwe' '-misa-spec=20191213'
'-march=rv32imac_zmmul_zaamo_zalrsc_zca' '-dumpdir' 'mwe.'
/usr/lib/gcc/riscv64-elf/16.2.0/collect2 -plugin
/usr/lib/gcc/riscv64-elf/16.2.0/liblto_plugin.so
-plugin-opt=/usr/lib/gcc/riscv64-elf/16.2.0/lto-wrapper
-plugin-opt=-fresolution=mwe.res -plugin-opt=-pass-through=-lgcc
-plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgloss
-plugin-opt=-pass-through=-lgcc --sysroot=/usr/riscv64-elf -melf32lriscv -X -o
mwe
/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/lib/rv32imac/ilp32/crt0.o
/usr/lib/gcc/riscv64-elf/16.2.0/rv32imac/ilp32/crtbegin.o
-L/usr/lib/gcc/riscv64-elf/16.2.0/rv32imac/ilp32
-L/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/lib/rv32imac/ilp32
-L/usr/riscv64-elf/lib/rv32imac/ilp32 -L/usr/lib/gcc/riscv64-elf/16.2.0
-L/usr/lib/gcc/riscv64-elf/16.2.0/../../../../riscv64-elf/lib
-L/usr/riscv64-elf/lib mwe.o -lgcc --start-group -lc -lgloss --end-group -lgcc
/usr/lib/gcc/riscv64-elf/16.2.0/rv32imac/ilp32/crtend.o
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-march=rv32imac'
'-mabi=ilp32' '-O2' '-o' 'mwe' '-misa-spec=20191213'
'-march=rv32imac_zmmul_zaamo_zalrsc_zca' '-dumpdir' 'mwe.'
---------------------------------------
Running with qemu-riscv32, I would expect return code 143. What I get is return
code 200 and checking with GDB, u actually computes to 9345992 (& 0xff = exit
code 200) instead of the expected 143. If I omit "-O2" from the command line, I
get the expected result.
Looking at the generated assembly, extract_field appears to be generated
correctly:
extract_field:
lui a5,%hi(data)
lw a0,%lo(data)(a5)
srli a0,a0,8
andi a0,a0,0xff
ret
A right shift by 8 and a subsequent andi 0xff extract the value of "target"
correctly. However, what gets inlined into main is not correct:
main:
lui a5,%hi(data)
lw a1,%lo(data)(a5)
li a2,29999104
addi sp,sp,-16
srli a1,a1,8
addi a2,a2,896
li a3,0
li a0,0
slli a1,a1,1
sw ra,12(sp)
call __udivdi3
lw ra,12(sp)
srli a0,a0,1
slli a1,a1,31
add a0,a1,a0
addi sp,sp,16
jr ra
Here we can see the right-shift again, but the andi 0xff is missing.