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 
makes sense
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 
for it.

Bootstrapped/regtested x86_64-linux, comitted.


        PR lto/51663
        * 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.
Index: cgraph.h
--- 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));
Index: ipa.c
--- ipa.c       (revision 185774)
+++ ipa.c       (working copy)
@@ -419,11 +419,6 @@ cgraph_remove_unreachable_nodes (bool be
   if (file)
     fprintf (file, "\n");
-  /* We must release unused extern inlines or sanity checking will fail.  Rest 
of transformations
-     are undesirable at -O0 since we do not want to remove anything.  */
-  if (!optimize)
-    return changed;
   if (file)
     fprintf (file, "Reclaiming variables:");
   for (vnode = varpool_nodes; vnode; vnode = vnext)
@@ -463,6 +458,10 @@ cgraph_remove_unreachable_nodes (bool be
   if (file)
     fprintf (file, "\n");
+  /* Rest of transformations are undesirable at -O0.  */
+  if (!optimize)
+    return changed;
   verify_cgraph ();
Index: varpool.c
--- varpool.c   (revision 185774)
+++ varpool.c   (working copy)
@@ -334,10 +334,6 @@ decide_is_variable_needed (struct varpoo
       && !DECL_EXTERNAL (decl))
     return true;
-  /* When not reordering top level variables, we have to assume that
-     we are going to keep everything.  */
-  if (!flag_toplevel_reorder)
-    return true;
   return false;
@@ -405,7 +401,11 @@ varpool_finalize_decl (tree decl)
   if (node->needed)
     varpool_enqueue_needed_node (node);
   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))

Reply via email to