On Thu, 14 Jun 2018, Richard Biener wrote: > Can you make sure to add a testcase?
Apologies, I got a bit too excited and forgot that my local testcase had void *unused_ref = &foo; which masked another issue: unreferenced declarations won't even appear in the symtab, even if they have __attribute__((used)). I took a shot at fixing that. The following patch makes sure the decl appears in the symtab and is not deleted by ipa-visibility. However, it is not added to LTO streamed-out symtab, so WPA does not see it. If the direction looks fine overall, I'll look into getting over this streaming hurdle (hints much appreciated). WIP patch (untested), now with a minimal testcase: * c-family/c-attribs.c (handle_used_attribute): Create a symtab node. * cgraphunit.c (symtab_node::needed_p): Respect force_output even for external nodes. * ipa-visibility.c (function_and_variable_visibility): Do not reset node->force_output. * ipa.c (symbol_table::remove_unreachable_nodes): Do not remove nodes that are needed_p. diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 73901bdf47c..f28bb529092 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -1052,6 +1052,7 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), DECL_PRESERVE_P (node) = 1; if (VAR_P (node)) DECL_READ_P (node) = 1; + symtab_node::get_create (node); } else { diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 04b6919be48..3931a79aa3d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -244,16 +244,16 @@ symtab_node::needed_p (void) (!DECL_ASSEMBLER_NAME_SET_P (decl) || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); + /* If the user told us it is used, then it must be so. */ + if (force_output) + return true; + if (!definition) return false; if (DECL_EXTERNAL (decl)) return false; - /* If the user told us it is used, then it must be so. */ - if (force_output) - return true; - /* ABI forced symbols are needed when they are external. */ if (forced_by_abi && TREE_PUBLIC (decl)) return true; diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c index 907dc9d0e2b..3e167567b45 100644 --- a/gcc/ipa-visibility.c +++ b/gcc/ipa-visibility.c @@ -668,10 +668,7 @@ function_and_variable_visibility (bool whole_program) is finished. We may end up marking as node external nodes where this flag is meaningless strip it. */ if (DECL_EXTERNAL (node->decl) || !node->definition) - { - node->force_output = 0; - node->forced_by_abi = 0; - } + node->forced_by_abi = 0; /* C++ FE on lack of COMDAT support create local COMDAT functions (that ought to be shared but can not due to object format diff --git a/gcc/ipa.c b/gcc/ipa.c index 82fc334ec0b..8e011d00cc4 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -507,7 +507,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) next = next_function (node); /* If node is not needed at all, remove it. */ - if (!node->aux) + if (!node->aux && !node->needed_p ()) { if (file) fprintf (file, " %s", node->dump_name ()); diff --git a/gcc/testsuite/gcc.dg/lto/tlasm_0.c b/gcc/testsuite/gcc.dg/lto/tlasm_0.c index e69de29bb2d..ba31c01e17c 100644 --- a/gcc/testsuite/gcc.dg/lto/tlasm_0.c +++ b/gcc/testsuite/gcc.dg/lto/tlasm_0.c @@ -0,0 +1,19 @@ +/* { dg-lto-do link } */ +/* { dg-require-effective-target gas } */ + +/* Test that __attribute__((used)) can be used to preserve definitions of + * symbols referenced in toplevel asm even when the definition is provided + * in another translation unit, i.e. the attribute is not lost before WPA. */ + +__attribute__ ((used)) +void foo (void); + +#if __SIZEOF_POINTER__ == 64 +asm (".quad foo"); +#else +asm (".long foo"); +#endif + +int main () +{ +} diff --git a/gcc/testsuite/gcc.dg/lto/tlasm_1.c b/gcc/testsuite/gcc.dg/lto/tlasm_1.c index e69de29bb2d..a4b7f5afa52 100644 --- a/gcc/testsuite/gcc.dg/lto/tlasm_1.c +++ b/gcc/testsuite/gcc.dg/lto/tlasm_1.c @@ -0,0 +1,3 @@ +void foo (void) +{ +}