LCOV - code coverage report
Current view: top level - gcc - ipa-visibility.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.2 % 400 381
Test Date: 2025-03-22 13:13:03 Functions: 100.0 % 20 20
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* IPA visibility pass
       2                 :             :    Copyright (C) 2003-2025 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : /* This file implements two related passes:
      21                 :             : 
      22                 :             :      - pass_data_ipa_function_and_variable_visibility run just after
      23                 :             :        symbol table, references and callgraph are built
      24                 :             : 
      25                 :             :      - pass_data_ipa_function_and_variable_visibility run as first
      26                 :             :        proper IPA pass (that is after early optimization, or, (with LTO)
      27                 :             :        as a first pass done at link-time.
      28                 :             : 
      29                 :             :    Purpose of both passes is to set correctly visibility properties
      30                 :             :    of all symbols.  This includes:
      31                 :             : 
      32                 :             :     - Symbol privatization:
      33                 :             : 
      34                 :             :       Some symbols that are declared public by frontend may be
      35                 :             :       turned local (either by -fwhole-program flag, by linker plugin feedback
      36                 :             :       or by other reasons)
      37                 :             : 
      38                 :             :     - Discovery of local functions:
      39                 :             : 
      40                 :             :       A local function is one whose calls can occur only in the current
      41                 :             :       compilation unit and all its calls are explicit, so we can change
      42                 :             :       its calling convention.  We simply mark all static functions whose
      43                 :             :       address is not taken as local.
      44                 :             : 
      45                 :             :       externally_visible flag is set for symbols that cannot be privatized.
      46                 :             :       For privatized symbols we clear TREE_PUBLIC flag and dismantle comdat
      47                 :             :       group.
      48                 :             : 
      49                 :             :     - Dismantling of comdat groups:
      50                 :             : 
      51                 :             :       Comdat group represent a section that may be replaced by linker by
      52                 :             :       a different copy of the same section from other unit.
      53                 :             :       If we have resolution information (from linker plugin) and we know that
      54                 :             :       a given comdat gorup is prevailing, we can dismantle it and turn symbols
      55                 :             :       into normal symbols.  If the resolution information says that the
      56                 :             :       section was previaled by copy from non-LTO code, we can also dismantle
      57                 :             :       it and turn all symbols into external.
      58                 :             : 
      59                 :             :     - Local aliases:
      60                 :             : 
      61                 :             :       Some symbols can be interposed by dynamic linker. Refering to these
      62                 :             :       symbols is expensive, since it needs to be overwritable by the dynamic
      63                 :             :       linker.  In some cases we know that the interposition does not change
      64                 :             :       semantic and we can always refer to a local copy (as in the case of
      65                 :             :       inline function).  In this case we produce a local alias and redirect
      66                 :             :       calls to it.
      67                 :             : 
      68                 :             :       TODO: This should be done for references, too.
      69                 :             : 
      70                 :             :     - Removal of static ocnstructors and destructors that have no side effects.
      71                 :             : 
      72                 :             :     - Regularization of several oddities introduced by frontends that may
      73                 :             :       be impractical later in the optimization queue.  */
      74                 :             : 
      75                 :             : #include "config.h"
      76                 :             : #include "system.h"
      77                 :             : #include "coretypes.h"
      78                 :             : #include "tm.h"
      79                 :             : #include "function.h"
      80                 :             : #include "tree.h"
      81                 :             : #include "gimple-expr.h"
      82                 :             : #include "tree-pass.h"
      83                 :             : #include "cgraph.h"
      84                 :             : #include "calls.h"
      85                 :             : #include "varasm.h"
      86                 :             : #include "ipa-utils.h"
      87                 :             : #include "stringpool.h"
      88                 :             : #include "attribs.h"
      89                 :             : 
      90                 :             : /* Return true when NODE cannot be local. Worker for cgraph_local_node_p.  */
      91                 :             : 
      92                 :             : static bool
      93                 :     4893991 : non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
      94                 :             : {
      95                 :     4893991 :   return !(node->only_called_directly_or_aliased_p ()
      96                 :             :            /* i386 would need update to output thunk with local calling
      97                 :             :               conventions.  */
      98                 :      468921 :            && !node->thunk
      99                 :      468921 :            && node->definition
     100                 :      468919 :            && !DECL_EXTERNAL (node->decl)
     101                 :      251993 :            && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))
     102                 :             :            && !node->externally_visible
     103                 :             :            && !node->used_from_other_partition
     104                 :      251185 :            && !node->in_other_partition
     105                 :      251185 :            && node->get_availability () >= AVAIL_AVAILABLE
     106                 :      251185 :            && !DECL_STATIC_CONSTRUCTOR (node->decl)
     107                 :      251185 :            && !DECL_STATIC_DESTRUCTOR (node->decl));
     108                 :             : }
     109                 :             : 
     110                 :             : /* Return true when function can be marked local.  */
     111                 :             : 
     112                 :             : bool
     113                 :     4849761 : cgraph_node::local_p (void)
     114                 :             : {
     115                 :     4855735 :    cgraph_node *n = ultimate_alias_target ();
     116                 :             : 
     117                 :     4855735 :    if (n->thunk)
     118                 :        5974 :      return n->callees->callee->local_p ();
     119                 :     4849761 :    return !n->call_for_symbol_thunks_and_aliases (non_local_p,
     120                 :     4849761 :                                                   NULL, true);
     121                 :             : }
     122                 :             : 
     123                 :             : /* A helper for comdat_can_be_unshared_p.  */
     124                 :             : 
     125                 :             : static bool
     126                 :        1952 : comdat_can_be_unshared_p_1 (symtab_node *node)
     127                 :             : {
     128                 :        1952 :   if (!node->externally_visible)
     129                 :             :     return true;
     130                 :        1741 :   if (node->address_can_be_compared_p ())
     131                 :             :     {
     132                 :             :       struct ipa_ref *ref;
     133                 :             : 
     134                 :        1102 :       for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
     135                 :         570 :         if (ref->address_matters_p ())
     136                 :         404 :           return false;
     137                 :             :     }
     138                 :             : 
     139                 :             :   /* If the symbol is used in some weird way, better to not touch it.  */
     140                 :        1337 :   if (node->force_output)
     141                 :             :     return false;
     142                 :             : 
     143                 :             :   /* Explicit instantiations needs to be output when possibly
     144                 :             :      used externally.  */
     145                 :        1337 :   if (node->forced_by_abi
     146                 :          58 :       && TREE_PUBLIC (node->decl)
     147                 :          58 :       && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
     148                 :          58 :           && !flag_whole_program))
     149                 :             :     return false;
     150                 :             : 
     151                 :             :   /* Non-readonly and volatile variables cannot be duplicated.  */
     152                 :             :   if (is_a <varpool_node *> (node)
     153                 :         198 :       && (!TREE_READONLY (node->decl)
     154                 :         195 :           || TREE_THIS_VOLATILE (node->decl)))
     155                 :             :     return false;
     156                 :             :   return true;
     157                 :             : }
     158                 :             : 
     159                 :             : /* COMDAT functions must be shared only if they have address taken,
     160                 :             :    otherwise we can produce our own private implementation with
     161                 :             :    -fwhole-program.
     162                 :             :    Return true when turning COMDAT function static cannot lead to wrong
     163                 :             :    code when the resulting object links with a library defining same COMDAT.
     164                 :             : 
     165                 :             :    Virtual functions do have their addresses taken from the vtables,
     166                 :             :    but in C++ there is no way to compare their addresses for equality.  */
     167                 :             : 
     168                 :             : static bool
     169                 :        1468 : comdat_can_be_unshared_p (symtab_node *node)
     170                 :             : {
     171                 :        1468 :   if (!comdat_can_be_unshared_p_1 (node))
     172                 :             :     return false;
     173                 :        1009 :   if (node->same_comdat_group)
     174                 :             :     {
     175                 :             :       symtab_node *next;
     176                 :             : 
     177                 :             :       /* If more than one function is in the same COMDAT group, it must
     178                 :             :          be shared even if just one function in the comdat group has
     179                 :             :          address taken.  */
     180                 :         484 :       for (next = node->same_comdat_group;
     181                 :         822 :            next != node; next = next->same_comdat_group)
     182                 :         484 :         if (!comdat_can_be_unshared_p_1 (next))
     183                 :             :           return false;
     184                 :             :     }
     185                 :             :   return true;
     186                 :             : }
     187                 :             : 
     188                 :             : /* Return true when function NODE should be considered externally visible.  */
     189                 :             : 
     190                 :             : static bool
     191                 :     8372187 : cgraph_externally_visible_p (struct cgraph_node *node,
     192                 :             :                              bool whole_program)
     193                 :             : {
     194                 :     8372236 :   while (node->transparent_alias && node->definition)
     195                 :          49 :     node = node->get_alias_target ();
     196                 :     8372187 :   if (!node->definition)
     197                 :             :     return false;
     198                 :     4956445 :   if (!TREE_PUBLIC (node->decl)
     199                 :     4956445 :       || DECL_EXTERNAL (node->decl))
     200                 :             :     return false;
     201                 :             : 
     202                 :             :   /* Do not try to localize built-in functions yet.  One of problems is that we
     203                 :             :      end up mangling their asm for WHOPR that makes it impossible to call them
     204                 :             :      using the implicit built-in declarations anymore.  Similarly this enables
     205                 :             :      us to remove them as unreachable before actual calls may appear during
     206                 :             :      expansion or folding.  */
     207                 :     4069227 :   if (fndecl_built_in_p (node->decl))
     208                 :             :     return true;
     209                 :             : 
     210                 :             :   /* If linker counts on us, we must preserve the function.  */
     211                 :     4058885 :   if (node->used_from_object_file_p ())
     212                 :             :     return true;
     213                 :     4050468 :   if (DECL_PRESERVE_P (node->decl))
     214                 :             :     return true;
     215                 :     4043043 :   if (lookup_attribute ("externally_visible",
     216                 :     4043043 :                         DECL_ATTRIBUTES (node->decl)))
     217                 :             :     return true;
     218                 :     3991205 :   if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
     219                 :             :     return true;
     220                 :             :   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     221                 :             :       && lookup_attribute ("dllexport",
     222                 :             :                            DECL_ATTRIBUTES (node->decl)))
     223                 :             :     return true;
     224                 :             : 
     225                 :             :   /* Limitation of gas requires us to output targets of symver aliases as
     226                 :             :      global symbols.  This is binutils PR 25295.  */
     227                 :             :   ipa_ref *ref;
     228                 :     4368717 :   FOR_EACH_ALIAS (node, ref)
     229                 :      412948 :     if (ref->referring->symver)
     230                 :             :       return true;
     231                 :             : 
     232                 :     3955769 :   if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
     233                 :             :     return false;
     234                 :             :   /* When doing LTO or whole program, we can bring COMDAT functions static.
     235                 :             :      This improves code quality and we know we will duplicate them at most twice
     236                 :             :      (in the case that we are not using plugin and link with object file
     237                 :             :       implementing same COMDAT)  */
     238                 :     3919641 :   if (((in_lto_p || whole_program) && !flag_incremental_link)
     239                 :       30958 :       && DECL_COMDAT (node->decl)
     240                 :     3920566 :       && comdat_can_be_unshared_p (node))
     241                 :             :     return false;
     242                 :             : 
     243                 :             :   /* When doing link time optimizations, hidden symbols become local.  */
     244                 :       30034 :   if ((in_lto_p && !flag_incremental_link)
     245                 :       29783 :       && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
     246                 :       29781 :           || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
     247                 :             :       /* Be sure that node is defined in IR file, not in other object
     248                 :             :          file.  In that case we don't set used_from_other_object_file.  */
     249                 :     3918730 :       && node->definition)
     250                 :             :     ;
     251                 :     3918726 :   else if (!whole_program)
     252                 :             :     return true;
     253                 :             : 
     254                 :         286 :   if (MAIN_NAME_P (DECL_NAME (node->decl)))
     255                 :             :     return true;
     256                 :             : 
     257                 :             :   return false;
     258                 :             : }
     259                 :             : 
     260                 :             : /* Return true when variable should be considered externally visible.  */
     261                 :             : 
     262                 :             : bool
     263                 :     5809539 : varpool_node::externally_visible_p (void)
     264                 :             : {
     265                 :     5809547 :   while (transparent_alias && definition)
     266                 :           8 :     return get_alias_target ()->externally_visible_p ();
     267                 :     5809539 :   if (DECL_EXTERNAL (decl))
     268                 :             :     return true;
     269                 :             : 
     270                 :     5791490 :   if (!TREE_PUBLIC (decl))
     271                 :             :     return false;
     272                 :             : 
     273                 :             :   /* If linker counts on us, we must preserve the function.  */
     274                 :     2931350 :   if (used_from_object_file_p ())
     275                 :             :     return true;
     276                 :             : 
     277                 :             :   /* Bringing TLS variables local may cause dynamic linker failures
     278                 :             :      on limits of static TLS vars.  */
     279                 :     2931339 :   if (DECL_THREAD_LOCAL_P (decl)
     280                 :     2937014 :       && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED
     281                 :        5675 :           && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC))
     282                 :             :     return true;
     283                 :             : 
     284                 :     2925811 :   if (DECL_HARD_REGISTER (decl))
     285                 :             :     return true;
     286                 :     2925638 :   if (DECL_PRESERVE_P (decl))
     287                 :             :     return true;
     288                 :     2924288 :   if (lookup_attribute ("externally_visible",
     289                 :     2924288 :                         DECL_ATTRIBUTES (decl)))
     290                 :             :     return true;
     291                 :             :   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     292                 :             :       && lookup_attribute ("dllexport",
     293                 :             :                            DECL_ATTRIBUTES (decl)))
     294                 :             :     return true;
     295                 :             : 
     296                 :             :   /* Limitation of gas requires us to output targets of symver aliases as
     297                 :             :      global symbols.  This is binutils PR 25295.  */
     298                 :             :   ipa_ref *ref;
     299                 :     2924425 :   FOR_EACH_ALIAS (this, ref)
     300                 :         208 :     if (ref->referring->symver)
     301                 :             :       return true;
     302                 :             : 
     303                 :     2924217 :   if (resolution == LDPR_PREVAILING_DEF_IRONLY)
     304                 :             :     return false;
     305                 :             : 
     306                 :             :   /* As a special case, the COMDAT virtual tables can be unshared.
     307                 :             :      In LTO mode turn vtables into static variables.  The variable is readonly,
     308                 :             :      so this does not enable more optimization, but referring static var
     309                 :             :      is faster for dynamic linking.  Also this match logic hidding vtables
     310                 :             :      from LTO symbol tables.  */
     311                 :     2912730 :   if (((in_lto_p || flag_whole_program) && !flag_incremental_link)
     312                 :        6319 :       && DECL_COMDAT (decl)
     313                 :     2913273 :       && comdat_can_be_unshared_p (this))
     314                 :             :     return false;
     315                 :             : 
     316                 :             :   /* When doing link time optimizations, hidden symbols become local.  */
     317                 :        6197 :   if (in_lto_p && !flag_incremental_link
     318                 :        6022 :       && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN
     319                 :        6021 :           || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL)
     320                 :             :       /* Be sure that node is defined in IR file, not in other object
     321                 :             :          file.  In that case we don't set used_from_other_object_file.  */
     322                 :     2912635 :       && definition)
     323                 :             :     ;
     324                 :     2912633 :   else if (!flag_whole_program)
     325                 :             :     return true;
     326                 :             : 
     327                 :             :   /* Do not attempt to privatize COMDATS by default.
     328                 :             :      This would break linking with C++ libraries sharing
     329                 :             :      inline definitions.
     330                 :             : 
     331                 :             :      FIXME: We can do so for readonly vars with no address taken and
     332                 :             :      possibly also for vtables since no direct pointer comparsion is done.
     333                 :             :      It might be interesting to do so to reduce linking overhead.  */
     334                 :         234 :   if (DECL_COMDAT (decl) || DECL_WEAK (decl))
     335                 :             :     return true;
     336                 :             :   return false;
     337                 :             : }
     338                 :             : 
     339                 :             : /* Return true if reference to NODE can be replaced by a local alias.
     340                 :             :    Local aliases save dynamic linking overhead and enable more optimizations.
     341                 :             :  */
     342                 :             : 
     343                 :             : static bool
     344                 :     2834304 : can_replace_by_local_alias (symtab_node *node)
     345                 :             : {
     346                 :             :   /* If aliases aren't supported, we can't do replacement.  */
     347                 :     2834304 :   if (!TARGET_SUPPORTS_ALIASES)
     348                 :             :     return false;
     349                 :             : 
     350                 :             :   /* Weakrefs have a reason to be non-local.  Be sure we do not replace
     351                 :             :      them.  */
     352                 :     2834316 :   while (node->transparent_alias && node->definition && !node->weakref)
     353                 :          12 :     node = node->get_alias_target ();
     354                 :     2834304 :   if (node->weakref)
     355                 :             :     return false;
     356                 :             : 
     357                 :     2834302 :   return (node->get_availability () > AVAIL_INTERPOSABLE
     358                 :     2760873 :           && !decl_binds_to_current_def_p (node->decl)
     359                 :     4672808 :           && !node->can_be_discarded_p ());
     360                 :             : }
     361                 :             : 
     362                 :             : /* Return true if we can replace reference to NODE by local alias
     363                 :             :    within a virtual table.  Generally we can replace function pointers
     364                 :             :    and virtual table pointers.  */
     365                 :             : 
     366                 :             : static bool
     367                 :      250083 : can_replace_by_local_alias_in_vtable (symtab_node *node)
     368                 :             : {
     369                 :      250083 :   if (is_a <varpool_node *> (node)
     370                 :      140632 :       && !DECL_VIRTUAL_P (node->decl))
     371                 :             :     return false;
     372                 :      167850 :   return can_replace_by_local_alias (node);
     373                 :             : }
     374                 :             : 
     375                 :             : /* walk_tree callback that rewrites initializer references.   */
     376                 :             : 
     377                 :             : static tree
     378                 :          25 : update_vtable_references (tree *tp, int *walk_subtrees,
     379                 :             :                           void *data ATTRIBUTE_UNUSED)
     380                 :             : {
     381                 :          25 :   if (VAR_OR_FUNCTION_DECL_P (*tp))
     382                 :             :     {
     383                 :           5 :       if (can_replace_by_local_alias_in_vtable (symtab_node::get (*tp)))
     384                 :           4 :         *tp = symtab_node::get (*tp)->noninterposable_alias ()->decl;
     385                 :           5 :       *walk_subtrees = 0;
     386                 :             :     }
     387                 :          20 :   else if (IS_TYPE_OR_DECL_P (*tp))
     388                 :           0 :     *walk_subtrees = 0;
     389                 :          25 :   return NULL;
     390                 :             : }
     391                 :             : 
     392                 :             : /* In LTO we can remove COMDAT groups and weak symbols.
     393                 :             :    Either turn them into normal symbols or external symbol depending on
     394                 :             :    resolution info.  */
     395                 :             : 
     396                 :             : static void
     397                 :    14179589 : update_visibility_by_resolution_info (symtab_node * node)
     398                 :             : {
     399                 :    14179589 :   bool define;
     400                 :             : 
     401                 :    14179589 :   if (!node->externally_visible
     402                 :     6967526 :       || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl))
     403                 :    16825589 :       || node->resolution == LDPR_UNKNOWN)
     404                 :    14179222 :     return;
     405                 :             : 
     406                 :         734 :   define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
     407                 :             :             || node->resolution == LDPR_PREVAILING_DEF
     408                 :         367 :             || node->resolution == LDPR_UNDEF
     409                 :         367 :             || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
     410                 :             : 
     411                 :             :   /* The linker decisions ought to agree in the whole group.  */
     412                 :         367 :   if (node->same_comdat_group)
     413                 :         108 :     for (symtab_node *next = node->same_comdat_group;
     414                 :         176 :          next != node; next = next->same_comdat_group)
     415                 :             :       {
     416                 :         108 :         if (!next->externally_visible || next->transparent_alias)
     417                 :           4 :           continue;
     418                 :             : 
     419                 :         104 :         bool same_def
     420                 :         104 :           = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
     421                 :             :                        || next->resolution == LDPR_PREVAILING_DEF
     422                 :             :                        || next->resolution == LDPR_UNDEF
     423                 :         104 :                        || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
     424                 :         104 :         gcc_assert (in_lto_p || same_def);
     425                 :         104 :         if (!same_def)
     426                 :             :           return;
     427                 :             :       }
     428                 :             : 
     429                 :         367 :   if (node->same_comdat_group)
     430                 :         108 :     for (symtab_node *next = node->same_comdat_group;
     431                 :         176 :          next != node; next = next->same_comdat_group)
     432                 :             :       {
     433                 :             :         /* During incremental linking we need to keep symbol weak for future
     434                 :             :            linking.  We can still drop definition if we know non-LTO world
     435                 :             :            prevails.  */
     436                 :         108 :         if (!flag_incremental_link)
     437                 :             :           {
     438                 :           8 :             DECL_WEAK (next->decl) = false;
     439                 :           8 :             next->set_comdat_group (NULL);
     440                 :             :           }
     441                 :         108 :         if (!define)
     442                 :             :           {
     443                 :           0 :             if (next->externally_visible)
     444                 :           0 :               DECL_EXTERNAL (next->decl) = true;
     445                 :           0 :             next->set_comdat_group (NULL);
     446                 :             :           }
     447                 :             :       }
     448                 :             : 
     449                 :             :   /* During incremental linking we need to keep symbol weak for future
     450                 :             :      linking.  We can still drop definition if we know non-LTO world prevails.  */
     451                 :         367 :   if (!flag_incremental_link)
     452                 :             :     {
     453                 :         217 :       DECL_WEAK (node->decl) = false;
     454                 :         217 :       node->set_comdat_group (NULL);
     455                 :         217 :       node->dissolve_same_comdat_group_list ();
     456                 :             :     }
     457                 :         367 :   if (!define)
     458                 :             :     {
     459                 :           0 :       DECL_EXTERNAL (node->decl) = true;
     460                 :           0 :       node->set_comdat_group (NULL);
     461                 :           0 :       node->dissolve_same_comdat_group_list ();
     462                 :             :     }
     463                 :             : }
     464                 :             : 
     465                 :             : /* Try to get rid of weakref.  */
     466                 :             : 
     467                 :             : static void
     468                 :         320 : optimize_weakref (symtab_node *node)
     469                 :             : {
     470                 :         320 :   bool strip_weakref = false;
     471                 :         320 :   bool static_alias = false;
     472                 :             : 
     473                 :         320 :   gcc_assert (node->weakref);
     474                 :             : 
     475                 :             :   /* Weakrefs with no target defined cannot be optimized.  */
     476                 :         320 :   if (!node->analyzed)
     477                 :             :     return;
     478                 :          47 :   symtab_node *target = node->get_alias_target ();
     479                 :             : 
     480                 :             :   /* Weakrefs to weakrefs can be optimized only if target can be.  */
     481                 :          47 :   if (target->weakref)
     482                 :          16 :     optimize_weakref (target);
     483                 :          47 :   if (target->weakref)
     484                 :             :     return;
     485                 :             : 
     486                 :             :   /* If we have definition of weakref's target and we know it binds locally,
     487                 :             :      we can turn weakref to static alias.  */
     488                 :          31 :   if (TARGET_SUPPORTS_ALIASES
     489                 :          31 :       && target->definition && decl_binds_to_current_def_p (target->decl))
     490                 :             :     strip_weakref = static_alias = true;
     491                 :             :   /* Otherwise we can turn weakref into transparent alias.  This transformation
     492                 :             :      may break asm statements which directly refers to symbol name and expect
     493                 :             :      GNU as to translate it via .weakref directive. So do not optimize when
     494                 :             :      DECL_PRESERVED is set and .weakref is supported.  */
     495                 :           2 :   else if ((!DECL_PRESERVE_P (target->decl)
     496                 :           0 :             || IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)))
     497                 :           2 :            && !DECL_WEAK (target->decl)
     498                 :           0 :            && !DECL_EXTERNAL (target->decl)
     499                 :           2 :            && ((target->definition && !target->can_be_discarded_p ())
     500                 :           0 :                || target->resolution != LDPR_UNDEF))
     501                 :             :     strip_weakref = true;
     502                 :           2 :   if (!strip_weakref)
     503                 :           2 :     return;
     504                 :          29 :   node->weakref = false;
     505                 :          29 :   IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0;
     506                 :          29 :   TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE;
     507                 :          29 :   DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref",
     508                 :          29 :                                                    DECL_ATTRIBUTES
     509                 :             :                                                          (node->decl));
     510                 :             : 
     511                 :          29 :   if (dump_file)
     512                 :           0 :     fprintf (dump_file, "Optimizing weakref %s %s\n",
     513                 :             :              node->dump_name (),
     514                 :             :              static_alias ? "as static alias" : "as transparent alias");
     515                 :             : 
     516                 :          29 :   if (static_alias)
     517                 :             :     {
     518                 :             :       /* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC.
     519                 :             :          be sure it really clears the WEAK flag.  */
     520                 :          29 :       TREE_PUBLIC (node->decl) = true;
     521                 :          29 :       node->make_decl_local ();
     522                 :          29 :       node->forced_by_abi = false;
     523                 :          29 :       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     524                 :          29 :       node->externally_visible = false;
     525                 :          29 :       gcc_assert (!DECL_WEAK (node->decl));
     526                 :          29 :       node->transparent_alias = false;
     527                 :             :     }
     528                 :             :   else
     529                 :             :     {
     530                 :           0 :       symtab->change_decl_assembler_name
     531                 :           0 :         (node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
     532                 :           0 :       node->transparent_alias = true;
     533                 :           0 :       node->copy_visibility_from (target);
     534                 :             :     }
     535                 :          29 :   gcc_assert (node->alias);
     536                 :             : }
     537                 :             : 
     538                 :             : /* NODE is an externally visible definition, which we've discovered is
     539                 :             :    not needed externally.  Make it local to this compilation.  */
     540                 :             : 
     541                 :             : static void
     542                 :     3559018 : localize_node (bool whole_program, symtab_node *node)
     543                 :             : {
     544                 :     3559018 :   gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
     545                 :             : 
     546                 :             :   /* It is possible that one comdat group contains both hidden and non-hidden
     547                 :             :      symbols.  In this case we can privatize all hidden symbol but we need
     548                 :             :      to keep non-hidden exported.  */
     549                 :     3559018 :   if (node->same_comdat_group
     550                 :        9428 :       && (node->resolution == LDPR_PREVAILING_DEF_IRONLY
     551                 :        7938 :           || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
     552                 :             :     {
     553                 :             :       symtab_node *next;
     554                 :        1785 :       for (next = node->same_comdat_group;
     555                 :        3431 :            next != node; next = next->same_comdat_group)
     556                 :        1863 :         if (next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
     557                 :        1785 :             || next->resolution == LDPR_PREVAILING_DEF)
     558                 :             :           break;
     559                 :        1646 :       if (node != next)
     560                 :             :         {
     561                 :          78 :           if (!node->transparent_alias)
     562                 :             :             {
     563                 :          78 :               node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     564                 :          78 :               node->make_decl_local ();
     565                 :          78 :               if (!flag_incremental_link)
     566                 :          78 :                 node->unique_name |= true;
     567                 :          78 :               return;
     568                 :             :             }
     569                 :             :         }
     570                 :             :     }
     571                 :             :   /* For similar reason do not privatize whole comdat when seeing comdat
     572                 :             :      local.  Wait for non-comdat symbol to be privatized first.  */
     573                 :     3558940 :   if (node->comdat_local_p ())
     574                 :             :     return;
     575                 :             : 
     576                 :     3551340 :   if (node->same_comdat_group && TREE_PUBLIC (node->decl))
     577                 :             :     {
     578                 :        2097 :       for (symtab_node *next = node->same_comdat_group;
     579                 :        3847 :            next != node; next = next->same_comdat_group)
     580                 :             :         {
     581                 :        2097 :           next->set_comdat_group (NULL);
     582                 :        2097 :           if (!next->alias)
     583                 :        1890 :             next->set_section (NULL);
     584                 :        2097 :           if (!next->transparent_alias)
     585                 :        2097 :             next->make_decl_local ();
     586                 :        2097 :           next->unique_name
     587                 :        2097 :             |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
     588                 :         365 :                  || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
     589                 :        1732 :                 && TREE_PUBLIC (next->decl)
     590                 :        2097 :                 && !flag_incremental_link);
     591                 :             :         }
     592                 :             : 
     593                 :             :       /* Now everything's localized, the grouping has no meaning, and
     594                 :             :          will cause crashes if we keep it around.  */
     595                 :        1750 :       node->dissolve_same_comdat_group_list ();
     596                 :             :     }
     597                 :             : 
     598                 :     3551340 :   node->unique_name
     599                 :     7102680 :     |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
     600                 :     1805868 :          || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
     601                 :     1745874 :         && TREE_PUBLIC (node->decl)
     602                 :     3599344 :         && !flag_incremental_link);
     603                 :             : 
     604                 :     3551340 :   if (TREE_PUBLIC (node->decl))
     605                 :       48880 :     node->set_comdat_group (NULL);
     606                 :     3551340 :   if (DECL_COMDAT (node->decl) && !node->alias)
     607                 :        5047 :     node->set_section (NULL);
     608                 :     3551340 :   if (!node->transparent_alias)
     609                 :             :     {
     610                 :     3551340 :       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     611                 :     3551340 :       node->make_decl_local ();
     612                 :             :     }
     613                 :             : }
     614                 :             : 
     615                 :             : /* Decide on visibility of all symbols.  */
     616                 :             : 
     617                 :             : static unsigned int
     618                 :      454244 : function_and_variable_visibility (bool whole_program)
     619                 :             : {
     620                 :      454244 :   struct cgraph_node *node;
     621                 :      454244 :   varpool_node *vnode;
     622                 :             : 
     623                 :             :   /* All aliases should be processed at this point.  */
     624                 :      454244 :   gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
     625                 :             : 
     626                 :      454244 :   if (TARGET_SUPPORTS_ALIASES)
     627                 :             :     {
     628                 :     5410428 :       FOR_EACH_DEFINED_FUNCTION (node)
     629                 :             :         {
     630                 :     4956184 :           if (node->get_availability () != AVAIL_INTERPOSABLE
     631                 :      109890 :               || DECL_EXTERNAL (node->decl)
     632                 :      109890 :               || node->has_aliases_p ()
     633                 :     5061766 :               || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
     634                 :     4887635 :             continue;
     635                 :             : 
     636                 :       68549 :           cgraph_node *alias = 0;
     637                 :       68549 :           cgraph_edge *next_edge;
     638                 :      312193 :           for (cgraph_edge *e = node->callees; e; e = next_edge)
     639                 :             :             {
     640                 :      243644 :               next_edge = e->next_callee;
     641                 :             :               /* Recursive function calls usually can't be interposed.  */
     642                 :             : 
     643                 :      243644 :               if (!e->recursive_p ())
     644                 :      242697 :                 continue;
     645                 :             : 
     646                 :         947 :               if (!alias)
     647                 :             :                 {
     648                 :         271 :                   alias
     649                 :         271 :                     = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
     650                 :         271 :                   gcc_assert (alias && alias != node);
     651                 :             :                 }
     652                 :             : 
     653                 :         947 :               e->redirect_callee (alias);
     654                 :         947 :               if (gimple_has_body_p (e->caller->decl))
     655                 :             :                 {
     656                 :         947 :                   push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
     657                 :         947 :                   cgraph_edge::redirect_call_stmt_to_callee (e);
     658                 :         947 :                   pop_cfun ();
     659                 :             :                 }
     660                 :             :             }
     661                 :             :         }
     662                 :             :     }
     663                 :             : 
     664                 :    17652862 :   FOR_EACH_FUNCTION (node)
     665                 :             :     {
     666                 :     8372187 :       int flags = flags_from_decl_or_type (node->decl);
     667                 :             : 
     668                 :             :       /* Optimize away PURE and CONST constructors and destructors.  */
     669                 :     8372187 :       if (node->analyzed
     670                 :     4956455 :           && (DECL_STATIC_CONSTRUCTOR (node->decl)
     671                 :     4917703 :               || DECL_STATIC_DESTRUCTOR (node->decl))
     672                 :       39326 :           && (flags & (ECF_CONST | ECF_PURE))
     673                 :          23 :           && !(flags & ECF_LOOPING_CONST_OR_PURE)
     674                 :     8372187 :           && opt_for_fn (node->decl, optimize))
     675                 :             :         {
     676                 :           0 :           DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
     677                 :           0 :           DECL_STATIC_DESTRUCTOR (node->decl) = 0;
     678                 :             :         }
     679                 :             : 
     680                 :             :       /* Frontends and alias code marks nodes as needed before parsing
     681                 :             :          is finished.  We may end up marking as node external nodes
     682                 :             :          where this flag is meaningless strip it.  */
     683                 :     8372187 :       if (DECL_EXTERNAL (node->decl) || !node->definition)
     684                 :             :         {
     685                 :     3653025 :           node->force_output = 0;
     686                 :     3653025 :           node->forced_by_abi = 0;
     687                 :             :         }
     688                 :             : 
     689                 :             :       /* C++ FE on lack of COMDAT support create local COMDAT functions
     690                 :             :          (that ought to be shared but cannot due to object format
     691                 :             :          limitations).  It is necessary to keep the flag to make rest of C++ FE
     692                 :             :          happy.  Clear the flag here to avoid confusion in middle-end.  */
     693                 :     8372187 :       if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
     694                 :          29 :         DECL_COMDAT (node->decl) = 0;
     695                 :             : 
     696                 :             :       /* For external decls stop tracking same_comdat_group. It doesn't matter
     697                 :             :          what comdat group they are in when they won't be emitted in this TU.
     698                 :             : 
     699                 :             :          An exception is LTO where we may end up with both external
     700                 :             :          and non-external declarations in the same comdat group in
     701                 :             :          the case declarations was not merged.  */
     702                 :     8372187 :       if (node->same_comdat_group && DECL_EXTERNAL (node->decl) && !in_lto_p)
     703                 :             :         {
     704                 :          24 :           if (flag_checking)
     705                 :             :             {
     706                 :          30 :               for (symtab_node *n = node->same_comdat_group;
     707                 :          54 :                    n != node;
     708                 :          30 :                    n = n->same_comdat_group)
     709                 :             :                 /* If at least one of same comdat group functions is external,
     710                 :             :                    all of them have to be, otherwise it is a front-end bug.  */
     711                 :          30 :                 gcc_assert (DECL_EXTERNAL (n->decl));
     712                 :             :             }
     713                 :          24 :           node->dissolve_same_comdat_group_list ();
     714                 :             :         }
     715                 :     8372187 :       gcc_assert ((!DECL_WEAK (node->decl)
     716                 :             :                   && !DECL_COMDAT (node->decl))
     717                 :             :                   || TREE_PUBLIC (node->decl)
     718                 :             :                   || node->weakref
     719                 :             :                   || DECL_EXTERNAL (node->decl));
     720                 :     8372187 :       if (cgraph_externally_visible_p (node, whole_program))
     721                 :             :         {
     722                 :     4032070 :           gcc_assert (!node->inlined_to);
     723                 :     4032070 :           node->externally_visible = true;
     724                 :             :         }
     725                 :             :       else
     726                 :             :         {
     727                 :     4340117 :           node->externally_visible = false;
     728                 :     4340117 :           node->forced_by_abi = false;
     729                 :             :         }
     730                 :     8372187 :       if (!node->externally_visible
     731                 :     8372187 :           && node->definition && !node->weakref
     732                 :     8372187 :           && !DECL_EXTERNAL (node->decl))
     733                 :      687080 :         localize_node (whole_program, node);
     734                 :             : 
     735                 :     8372187 :       if (node->thunk
     736                 :        5935 :           && TREE_PUBLIC (node->decl))
     737                 :             :         {
     738                 :        5792 :           struct cgraph_node *decl_node = node;
     739                 :             : 
     740                 :        5792 :           decl_node = decl_node->callees->callee->function_symbol ();
     741                 :             : 
     742                 :             :           /* Thunks have the same visibility as function they are attached to.
     743                 :             :              Make sure the C++ front end set this up properly.  */
     744                 :        5792 :           if (DECL_ONE_ONLY (decl_node->decl))
     745                 :             :             {
     746                 :        4641 :               gcc_checking_assert (DECL_COMDAT (node->decl)
     747                 :             :                                    == DECL_COMDAT (decl_node->decl));
     748                 :        4641 :               gcc_checking_assert (node->in_same_comdat_group_p (decl_node));
     749                 :        4641 :               gcc_checking_assert (node->same_comdat_group);
     750                 :             :             }
     751                 :        5792 :           node->forced_by_abi = decl_node->forced_by_abi;
     752                 :        5792 :           if (DECL_EXTERNAL (decl_node->decl))
     753                 :           2 :             DECL_EXTERNAL (node->decl) = 1;
     754                 :             :         }
     755                 :             : 
     756                 :     8372187 :       update_visibility_by_resolution_info (node);
     757                 :     8372187 :       if (node->weakref)
     758                 :         230 :         optimize_weakref (node);
     759                 :             :     }
     760                 :     5410699 :   FOR_EACH_DEFINED_FUNCTION (node)
     761                 :             :     {
     762                 :     4956455 :       if (!node->local)
     763                 :     4814711 :         node->local |= node->local_p ();
     764                 :             : 
     765                 :             :       /* If we know that function cannot be overwritten by a
     766                 :             :          different semantics and moreover its section cannot be
     767                 :             :          discarded, replace all direct calls by calls to an
     768                 :             :          noninterposable alias.  This make dynamic linking cheaper and
     769                 :             :          enable more optimization.
     770                 :             : 
     771                 :             :          TODO: We can also update virtual tables.  */
     772                 :     4956455 :       if (node->callers
     773                 :     4956455 :           && can_replace_by_local_alias (node))
     774                 :             :         {
     775                 :          96 :           cgraph_node *alias = dyn_cast<cgraph_node *>
     776                 :          96 :             (node->noninterposable_alias ());
     777                 :             : 
     778                 :          96 :           if (alias && alias != node)
     779                 :             :             {
     780                 :         223 :               while (node->callers)
     781                 :             :                 {
     782                 :         128 :                   struct cgraph_edge *e = node->callers;
     783                 :             : 
     784                 :         128 :                   e->redirect_callee (alias);
     785                 :         128 :                   if (gimple_has_body_p (e->caller->decl))
     786                 :             :                     {
     787                 :         125 :                       push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
     788                 :         125 :                       cgraph_edge::redirect_call_stmt_to_callee (e);
     789                 :         125 :                       pop_cfun ();
     790                 :             :                     }
     791                 :             :                 }
     792                 :             :             }
     793                 :             :         }
     794                 :             :     }
     795                 :    13694694 :   FOR_EACH_VARIABLE (vnode)
     796                 :             :     {
     797                 :             :       /* weak flag makes no sense on local variables.  */
     798                 :     6393103 :       gcc_assert (!DECL_WEAK (vnode->decl)
     799                 :             :                   || vnode->weakref
     800                 :             :                   || TREE_PUBLIC (vnode->decl)
     801                 :             :                   || DECL_EXTERNAL (vnode->decl));
     802                 :             :       /* In several cases declarations cannot be common:
     803                 :             : 
     804                 :             :          - when declaration has initializer
     805                 :             :          - when it is in weak
     806                 :             :          - when it has specific section
     807                 :             :          - when it resides in non-generic address space.
     808                 :             :          - if declaration is local, it will get into .local common section
     809                 :             :            so common flag is not needed.  Frontends still produce these in
     810                 :             :            certain cases, such as for:
     811                 :             : 
     812                 :             :              static int a __attribute__ ((common))
     813                 :             : 
     814                 :             :          Canonicalize things here and clear the redundant flag.  */
     815                 :     6393103 :       if (DECL_COMMON (vnode->decl)
     816                 :     6393103 :           && (!(TREE_PUBLIC (vnode->decl)
     817                 :          47 :               || DECL_EXTERNAL (vnode->decl))
     818                 :       26360 :               || (DECL_INITIAL (vnode->decl)
     819                 :       23465 :                   && DECL_INITIAL (vnode->decl) != error_mark_node)
     820                 :        2895 :               || DECL_WEAK (vnode->decl)
     821                 :        2892 :               || DECL_SECTION_NAME (vnode->decl) != NULL
     822                 :        2887 :               || ! (ADDR_SPACE_GENERIC_P
     823                 :             :                     (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
     824                 :       23520 :         DECL_COMMON (vnode->decl) = 0;
     825                 :     6393103 :       if (vnode->weakref)
     826                 :          74 :         optimize_weakref (vnode);
     827                 :             :     }
     828                 :     6261646 :   FOR_EACH_DEFINED_VARIABLE (vnode)
     829                 :             :     {
     830                 :     5807402 :       if (!vnode->definition)
     831                 :           0 :         continue;
     832                 :     5807402 :       if (vnode->externally_visible_p ())
     833                 :     2935456 :         vnode->externally_visible = true;
     834                 :             :       else
     835                 :             :         {
     836                 :     2871946 :           vnode->externally_visible = false;
     837                 :     2871946 :           vnode->forced_by_abi = false;
     838                 :             :         }
     839                 :     5807402 :       if (lookup_attribute ("no_reorder",
     840                 :     5807402 :                             DECL_ATTRIBUTES (vnode->decl)))
     841                 :           4 :         vnode->no_reorder = 1;
     842                 :             : 
     843                 :     5807402 :       if (!vnode->externally_visible
     844                 :     5807402 :           && !vnode->transparent_alias
     845                 :     5807402 :           && !DECL_EXTERNAL (vnode->decl))
     846                 :     2871938 :         localize_node (whole_program, vnode);
     847                 :             : 
     848                 :     5807402 :       update_visibility_by_resolution_info (vnode);
     849                 :             : 
     850                 :             :       /* Update virtual tables to point to local aliases where possible.  */
     851                 :     5807402 :       if (DECL_VIRTUAL_P (vnode->decl)
     852                 :     5807402 :           && !DECL_EXTERNAL (vnode->decl))
     853                 :             :         {
     854                 :             :           int i;
     855                 :             :           struct ipa_ref *ref;
     856                 :      292402 :           bool found = false;
     857                 :             : 
     858                 :             :           /* See if there is something to update.  */
     859                 :      292402 :           for (i = 0; vnode->iterate_reference (i, ref); i++)
     860                 :      250078 :             if (ref->use == IPA_REF_ADDR
     861                 :      250078 :                 && can_replace_by_local_alias_in_vtable (ref->referred))
     862                 :             :               {
     863                 :             :                 found = true;
     864                 :             :                 break;
     865                 :             :               }
     866                 :       42327 :           if (found)
     867                 :             :             {
     868                 :           3 :               hash_set<tree> visited_nodes;
     869                 :             : 
     870                 :           3 :               vnode->get_constructor ();
     871                 :           3 :               walk_tree (&DECL_INITIAL (vnode->decl),
     872                 :             :                          update_vtable_references, NULL, &visited_nodes);
     873                 :           3 :               vnode->remove_all_references ();
     874                 :           3 :               record_references_in_initializer (vnode->decl, false);
     875                 :           3 :             }
     876                 :             :         }
     877                 :             :     }
     878                 :             : 
     879                 :      454244 :   if (symtab->state >= IPA_SSA)
     880                 :             :     {
     881                 :     3593533 :       FOR_EACH_VARIABLE (vnode)
     882                 :             :         {
     883                 :     3139827 :           tree decl = vnode->decl;
     884                 :             : 
     885                 :             :           /* Upgrade TLS access model based on optimized visibility status,
     886                 :             :              unless it was specified explicitly or no references remain.  */
     887                 :     3139827 :           if (DECL_THREAD_LOCAL_P (decl)
     888                 :        4214 :               && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl))
     889                 :     6283379 :               && vnode->ref_list.referring.length ())
     890                 :             :             {
     891                 :        3725 :               enum tls_model new_model = decl_default_tls_model (decl);
     892                 :        3725 :               STATIC_ASSERT (TLS_MODEL_GLOBAL_DYNAMIC < TLS_MODEL_LOCAL_DYNAMIC);
     893                 :        3725 :               STATIC_ASSERT (TLS_MODEL_INITIAL_EXEC < TLS_MODEL_LOCAL_EXEC);
     894                 :             :               /* We'd prefer to assert that recomputed model is not weaker than
     895                 :             :                  what the front-end assigned, but cannot: see PR 107353.  */
     896                 :        3725 :               if (new_model >= decl_tls_model (decl))
     897                 :        3725 :                 set_decl_tls_model (decl, new_model);
     898                 :             :             }
     899                 :             :         }
     900                 :             :     }
     901                 :             : 
     902                 :      454244 :   if (dump_file)
     903                 :             :     {
     904                 :         117 :       fprintf (dump_file, "\nMarking local functions:");
     905                 :         277 :       FOR_EACH_DEFINED_FUNCTION (node)
     906                 :         160 :         if (node->local)
     907                 :           0 :           fprintf (dump_file, " %s", node->dump_name ());
     908                 :         117 :       fprintf (dump_file, "\n\n");
     909                 :         117 :       fprintf (dump_file, "\nMarking externally visible functions:");
     910                 :         277 :       FOR_EACH_DEFINED_FUNCTION (node)
     911                 :         160 :         if (node->externally_visible)
     912                 :         157 :           fprintf (dump_file, " %s", node->dump_name ());
     913                 :         117 :       fprintf (dump_file, "\n\n");
     914                 :         117 :       fprintf (dump_file, "\nMarking externally visible variables:");
     915                 :         189 :       FOR_EACH_DEFINED_VARIABLE (vnode)
     916                 :          72 :         if (vnode->externally_visible)
     917                 :          41 :           fprintf (dump_file, " %s", vnode->dump_name ());
     918                 :         117 :       fprintf (dump_file, "\n\n");
     919                 :             :     }
     920                 :      454244 :   symtab->function_flags_ready = true;
     921                 :      454244 :   return 0;
     922                 :             : }
     923                 :             : 
     924                 :             : /* Local function pass handling visibilities.  This happens before LTO streaming
     925                 :             :    so in particular -fwhole-program should be ignored at this level.  */
     926                 :             : 
     927                 :             : namespace {
     928                 :             : 
     929                 :             : const pass_data pass_data_ipa_function_and_variable_visibility =
     930                 :             : {
     931                 :             :   SIMPLE_IPA_PASS, /* type */
     932                 :             :   "visibility", /* name */
     933                 :             :   OPTGROUP_NONE, /* optinfo_flags */
     934                 :             :   TV_CGRAPHOPT, /* tv_id */
     935                 :             :   0, /* properties_required */
     936                 :             :   0, /* properties_provided */
     937                 :             :   0, /* properties_destroyed */
     938                 :             :   0, /* todo_flags_start */
     939                 :             :   ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
     940                 :             : };
     941                 :             : 
     942                 :             : /* Bring functions local at LTO time with -fwhole-program.  */
     943                 :             : 
     944                 :             : static unsigned int
     945                 :      226853 : whole_program_function_and_variable_visibility (void)
     946                 :             : {
     947                 :      226853 :   function_and_variable_visibility (flag_whole_program);
     948                 :      226853 :   if (optimize || in_lto_p)
     949                 :      148877 :     ipa_discover_variable_flags ();
     950                 :      226853 :   return 0;
     951                 :             : }
     952                 :             : 
     953                 :             : } // anon namespace
     954                 :             : 
     955                 :             : namespace {
     956                 :             : 
     957                 :             : const pass_data pass_data_ipa_whole_program_visibility =
     958                 :             : {
     959                 :             :   IPA_PASS, /* type */
     960                 :             :   "whole-program", /* name */
     961                 :             :   OPTGROUP_NONE, /* optinfo_flags */
     962                 :             :   TV_CGRAPHOPT, /* tv_id */
     963                 :             :   0, /* properties_required */
     964                 :             :   0, /* properties_provided */
     965                 :             :   0, /* properties_destroyed */
     966                 :             :   0, /* todo_flags_start */
     967                 :             :   ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
     968                 :             : };
     969                 :             : 
     970                 :             : class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
     971                 :             : {
     972                 :             : public:
     973                 :      283157 :   pass_ipa_whole_program_visibility (gcc::context *ctxt)
     974                 :             :     : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
     975                 :             :                       NULL, /* generate_summary */
     976                 :             :                       NULL, /* write_summary */
     977                 :             :                       NULL, /* read_summary */
     978                 :             :                       NULL, /* write_optimization_summary */
     979                 :             :                       NULL, /* read_optimization_summary */
     980                 :             :                       NULL, /* stmt_fixup */
     981                 :             :                       0, /* function_transform_todo_flags_start */
     982                 :             :                       NULL, /* function_transform */
     983                 :      283157 :                       NULL) /* variable_transform */
     984                 :      283157 :   {}
     985                 :             : 
     986                 :             :   /* opt_pass methods: */
     987                 :             : 
     988                 :      558814 :   bool gate (function *) final override
     989                 :             :     {
     990                 :             :       /* Do not re-run on ltrans stage.  */
     991                 :      558814 :       return !flag_ltrans;
     992                 :             :     }
     993                 :      226853 :   unsigned int execute (function *) final override
     994                 :             :     {
     995                 :      226853 :       return whole_program_function_and_variable_visibility ();
     996                 :             :     }
     997                 :             : 
     998                 :             : }; // class pass_ipa_whole_program_visibility
     999                 :             : 
    1000                 :             : } // anon namespace
    1001                 :             : 
    1002                 :             : ipa_opt_pass_d *
    1003                 :      283157 : make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
    1004                 :             : {
    1005                 :      283157 :   return new pass_ipa_whole_program_visibility (ctxt);
    1006                 :             : }
    1007                 :             : 
    1008                 :             : class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
    1009                 :             : {
    1010                 :             : public:
    1011                 :      283157 :   pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
    1012                 :             :     : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
    1013                 :      566314 :                            ctxt)
    1014                 :             :   {}
    1015                 :             : 
    1016                 :             :   /* opt_pass methods: */
    1017                 :      227391 :   unsigned int execute (function *) final override
    1018                 :             :     {
    1019                 :      454687 :       return function_and_variable_visibility (flag_whole_program && !flag_lto);
    1020                 :             :     }
    1021                 :             : 
    1022                 :             : }; // class pass_ipa_function_and_variable_visibility
    1023                 :             : 
    1024                 :             : simple_ipa_opt_pass *
    1025                 :      283157 : make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
    1026                 :             : {
    1027                 :      283157 :   return new pass_ipa_function_and_variable_visibility (ctxt);
    1028                 :             : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.