On Tue, 1 Sep 2026, Filip Kastl wrote:

> Hi.
> 
> (by aggregates, I will mean C structs and arrays and similar constructs that
> aggregate data from other languages that GCC compiles)
> 
> The first question:
> -------------------
> 
> I'm trying to understand the IPA PTA code related to shadow vars.  In the code
> snippet from tree-ssa-structalias.cc:ipa_pta_execute() below, why do we need
> the second 'for' loop over vi_next()?  Are the varinfos that represent fields
> of a global aggregate variable not is_global_var = true?  If they were
> is_global_var = true, then the for loop would be redundant, right? (the outer
> for loop would suffice to visit all the varinfos we need to visit)
>
> 1876   /* Now post-process solutions to handle locals from different
> 1877      runtime instantiations coming in through recursive invocations.  */
> 1878   unsigned shadow_var_cnt = 0;
> 1879   for (unsigned i = 1; i < varmap.length (); ++i)
> 1880     {
> 1881       varinfo_t fi = get_varinfo (i);
> 1882       if (fi->is_fn_info
> 1883           && fi->decl)
> 1884         /* Automatic variables pointed to by their containing functions
> 1885            parameters need this treatment.  */
> 1886         for (varinfo_t ai = first_vi_for_offset (fi, fi_parm_base);
> 1887              ai; ai = vi_next (ai))
> 1888           {
> 1889             varinfo_t vi = get_varinfo (var_rep[ai->id]);
> 1890             bitmap_iterator bi;
> 1891             unsigned j;
> 1892             EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi)
> 1893               {
> 1894                 varinfo_t pt = get_varinfo (j);
> 1895                 if (pt->shadow_var_uid == 0
> 1896                     && pt->decl
> 1897                     && auto_var_in_fn_p (pt->decl, fi->decl))
> 1898                   {
> 1899                     pt->shadow_var_uid = allocate_decl_uid ();
> 1900                     shadow_var_cnt++;
> 1901                   }
> 1902               }
> 1903           }
> 1904       /* As well as global variables which are another way of passing
> 1905          arguments to recursive invocations.  */
> 1906       else if (fi->is_global_var)
> 1907         {
> 1908           for (varinfo_t ai = fi; ai; ai = vi_next (ai))

Yes, I think this loop is redundant - the outer iteration over varmap
should already walk over all subfields and subfields should have
->is_global_var set.

> 1909             {
> 1910               varinfo_t vi = get_varinfo (var_rep[ai->id]);
> 1911               bitmap_iterator bi;
> 1912               unsigned j;
> 1913               EXECUTE_IF_SET_IN_BITMAP (vi->solution, 0, j, bi)
> 1914                 {
> 1915                   varinfo_t pt = get_varinfo (j);
> 1916                   if (pt->shadow_var_uid == 0
> 1917                       && pt->decl
> 1918                       && auto_var_p (pt->decl))
> 1919                     {
> 1920                       pt->shadow_var_uid = allocate_decl_uid ();
> 1921                       shadow_var_cnt++;
> 1922                     }
> 1923                 }
> 1924             }
> 1925         }
> 1926     }
> 
> The second question:
> --------------------
> 
> I've tried to find the answer to my first question by inspecting how GCC
> represents global aggregate variables in a debugger / look at IPA PTA dumps.
> But this confused me even more because GCC seems to represent the whole
> aggregate with a single varinfo. Like here for example:
> 
> struct A {
>     int *p;
>     int *q;
> } a;
> 
> int x;
> int y;
> 
> void bar()
> {
>     a.p = &x;
>     a.q = &y;
> }
> 
> int foo()
> {
>     return (int) a.p + (int) a.q;
> }
> 
> ->
> 
> from ipa pta dump:
> a = &x
> a = &y
> 
> I would instead expect
> a.p = &x
> a.q = &y
> 
> Does GCC's PTA ever represent fields of global aggregate variables as separate
> varinfos?  If it does, is there a simple testcase that shows it?

  /* Collect field information.  */
  if (use_field_sensitive
      && var_can_have_subvars (decl)
      /* ???  Force us to not use subfields for globals in IPA mode.
         Else we'd have to parse arbitrary initializers.  */
      && !(in_ipa_mode
           && is_global_var (decl)))

so no, due to limits in how we parse global CTORs (-> meaning we
could check here, if there _is_ a CTOR and/or if we can parse it),
we are refraining from this due to correctness issues.  Consider

struct S s = { { .ptr = &a }, [7] = &b };

we have no code to walk CTOR elements and figure the PTA subvariable(s)
an initialization overlaps with.  Instead we do the very simple
thing,

  for-each-CTOR-eleemnt
    generate VAR = element constaint

See

      /* In IPA mode parse the initializer and generate proper constraints
         for it.  */ 
      else
        {
          varpool_node *vnode = varpool_node::get (decl);
      
...

Richard.

> Thanks,
> Filip Kastl
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to