Hi,
this patch puts varpool more into control of what is output.  Traditionally
frontends were outputting variables as they parsed them via
tree_rest_of_compilation or at the end of compilation via
wrapup_global_declarations that went through all the decls, output unused
warnings and called tree_rest_of_decl_compilation on those that was not
compiled yet.

The difference was that in first case var was output always, while in the
second case only if needed.

I eventually hooked varpool into tree_rest_of_decl_compilation and collected
variables by that.  This however does not collect all variables in all
frontends.  C and C++ frontends calls tree_rest_of_decl_compilation while
for example fortran frontend often relies on wrapup_global_decls.

Moreover there are not only variables but other kind of weirdos flying
around.  First are VAR_DECLs with HAS_VALUE_EXPR_SET.  Those are not
real variables (and are not output to assembly) but they matter for debugging.
Moreover emutls uses this mechanizm to replace TLS vars by their emulation
code.

Next ther are constant pool decls that are not output from varpool but via
special code handling constant pool.

This patch regularizes things somewhat.  First wrapup of global declaration
now happens consistently before finalizing complation unit.  This makes
fortran behave like C and makes varpool complette.

Next I avoid adding variables with VALUE_EXPR into varpool, since they 
are not real symbols.
There is problem with emutls where the variables are insterted but later
replaced. Emutls should update reference lists but does not, I will do that
in followup patch.

Finally it informs varpool that constant pool decls goes into assembly
automatically behind scenes (this is used on some funnier targets to interleave
code with constants)

The patch also adds bunch of sanity checking that things works as expected
and varpool is finally in control of variable output.

This avoids need of frontend to mess with TREE_ASM_WRITTEN flag to convince
backend to skip variables that are just fake varibales.  I removed this from
fortran frontend where it is easy. C++ is less easy since it checks the flag
itself.  I will look into that as followup, too.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

        * cgraphbuild.c (build_cgraph_edges): Do not finalize vars
        with VALUE_EXPR.
        * cgraph.h (varpool_can_remove_if_no_refs): Vars with VALUE_EXPR
        are removable.
        * toplev.c (wrapup_global_declaration_2): Vars with VALUE_EXPR
        need to wrapup.
        (compile_file): Do not output variables.
        * cgraphbuild.c (varpool_finalize_decl): When var is finalized late,
        output it.
        * langhooks.c: Include timevar.h
        (write_global_declarations): Finalize compilation unit after wrapup;
        set timevars correctly.
        * passes.c (rest_of_decl_compilation): Decls with VALUE_EXPR needs
        not to be added to varpool.
        * varpool.c (varpool_assemble_decl): Sanity check that we are called
        only on cases where it makes sense; skip constant pool and value expr
        vars.

        * lto.c (do_whole_program_analysis): Set timevars correctly.
        (lto_main): Likewise.
        
        * trans-common.c (create_common): Do not fake TREE_ASM_WRITTEN.
        * trans-decl.c (gfc_finish_cray_pointee): Likewise.
Index: cgraphbuild.c
===================================================================
*** cgraphbuild.c       (revision 187296)
--- cgraphbuild.c       (working copy)
*************** build_cgraph_edges (void)
*** 356,362 ****
    /* Look for initializers of constant variables and private statics.  */
    FOR_EACH_LOCAL_DECL (cfun, ix, decl)
      if (TREE_CODE (decl) == VAR_DECL
!       && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl)))
        varpool_finalize_decl (decl);
    record_eh_tables (node, cfun);
  
--- 356,363 ----
    /* Look for initializers of constant variables and private statics.  */
    FOR_EACH_LOCAL_DECL (cfun, ix, decl)
      if (TREE_CODE (decl) == VAR_DECL
!       && (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
!       && !DECL_HAS_VALUE_EXPR_P (decl))
        varpool_finalize_decl (decl);
    record_eh_tables (node, cfun);
  
Index: cgraph.h
===================================================================
*** cgraph.h    (revision 187296)
--- cgraph.h    (working copy)
*************** varpool_can_remove_if_no_refs (struct va
*** 1126,1131 ****
--- 1126,1132 ----
    return (!node->symbol.force_output && 
!node->symbol.used_from_other_partition
          && (DECL_COMDAT (node->symbol.decl)
          || !node->symbol.externally_visible
+         || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)
          || DECL_EXTERNAL (node->symbol.decl)));
  }
  
