https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126074
Bug ID: 126074
Summary: Missing cases for constant synthesis on RISC-V
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: law at gcc dot gnu.org
Target Milestone: ---
The constant synthesis code for the RISC-V port does not currently utilize
shNadd.uw instructions. There is a class of constants where doing so would be
useful, though it's unclear how often these constants are occurring in
practice.
Conceptually these constants are going to be fairly narrow as many of the cases
are handled by existing shNadd support as well as other mechanisms.
What I've come up with is the constant must have bit 31+N on. Bits 32+N up to
bit 63 must be off. The constant must be evenly divisible by 3, 5, or 9 for N
== 1, 2 or 3 respectively. If we divide the constant by 3, 5 or 9 the result
of that division must have bit 31 set and the low 12 bits clear.
As a concrete example, consider 0x180005000UL.
lui t0, 0x80001 // Produces 0xffffffff80001000
sh2add dest,t0,t0 // Produces 0x180005000
Right now LLVM and gcc generate
lui a0, 384 // produces 0x180000
addi a0, a0, 5 // produces 0x180005
slli a0, a0, 12 // produces 0x180005000
So we'd save one instruction for this class of constants.
The biggest worry I'd have would be if there are constants that fit this
pattern, but which are more efficiently synthesized through other means.