re PR lto/61886 (LTO breaks fread with _FORTIFY_SOURCE=2)
PR ipa/61886 * lto-streamer.h (lto_symtab_merge_decls, lto_symtab_merge_symbols, lto_symtab_prevailing_decl): MOve to lto-symtab.h. * lto-streamer-out.c (DFS::DFS_write_tree_body): Check that DECL_ABSTRACT_ORIGIN is not error_mark_node. * lto-symtab.c: Include lto-symtab.h. (lto_cgraph_replace_node): Do not merge profiles here. (lto_symtab_merge_p): New function. (lto_symtab_merge_decls_2): Honor lto_symtab_merge_p. (lto_symtab_merge_symbols_1): Turn unmerged decls into transparent aliases. (lto_symtab_merge_symbols): Do not clear node->aux; we no longer use it. (lto_symtab_prevailing_decl): Move to lto-symtab.h; rewrite. * lto.c: Include lto-symtab.h * lto-symtab.h: New. From-SVN: r231438
This commit is contained in:
parent
1a161cd7a7
commit
6b9ac1796e
@ -1,3 +1,11 @@
|
||||
2015-12-08 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
PR ipa/61886
|
||||
* lto-streamer.h (lto_symtab_merge_decls, lto_symtab_merge_symbols,
|
||||
lto_symtab_prevailing_decl): MOve to lto-symtab.h.
|
||||
* lto-streamer-out.c (DFS::DFS_write_tree_body): Check that
|
||||
DECL_ABSTRACT_ORIGIN is not error_mark_node.
|
||||
|
||||
2015-12-08 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* tree-nested.c (convert_tramp_reference_stmt): Fix indentation.
|
||||
|
@ -731,7 +731,11 @@ DFS::DFS_write_tree_body (struct output_block *ob,
|
||||
|
||||
/* Do not follow DECL_ABSTRACT_ORIGIN. We cannot handle debug information
|
||||
for early inlining so drop it on the floor instead of ICEing in
|
||||
dwarf2out.c. */
|
||||
dwarf2out.c.
|
||||
We however use DECL_ABSTRACT_ORIGIN == error_mark_node to mark
|
||||
declarations which should be eliminated by decl merging. Be sure none
|
||||
leaks to this point. */
|
||||
gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
|
||||
|
||||
if ((TREE_CODE (expr) == VAR_DECL
|
||||
|| TREE_CODE (expr) == PARM_DECL)
|
||||
|
@ -927,11 +927,6 @@ void cl_optimization_stream_out (struct bitpack_d *, struct cl_optimization *);
|
||||
void cl_optimization_stream_in (struct bitpack_d *, struct cl_optimization *);
|
||||
|
||||
|
||||
/* In lto-symtab.c. */
|
||||
extern void lto_symtab_merge_decls (void);
|
||||
extern void lto_symtab_merge_symbols (void);
|
||||
extern tree lto_symtab_prevailing_decl (tree decl);
|
||||
|
||||
|
||||
/* In lto-opts.c. */
|
||||
extern void lto_write_options (void);
|
||||
|
@ -1,3 +1,17 @@
|
||||
2015-12-08 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
PR ipa/61886
|
||||
* lto-symtab.c: Include lto-symtab.h.
|
||||
(lto_cgraph_replace_node): Do not merge profiles here.
|
||||
(lto_symtab_merge_p): New function.
|
||||
(lto_symtab_merge_decls_2): Honor lto_symtab_merge_p.
|
||||
(lto_symtab_merge_symbols_1): Turn unmerged decls into transparent
|
||||
aliases.
|
||||
(lto_symtab_merge_symbols): Do not clear node->aux; we no longer use it.
|
||||
(lto_symtab_prevailing_decl): Move to lto-symtab.h; rewrite.
|
||||
* lto.c: Include lto-symtab.h
|
||||
* lto-symtab.h: New.
|
||||
|
||||
2015-12-08 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
PR ipa/61886
|
||||
|
@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "ipa-utils.h"
|
||||
#include "builtins.h"
|
||||
#include "alias.h"
|
||||
#include "lto-symtab.h"
|
||||
|
||||
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
|
||||
all edges and removing the old node. */
|
||||
@ -99,7 +100,6 @@ lto_cgraph_replace_node (struct cgraph_node *node,
|
||||
node->instrumented_version = NULL;
|
||||
}
|
||||
|
||||
ipa_merge_profiles (prevailing_node, node);
|
||||
lto_free_function_in_decl_state_for_node (node);
|
||||
|
||||
if (node->decl != prevailing_node->decl)
|
||||
@ -503,6 +503,30 @@ lto_symtab_resolve_symbols (symtab_node *first)
|
||||
return prevailing;
|
||||
}
|
||||
|
||||
/* Decide if it is OK to merge DECL into PREVAILING.
|
||||
Because we wrap most of uses of declarations in MEM_REF, we can tolerate
|
||||
some differences but other code may inspect directly the DECL. */
|
||||
|
||||
static bool
|
||||
lto_symtab_merge_p (tree prevailing, tree decl)
|
||||
{
|
||||
if (TREE_CODE (prevailing) != TREE_CODE (decl))
|
||||
return false;
|
||||
if (TREE_CODE (prevailing) == FUNCTION_DECL)
|
||||
{
|
||||
if (DECL_BUILT_IN (prevailing) != DECL_BUILT_IN (decl))
|
||||
return false;
|
||||
if (DECL_BUILT_IN (prevailing)
|
||||
&& (DECL_BUILT_IN_CLASS (prevailing) != DECL_BUILT_IN_CLASS (decl)
|
||||
|| DECL_FUNCTION_CODE (prevailing) != DECL_FUNCTION_CODE (decl)))
|
||||
return false;
|
||||
}
|
||||
/* There are several other cases where merging can not be done, but until
|
||||
aliasing code is fixed to support aliases it we can not really return
|
||||
false on non-readonly var, yet. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Merge all decls in the symbol table chain to the prevailing decl and
|
||||
issue diagnostics about type mismatches. If DIAGNOSED_P is true
|
||||
do not issue further diagnostics.*/
|
||||
@ -523,15 +547,59 @@ lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
|
||||
return;
|
||||
|
||||
/* Try to merge each entry with the prevailing one. */
|
||||
for (e = prevailing->next_sharing_asm_name;
|
||||
e; e = e->next_sharing_asm_name)
|
||||
if (TREE_PUBLIC (e->decl))
|
||||
{
|
||||
if (!lto_symtab_merge (prevailing, e)
|
||||
&& !diagnosed_p
|
||||
&& !DECL_ARTIFICIAL (e->decl))
|
||||
mismatches.safe_push (e->decl);
|
||||
}
|
||||
symtab_node *last_prevailing = prevailing, *next;
|
||||
for (e = prevailing->next_sharing_asm_name; e; e = next)
|
||||
{
|
||||
next = e->next_sharing_asm_name;
|
||||
|
||||
/* Skip non-LTO symbols and symbols whose declaration we already
|
||||
visited. */
|
||||
if (lto_symtab_prevailing_decl (e->decl) != e->decl
|
||||
|| !lto_symtab_symbol_p (e)
|
||||
|| e->decl == prevailing->decl)
|
||||
continue;
|
||||
|
||||
if (!lto_symtab_merge (prevailing, e)
|
||||
&& !diagnosed_p
|
||||
&& !DECL_ARTIFICIAL (e->decl))
|
||||
mismatches.safe_push (e->decl);
|
||||
|
||||
symtab_node *this_prevailing;
|
||||
for (this_prevailing = prevailing; ;
|
||||
this_prevailing = this_prevailing->next_sharing_asm_name)
|
||||
{
|
||||
if (lto_symtab_merge_p (this_prevailing->decl, e->decl))
|
||||
break;
|
||||
if (this_prevailing == last_prevailing)
|
||||
{
|
||||
this_prevailing = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this_prevailing)
|
||||
lto_symtab_prevail_decl (this_prevailing->decl, e->decl);
|
||||
/* Maintain LRU list: relink the new prevaililng symbol
|
||||
just after previaling node in the chain and update last_prevailing.
|
||||
Since the number of possible declarations of a given symbol is
|
||||
small, this should be faster than building a hash. */
|
||||
else if (e == prevailing->next_sharing_asm_name)
|
||||
last_prevailing = e;
|
||||
else
|
||||
{
|
||||
if (e->next_sharing_asm_name)
|
||||
e->next_sharing_asm_name->previous_sharing_asm_name
|
||||
= e->previous_sharing_asm_name;
|
||||
e->previous_sharing_asm_name->next_sharing_asm_name
|
||||
= e->next_sharing_asm_name;
|
||||
e->previous_sharing_asm_name = prevailing;
|
||||
e->next_sharing_asm_name = prevailing->next_sharing_asm_name;
|
||||
prevailing->next_sharing_asm_name->previous_sharing_asm_name = e;
|
||||
prevailing->next_sharing_asm_name = e;
|
||||
if (last_prevailing == prevailing)
|
||||
last_prevailing = e;
|
||||
}
|
||||
}
|
||||
if (mismatches.is_empty ())
|
||||
return;
|
||||
|
||||
@ -729,6 +797,8 @@ lto_symtab_merge_symbols_1 (symtab_node *prevailing)
|
||||
symtab_node *e;
|
||||
symtab_node *next;
|
||||
|
||||
prevailing->decl->decl_with_vis.symtab_node = prevailing;
|
||||
|
||||
/* Replace the cgraph node of each entry with the prevailing one. */
|
||||
for (e = prevailing->next_sharing_asm_name; e;
|
||||
e = next)
|
||||
@ -738,10 +808,47 @@ lto_symtab_merge_symbols_1 (symtab_node *prevailing)
|
||||
if (!lto_symtab_symbol_p (e))
|
||||
continue;
|
||||
cgraph_node *ce = dyn_cast <cgraph_node *> (e);
|
||||
if (ce && !DECL_BUILT_IN (e->decl))
|
||||
lto_cgraph_replace_node (ce, dyn_cast<cgraph_node *> (prevailing));
|
||||
if (varpool_node *ve = dyn_cast <varpool_node *> (e))
|
||||
lto_varpool_replace_node (ve, dyn_cast<varpool_node *> (prevailing));
|
||||
symtab_node *to = symtab_node::get (lto_symtab_prevailing_decl (e->decl));
|
||||
|
||||
/* No matter how we are going to deal with resolution, we will ultimately
|
||||
use prevailing definition. */
|
||||
if (ce)
|
||||
ipa_merge_profiles (dyn_cast<cgraph_node *> (prevailing),
|
||||
dyn_cast<cgraph_node *> (e));
|
||||
|
||||
/* If we decided to replace the node by TO, do it. */
|
||||
if (e != to)
|
||||
{
|
||||
if (ce)
|
||||
lto_cgraph_replace_node (ce, dyn_cast<cgraph_node *> (to));
|
||||
else if (varpool_node *ve = dyn_cast <varpool_node *> (e))
|
||||
lto_varpool_replace_node (ve, dyn_cast<varpool_node *> (to));
|
||||
}
|
||||
/* Watch out for duplicated symbols for a given declaration. */
|
||||
else if (!e->transparent_alias
|
||||
|| !e->definition || e->get_alias_target () != to)
|
||||
{
|
||||
/* We got a new declaration we do not want to merge. In this case
|
||||
get rid of the existing definition and create a transparent
|
||||
alias. */
|
||||
if (ce)
|
||||
{
|
||||
lto_free_function_in_decl_state_for_node (ce);
|
||||
if (!ce->weakref)
|
||||
ce->release_body ();
|
||||
ce->reset ();
|
||||
symtab->call_cgraph_removal_hooks (ce);
|
||||
}
|
||||
else
|
||||
{
|
||||
DECL_INITIAL (e->decl) = error_mark_node;
|
||||
symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e));
|
||||
}
|
||||
e->remove_all_references ();
|
||||
e->analyzed = e->body_removed = false;
|
||||
e->resolve_alias (prevailing, true);
|
||||
gcc_assert (e != prevailing);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -782,9 +889,8 @@ lto_symtab_merge_symbols (void)
|
||||
symtab_node *tgt = symtab_node::get_for_asmname (node->alias_target);
|
||||
gcc_assert (node->weakref);
|
||||
if (tgt)
|
||||
node->resolve_alias (tgt);
|
||||
node->resolve_alias (tgt, true);
|
||||
}
|
||||
node->aux = NULL;
|
||||
|
||||
if (!(cnode = dyn_cast <cgraph_node *> (node))
|
||||
|| !cnode->clone_of
|
||||
@ -821,45 +927,3 @@ lto_symtab_merge_symbols (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given the decl DECL, return the prevailing decl with the same name. */
|
||||
|
||||
tree
|
||||
lto_symtab_prevailing_decl (tree decl)
|
||||
{
|
||||
symtab_node *ret;
|
||||
|
||||
/* Builtins and local symbols are their own prevailing decl. */
|
||||
if ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) || is_builtin_fn (decl))
|
||||
return decl;
|
||||
|
||||
/* DECL_ABSTRACT_Ps are their own prevailing decl. */
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT_P (decl))
|
||||
return decl;
|
||||
|
||||
/* When decl did not participate in symbol resolution leave it alone.
|
||||
This can happen when we streamed the decl as abstract origin
|
||||
from the block tree of inlining a partially inlined function.
|
||||
If all, the split function and the original function end up
|
||||
optimized away early we do not put the abstract origin into the
|
||||
ltrans boundary and we'll end up ICEing in
|
||||
dwarf2out.c:gen_inlined_subroutine_die because we eventually
|
||||
replace a decl with DECL_POSSIBLY_INLINED set with one without. */
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& ! cgraph_node::get (decl))
|
||||
return decl;
|
||||
|
||||
/* Ensure DECL_ASSEMBLER_NAME will not set assembler name. */
|
||||
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
|
||||
|
||||
/* Walk through the list of candidates and return the one we merged to. */
|
||||
ret = symtab_node::get_for_asmname (DECL_ASSEMBLER_NAME (decl));
|
||||
if (!ret)
|
||||
return decl;
|
||||
|
||||
/* Do not replace a non-builtin with a builtin. */
|
||||
if (is_builtin_fn (ret->decl))
|
||||
return decl;
|
||||
|
||||
return ret->decl;
|
||||
}
|
||||
|
47
gcc/lto/lto-symtab.h
Normal file
47
gcc/lto/lto-symtab.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* LTO symbol table merging.
|
||||
Copyright (C) 2009-2015 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
extern void lto_symtab_merge_decls (void);
|
||||
extern void lto_symtab_merge_symbols (void);
|
||||
extern tree lto_symtab_prevailing_decl (tree decl);
|
||||
|
||||
/* Mark DECL to be previailed by PREVAILING.
|
||||
Use DECL_ABSTRACT_ORIGIN and DECL_CHAIN as special markers; those do not
|
||||
disturb debug_tree and diagnostics.
|
||||
We are safe to modify them as we wish, becuase the declarations disappear
|
||||
from the IL after the merging. */
|
||||
|
||||
inline void
|
||||
lto_symtab_prevail_decl (tree prevailing, tree decl)
|
||||
{
|
||||
gcc_checking_assert (DECL_ABSTRACT_ORIGIN (decl) != error_mark_node);
|
||||
DECL_CHAIN (decl) = prevailing;
|
||||
DECL_ABSTRACT_ORIGIN (decl) = error_mark_node;
|
||||
}
|
||||
|
||||
/* Given the decl DECL, return the prevailing decl with the same name. */
|
||||
|
||||
inline tree
|
||||
lto_symtab_prevailing_decl (tree decl)
|
||||
{
|
||||
if (DECL_ABSTRACT_ORIGIN (decl) == error_mark_node)
|
||||
return DECL_CHAIN (decl);
|
||||
else
|
||||
return decl;
|
||||
}
|
@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "params.h"
|
||||
#include "ipa-utils.h"
|
||||
#include "gomp-constants.h"
|
||||
#include "lto-symtab.h"
|
||||
|
||||
|
||||
/* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */
|
||||
|
Loading…
Reference in New Issue
Block a user