From 7157aa8583f7ca32d5bee783e83103da92e3a1f3 Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Wed, 16 Nov 2016 16:23:36 +0100 Subject: [PATCH] df: Change defs in entry and uses in exit block during separate shrink-wrapping 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. From-SVN: r242497 --- gcc/ChangeLog | 13 +++++++++++++ gcc/config/rs6000/rs6000.c | 3 ++- gcc/df-scan.c | 16 ++++++++++++++++ gcc/df.h | 7 +++++++ gcc/shrink-wrap.c | 19 +++++++++++++------ 5 files changed, 51 insertions(+), 7 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cd59b0280c8..c3b99edf227 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2016-11-16 Segher Boessenkool + + * 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 Alan Hayward David Sherwood diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index c2234345f32..e85d3eeeb5e 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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); diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 7cfd34b5419..e6b55b51d6b 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 40c3794343a..7a2a6a1404f 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 4395d8a1cf7..6996d25db4a 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -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 (); } -- 2.30.2