https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123689
Bug ID: 123689
Summary: Missed optimization in RISCV, LI instruction
duplicated
Product: gcc
Version: 15.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: gregory.trunde at tdk dot com
Target Milestone: ---
Created attachment 63387
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63387&action=edit
Test case C source file
Hi,
I am working with a RISCV processor in an embedded system, in which it is
frequent to do load/store to memory mapped peripheral I/O registers. In certain
circumstances the assembly generated by GCC is not optimal. The LI instruction
loading the higher bits of the address may be duplicated when accessing several
adjacent memory mapped registers.
Here is the test case C code (test.c):
=======================================================
#define _REG4(offset) (*(int*)(0x81000000 + (offset)))
#define TEST0_REG _REG4(0x9000)
#define TEST1_REG _REG4(0x90c8)
#define TEST2_REG _REG4(0x9190)
#define TEST3_REG _REG4(0x9258)
void test(int samples[4])
{
samples[0] = TEST0_REG;
samples[1] = TEST1_REG;
samples[2] = TEST2_REG;
samples[3] = TEST3_REG;
}
=======================================================
The code is compiled for RV32 target:
riscv64-unknown-elf-gcc -o test.s test.c -S -Os -march=rv32i -mabi=ilp32
The output assembly shows duplicated LI instructions loading the same value
four times, which takes cycles and code space:
=======================================================
test:
li a5,-2130669568
lw a5,0(a5)
sw a5,0(a0)
li a5,-2130669568
lw a5,200(a5)
sw a5,4(a0)
li a5,-2130669568
lw a5,400(a5)
sw a5,8(a0)
li a5,-2130669568
lw a5,600(a5)
sw a5,12(a0)
ret
=======================================================
It is expected that the LI instruction appears only once, and is shared by all
LW operations, like this:
=======================================================
test:
li t0,-2130669568
lw a5,0(t0)
sw a5,0(a0)
lw a5,200(t0)
sw a5,4(a0)
lw a5,400(t0)
sw a5,8(a0)
lw a5,600(t0)
sw a5,12(a0)
ret
=======================================================
During my experimentation I noticed that this optimization bug can appear or
disappear for no apparent reason.
Can you please fix GCC so this optimization is applied consistently ? Thank you
very much.
Version of GCC:
riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=C:\msys64\opt\riscv-gnu-toolchain\bin\riscv64-unknown-elf-gcc.exe
COLLECT_LTO_WRAPPER=C:/msys64/opt/riscv-gnu-toolchain/libexec/gcc/riscv64-unknown-elf/15.2.0/lto-wrapper.exe
Target: riscv64-unknown-elf
Configured with: /home/****/riscv-gnu-toolchain/gcc/configure
--target=riscv64-unknown-elf --prefix=/opt/riscv-gnu-toolchain --disable-shared
--disable-threads --enable-languages=c,c++ --with-pkgversion=
--with-system-zlib --enable-tls --with-newlib
--with-sysroot=/opt/riscv-gnu-toolchain/riscv64-unknown-elf
--with-native-system-header-dir=/include --disable-libmudflap --disable-libssp
--disable-libquadmath --disable-libgomp --disable-nls
--disable-tm-clone-registry --src=.././gcc --disable-multilib --with-abi=lp64d
--with-arch=rv64gc --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os
-mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 15.2.0 ()
Best regards