Commit 0a7246ee by Jan Hubicka Committed by Jan Hubicka

re PR bootstrap/65150 (r220875 causes bootstrap failure on x86_64 darwin)

	PR bootstrap/65150
	* ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
	Use address_matters_p.
	(redirect_all_callers, set_addressable): New functions.
	(sem_function::merge): Reorganize and fix merging issues.
	(sem_variable::merge): Likewise.
	(sem_variable::compare_sections): Remove.
	* common.opt (fmerge-all-constants, fmerge-constants): Remove
	Optimization flag.
	* symtab.c (symtab_node::resolve_alias): When alias has aliases,
	redirect them.
	(symtab_node::make_decl_local): Set ADDRESSABLE bit when
	decl is used.
	(address_matters_1): New function.
	(symtab_node::address_matters_p): New function.
	* cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
	check for merged flag.
	* cgraph.h (address_matters_p): Declare.
	(symtab_node::address_taken_from_non_vtable_p): Remove.
	(symtab_node::address_can_be_compared_p): New method.
	(ipa_ref::address_matters_p): Move here from ipa-ref.c; simplify.
	* ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
	Remove.
	(comdat_can_be_unshared_p_1) Use address_matters_p.
	(update_vtable_references): Fix formating.
	* ipa-ref.c (ipa_ref::address_matters_p): Move inline.
	* cgraphunit.c (cgraph_node::create_wrapper): Drop UNINLINABLE flag.
	* cgraphclones.c: Preserve merged and icf_merged flags.

Co-Authored-By: Martin Liska <mliska@suse.cz>