Index: toplev.c
===================================================================
*** toplev.c    (revision 187296)
--- toplev.c    (working copy)
*************** wrapup_global_declaration_1 (tree decl)
*** 364,370 ****
  bool
  wrapup_global_declaration_2 (tree decl)
  {
!   if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl))
      return false;
  
    /* Don't write out static consts, unless we still need them.
--- 364,371 ----
  bool
  wrapup_global_declaration_2 (tree decl)
  {
!   if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)
!       || (TREE_CODE (decl) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (decl)))
      return false;
  
    /* Don't write out static consts, unless we still need them.
*************** compile_file (void)
*** 576,582 ****
       basically finished.  */
    if (in_lto_p || !flag_lto || flag_fat_lto_objects)
      {
-       varpool_output_variables ();
        finish_aliases_2 ();
  
        /* Likewise for mudflap static object registrations.  */
--- 577,582 ----
Index: cgraphunit.c
===================================================================
*** cgraphunit.c        (revision 187296)
--- cgraphunit.c        (working copy)
*************** varpool_finalize_decl (tree decl)
*** 834,839 ****
--- 834,843 ----
      enqueue_node ((symtab_node)node);
    if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
      varpool_analyze_node (node);
+   /* Some frontends produce various interface variables after compilation
+      finished.  */
+   if (cgraph_state == CGRAPH_STATE_FINISHED)
+     varpool_assemble_decl (node);
  }
  
  /* Discover all functions and variables that are trivially needed, analyze
Index: fortran/trans-common.c
===================================================================
*** fortran/trans-common.c      (revision 187296)
--- fortran/trans-common.c      (working copy)
*************** create_common (gfc_common_head *com, seg
*** 697,704 ****
        DECL_IGNORED_P (var_decl) = 1;
        if (s->sym->attr.target)
        TREE_ADDRESSABLE (var_decl) = 1;
-       /* This is a fake variable just for debugging purposes.  */
-       TREE_ASM_WRITTEN (var_decl) = 1;
        /* Fake variables are not visible from other translation units. */
        TREE_PUBLIC (var_decl) = 0;
  
--- 697,702 ----
Index: fortran/trans-decl.c
===================================================================
*** fortran/trans-decl.c        (revision 187296)
--- fortran/trans-decl.c        (working copy)
*************** gfc_finish_cray_pointee (tree decl, gfc_
*** 457,464 ****
    SET_DECL_VALUE_EXPR (decl, value);
    DECL_HAS_VALUE_EXPR_P (decl) = 1;
    GFC_DECL_CRAY_POINTEE (decl) = 1;
-   /* This is a fake variable just for debugging purposes.  */
-   TREE_ASM_WRITTEN (decl) = 1;
  }
  
  
--- 457,462 ----
Index: langhooks.c
===================================================================
*** langhooks.c (revision 187296)
--- langhooks.c (working copy)
*************** along with GCC; see the file COPYING3.  
*** 39,44 ****
--- 39,45 ----
  #include "diagnostic.h"
  #include "tree-diagnostic.h"
  #include "cgraph.h"
+ #include "timevar.h"
  #include "output.h"
  
  /* Do nothing; in many cases the default hook.  */
*************** write_global_declarations (void)
*** 298,307 ****
    tree globals, decl, *vec;
    int len, i;
  
!   /* This lang hook is dual-purposed, and also finalizes the
!      compilation unit.  */
!   finalize_compilation_unit ();
! 
    /* Really define vars that have had only a tentative definition.
       Really output inline functions that must actually be callable
       and have not been output so far.  */
--- 299,305 ----
    tree globals, decl, *vec;
    int len, i;
  
!   timevar_start (TV_PHASE_DEFERRED);
    /* Really define vars that have had only a tentative definition.
       Really output inline functions that must actually be callable
       and have not been output so far.  */
*************** write_global_declarations (void)
*** 318,324 ****
--- 316,332 ----
  
    wrapup_global_declarations (vec, len);
    check_global_declarations (vec, len);
+   timevar_stop (TV_PHASE_DEFERRED);
+ 
+   timevar_start (TV_PHASE_CGRAPH);
+   /* This lang hook is dual-purposed, and also finalizes the
+      compilation unit.  */
+   finalize_compilation_unit ();
+   timevar_stop (TV_PHASE_CGRAPH);
+ 
+   timevar_start (TV_PHASE_CHECK_DBGINFO);
    emit_debug_global_declarations (vec, len);
