From b5107db65d487765d0bf0ba184d01f5211e20006 Mon Sep 17 00:00:00 2001
From: Ajit Kumar Agarwal <ajitkum@xilix.com>
Date: Tue, 15 Dec 2015 13:25:04 +0530
Subject: [PATCH] [Patch,rtl Optimization]: Better register pressure estimate for loop invariant code motion

Calculate the loop liveness used for regs for calculating the register pressure
in the cost estimation.  Loop liveness is based on the following properties.
We only need to find the set of objects that are live at the birth or the header
of the loop. We don't need to calculate the live through the loop by considering
live in and live out of all the basic blocks of the loop. This is based on the
point that the set of objects that are live-in at the birth or header of the loop
will be live-in at every node in the loop.

If a v live is out at the header of the loop then the variable is live-in at every node
in the loop. To prove this, consider a loop L with header h such that the variable v
defined at d is live-in at h. Since v is live at h, d is not part of L. This follows i
from the dominance property, i.e. h is strictly dominated by d. Furthermore, there
exists a path from h to a use of v which does not go through d. For every node p in
the loop, since the loop is strongly connected and node is a component of the CFG,
there exists a path, consisting only of nodes of L from p to h. Concatenating these
two paths proves that v is live-in and live-out of p.

Calculate the live-out and live-in for the exit edge of the loop. This patch considers
liveness for not only the loop latch but also the liveness outside the loops.

ChangeLog:
2015-12-15  Ajit Agarwal  <ajitkum@xilinx.com>

	* loop-invariant.c
	(find_invariants_to_move): Add the logic of regs_used based
	on liveness.
	* cfgloopanal.c
	(estimate_reg_pressure_cost): Update the heuristics in presence
	of call_p.

Signed-off-by:Ajit Agarwal ajitkum@xilinx.com.
---
 gcc/cfgloopanal.c    |   12 +++++++-
 gcc/loop-invariant.c |   70 +++++++++++++++++++++++++++++++++++--------------
 2 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c
index 2220e86..c2b2947 100644
--- a/gcc/cfgloopanal.c
+++ b/gcc/cfgloopanal.c
@@ -373,15 +373,23 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed,
 
   /* If there is a call in the loop body, the call-clobbered registers
      are not available for loop invariants.  */
+
   if (call_p)
     available_regs = available_regs - target_clobbered_regs;
-
+  
   /* If we have enough registers, we should use them and not restrict
      the transformations unnecessarily.  */
   if (regs_needed + target_res_regs <= available_regs)
     return 0;
 
-  if (regs_needed <= available_regs)
+  /* Estimation of target_clobbered register is based on the call_used
+     arrays which is not the right estimate for the clobbered register
+     used in called function. Instead of considering the spill cost we
+     consider only the reg_cost aggressively.  */
+
+  if ((regs_needed <= available_regs) 
+      || (call_p && (regs_needed <= 
+          (available_regs + target_clobbered_regs))))
     /* If we are close to running out of registers, try to preserve
        them.  */
     cost = target_reg_cost [speed] * n_new;
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 53d1377..62896dd 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1365,8 +1365,7 @@ gain_for_invariant (struct invariant *inv, unsigned *regs_needed,
       else
 	size_cost = 0;
     }
-
-  return comp_cost - size_cost;
+  return comp_cost - size_cost + 1;
 }
 
 /* Finds invariant with best gain for moving.  Returns the gain, stores
@@ -1460,23 +1459,54 @@ find_invariants_to_move (bool speed, bool call_p)
     /* REGS_USED is actually never used when the flag is on.  */
     regs_used = 0;
   else
-    /* We do not really do a good job in estimating number of
-       registers used; we put some initial bound here to stand for
-       induction variables etc.  that we do not detect.  */
+    /* The logic used in estimating the number of regs_used is changed.
+       Now it will be based on liveness of the loop. */
     {
-      unsigned int n_regs = DF_REG_SIZE (df);
-
-      regs_used = 2;
-
-      for (i = 0; i < n_regs; i++)
-	{
-	  if (!DF_REGNO_FIRST_DEF (i) && DF_REGNO_LAST_USE (i))
-	    {
-	      /* This is a value that is used but not changed inside loop.  */
-	      regs_used++;
-	    }
-	}
-    }
+      int  i;
+      edge e;
+      vec<edge> edges;
+      bitmap_head regs_live;
+
+      bitmap_initialize (&regs_live, &reg_obstack);
+      edges = get_loop_exit_edges (curr_loop);
+
+      /* Loop liveness is based on the following properties.
+         We only need to find the set of objects that are live at the
+         birth or the header of the loop.
+         We don't need to calculate the live through the loop considering
+         live-in and live-out of all the basic blocks of the loop. This is
+         based on the point that the set of objects that are live-in at the
+         birth or header of the loop will be live-in at every block in the
+         loop.
+
+         If a v live out at the header of the loop then the variable is
+         live-in at every node in the Loop. To prove this, consider a loop
+         L with header h such that the variable v defined at d is live-in
+         at h. Since v is live at h, d is not part of L. This follows from
+         the dominance property, i.e. h is strictly dominated by d. Furthermore,
+         there exists a path from h to a use of v which does not go through d.
+         For every node of the loop, p, since the loop is strongly connected
+         component of the CFG, there exists a path, consisting only of nodes
+         of L from p to h. Concatenating these two paths prove that v is
+         live-in and live-out of p.  */
+
+       bitmap_ior_into (&regs_live, DF_LR_IN (curr_loop->header));
+       bitmap_ior_into (&regs_live, DF_LR_OUT (curr_loop->header));
+
+       /* Calculate the live-out and live-in for the exit edge of the loop.
+          This considers liveness for not only the loop latch but also the
+          liveness outside the loops.  */
+
+       FOR_EACH_VEC_ELT (edges, i, e)
+         {
+           bitmap_ior_into (&regs_live, DF_LR_OUT (e->src));
+           bitmap_ior_into (&regs_live, DF_LR_IN (e->dest));
+         }
+
+       regs_used = bitmap_count_bits (&regs_live) + 2;
+       bitmap_clear (&regs_live);
+       edges.release ();
+     }
 
   if (! flag_ira_loop_pressure)
     new_regs[0] = regs_needed[0] = 0;
@@ -1967,6 +1997,7 @@ mark_ref_regs (rtx x)
 }
 
 /* Calculate register pressure in the loops.  */
+
 static void
 calculate_loop_reg_pressure (void)
 {
@@ -2085,9 +2116,7 @@ calculate_loop_reg_pressure (void)
       fprintf (dump_file, "\n");
     }
 }
-
 
-
 /* Move the invariants out of the loops.  */
 
 void
@@ -2103,6 +2132,7 @@ move_loop_invariants (void)
       calculate_loop_reg_pressure ();
       regstat_free_n_sets_and_refs ();
     }
+
   df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN);
   /* Process the loops, innermost first.  */
   FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
-- 
1.7.1

