On 8/23/23 13:04, Jeff Law wrote:
Thanks for your patience on this. I needed a bit of time to gather my
thoughts and review some code.
No worries at all.
index 8b7256108157..1802eef908fc 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2464,14 +2464,9 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
case CONST:
if ((cost = riscv_const_insns (x)) > 0)
{
- /* If the constant is likely to be stored in a GPR, SETs of
- single-insn constants are as cheap as register sets; we
- never want to CSE them. */
+ /* Hoist will GCSE constants only if cost is non-zero. */
if (cost == 1 && outer_code == SET)
- *total = 0;
- /* When we load a constant more than once, it usually is better
- to duplicate the last operation in the sequence than to CSE
- the constant itself. */
+ *total = COSTS_N_INSNS (1);
else if (outer_code == SET || GET_MODE (x) == VOIDmode)
*total = COSTS_N_INSNS (1);
}
So the concern here was we have two classes of constants which can be
synthesized in a single instruction.
One class would be those constants that can be used as-is in most
instructions. (const_int 0) being the most obvious, but of course
there's many others.
The other class can be synthesized in a single instruction, but aren't
typically usable in something like addi, andi, etc. A good example
might be (const_int 0x40000000).
I wanted to make sure we were doing something sensible across those
two cases. And I think we probably are as we have an earlier check in
the CONST_INT case
Exactly, I have a note written down to trace the call flow to remind
myself how this works. I'll add a comment here to make this clear.
(no I don't like the case fallthrus at all :(
Seriously, I detest it too, but the irony is I've now made my 2nd change
in there and keep adding to ugliness :-(
So I think your change makes sense. But I think it can be refined to
simplify the larger chunk of code we're looking at:
/* If the constant is likely to be stored in a GPR, SETs of
single-insn constants are as cheap as register sets; we
never want to CSE them. */
if (cost == 1 && outer_code == SET)
*total = 0;
/* When we load a constant more than once, it usually is
better
to duplicate the last operation in the sequence than to CSE
the constant itself. */
else if (outer_code == SET || GET_MODE (x) == VOIDmode)
*total = COSTS_N_INSNS (1);
Turns into
if (outer_code == SET || GET_MODE (x) == VOIDmode)
*total = COSTS_N_INSNS (1);
Yep that's what I started with too but then left it, leaving it as an
visual indication to fix things up when ultimately cost model returns
the actual num of insns for a non trivial large const.Leaving the code
there meant we But I agree I'll fold it and add a TODO comment for
improving the cost model.
For the current proposal I do want to understand/reason what is left
there - what cases are we trying to filter out with #2467 ?
| case CONST:
| if ((cost = riscv_const_insns (x)) > 0) # 2465
| {
| if (outer_code == SET || GET_MODE (x) == VOIDmode) # 2467
| *total = COSTS_N_INSNS
(1); # 2468
(1) AFAIU, VOIDmode is for const_int - and supposedly true for symbolic
addresses etc whose actual values are not known at compile time ? Or is
it needed just as an artifact of the weird fall through.
(2) outer_code SET will kick in for set_src_cost( ) call from Hoist,
which passes a const_int rtx directly.
But in case of say expand_mult () -> set_src_cost ( ) called for say
(mult:DI (reg:DI 134)
(const_int [0x202020202020202]))
In the eventual call for const_int operand, outer_code is MULT,
so we elide #2468
But wait we don't even hit #2467 since #2465 has a weird cap
inside which caps 6 to 0.
| case CONST_INT:
| {
| int cost = riscv_integer_cost (INTVAL (x));
| /* Force complicated constants to memory. */
| return cost < 4 ? cost : 0; #1321
| }
This definitely needs to be tracked separately in a PR
With a suitable comment about GCSE and the general desire to duplicate
the last op rather than CSE the constant for multi instruction
constant synthesis cases.
Hmm, do we not prefer GCSE/CSE a 3-4 insn const sequence. It seems the
RA is capable enough of undoing that ;-)
For now I can I can keep the comment with current philosophy
If you agree, then consider the patch pre-approved with that change.
If not, then state why and your original patch is OK as well.
I'm afraid I have more questions than either of us were hoping for :-)
But it seems we can chunk up the work for just Hoist enabling and then
improve the const cost model with that new PR.
I'll spin up a buildroot testbed to get a wider impact of that change.
Thx,
-Vineet