]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
df: Change defs in entry and uses in exit block during separate shrink-wrapping
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Nov 2016 15:23:36 +0000 (15:23 +0000)
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Nov 2016 15:23:36 +0000 (15:23 +0000)
So far all target implementations of the separate shrink-wrapping hooks
use the DF LIVE info to figure out around which basic blocks the non-
volatile registers need to be saved.  This is done by looking at the
IN+GEN+KILL sets of the basic blocks.  However, that doesn't work for
registers that DF says are defined in the entry block, or used in the
exit block.

This patch introduces a local flag DF_SCAN_EMPTY_ENTRY_EXIT that says
no registers should be defined in the entry block, and none used in the
exit block.  It also makes try_shrink_wrapping_separate use it.  The
rs6000 port is changed to use IN+GEN+KILL for the LR component.

* config/rs6000/rs6000.c (rs6000_components_for_bb): Mark the LR
component as used also if LR_REGNO is a live input to the bb.
* df-scan.c (df_get_entry_block_def_set): Return immediately after
clearing the set if DF_SCAN_EMPTY_ENTRY_EXIT is set.
(df_get_exit_block_use_set): Ditto.
* df.h (df_scan_flags): New enum.
* shrink-wrap.c (try_shrink_wrapping_separate): Set
DF_SCAN_EMPTY_ENTRY_EXIT in df_scan->local_flags, and call
df_update_entry_block_defs and df_update_exit_block_uses
at the start; clear the flag and call those functions at the end.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242497 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/df-scan.c
gcc/df.h
gcc/shrink-wrap.c

index cd59b0280c83545c078588bbee78eec444106503..c3b99edf227dcd15b5fc934b1ee5c3df31f30921 100644 (file)
@@ -1,3 +1,16 @@
+2016-11-16  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * config/rs6000/rs6000.c (rs6000_components_for_bb): Mark the LR
+       component as used also if LR_REGNO is a live input to the bb.
+       * df-scan.c (df_get_entry_block_def_set): Return immediately after
+       clearing the set if DF_SCAN_EMPTY_ENTRY_EXIT is set.
+       (df_get_exit_block_use_set): Ditto.
+       * df.h (df_scan_flags): New enum.
+       * shrink-wrap.c (try_shrink_wrapping_separate): Set
+       DF_SCAN_EMPTY_ENTRY_EXIT in df_scan->local_flags, and call
+       df_update_entry_block_defs and df_update_exit_block_uses
+       at the start; clear the flag and call those functions at the end.
+
 2016-11-16  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index c2234345f32bd062dd41b77d9678a5f0e0878088..e85d3eeeb5e4f99a4be15d2932e4b5e8cbd744f6 100644 (file)
@@ -27823,7 +27823,8 @@ rs6000_components_for_bb (basic_block bb)
       bitmap_set_bit (components, regno);
 
   /* LR needs to be saved around a bb if it is killed in that bb.  */
-  if (bitmap_bit_p (gen, LR_REGNO)
+  if (bitmap_bit_p (in, LR_REGNO)
+      || bitmap_bit_p (gen, LR_REGNO)
       || bitmap_bit_p (kill, LR_REGNO))
     bitmap_set_bit (components, 0);
 
index 7cfd34b541993fc3246ce0ab131e24b7694e4fee..e6b55b51d6b02e3d5a485683bbbc6dea741138f4 100644 (file)
@@ -3506,6 +3506,14 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
 
   bitmap_clear (entry_block_defs);
 
+  /* For separate shrink-wrapping we use LIVE to analyze which basic blocks
+     need a prologue for some component to be executed before that block,
+     and we do not care about any other registers.  Hence, we do not want
+     any register for any component defined in the entry block, and we can
+     just leave all registers undefined.  */
+  if (df_scan->local_flags & DF_SCAN_EMPTY_ENTRY_EXIT)
+    return;
+
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
       if (global_regs[i])
@@ -3665,6 +3673,14 @@ df_get_exit_block_use_set (bitmap exit_block_uses)
 
   bitmap_clear (exit_block_uses);
 
+  /* For separate shrink-wrapping we use LIVE to analyze which basic blocks
+     need an epilogue for some component to be executed after that block,
+     and we do not care about any other registers.  Hence, we do not want
+     any register for any component seen as used in the exit block, and we
+     can just say no registers at all are used.  */
+  if (df_scan->local_flags & DF_SCAN_EMPTY_ENTRY_EXIT)
+    return;
+
   /* Stack pointer is always live at the exit.  */
   bitmap_set_bit (exit_block_uses, STACK_POINTER_REGNUM);
 
index 40c3794343acf382df7ec16931ed0ddd667a9939..7a2a6a1404f10a1bbd98d9368dec7baef9a4d048 100644 (file)
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -450,6 +450,13 @@ enum df_chain_flags
   DF_UD_CHAIN      =  2  /* Build UD chains.  */
 };
 
+enum df_scan_flags
+{
+  /* Flags for the SCAN problem.  */
+  DF_SCAN_EMPTY_ENTRY_EXIT = 1  /* Don't define any registers in the entry
+                                  block; don't use any in the exit block.  */
+};
+
 enum df_changeable_flags
 {
   /* Scanning flags.  */
index 4395d8a1cf75e98030fe15d8674aced27807c5e6..6996d25db4aeed485b8387c5afac018d823ea984 100644 (file)
@@ -1682,7 +1682,13 @@ try_shrink_wrapping_separate (basic_block first_bb)
   if (!components)
     return;
 
-  /* We need LIVE info.  */
+  /* We need LIVE info, not defining anything in the entry block and not
+     using anything in the exit block.  A block then needs a component if
+     the register for that component is in the IN or GEN or KILL set for
+     that block.  */
+  df_scan->local_flags |= DF_SCAN_EMPTY_ENTRY_EXIT;
+  df_update_entry_block_defs ();
+  df_update_exit_block_uses ();
   df_live_add_problem ();
   df_live_set_all_dirty ();
   df_analyze ();
@@ -1748,9 +1754,10 @@ try_shrink_wrapping_separate (basic_block first_bb)
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
 
-  if (crtl->shrink_wrapped_separate)
-    {
-      df_live_set_all_dirty ();
-      df_analyze ();
-    }
+  /* All done.  */
+  df_scan->local_flags &= ~DF_SCAN_EMPTY_ENTRY_EXIT;
+  df_update_entry_block_defs ();
+  df_update_exit_block_uses ();
+  df_live_set_all_dirty ();
+  df_analyze ();
 }