From-SVN: r221040
parent f91f1c13
2015-02-26 Jan Hubicka <hubicka@ucw.cz>
Martin Liska <mliska@suse.cz>
PR bootstrap/65150
* ipa-icf.c (symbol_compare_collection::symbol_compare_colleciton):
Use address_matters_p.
(redirect_all_callers, set_addressable): New functions.
(sem_function::merge): Reorganize and fix merging issues.
(sem_variable::merge): Likewise.
(sem_variable::compare_sections): Remove.
* common.opt (fmerge-all-constants, fmerge-constants): Remove
Optimization flag.
* symtab.c (symtab_node::resolve_alias): When alias has aliases,
redirect them.
(symtab_node::make_decl_local): Set ADDRESSABLE bit when
decl is used.
(address_matters_1): New function.
(symtab_node::address_matters_p): New function.
* cgraph.c (cgraph_edge::verify_corresponds_to_fndecl): Fix
check for merged flag.
* cgraph.h (address_matters_p): Declare.
(symtab_node::address_taken_from_non_vtable_p): Remove.
(symtab_node::address_can_be_compared_p): New method.
(ipa_ref::address_matters_p): Move here from ipa-ref.c; simplify.
* ipa-visibility.c (symtab_node::address_taken_from_non_vtable_p):
Remove.
(comdat_can_be_unshared_p_1) Use address_matters_p.
(update_vtable_references): Fix formating.
* ipa-ref.c (ipa_ref::address_matters_p): Move inline.
* cgraphunit.c (cgraph_node::create_wrapper): Drop UNINLINABLE flag.
* cgraphclones.c: Preserve merged and icf_merged flags.
2015-02-26 Sandra Loosemore <sandra@codesourcery.com> 2015-02-26 Sandra Loosemore <sandra@codesourcery.com>
* doc/extend.texi (Function Attributes): Fix spelling and typos. * doc/extend.texi (Function Attributes): Fix spelling and typos.
......
...@@ -2630,7 +2630,7 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl) ...@@ -2630,7 +2630,7 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl)
if (!node if (!node
|| node->body_removed || node->body_removed
|| node->in_other_partition || node->in_other_partition
|| node->icf_merged || callee->icf_merged
|| callee->in_other_partition) || callee->in_other_partition)
return false; return false;
......
...@@ -326,9 +326,6 @@ public: ...@@ -326,9 +326,6 @@ public:
/* Return true if ONE and TWO are part of the same COMDAT group. */ /* Return true if ONE and TWO are part of the same COMDAT group. */
inline bool in_same_comdat_group_p (symtab_node *target); inline bool in_same_comdat_group_p (symtab_node *target);
/* Return true when there is a reference to node and it is not vtable. */
bool address_taken_from_non_vtable_p (void);
/* Return true if symbol is known to be nonzero. */ /* Return true if symbol is known to be nonzero. */
bool nonzero_address (); bool nonzero_address ();
...@@ -337,6 +334,15 @@ public: ...@@ -337,6 +334,15 @@ public:
return 2 otherwise. */ return 2 otherwise. */
int equal_address_to (symtab_node *s2); int equal_address_to (symtab_node *s2);
/* Return true if symbol's address may possibly be compared to other
symbol's address. */
bool address_matters_p ();
/* Return true if NODE's address can be compared. This use properties
of NODE only and does not look if the address is actually taken in
interesting way. For that use ADDRESS_MATTERS_P instead. */
bool address_can_be_compared_p (void);
/* Return symbol table node associated with DECL, if any, /* Return symbol table node associated with DECL, if any,
and NULL otherwise. */ and NULL otherwise. */
static inline symtab_node *get (const_tree decl) static inline symtab_node *get (const_tree decl)
...@@ -3022,6 +3028,43 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *, ...@@ -3022,6 +3028,43 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
return false; return false;
} }
/* Return true if NODE's address can be compared. */
inline bool
symtab_node::address_can_be_compared_p ()
{
/* Address of virtual tables and functions is never compared. */
if (DECL_VIRTUAL_P (decl))
return false;
/* Address of C++ cdtors is never compared. */
if (is_a <cgraph_node *> (this)
&& (DECL_CXX_CONSTRUCTOR_P (decl)
|| DECL_CXX_DESTRUCTOR_P (decl)))
return false;
/* Constant pool symbols addresses are never compared.
flag_merge_constants permits us to assume the same on readonly vars. */
if (is_a <varpool_node *> (this)
&& (DECL_IN_CONSTANT_POOL (decl)
|| (flag_merge_constants >= 2
&& TREE_READONLY (decl) && !TREE_THIS_VOLATILE (decl))))
return false;
return true;
}
/* Return true if refernece may be used in address compare. */
inline bool
ipa_ref::address_matters_p ()
{
if (use != IPA_REF_ADDR)
return false;
/* Addresses taken from virtual tables are never compared. */
if (is_a <varpool_node *> (referring)
&& DECL_VIRTUAL_P (referring->decl))
return false;
return referred->address_can_be_compared_p ();
}
/* Build polymorphic call context for indirect call E. */ /* Build polymorphic call context for indirect call E. */
inline inline
......
...@@ -471,6 +471,8 @@ cgraph_node::create_clone (tree decl, gcov_type gcov_count, int freq, ...@@ -471,6 +471,8 @@ cgraph_node::create_clone (tree decl, gcov_type gcov_count, int freq,
new_node->frequency = frequency; new_node->frequency = frequency;
new_node->tp_first_run = tp_first_run; new_node->tp_first_run = tp_first_run;
new_node->tm_clone = tm_clone; new_node->tm_clone = tm_clone;
new_node->icf_merged = icf_merged;
new_node->merged = merged;
new_node->clone.tree_map = NULL; new_node->clone.tree_map = NULL;
new_node->clone.args_to_skip = args_to_skip; new_node->clone.args_to_skip = args_to_skip;
......
...@@ -2468,6 +2468,7 @@ cgraph_node::create_wrapper (cgraph_node *target) ...@@ -2468,6 +2468,7 @@ cgraph_node::create_wrapper (cgraph_node *target)
release_body (true); release_body (true);
reset (); reset ();
DECL_UNINLINABLE (decl) = false;
DECL_RESULT (decl) = decl_result; DECL_RESULT (decl) = decl_result;
DECL_INITIAL (decl) = NULL; DECL_INITIAL (decl) = NULL;
allocate_struct_function (decl, false); allocate_struct_function (decl, false);
......
...@@ -1644,11 +1644,11 @@ Report on permanent memory allocation in WPA only ...@@ -1644,11 +1644,11 @@ Report on permanent memory allocation in WPA only
; string constants and constants from constant pool, if 2 also constant ; string constants and constants from constant pool, if 2 also constant
; variables. ; variables.
fmerge-all-constants fmerge-all-constants
Common Report Var(flag_merge_constants,2) Init(1) Optimization Common Report Var(flag_merge_constants,2) Init(1)
Attempt to merge identical constants and constant variables Attempt to merge identical constants and constant variables
fmerge-constants fmerge-constants
Common Report Var(flag_merge_constants,1) Optimization Common Report Var(flag_merge_constants,1)
Attempt to merge identical constants across compilation units Attempt to merge identical constants across compilation units
fmerge-debug-strings fmerge-debug-strings
......
...@@ -124,23 +124,3 @@ ipa_ref::referred_ref_list (void) ...@@ -124,23 +124,3 @@ ipa_ref::referred_ref_list (void)
{ {
return &referred->ref_list; return &referred->ref_list;
} }
/* Return true if refernece may be used in address compare. */
bool
ipa_ref::address_matters_p ()
{
if (use != IPA_REF_ADDR)
return false;
/* Addresses taken from virtual tables are never compared. */
if (is_a <varpool_node *> (referring)
&& DECL_VIRTUAL_P (referring->decl))
return false;
/* Address of virtual tables and functions is never compared. */
if (DECL_VIRTUAL_P (referred->decl))
return false;
/* Address of C++ cdtors is never compared. */
if (is_a <cgraph_node *> (referred)
&& (DECL_CXX_CONSTRUCTOR_P (referred->decl) || DECL_CXX_DESTRUCTOR_P (referred->decl)))
return false;
return true;
}
...@@ -129,27 +129,6 @@ cgraph_node::local_p (void) ...@@ -129,27 +129,6 @@ cgraph_node::local_p (void)
} }
/* Return true when there is a reference to node and it is not vtable. */
bool
symtab_node::address_taken_from_non_vtable_p (void)
{
int i;
struct ipa_ref *ref = NULL;
for (i = 0; iterate_referring (i, ref); i++)
if (ref->use == IPA_REF_ADDR)
{
varpool_node *node;
if (is_a <cgraph_node *> (ref->referring))
return true;
node = dyn_cast <varpool_node *> (ref->referring);
if (!DECL_VIRTUAL_P (node->decl))
return true;
}
return false;
}
/* A helper for comdat_can_be_unshared_p. */ /* A helper for comdat_can_be_unshared_p. */
static bool static bool
...@@ -157,16 +136,14 @@ comdat_can_be_unshared_p_1 (symtab_node *node) ...@@ -157,16 +136,14 @@ comdat_can_be_unshared_p_1 (symtab_node *node)
{ {
if (!node->externally_visible) if (!node->externally_visible)
return true; return true;
/* When address is taken, we don't know if equality comparison won't if (node->address_can_be_compared_p ())
break eventually. Exception are virutal functions, C++ {
constructors/destructors and vtables, where this is not possible by struct ipa_ref *ref;
language standard. */
if (!DECL_VIRTUAL_P (node->decl) for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
&& (TREE_CODE (node->decl) != FUNCTION_DECL if (ref->address_matters_p ())
|| (!DECL_CXX_CONSTRUCTOR_P (node->decl) return false;
&& !DECL_CXX_DESTRUCTOR_P (node->decl))) }
&& node->address_taken_from_non_vtable_p ())
return false;
/* If the symbol is used in some weird way, better to not touch it. */ /* If the symbol is used in some weird way, better to not touch it. */
if (node->force_output) if (node->force_output)
...@@ -387,7 +364,8 @@ can_replace_by_local_alias_in_vtable (symtab_node *node) ...@@ -387,7 +364,8 @@ can_replace_by_local_alias_in_vtable (symtab_node *node)
/* walk_tree callback that rewrites initializer references. */ /* walk_tree callback that rewrites initializer references. */
static tree static tree
update_vtable_references (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) update_vtable_references (tree *tp, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{ {
if (TREE_CODE (*tp) == VAR_DECL if (TREE_CODE (*tp) == VAR_DECL
|| TREE_CODE (*tp) == FUNCTION_DECL) || TREE_CODE (*tp) == FUNCTION_DECL)
......
...@@ -1156,7 +1156,11 @@ symtab_node::make_decl_local (void) ...@@ -1156,7 +1156,11 @@ symtab_node::make_decl_local (void)
return; return;
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
DECL_COMMON (decl) = 0; {
DECL_COMMON (decl) = 0;
/* ADDRESSABLE flag is not defined for public symbols. */
TREE_ADDRESSABLE (decl) = 1;
}
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
DECL_COMDAT (decl) = 0; DECL_COMDAT (decl) = 0;
...@@ -1513,6 +1517,19 @@ symtab_node::resolve_alias (symtab_node *target) ...@@ -1513,6 +1517,19 @@ symtab_node::resolve_alias (symtab_node *target)
/* If alias has address taken, so does the target. */ /* If alias has address taken, so does the target. */
if (address_taken) if (address_taken)
target->ultimate_alias_target ()->address_taken = true; target->ultimate_alias_target ()->address_taken = true;
/* All non-weakref aliases of THIS are now in fact aliases of TARGET. */
ipa_ref *ref;
for (unsigned i = 0; iterate_direct_aliases (i, ref);)
{
struct symtab_node *alias_alias = ref->referring;
if (!alias_alias->weakref)
{
alias_alias->remove_all_references ();
alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
}
else i++;
}
return true; return true;
} }
...@@ -1863,3 +1880,31 @@ symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, ...@@ -1863,3 +1880,31 @@ symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *,
} }
return false; return false;
} }
/* Return ture if address of N is possibly compared. */
static bool
address_matters_1 (symtab_node *n, void *)
{
struct ipa_ref *ref;
if (!n->address_can_be_compared_p ())
return false;
if (n->externally_visible || n->force_output)
return true;
for (unsigned int i = 0; n->iterate_referring (i, ref); i++)
if (ref->address_matters_p ())
return true;
return false;
}
/* Return true if symbol's address may possibly be compared to other
symbol's address. */
bool
symtab_node::address_matters_p ()
{
gcc_assert (!alias);
return call_for_symbol_and_aliases (address_matters_1, NULL, true);
}
2015-02-26 Jan Hubicka <hubicka@ucw.cz>
Martin Liska <mliska@suse.cz>
PR bootstrap/65150
* gcc.dg/pr64454.c: Disable ICF.
* gcc.dg/pr28685-1.c: Disable ICF
* gcc.dg/ipa/iinline-5.c: Disable ICF.
* g++.dg/warn/Wsuggest-final.C: Force methods to be different.
* g++.dg/ipa/ipa-icf-4.C: Update template.
2015-02-26 Jakub Jelinek <jakub@redhat.com> 2015-02-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/65216 PR tree-optimization/65216
......
...@@ -43,6 +43,6 @@ int main() ...@@ -43,6 +43,6 @@ int main()
return 123; return 123;
} }
/* { dg-final { scan-ipa-dump "\(Varpool alias has been created\)|\(Symbol aliases are not supported by target\)" "icf" } } */ /* { dg-final { scan-ipa-dump "\(Unified; Variable alias has been created\)|\(Symbol aliases are not supported by target\)" "icf" } } */
/* { dg-final { scan-ipa-dump "Equal symbols: 6" "icf" } } */ /* { dg-final { scan-ipa-dump "Equal symbols: 6" "icf" } } */
/* { dg-final { cleanup-ipa-dump "icf" } } */ /* { dg-final { cleanup-ipa-dump "icf" } } */
// { dg-do compile } // { dg-do compile }
// { dg-options "-O2 -Wsuggest-final-types -Wsuggest-final-methods" } // { dg-options "-O2 -Wsuggest-final-types -Wsuggest-final-methods" }
int c;
struct A { // { dg-warning "final would enable devirtualization of 4 calls" } struct A { // { dg-warning "final would enable devirtualization of 4 calls" }
virtual void a() {} // { dg-warning "final would enable devirtualization of 2 calls" } virtual void a() {} // { dg-warning "final would enable devirtualization of 2 calls" }
virtual void b() {} // { dg-warning "final would enable devirtualization of 2 calls" } virtual void b() {c++;} // { dg-warning "final would enable devirtualization of 2 calls" }
}; };
void void
t(struct A *a) t(struct A *a)
......
/* Verify that simple indirect calls are inlined even without early /* Verify that simple indirect calls are inlined even without early
inlining.. */ inlining.. */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining" } */ /* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-icf" } */
extern void abort (void); extern void abort (void);
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-cp" } */
int n;
static void
__attribute__ ((noinline))
test(void *a)
{
__builtin_memset (a,0,n);
}
int
main()
{
int aa;
short bb;
test (&aa);
test (&bb);
return 0;
}
/* { dg-final { scan-ipa-dump "Alignment 2" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-cp" } */
int n;
static void
__attribute__ ((noinline))
test(void *a)
{
__builtin_memset (a,0,n);
}
static __attribute__ ((aligned(16))) int aa[10];
int
main()
{
test (&aa[1]);
test (&aa[3]);
return 0;
}
/* { dg-final { scan-ipa-dump "Alignment 8, misalignment 4" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */ /* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-icf" } */
/* Should produce <=. */ /* Should produce <=. */
int test1 (int a, int b) int test1 (int a, int b)
......
/* PR tree-optimization/64454 */ /* PR tree-optimization/64454 */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */ /* { dg-options "-O2 -fdump-tree-vrp1 -fno-ipa-icf" } */
unsigned unsigned
f1 (unsigned x) f1 (unsigned x)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment