tree-ssa-structalias.cc: Why do we iterate over fields of a global varinfo

Filip Kastl fkastl@suse.cz
Tue Sep 15 14:11:31 GMT 2026


I've got no more questions at the moment, but I verified our conclusions with
some easy experiments (see inline).

On Tue 2026-09-01 11:28:37, Richard Biener wrote:
> 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.

I've just checked and you're right.  I modified GCC like this...

diff --git a/gcc/gimple-ssa-pta-constraints.cc b/gcc/gimple-ssa-pta-constraints.cc
index 2132f18ab85..7904ad7e719 100644
--- a/gcc/gimple-ssa-pta-constraints.cc
+++ b/gcc/gimple-ssa-pta-constraints.cc
@@ -3342,7 +3342,7 @@ create_variable_info_for_1 (tree decl, const char *name, bool add_id,
       && 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
+      && !(false
           && is_global_var (decl)))
     {
       fieldoff_s *fo = NULL;
diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc
index b7a3669be3e..e005b186f54 100644
--- a/gcc/tree-ssa-structalias.cc
+++ b/gcc/tree-ssa-structalias.cc
@@ -2295,6 +2296,7 @@ ipa_pta_execute (void)
              timevar_push (TV_IPA_PTA_GLOBAL_POST);
              for (varinfo_t ai = fi; ai; ai = vi_next (ai))
                {
+                 debug_varinfo (ai);
                  varinfo_t vi = get_varinfo (var_rep[ai->id]);
                  bitmap_iterator bi;
                  unsigned j;

...and I compiled this...

struct {
    int *x;
    int *y;
} a;

int b1;
int b2;

int foo(int *p)
{
    if (b1) a.x = p;
    if (b2) a.y = p;
    return (int) a.x + (int) a.y;
}


...like this...

$HOME/gcc/thesis-build/gcc/xgcc -B$HOME/gcc/thesis-build/gcc/ foo.c -O2 -fipa-pta -fdump-ipa-pta2

...and I see this on stderr:

18: a.0+64
 may-have-pointers global ipa-escape-point next:19 size:64 fullsize:128
19: a.64+64
 may-have-pointers global head:18 offset:64 size:64 fullsize:128
19: a.64+64
 may-have-pointers global head:18 offset:64 size:64 fullsize:128

So indeed all the varinfos representing fields of a have ->is_global = true.
Furthermore, if I remove the outer loop, we visit a.y (a.64+64) only once.

18: a.0+64
 may-have-pointers global ipa-escape-point next:19 size:64 fullsize:128
19: a.64+64
 may-have-pointers global head:18 offset:64 size:64 fullsize:128

So the outer loop is indeed redundant.  Btw, it even seems to me that it is
doubly redundant -- because of the mentioned check:

   /* 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)))

I'll submit a patch removing the outer loop.

Thanks,
Filip


More information about the Gcc mailing list