With some functions, there might be the case where every stack variable is a 
live at the end of a
basic block. If that is the case then it is known that all stack variables will 
conflict with each
other so there is no reason to go through figuring out what variables conflict 
with each other.
Since we hold the live variables in a bitmap, we can just count the number of 
bits and compare it to
the number of stack variables.  Currently the bitmap is a linked-list of 
128bits each, on average there
is going to be less than 128 stack variables in a function so this is not 
adding much overhead to check.

In the case of the testcase from PR 114480 with `-fstack-reuse=none`, this 
reduces `expand var` from 70s
down to less than 1s.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

        * cfgexpand.cc (add_scope_conflicts): Return true if all variables are
        alive at the end of a basic block.
        (partition_stack_vars): Take a new argument, all_active. Return early if
        all_active is true after the qsort.
        (expand_used_vars): Update call to partition_stack_vars.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/cfgexpand.cc | 46 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 10 deletions(-)

diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 277ef659f30..e84f12a5e93 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -941,21 +941,23 @@ add_scope_conflicts_1 (vars_ssa_cache &cache, basic_block 
bb, bitmap work, bool
 }
 
 /* Generate stack partition conflicts between all partitions that are
-   simultaneously live.  */
+   simultaneously live. Returns true if it is known that every stack
+   vars will conflict with each other.  */
 
-static void
+static bool
 add_scope_conflicts (void)
 {
   /* If there is only one variable, there is nothing to be done as
      there is only possible partition.  */
   if (stack_vars_num == 1)
-    return;
+    return true;
 
   basic_block bb;
   bool changed;
   bitmap work = BITMAP_ALLOC (NULL);
   int *rpo;
   int n_bbs;
+  bool all_active = false;
 
   vars_ssa_cache cache;
 
@@ -987,20 +989,41 @@ add_scope_conflicts (void)
          active = (bitmap)bb->aux;
          add_scope_conflicts_1 (cache, bb, work, false);
          if (bitmap_ior_into (active, work))
-           changed = true;
+           {
+             /* If all of the stack variables
+                are alive at the end at any of the basic blocks,
+                then we know all of them will conflict with each
+                other.  */
+             unsigned numactive = bitmap_count_bits (active);
+             if (numactive == stack_vars_num)
+               {
+                 all_active = true;
+                 changed = false;
+                 break;
+               }
+             changed = true;
+           }
        }
     }
 
-  FOR_EACH_BB_FN (bb, cfun)
-    add_scope_conflicts_1 (cache, bb, work, true);
+  if (!all_active)
+    {
+      FOR_EACH_BB_FN (bb, cfun)
+       add_scope_conflicts_1 (cache, bb, work, true);
+    }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    cache.dump (dump_file);
+    {
+      cache.dump (dump_file);
+      if (all_active)
+       fprintf (dump_file, "All stack variables conflict.\n");
+    }
 
   free (rpo);
   BITMAP_FREE (work);
   FOR_ALL_BB_FN (bb, cfun)
     BITMAP_FREE (bb->aux);
+  return all_active;
 }
 
 /* A subroutine of partition_stack_vars.  A comparison function for qsort,
@@ -1233,7 +1256,7 @@ union_stack_vars (unsigned a, unsigned b)
 */
 
 static void
-partition_stack_vars (void)
+partition_stack_vars (bool all_active)
 {
   unsigned si, sj, n = stack_vars_num;
 
@@ -1246,6 +1269,9 @@ partition_stack_vars (void)
 
   qsort (stack_vars_sorted, n, sizeof (unsigned), stack_var_cmp);
 
+  if (all_active)
+    return;
+
   for (si = 0; si < n; ++si)
     {
       unsigned i = stack_vars_sorted[si];
@@ -2580,7 +2606,7 @@ expand_used_vars (bitmap forced_stack_vars)
     {
       bool has_addressable_vars = false;
 
-      add_scope_conflicts ();
+      bool all_active = add_scope_conflicts ();
 
       /* If stack protection is enabled, we don't share space between
         vulnerable data and non-vulnerable data.  */
@@ -2596,7 +2622,7 @@ expand_used_vars (bitmap forced_stack_vars)
 
       /* Now that we have collected all stack variables, and have computed a
         minimal interference graph, attempt to save some stack space.  */
-      partition_stack_vars ();
+      partition_stack_vars (all_active);
       if (dump_file)
        dump_stack_var_partition ();
     }
-- 
2.43.0

Reply via email to