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.  */
-- 
2.34.1

Reply via email to