https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127778
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jeff Law <[email protected]>: https://gcc.gnu.org/g:8ebf07db4065afb654756ae77d397e2024fef436 commit r17-5116-g8ebf07db4065afb654756ae77d397e2024fef436 Author: Jeff Law <[email protected]> Date: Tue Oct 13 07:17:57 2026 -0600 [RISC-V][PR target/127778] Use synthesize_add more on RISC-V As the pr127778 shows the changes to generally improve how we synthesize x+C regressed a class of cases, particularly those with C in the range [2048..4095] that are used as an address for a memory reference during initial RTL generation. The problem can be seen in this .expand fragment: (insn 7 4 8 2 (set (reg:DI 136) (const_int 4096 [0x1000])) "j.c":4:11 -1 (nil)) (insn 8 7 9 2 (set (reg/f:DI 137) (plus:DI (reg/v/f:DI 134 [ p ]) (reg:DI 136))) "j.c":4:11 -1 (nil)) (insn 9 8 0 2 (set (mem:SI (plus:DI (reg/f:DI 137) (const_int -96 [0xffffffffffffffa0])) [1 MEM[(int *)p_1(D) + 4000B]+0 S4 A32]) (subreg/s/u:SI (reg/v:DI 135 [ v ]) 0)) "j.c":4:11 -1 (nil)) So we're not using add synthesis, but instead falling back to naive code generation. It turns out there's a path through the RISC-V target files which avoids the add expanders. So while we could try to recover good code generation later, it seems much better to just generate reasonable code at the gimple-RTL phase. This patch intercepts the path through riscv_add_offset and will use synthesize_add when possible. So we get this kind of initial RTL instead: (insn 7 4 8 2 (set (reg/f:SI 136) (plus:SI (reg/v/f:SI 134 [ p ]) (const_int 1953 [0x7a1]))) "j.c":4:15 -1 (nil)) (insn 8 7 9 2 (set (reg/f:SI 136) (plus:SI (reg/f:SI 136) (const_int 2047 [0x7ff]))) "j.c":4:15 -1 (nil)) (insn 9 8 0 2 (set (mem:SI (reg/f:SI 136) [1 MEM[(int *)p_1(D) + 4000B]+0 S4 A32]) (reg/v:SI 135 [ v ])) "j.c":4:15 -1 (nil)) It's trivial to combine insn 8 and insn 9 resulting in the final code generation we want to see. We still bypass the synthesis code when presented with the code in pr105733: > #define BUF_SIZE 2064 > > void > foo(unsigned long i) > { > volatile char buf[BUF_SIZE]; > > buf[i] = 0; > } > In this case the offset is going to be formed with virtual-stack-vars. That later gets turned into sp+offset. Anyway, the initial code generation for that case looks like this if we're not careful: (insn 6 3 7 2 (set (reg/f:SI 135) (plus:SI (reg/f:SI 129 virtual-stack-vars) (const_int -16 [0xfffffffffffffff0]))) "j.c":8:12 -1 (nil)) (insn 7 6 8 2 (set (reg/f:SI 135) (plus:SI (reg/f:SI 135) (const_int -2048 [0xfffffffffffff800]))) "j.c":8:12 -1 (nil)) (insn 8 7 9 2 (set (reg/f:SI 136) (plus:SI (reg/f:SI 135) (reg/v:SI 134 [ i ]))) "j.c":8:12 -1 (nil)) (insn 9 8 0 2 (set (mem/v:QI (reg/f:SI 136) [0 buf[i_2(D)]+0 S1 A8]) (const_int 0 [0])) "j.c":8:12 -1 (nil)) In this case we'd be dependent upon something rewriting this mess to push the constant offset down into the mem, and clean up the virtual-stack-vars reference post-reload. fold-mem-offsets would be the natural choice. But it's easy enough to special case the base registers that get eliminated so that the initial RTL we generate looks like this: (insn 6 3 7 2 (set (reg:SI 135) (const_int -4096 [0xfffffffffffff000])) "j.c":8:12 -1 (nil)) (insn 7 6 8 2 (set (reg/f:SI 136) (plus:SI (reg/f:SI 129 virtual-stack-vars) (reg:SI 135))) "j.c":8:12 -1 (nil)) (insn 8 7 9 2 (set (reg/f:SI 137) (plus:SI (reg/f:SI 136) (reg/v:SI 134 [ i ]))) "j.c":8:12 -1 (nil)) (insn 9 8 0 2 (set (mem/v:QI (plus:SI (reg/f:SI 137) (const_int 2032 [0x7f0])) [0 buf[i_2(D)]+0 S1 A8]) (const_int 0 [0])) "j.c":8:12 -1 (nil)) Which avoids regressing pr105733. There's still some cruft in the final assembly, but I think that's ultimately a failing of fold-mem-offsets that I haven't chased down. I'll get that cruft filed as a distinct bug against f-m-o. Tested on riscv32-elf and riscv64-elf. I don't recall if this made it into my tester's git repo early enough to make the overnight bootstraps. Regardless, it'll get picked up today/tonight. PR target/127778 gcc/ * config/riscv/riscv.cc (riscv_add_offset): Use synthesize_add when safe and likely profitable. gcc/testsuite * gcc.target/riscv/pr127778.c: New test.
