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