+   timevar_stop (TV_PHASE_CHECK_DBGINFO);
  
    /* Clean up.  */
    free (vec);
Index: lto/lto.c
===================================================================
*** lto/lto.c   (revision 187296)
--- lto/lto.c   (working copy)
*************** materialize_cgraph (void)
*** 1958,1963 ****
--- 1958,1964 ----
  static void
  do_whole_program_analysis (void)
  {
+   timevar_start (TV_PHASE_CGRAPH);
    /* Note that since we are in WPA mode, materialize_cgraph will not
       actually read in all the function bodies.  It only materializes
       the decls and cgraph nodes so that analysis can be performed.  */
*************** do_whole_program_analysis (void)
*** 2017,2022 ****
--- 2018,2024 ----
        dump_memory_report (false);
      }
  
+   timevar_stop (TV_PHASE_CGRAPH);
    /* Show the LTO report before launching LTRANS.  */
    if (flag_lto_report)
      print_lto_report ();
*************** lto_main (void)
*** 2116,2122 ****
--- 2118,2126 ----
  
          /* Let the middle end know that we have read and merged all of
             the input files.  */ 
+         timevar_start (TV_PHASE_CGRAPH);
          compile ();
+         timevar_stop (TV_PHASE_CGRAPH);
  
          /* FIXME lto, if the processes spawned by WPA fail, we miss
             the chance to print WPA's report, so WPA will call
Index: passes.c
===================================================================
*** passes.c    (revision 187296)
--- passes.c    (working copy)
*************** rest_of_decl_compilation (tree decl,
*** 186,191 ****
--- 186,192 ----
        if ((at_end
           || !DECL_DEFER_OUTPUT (decl)
           || DECL_INITIAL (decl))
+         && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl))
          && !DECL_EXTERNAL (decl))
        {
          /* When reading LTO unit, we also read varpool, so do not
Index: varpool.c
===================================================================
*** varpool.c   (revision 187296)
--- varpool.c   (working copy)
*************** assemble_aliases (struct varpool_node *n
*** 269,292 ****
  }
  
  /* Output one variable, if necessary.  Return whether we output it.  */
  bool
  varpool_assemble_decl (struct varpool_node *node)
  {
    tree decl = node->symbol.decl;
  
!   if (!TREE_ASM_WRITTEN (decl)
!       && !node->alias
!       && !node->symbol.in_other_partition
!       && !DECL_EXTERNAL (decl)
!       && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
      {
        assemble_variable (decl, 0, 1, 0);
!       if (TREE_ASM_WRITTEN (decl))
!       {
!         node->finalized = 1;
!         assemble_aliases (node);
!         return true;
!       }
      }
  
    return false;
--- 269,310 ----
  }
  
  /* Output one variable, if necessary.  Return whether we output it.  */
+ 
  bool
  varpool_assemble_decl (struct varpool_node *node)
  {
    tree decl = node->symbol.decl;
  
!   /* Aliases are outout when their target is produced or by
!      output_weakrefs.  */
!   if (node->alias)
!     return false;
! 
!   /* Constant pool is output from RTL land when the reference
!      survive till this level.  */
!   if (DECL_IN_CONSTANT_POOL (decl))
!     return false;
! 
!   /* Decls with VALUE_EXPR should not be in the varpool at all.  They
!      are not real variables, but just info for debugging and codegen.
!      Unfortunately at the moment emutls is not updating varpool correctly
!      after turning real vars into value_expr vars.  */
!   if (DECL_HAS_VALUE_EXPR_P (decl)
!       && !targetm.have_tls)
!     return false;
! 
!   gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
!                      && TREE_CODE (decl) == VAR_DECL
!                      && !DECL_HAS_VALUE_EXPR_P (decl));
! 
!   if (!node->symbol.in_other_partition
!       && !DECL_EXTERNAL (decl))
      {
        assemble_variable (decl, 0, 1, 0);
!       gcc_assert (TREE_ASM_WRITTEN (decl));
!       node->finalized = 1;
!       assemble_aliases (node);
!       return true;
      }
  
    return false;

Reply via email to