diff mbox

[loop2_invariant,1/2] Check only one register class

Message ID CACgzC7AM5DkDyibuCuTJp=DosH7q8fRM3TfEz_6WGkSYtkNLZA@mail.gmail.com
State New
Headers show

Commit Message

Zhenqiang Chen June 10, 2014, 9:22 a.m. UTC
Hi,

For loop2-invariant pass, when flag_ira_loop_pressure is enabled,
function gain_for_invariant checks the pressures of all register
classes. This does not make sense since one invariant might impact
only one register class.

The patch enhances functions get_inv_cost and gain_for_invariant to
check only the register pressure of the invariant if possible.

Bootstrap and no make check regression on X86-64.
Bootstrap and no make check regression on X86-64 with
flag_ira_loop_pressure = true.

OK for trunk?

Thanks!
-Zhenqiang

ChangeLog:
2014-06-10  Zhenqiang Chen  <zhenqiang.chen@linaro.org>

        * loop-invariant.c (get_inv_cost): Handle register class.
        (gain_for_invariant): Check the register pressure of the inv,
        other than all.

   if (! flag_ira_loop_pressure)
@@ -1095,6 +1101,8 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)

       pressure_class = get_pressure_class_and_nregs (inv->insn, &nregs);
       regs_needed[pressure_class] += nregs;
+      *cl = pressure_class;
+      ret = 1;
     }
   if (!inv->cheap_address
@@ -1135,10 +1143,12 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
   EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
     {
       bool check_p;
+      enum reg_class dep_cl = NO_REGS;
+      int dep_ret;

       dep = invariants[depno];

-      get_inv_cost (dep, &acomp_cost, aregs_needed);
+      dep_ret = get_inv_cost (dep, &acomp_cost, aregs_needed, &dep_cl);

       if (! flag_ira_loop_pressure)
        check_p = aregs_needed[0] != 0;
@@ -1148,6 +1158,11 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
            if (aregs_needed[ira_pressure_classes[i]] != 0)
              break;
          check_p = i < ira_pressure_classes_num;
+
+         if (dep_ret > 1)
+           ret += dep_ret;
+         else if ((dep_ret == 1) && (*cl != dep_cl))
+           ret++;
        }
       if (check_p
          /* We need to check always_executed, since if the original value of
@@ -1181,6 +1196,7 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
        }
       (*comp_cost) += acomp_cost;
     }
+  return ret;
 }

 /* Calculates gain for eliminating invariant INV.  REGS_USED is the number
@@ -1195,10 +1211,12 @@ gain_for_invariant (struct invariant *inv,
unsigned *regs_needed,
                    bool speed, bool call_p)
 {
   int comp_cost, size_cost;
+  enum reg_class cl;
+  int ret;

   actual_stamp++;

-  get_inv_cost (inv, &comp_cost, regs_needed);
+  ret = get_inv_cost (inv, &comp_cost, regs_needed, &cl);

   if (! flag_ira_loop_pressure)
     {
@@ -1207,6 +1225,24 @@ gain_for_invariant (struct invariant *inv,
unsigned *regs_needed,
                   - estimate_reg_pressure_cost (new_regs[0],
                                                 regs_used, speed, call_p));
     }
+  else if (ret == 0)
+    return -1;
+  else if (ret == 1)
+    {
+      /* Hoist it anyway since it does not impact register pressure.  */
+      if (cl == NO_REGS)
+       return 1;
+
+      size_cost = (int) new_regs[cl]
+                + (int) regs_needed[cl]
+                + LOOP_DATA (curr_loop)->max_reg_pressure[cl]
+                + IRA_LOOP_RESERVED_REGS
+                - ira_class_hard_regs_num[cl];
+      if (size_cost > 0)
+       return -1;
+      else
+       size_cost = 0;
+    }
   else
     {
       int i;

Comments

Steven Bosscher June 10, 2014, 11:06 a.m. UTC | #1
On Tue, Jun 10, 2014 at 11:22 AM, Zhenqiang Chen wrote:
> Hi,
>
> For loop2-invariant pass, when flag_ira_loop_pressure is enabled,
> function gain_for_invariant checks the pressures of all register
> classes. This does not make sense since one invariant might impact
> only one register class.
>
> The patch enhances functions get_inv_cost and gain_for_invariant to
> check only the register pressure of the invariant if possible.

This patch may work for targets with more-or-less orthogonal reg
classes, but not if there is a lot of overlap between reg classes.

So I don't think this approach is OK.

Ciao!
Steven
diff mbox

Patch

diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 100a2c1..e822bb6 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1058,16 +1058,22 @@  get_pressure_class_and_nregs (rtx insn, int *nregs)
 }

 /* Calculates cost and number of registers needed for moving invariant INV
-   out of the loop and stores them to *COST and *REGS_NEEDED.  */
+   out of the loop and stores them to *COST and *REGS_NEEDED.  *CL will be
+   the REG_CLASS of INV.  Return
+     0: if INV is invalid.
+     1: if INV and its depends_on have same reg_class
+   > 1: if INV and its depends_on have different reg_classes.  */

-static void
-get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed)
+static int
+get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed,
+             enum reg_class *cl)
 {
   int i, acomp_cost;
   unsigned aregs_needed[N_REG_CLASSES];
   unsigned depno;
   struct invariant *dep;
   bitmap_iterator bi;
+  int ret = 2;

   /* Find the representative of the class of the equivalent invariants.  */
   inv = invariants[inv->eqto];
@@ -1083,7 +1089,7 @@  get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)

   if (inv->move
       || inv->stamp == actual_stamp)
-    return;
+    return 0;
   inv->stamp = actual_stamp;