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>
* doc/extend.texi (Function Attributes): Fix spelling and typos.
......
......@@ -2630,7 +2630,7 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl)
if (!node
|| node->body_removed
|| node->in_other_partition
|| node->icf_merged
|| callee->icf_merged
|| callee->in_other_partition)
return false;
......
......@@ -326,9 +326,6 @@ public:
/* Return true if ONE and TWO are part of the same COMDAT group. */
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. */
bool nonzero_address ();
......@@ -337,6 +334,15 @@ public:
return 2 otherwise. */
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,
and NULL otherwise. */
static inline symtab_node *get (const_tree decl)
......@@ -3022,6 +3028,43 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
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. */
inline
......
......@@ -471,6 +471,8 @@ cgraph_node::create_clone (tree decl, gcov_type gcov_count, int freq,
new_node->frequency = frequency;
new_node->tp_first_run = tp_first_run;
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.args_to_skip = args_to_skip;
......
......@@ -2468,6 +2468,7 @@ cgraph_node::create_wrapper (cgraph_node *target)
release_body (true);
reset ();
DECL_UNINLINABLE (decl) = false;
DECL_RESULT (decl) = decl_result;
DECL_INITIAL (decl) = NULL;
allocate_struct_function (decl, false);
......
......@@ -1644,11 +1644,11 @@ Report on permanent memory allocation in WPA only
; string constants and constants from constant pool, if 2 also constant
; variables.
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
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
fmerge-debug-strings
......
......@@ -124,23 +124,3 @@ ipa_ref::referred_ref_list (void)
{
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)
}
/* 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. */
static bool
......@@ -157,16 +136,14 @@ comdat_can_be_unshared_p_1 (symtab_node *node)
{
if (!node->externally_visible)
return true;
/* When address is taken, we don't know if equality comparison won't
break eventually. Exception are virutal functions, C++
constructors/destructors and vtables, where this is not possible by
language standard. */
if (!DECL_VIRTUAL_P (node->decl)
&& (TREE_CODE (node->decl) != FUNCTION_DECL
|| (!DECL_CXX_CONSTRUCTOR_P (node->decl)
&& !DECL_CXX_DESTRUCTOR_P (node->decl)))
&& node->address_taken_from_non_vtable_p ())
return false;
if (node->address_can_be_compared_p ())
{
struct ipa_ref *ref;
for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
if (ref->address_matters_p ())
return false;
}
/* If the symbol is used in some weird way, better to not touch it. */
if (node->force_output)
......@@ -387,7 +364,8 @@ can_replace_by_local_alias_in_vtable (symtab_node *node)
/* walk_tree callback that rewrites initializer references. */
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
|| TREE_CODE (*tp) == FUNCTION_DECL)
......
......@@ -1156,7 +1156,11 @@ symtab_node::make_decl_local (void)
return;
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);
DECL_COMDAT (decl) = 0;
......@@ -1513,6 +1517,19 @@ symtab_node::resolve_alias (symtab_node *target)
/* If alias has address taken, so does the target. */
if (address_taken)
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;
}
......@@ -1863,3 +1880,31 @@ symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *,
}
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>
PR tree-optimization/65216
......
......@@ -43,6 +43,6 @@ int main()
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 { cleanup-ipa-dump "icf" } } */
// { dg-do compile }
// { dg-options "-O2 -Wsuggest-final-types -Wsuggest-final-methods" }
int c;
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 b() {} // { dg-warning "final would enable devirtualization of 2 calls" }
virtual void b() {c++;} // { dg-warning "final would enable devirtualization of 2 calls" }
};
void
t(struct A *a)
......
/* Verify that simple indirect calls are inlined even without early
inlining.. */
/* { 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);
......
/* { 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-options "-O2 -fdump-tree-optimized" } */
/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-icf" } */
/* Should produce <=. */
int test1 (int a, int b)
......
/* PR tree-optimization/64454 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */
/* { dg-options "-O2 -fdump-tree-vrp1 -fno-ipa-icf" } */
unsigned
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