On Tue, Nov 15, 2016 at 11:33 AM, Segher Boessenkool <seg...@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 <seg...@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 >