diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2015-03-01 02:09:25 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2015-03-01 01:09:25 +0000 |
commit | c7a06bc12629ce9c897e3cbf155a475eb7ac6375 (patch) | |
tree | 359daf7e7ac852181ec5f6a060ddc4d2b4a1b7ae /gcc | |
parent | eb140ba0334cd9d7fd0bf5a24cef6c6ab10eef2e (diff) | |
download | gcc-c7a06bc12629ce9c897e3cbf155a475eb7ac6375.zip gcc-c7a06bc12629ce9c897e3cbf155a475eb7ac6375.tar.gz gcc-c7a06bc12629ce9c897e3cbf155a475eb7ac6375.tar.bz2 |
ipa-icf.c (sem_function::merge): Fix handling of COMDAT.
* ipa-icf.c (sem_function::merge): Fix handling of COMDAT.
(sem_variable::merge) Likewise.
From-SVN: r221085
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ipa-icf.c | 49 |
2 files changed, 34 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee6f7fe..1b4b17d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2015-02-28 Jan Hubicka <hubicka@ucw.cz> + * ipa-icf.c (sem_function::merge): Fix handling of COMDAT. + (sem_variable::merge) Likewise. + +2015-02-28 Jan Hubicka <hubicka@ucw.cz> + * ipa-inline.c (can_inline_edge_p): Match opt_for_fn on inline target; also match flag_ipa_devirt. diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 6db5c08..70a2883 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -733,6 +733,7 @@ sem_function::merge (sem_item *alias_item) bool remove = false; bool original_discardable = false; + bool original_discarded = false; bool original_address_matters = original->address_matters_p (); bool alias_address_matters = alias->address_matters_p (); @@ -761,15 +762,16 @@ sem_function::merge (sem_item *alias_item) } /* See if original is in a section that can be discarded if the main - symbol is not used. + symbol is not used. */ - Also consider case where we have resolution info and we know that + if (original->can_be_discarded_p ()) + original_discardable = true; + /* Also consider case where we have resolution info and we know that original's definition is not going to be used. In this case we can not create alias to original. */ - if (original->can_be_discarded_p () - || (node->resolution != LDPR_UNKNOWN - && !decl_binds_to_current_def_p (node->decl))) - original_discardable = true; + if (node->resolution != LDPR_UNKNOWN + && !decl_binds_to_current_def_p (node->decl)) + original_discardable = original_discarded = true; /* Creating a symtab alias is the optimal way to merge. It however can not be used in the following cases: @@ -788,6 +790,7 @@ sem_function::merge (sem_item *alias_item) && (!DECL_COMDAT_GROUP (alias->decl) || (DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl)))) + || original_discarded || !sem_item::target_supports_symbol_aliases_p () || DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl)) { @@ -797,7 +800,7 @@ sem_function::merge (sem_item *alias_item) comdat group. Other compiler producing the body of the another comdat group may make opossite decision and with unfortunate linker choices this may close a loop. */ - if (DECL_COMDAT_GROUP (alias->decl) + if (DECL_COMDAT_GROUP (original->decl) && DECL_COMDAT_GROUP (alias->decl) && (DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl))) { @@ -854,26 +857,27 @@ sem_function::merge (sem_item *alias_item) /* Work out the symbol the wrapper should call. If ORIGINAL is interposable, we need to call a local alias. - Also produce local alias (if possible) as an optimization. */ - if (!original_discardable - || (DECL_COMDAT_GROUP (original->decl) - && (DECL_COMDAT_GROUP (original->decl) - == DECL_COMDAT_GROUP (alias->decl)))) + Also produce local alias (if possible) as an optimization. + + Local aliases can not be created inside comdat groups because that + prevents inlining. */ + if (!original_discardable && !original->get_comdat_group ()) { local_original = dyn_cast <cgraph_node *> (original->noninterposable_alias ()); if (!local_original && original->get_availability () > AVAIL_INTERPOSABLE) local_original = original; - /* If original is COMDAT local, we can not really redirect external - callers to it. */ - if (original->comdat_local_p ()) - redirect_callers = false; } /* If we can not use local alias, fallback to the original when possible. */ else if (original->get_availability () > AVAIL_INTERPOSABLE) local_original = original; + + /* If original is COMDAT local, we can not really redirect calls outside + of its comdat group to it. */ + if (original->comdat_local_p ()) + redirect_callers = false; if (!local_original) { if (dump_file) @@ -1545,11 +1549,16 @@ sem_variable::merge (sem_item *alias_item) "adress of original and alias may be compared.\n\n"); return false; } + if (DECL_COMDAT_GROUP (original->decl) != DECL_COMDAT_GROUP (alias->decl)) + { + if (dump_file) + fprintf (dump_file, "Not unifying; alias cannot be created; " + "across comdat group boundary\n\n"); + + return false; + } - if (original_discardable - && (!DECL_COMDAT_GROUP (original->decl) - || (DECL_COMDAT_GROUP (original->decl) - != DECL_COMDAT_GROUP (alias->decl)))) + if (original_discardable) { if (dump_file) fprintf (dump_file, "Not unifying; alias cannot be created; " |