diff options
Diffstat (limited to 'gcc/ipa-icf.c')
-rw-r--r-- | gcc/ipa-icf.c | 113 |
1 files changed, 93 insertions, 20 deletions
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 95fad30e83a..c8ca9566cb7 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -2132,23 +2132,6 @@ sem_variable::get_hash (void) return m_hash; } -/* Set all points-to UIDs of aliases pointing to node N as UID. */ - -static void -set_alias_uids (symtab_node *n, int uid) -{ - ipa_ref *ref; - FOR_EACH_ALIAS (n, ref) - { - if (dump_file) - fprintf (dump_file, " Setting points-to UID of [%s] as %d\n", - xstrdup_for_dump (ref->referring->asm_name ()), uid); - - SET_DECL_PT_UID (ref->referring->decl, uid); - set_alias_uids (ref->referring, uid); - } -} - /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can be applied. */ @@ -2275,7 +2258,6 @@ sem_variable::merge (sem_item *alias_item) if (dump_file) fprintf (dump_file, "Unified; Variable alias has been created.\n"); - set_alias_uids (original, DECL_UID (original->decl)); return true; } } @@ -2295,7 +2277,7 @@ unsigned int sem_item_optimizer::class_id = 0; sem_item_optimizer::sem_item_optimizer () : worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL), - m_varpool_node_hooks (NULL) + m_varpool_node_hooks (NULL), m_merged_variables () { m_items.create (0); bitmap_obstack_initialize (&m_bmstack); @@ -2320,6 +2302,7 @@ sem_item_optimizer::~sem_item_optimizer () m_items.release (); bitmap_obstack_release (&m_bmstack); + m_merged_variables.release (); } /* Write IPA ICF summary for symbols. */ @@ -3571,13 +3554,103 @@ sem_item_optimizer::merge_classes (unsigned int prev_class_count) } if (dbg_cnt (merged_ipa_icf)) - merged_p |= source->merge (alias); + { + bool merged = source->merge (alias); + merged_p |= merged; + + if (merged && alias->type == VAR) + { + symtab_pair p = symtab_pair (source->node, alias->node); + m_merged_variables.safe_push (p); + } + } } } + if (!m_merged_variables.is_empty ()) + fixup_points_to_sets (); + return merged_p; } +/* Fixup points to set PT. */ + +void +sem_item_optimizer::fixup_pt_set (struct pt_solution *pt) +{ + if (pt->vars == NULL) + return; + + unsigned i; + symtab_pair *item; + FOR_EACH_VEC_ELT (m_merged_variables, i, item) + if (bitmap_bit_p (pt->vars, DECL_UID (item->second->decl))) + bitmap_set_bit (pt->vars, DECL_UID (item->first->decl)); +} + +/* Set all points-to UIDs of aliases pointing to node N as UID. */ + +static void +set_alias_uids (symtab_node *n, int uid) +{ + ipa_ref *ref; + FOR_EACH_ALIAS (n, ref) + { + if (dump_file) + fprintf (dump_file, " Setting points-to UID of [%s] as %d\n", + xstrdup_for_dump (ref->referring->asm_name ()), uid); + + SET_DECL_PT_UID (ref->referring->decl, uid); + set_alias_uids (ref->referring, uid); + } +} + +/* Fixup points to analysis info. */ + +void +sem_item_optimizer::fixup_points_to_sets (void) +{ + /* TODO: remove in GCC 9 and trigger PTA re-creation after IPA passes. */ + cgraph_node *cnode; + + FOR_EACH_DEFINED_FUNCTION (cnode) + { + tree name; + unsigned i; + function *fn = DECL_STRUCT_FUNCTION (cnode->decl); + if (!gimple_in_ssa_p (fn)) + continue; + + FOR_EACH_SSA_NAME (i, name, fn) + if (POINTER_TYPE_P (TREE_TYPE (name)) + && SSA_NAME_PTR_INFO (name)) + fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt); + fixup_pt_set (&fn->gimple_df->escaped); + + /* The above get's us to 99% I guess, at least catching the + address compares. Below also gets us aliasing correct + but as said we're giving leeway to the situation with + readonly vars anyway, so ... */ + basic_block bb; + FOR_EACH_BB_FN (bb, fn) + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); + gsi_next (&gsi)) + { + gcall *call = dyn_cast<gcall *> (gsi_stmt (gsi)); + if (call) + { + fixup_pt_set (gimple_call_use_set (call)); + fixup_pt_set (gimple_call_clobber_set (call)); + } + } + } + + unsigned i; + symtab_pair *item; + FOR_EACH_VEC_ELT (m_merged_variables, i, item) + set_alias_uids (item->first, DECL_UID (item->first->decl)); +} + /* Dump function prints all class members to a FILE with an INDENT. */ void |