Hello everyone, I wanted to add that this patch makes ssa-sink-18.c test fail on x86, due to the similar reasons this test was expected to fail for some architectures; namely, if the ivopt uses two candidates for the testcase, that cuts down the amount of sinking optimizations we can do, making the test fail.
As this change is architecture-agnostic, I suspect this test will fail in general, due to the ivopt candidate selection being changed with this patch. I didn't want to mark the test as XFAIL until consulting the community on the proper course of action. All suggestions will be greatly appreciated. Thanks, Jovan On 5/20/26 14:37, Jovan Dmitrović wrote: > Currently, ivopt calculates register pressure cost so that the cost of > spilling induction variables is exactly double the cost of spilling > loop invariants, which is not exactly right. > As ivopts already has `adjust_setup_cost` function, we can use it > in order to make the invariant part of the cost relatively cheaper. > > Tested with CoreMark PRO on RISC-V P8700 CPU (~1.2% improvement), > and on x86-64 Intel Core i7-12700H CPU (~0.4% improvement). > > gcc/ChangeLog: > > * tree-ssa-loop-ivopts.cc (ivopts_estimate_reg_pressure): > Change register pressure estimate in order to respect > the impact of spilling induction variables, compared > to spilling loop invariants. > > Co-authored-by: Radosav Krunić <[email protected]> > Signed-off-by: Djordje Todorović <[email protected]> > Signed-off-by: Chao-Ying Fu <[email protected]> > Signed-off-by: Jovan Dmitrović <[email protected]> > Signed-off-by: Radosav Krunić <[email protected]> > --- > gcc/tree-ssa-loop-ivopts.cc | 23 +++++++++++++---------- > 1 file changed, 13 insertions(+), 10 deletions(-) > > diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc > index 776487d0f8b1..19ba620fb070 100644 > --- a/gcc/tree-ssa-loop-ivopts.cc > +++ b/gcc/tree-ssa-loop-ivopts.cc > @@ -6085,6 +6085,7 @@ ivopts_estimate_reg_pressure (struct ivopts_data *data, > unsigned n_invs, > unsigned cost; > unsigned n_old = data->regs_used, n_new = n_invs + n_cands; > unsigned regs_needed = n_new + n_old, available_regs = target_avail_regs; > + unsigned iv_spill_cost = 0; > bool speed = data->speed; > > /* If there is a call in the loop body, the call-clobbered registers > @@ -6094,7 +6095,7 @@ ivopts_estimate_reg_pressure (struct ivopts_data *data, > unsigned n_invs, > > /* If we have enough registers. */ > if (regs_needed + target_res_regs < available_regs) > - cost = n_new; > + cost = 0; > /* If close to running out of registers, try to preserve them. */ > else if (regs_needed <= available_regs) > cost = target_reg_cost [speed] * regs_needed; > @@ -6103,17 +6104,19 @@ ivopts_estimate_reg_pressure (struct ivopts_data > *data, unsigned n_invs, > else if (n_cands <= available_regs) > cost = target_reg_cost [speed] * available_regs > + target_spill_cost [speed] * (regs_needed - available_regs); > - /* If the number of candidates runs out available registers, we penalize > - extra candidate registers using target_spill_cost * 2. Because it is > - more expensive to spill induction variable than invariant. */ > + /* If the number of candidates runs out available registers, > + save the spill cost as separate variable iv_spill_cost. */ > else > - cost = target_reg_cost [speed] * available_regs > - + target_spill_cost [speed] * (n_cands - available_regs) * 2 > - + target_spill_cost [speed] * (regs_needed - n_cands); > + { > + cost = target_reg_cost [speed] * available_regs > + + target_spill_cost [speed] * (regs_needed - n_cands); > + iv_spill_cost = target_spill_cost[speed] * > + (n_cands - available_regs); > + } > > - /* Finally, add the number of candidates, so that we prefer eliminating > - induction variables if possible. */ > - return cost + n_cands; > + /* Adjust cost of invariant register pressure in order to make > + the spilling of induction variables the most taxing. */ > + return adjust_setup_cost(data, cost) + iv_spill_cost; > } > > /* For each size of the induction variable set determine the penalty. */
