https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122869
--- Comment #2 from Jeffrey A. Law <law at gcc dot gnu.org> ---
I don't see a viable solution here without a rethink of how we handle the FoF
loads. Before gimple lowering we have:
g = __riscv_vle16ff_v_i16mf2 (_1, &d, d.0_2);
d.1_3 = d;
That's fine. In that form we can essentially pretend we have a function call
that's going to set d to the new VL. When we lower we turn it into:
g = __riscv_vle16ff_v_i16mf2 (_1, &d, d.0_2);
new_vl.2 = __riscv_read_vl ();
MEM[(long unsigned int *)&d] = new_vl.2;
Which is fundamentally broken. We have absolutely no way to ensure that VL
doesn't get clobbered between the FoF and the _riscv_read_vl "call".
Imagine if "g" does not get a hard register (-O0 or due to spilling). In that
case we'll store "g" into memory, potentially generating a vsetvl which will
clobber the VL.
I *think* we need to keep it in the higher level form until RTL expansion at
which point we can control the generated code better. As we go from gimple to
RTL we'd emit the FoF insn, csrr to its final destination, store the result of
the FoF into its final destination.
Other ideas?