On 8/14/24 10:20 AM, Xianmiao Qu wrote:
As I described in the commit message, the absence of clobber could
potentially lead to the register's lifetime occupying the entire function,
according to the algorithm of the 'df_lr_bb_local_compute' function.
And avoiding unnecessary liveness has always been the point of these
clobbers.
In the (mostly) forgotten past, those clobbers were often paired with
REG_NO_CONFLICT notes to help the register allocator know that the full
register value was set, even though it was set in pieces and that
certain conflicts could be ignored during register allocation. In both
cases the notes were dealing with lifetime related problems.
We've been slowly moving to a space where these are much less of a
concern and in fact we've totally removed REG_NO_CONFLICT blocks from
the compiler.
[ ... ]
It will still be considered within the LR IN. And its lifetime spans the entire
function.
Right. It's not ideal because if its life spans the entire function,
then it's going to have many more conflicts than are strictly necessary
which in turn will inhibit good register allocation.
I use the use case in my patch as a use case for RISC-V:
double foo (double a)
{
if (a < 0.0)
return a + 1.0;
else if (a > 16.0)
return a - 3.0;
else if (a < 300.0)
return a - 30.0;
else
return a;
}
As riscv don´t expand multi-register move in during the expand phase,
it will generate the following sequence of instructions.
(insn 7 6 8 (set (reg:DF 136)
(const_double:DF 0.0 [0x0.0p+0])) "r.c":3:6 -1
(nil))
(insn 8 7 9 (set (reg:DF 12 a2)
(reg:DF 136)) "r.c":3:6 -1
(nil))
(insn 9 8 10 (set (reg:DF 10 a0)
(reg/v:DF 135 [ a ])) "r.c":3:6 -1
(nil))
These are normal move instructions and the `init-regs´ pass will not
generate initialization instructions for them. So the CLOBBER instructions
are important for them.
?!? I don't think that's correct. Unless perhaps you're dealing with
rv32 in which case the DFmode moves are multi-register moves. Is that
the case?
If that is the case, then one could argue that the problem is really the
risc-v backend exposing a DFmode move that has to be lowered later. The
alternate approach is to not expose DFmode moves for rv32 and let the
generic expansion code deal with it.
There's a natural tension between when to expose early vs exposing late
and some things will work better with the former and others with the
latter. It's just the nature of the problem.
The general guidance would be to not expose a pattern unless the target
can natively handle that case -- until such point as there's clear
evidence that pretending to handle something it can't is better.
I'm relatively new to the risc-v port, so I don't know the history
behind exposing DFmode patterns for rv32. So I can't really suggest
disabling them as that could well be reverting a conscious decision that
generally gives us better code. And since I'm mostly focused on rv64,
I'm not in a position to do the deep analysis necessary to make that a
viable option.
Hopefully that gives a bit more background here. That natural tension
between early exposure and late exposure of the target's actual
capabilities is always a tough nut -- and decisions are somewhat fluid
as can be seen by the ongoing discussion around mvconst_internal.
jeff