diff mbox

[v2] df: Change defs in entry and uses in exit block during separate shrink-wrapping

Message ID 78dffd1b3218e570034dafce8e30b7fdb551b08d.1479205438.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Nov. 15, 2016, 10:33 a.m. UTC
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.

Testing on powerpc64-linux {-m32,-m64}.  Is this okay for trunk if that
succeeds?


Segher


2016-11-15  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.
	* rtl.h (shrink_wrap_separate_in_progress): Declare new variable.
	* 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.

---
 gcc/config/rs6000/rs6000.c |  3 ++-
 gcc/df-scan.c              | 16 ++++++++++++++++
 gcc/df.h                   |  7 +++++++
 gcc/shrink-wrap.c          | 19 +++++++++++++------
 4 files changed, 38 insertions(+), 7 deletions(-)

Comments

Richard Biener Nov. 16, 2016, 1:25 p.m. UTC | #1
On Tue, Nov 15, 2016 at 11:33 AM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> 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.
>
> Testing on powerpc64-linux {-m32,-m64}.  Is this okay for trunk if that
> succeeds?

Yes - this works for me.

Richard.

>
> Segher
>
>
> 2016-11-15  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.
>         * rtl.h (shrink_wrap_separate_in_progress): Declare new variable.
>         * 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.
>
> ---
>  gcc/config/rs6000/rs6000.c |  3 ++-
>  gcc/df-scan.c              | 16 ++++++++++++++++
>  gcc/df.h                   |  7 +++++++
>  gcc/shrink-wrap.c          | 19 +++++++++++++------
>  4 files changed, 38 insertions(+), 7 deletions(-)
>
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 2ceddfd..d75d52c 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -27800,7 +27800,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);
>
> diff --git a/gcc/df-scan.c b/gcc/df-scan.c
> index 7cfd34b..e6b55b5 100644
> --- a/gcc/df-scan.c
> +++ b/gcc/df-scan.c
> @@ -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);
>
> diff --git a/gcc/df.h b/gcc/df.h
> index 40c3794..7a2a6a1 100644
> --- 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.  */
> diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
> index e480d4d..f838696 100644
> --- a/gcc/shrink-wrap.c
> +++ b/gcc/shrink-wrap.c
> @@ -1793,7 +1793,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 ();
> @@ -1859,9 +1865,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 ();
>  }
> --
> 1.9.3
>
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2ceddfd..d75d52c 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27800,7 +27800,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);
 
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 7cfd34b..e6b55b5 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -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);
 
diff --git a/gcc/df.h b/gcc/df.h
index 40c3794..7a2a6a1 100644
--- 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.  */
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
index e480d4d..f838696 100644
--- a/gcc/shrink-wrap.c
+++ b/gcc/shrink-wrap.c
@@ -1793,7 +1793,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 ();
@@ -1859,9 +1865,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 ();
 }