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

Reply via email to