On 5/28/2026 1:52 AM, Jin Ma wrote:
> The GCC Internals Manual, section 19.8 "Register Classes", documents
> REGNO_REG_CLASS as:
>
> REGNO_REG_CLASS (regno) [Macro]
> A C expression whose value is a register class containing hard
> register regno. In general there is more than one such class;
> choose a class which is minimal, meaning that no smaller class
> also contains the register.
>
> riscv_regno_to_class[] currently maps every FP hard register to
> RVC_FP_REGS, but RVC_FP_REGS only contains f8-f15. The entries for
> f0-f7 and f16-f31 therefore violate the "containing hard register
> regno" half of the contract: the returned class does not contain the
> register at all.
>
> The mismatch corrupts IRA's cost model. setup_allocno_cost_vector
> indexes the per-hard-reg cost slot via REGNO_REG_CLASS:
>
> rclass = REGNO_REG_CLASS (hard_regno);
> num = cost_classes_ptr->index[rclass];
> ...
> reg_costs[j] = COSTS (costs, i)->cost[num];
>
> After setup_regno_cost_classes_by_mode adds RVC_FP_REGS to the cost
> classes, the cost for e.g. f16 is silently read from the RVC_FP_REGS
> slot.
>
> The new fp-reg-class.c testcase puts eight "cf"- and sixteen "f"-
> constrained doubles live across a call. In the buggy state IRA
> places the cf pseudos outside the cf class and LRA recovers with
> sixteen fmv.d to fs* registers; with the fix IRA spills those values
> honestly and the IRA "+++Costs" line reports a non-zero "mem"
> component.
>
> Fix it by giving each FP hard register its minimal class: FP_REGS for
> f0-f7 and f16-f31, RVC_FP_REGS for f8-f15. As a companion change,
> switch riscv_secondary_memory_needed from class-equality tests to
> reg_class_subset_p so it still recognises the FP side regardless of
> which subclass the table returns.
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.cc (riscv_regno_to_class): Use the minimal
> class containing each FP hard register: FP_REGS for f0-f7 and
> f16-f31, RVC_FP_REGS for f8-f15.
> (riscv_secondary_memory_needed): Use reg_class_subset_p to
> detect FP classes.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/fp-reg-class.c: New test.
OK. Curious how you found this. Guessing you were looking at a
benchmark and saw more fmv instructions than looked sensible?
Thanks!
jeff