https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120146

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
          Component|tree-optimization           |ipa
                 CC|                            |hubicka at gcc dot gnu.org
     Ever confirmed|0                           |1
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org
   Last reconfirmed|                            |2025-05-07

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
I'd guess openacc creates a global but does not create a varpool node for it
and thus

          varpool_node *vnode = varpool_node::get (decl);

          /* For escaped variables initialize them from nonlocal.  */
          if (!vnode->all_refs_explicit_p ())
            make_copy_constraint (vi, nonlocal_id);

gets a NULL vnode.

Hmm, the decl is

$1 = <var_decl 0x7ffff6fe8390 _ZTV14basic_ifstreamIcE>
 <var_decl 0x7ffff6fe8390 _ZTV14basic_ifstreamIcE
...
    readonly addressable used public static tree_1 tree_2 ignored external read
virtual decl_5 decl_8 BLK t.c:5:28 size <integer_cst 0x7ffff6e20708 192>
unit-size <integer_cst 0x7ffff6e206d8 24>

which is referenced from the CONSTRUCTOR

{&MEM <int (*) ()> [(void *)&_ZTV14basic_ifstreamIcE + 24B], &MEM <int (*) ()>
[(void *)&_ZTC14basic_ifstreamIcE0_13basic_istream + 24B]}

of

$5 = <varpool_node * 0x7ffff6e26880 "_ZTT14basic_ifstreamIcE"/16>

and -fopenacc simply enables early IPA PTA it seems:

  PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc)
      NEXT_PASS (pass_ipa_pta);
      /* Pass group that runs when the function is an offloaded function
         containing oacc kernels loops.  */
      NEXT_PASS (pass_ipa_oacc_kernels);
...

Likely caused by my fix for PR119973.  I'm not sure why the variables
referenced in the global var initializer are not finalized?  I see

_ZTT14basic_ifstreamIcE/17 (constexpr const void*
basic_ifstream<char>::_ZTT14basic_ifstreamIcE [2])
  Type: variable definition analyzed
  Visibility: semantic_interposition external public virtual artificial
  Aux: @0x4f8c200
  References: _ZTV14basic_ifstreamIcE/8 (addr)
_ZTC14basic_ifstreamIcE0_13basic_istream/20 (addr) 

But at the time IPA PTA runs the symbol is elided, but the reference through
the CTOR is still there?  That is, DECL_INITIAL isn't pruned?  At the
IPA PTA point the variable refering to the elided node is

_ZTT14basic_ifstreamIcE/17 (constexpr const void*
basic_ifstream<char>::_ZTT14basic_ifstreamIcE [2])
  Type: variable
  Body removed by symtab_remove_unreachable_nodes
  Visibility: externally_visible semantic_interposition external public virtual
artificial
  References: 
  Referring: _Z18CompareFiles_path2v/7 (read) 
  Availability: not_available
  Varpool flags: initialized read-only const-value-known

so it's const-value-known, but it no longer has references (from said
initializer) and it's not_available, whatever that means.

IPA PTA in it's walk over globals still does the following, not sure
if it should skip some variables.  The one in question has !var->analyzed
for example, for whatever reason.

  /* Create constraints for global variables and their initializers.  */
  FOR_EACH_VARIABLE (var)
    {
      if (var->alias && var->analyzed)
        continue; 

      varinfo_t vi = get_vi_for_tree (var->decl);

      /* For the purpose of IPA PTA unit-local globals are not
         escape points.  */
      bool nonlocal_p = (DECL_EXTERNAL (var->decl)
                         || TREE_PUBLIC (var->decl)
                         || var->used_from_other_partition
                         || var->force_output);
      var->call_for_symbol_and_aliases (refered_from_nonlocal_var,
                                        &nonlocal_p, true);
      if (nonlocal_p)
        vi->is_ipa_escape_point = true;
    }

Not processing globals with !var->analyzed does not help since we still
refer to those from the IL (CompareFiles_path2):

# VUSE <.MEM_2>
_4 = MEM[(const void * *)&_ZTT14basic_ifstreamIcE + 8B];

so why was the varpool node "elided"?  Or why is it not analyzed/available?

I'm confused.

I can paper over the ICE by simply "dealing" with a NULL varpool node
but I think this is just playing whack-a-mole without understanding
what IPA does here :/

"Fix:"

diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
index 3ad0c69930c..1a6522593ba 100644
--- a/gcc/tree-ssa-structalias.cc
+++ b/gcc/tree-ssa-structalias.cc
@@ -6562,7 +6562,7 @@ create_variable_info_for (tree decl, const char *name,
bool add_id)
          varpool_node *vnode = varpool_node::get (decl);

          /* For escaped variables initialize them from nonlocal.  */
-         if (!vnode->all_refs_explicit_p ())
+         if (!vnode || !vnode->all_refs_explicit_p ())
            make_copy_constraint (vi, nonlocal_id);

          /* While we can in theory walk references for the varpool
@@ -6581,7 +6581,7 @@ create_variable_info_for (tree decl, const char *name,
bool add_id)
                process_constraint (new_constraint (lhs, *rhsp));
              /* If this is a variable that escapes from the unit
                 the initializer escapes as well.  */
-             if (!vnode->all_refs_explicit_p ())
+             if (!vnode || !vnode->all_refs_explicit_p ())
                {
                  lhs.var = escaped_id;
                  lhs.offset = 0;

Reply via email to