this PR is about odd inconsistencies about comdat variables being or not being
optimized out at -O0 with LTO. This is a side effect of the logic where COMDAT
variables are output on demand at -O0, while static variables are output
always. This logic is here from pre-cgraph times where we did not optimized
out unused static vars in C at all, but we did, sort-of, optimized out unused
comdats in C++ FE.
Some tools depends on strings stored into unused static vars to survive and it
probably makes sense to behave this way at -O0.
Now this all becomes bit incosistent when LTO brings COMDAT vars private with
LTO even at -O0.
This patch moves this handling earlier. At a time we finalize decl we check
toplevel_reorder and in !toplevel_reorder we mark all non-COMDAT non-artifical
variables as forced to output
Rest of compiler now can work same was at -O0 or not. This is cleaner and more
Richi, does this fix all issues you saw? It seems to work on the testcase
but I know it comes from some more involved analysis.
Do we want to avoid privatization of symbols with LTO at -O0? It probably
to do so as the privatization breaks debugging. What about -fwhole-program? In
case I would lean towards still honoring it since user has to explicitely ask
Bootstrapped/regtested x86_64-linux, comitted.
* varpool.c (varpool_finalize_decl): Handle toplevel_reorder here.
(decide_is_variable_needed): Do not handle toplevel reorder here.
* cgraph.h (varpool_can_remove_if_no_refs): Likewise.
* ipa.c (cgraph_remove_unreachable_nodes): Remove unreachable vars
even at -O0.
--- cgraph.h (revision 185774)
+++ cgraph.h (working copy)
@@ -947,8 +947,6 @@ static inline bool
varpool_can_remove_if_no_refs (struct varpool_node *node)
return (!node->force_output && !node->used_from_other_partition
- && (flag_toplevel_reorder || DECL_COMDAT (node->decl)
- || DECL_ARTIFICIAL (node->decl))
&& (DECL_COMDAT (node->decl) || !node->externally_visible));
--- ipa.c (revision 185774)
+++ ipa.c (working copy)
@@ -419,11 +419,6 @@ cgraph_remove_unreachable_nodes (bool be
fprintf (file, "\n");
- /* We must release unused extern inlines or sanity checking will fail. Rest
- are undesirable at -O0 since we do not want to remove anything. */
- if (!optimize)
- return changed;
fprintf (file, "Reclaiming variables:");
for (vnode = varpool_nodes; vnode; vnode = vnext)
@@ -463,6 +458,10 @@ cgraph_remove_unreachable_nodes (bool be
fprintf (file, "\n");
+ /* Rest of transformations are undesirable at -O0. */
+ if (!optimize)
+ return changed;
--- varpool.c (revision 185774)
+++ varpool.c (working copy)
@@ -334,10 +334,6 @@ decide_is_variable_needed (struct varpoo
&& !DECL_EXTERNAL (decl))
- /* When not reordering top level variables, we have to assume that
- we are going to keep everything. */
- if (!flag_toplevel_reorder)
- return true;
@@ -405,7 +401,11 @@ varpool_finalize_decl (tree decl)
node->finalized = true;
- if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl))
+ if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
+ /* Traditionally we do not eliminate static variables when not
+ optimizing and when not doing toplevel reoder. */
+ || (!flag_toplevel_reorder && !DECL_COMDAT (node->decl)
+ && !DECL_ARTIFICIAL (node->decl)))
node->force_output = true;
if (decide_is_variable_needed (node, decl))