On Thu, 20 Oct 2016, Jan Hubicka wrote:

> > 
> > The following tries to address the inconsistency with folding
> > two addresses based on two decls vs. one pointer vs a decl address
> > caused by the latter not honoring interposition.
> > 
> > Honza, is
> > 
> > +      /* If obj1 is interposable give up.  */
> > +      if (VAR_P (obj1)
> > +         && (TREE_STATIC (obj1) || DECL_EXTERNAL (obj1)))
> > +       {
> > +         varpool_node *node = varpool_node::get (obj1);
> > +         if (! node
> > +             || ! node->analyzed
> > +             || ! decl_binds_to_current_def_p (obj1))
> > +           return false;
> > +       }
> > 
> > conservatively correct?  I tried to learn from
> 
> I would drop node->analyzed. If decl_binds_to_current_def_p returns
> false positives, I would say it is bug of this predicate and also in
> late compilation we drop the bodies after compiling but they still
> bind to current def.

Ok.

> > symtab_node::equal_address_to but I'm not 100% sure.  Esp.
> > in what cases can I expect a NULL node from varpool_node::get?
> 
> If you do folding from fold-const.c, then you need to be conservative
> when symbol table is not built yet.  If you analyze gimple bodies
> after cgraph construction we should be able to assume that the symbol
> table entries are created (I know we had some side cases with this in
> past but I hope they are fixed or I will fix it).
> 
> symtab_node::equal_address_to contains the magic mostly becuase of early
> folding.

I see.  As this is part of the code happens when points-to is available
we should be safe then, but I guess "safe" would be to handle ! node
conservatively then.

> > 
> > Basically I am using the above to decide whether I can use
> > the ultimate alias target of two decls to decide whether they
> > are not equal (points-to uses the DECL_UID of the ultimate alias
> > target in the bitmaps).
> > 
> > Maybe you can factor out a symtab helper for me?  I think I
> > want to catch all cases where symtab_node::equal_address_to
> > would return -1 (thus with respect to aliases the above doesn't
> > look conservative?)
> 
> OK, so you need a predicate such that if it returns true on
> node1, node2 then node1==node2 if and only if ultimate alias targets are the
> same?

Yes.

> I can do that.  Wonder what would be proper name for this beast?

Is it equal to node1 and node2 being not interposable?  (if we
factor out nonnull-ness)

If so interposable ()?

Not sure if this captures the alias behavior.

> Note that we are generally inconsistent about what aliases are valid. In older
> GCCs I think generally you can't safely use two aliases of the same symbol for
> non-readonly memory.
> 
> I was thining that we may just impose an requirement for the aliases to be 
> explicitely
> declared.  I.e.
> 
> extern int a;
> extern int b __attribute__ ((alias("a")));
> 
> would be only valid way to mix a and b pointing to the same memory location.
> 
> The fact that difference declarations are actually different objects is quite
> burried into nature of C/C++ standards and trying to fully support this may be
> quite some work.  What are the consequences on the base+offset alias oracle
> accuracy?

No idea but part of PR78035 notes that we are conservative when
comparing pointers but quite optimistic for aliasing here.  This
causes issue when we propagate pointer equivalences, like

extern int a;
extern int b;

ptr = &a;

...

if (ptr == &b)
  {
    *ptr = 3;
    .. = a;
  }

where we end up with

   b = 3;
   .. = a;

and thus breaking aliasing when a and b are the same.

But interposition would mean that (without LTO) all globals are
to be treated the same by points-to and we'd be left with
TBAA for the disambiguations?  At least for externs and for
all globals with -fPIC.

I guess the effect would be pretty bad...

(I'm trying to "fix" PR77964)

Richard.

> Honza
> > 
> > Thanks,
> > Richard.
> > 
> > 2016-10-19  Richard Biener  <rguent...@suse.de>
> > 
> >     PR tree-optimization/78035
> >     * tree-ssa-alias.h (struct pt_solution): Add vars_contains_interposable
> >     flag.
> >     * tree-ssa-structalias.c: Include varasm.h.
> >     (set_uids_in_ptset): Set vars_contains_interposable for
> >     interposable variables.
> >     (ipa_escaped_pt): Adjust.
> >     * tree-ssa-alias.c: Include varasm.h.
> >     (ptrs_compare_unequal): If pt->vars_contains_interposable or
> >     a decl is interposable then do not conclude anything about
> >     address equality.
> >     (dump_points_to_solution): Handle vars_contains_interposable.
> >     * gimple-pretty-print.c (pp_points_to_solution): Likewise.
> > 
> >     * gcc.target/i386/pr78035.c: New testcase.
> > 
> > 
> > Index: gcc/testsuite/gcc.target/i386/pr78035.c
> > ===================================================================
> > --- gcc/testsuite/gcc.target/i386/pr78035.c (revision 0)
> > +++ gcc/testsuite/gcc.target/i386/pr78035.c (revision 0)
> > @@ -0,0 +1,24 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +extern int a;
> > +extern int b;
> > +extern int c;
> > +
> > +int foo(int choose_a)
> > +{
> > +  int *p;
> > +  if (choose_a)
> > +    p = &a;
> > +  else
> > +    p = &b;
> > +  return p != &c;
> > +}
> > +
> > +int bar ()
> > +{
> > +  return &a != &c;
> > +}
> > +
> > +/* We should not optimize away either comparison.  */
> > +/* { dg-final { scan-assembler-times "cmp" 2 } } */
> > Index: gcc/tree-ssa-alias.c
> > ===================================================================
> > --- gcc/tree-ssa-alias.c    (revision 241362)
> > +++ gcc/tree-ssa-alias.c    (working copy)
> > @@ -32,12 +32,12 @@ along with GCC; see the file COPYING3.
> >  #include "tree-pretty-print.h"
> >  #include "alias.h"
> >  #include "fold-const.h"
> > -
> >  #include "langhooks.h"
> >  #include "dumpfile.h"
> >  #include "tree-eh.h"
> >  #include "tree-dfa.h"
> >  #include "ipa-reference.h"
> > +#include "varasm.h"
> >  
> >  /* Broad overview of how alias analysis on gimple works:
> >  
> > @@ -366,15 +366,39 @@ ptrs_compare_unequal (tree ptr1, tree pt
> >        /* We may not use restrict to optimize pointer comparisons.
> >           See PR71062.  So we have to assume that restrict-pointed-to
> >      may be in fact obj1.  */
> > -      if (!pi || pi->pt.vars_contains_restrict)
> > +      if (! pi
> > +     || pi->pt.vars_contains_restrict
> > +     || pi->pt.vars_contains_interposable)
> >     return false;
> > +      /* If obj1 is interposable give up.  */
> > +      if (VAR_P (obj1)
> > +     && (TREE_STATIC (obj1) || DECL_EXTERNAL (obj1)))
> > +   {
> > +     varpool_node *node = varpool_node::get (obj1);
> > +     if (! node
> > +         || ! node->analyzed
> > +         || ! decl_binds_to_current_def_p (obj1))
> > +       return false;
> > +   }
> >        return !pt_solution_includes (&pi->pt, obj1);
> >      }
> >    else if (TREE_CODE (ptr1) == SSA_NAME && obj2)
> >      {
> >        struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr1);
> > -      if (!pi || pi->pt.vars_contains_restrict)
> > +      if (! pi
> > +     || pi->pt.vars_contains_restrict
> > +     || pi->pt.vars_contains_interposable)
> >     return false;
> > +      /* If obj2 is interposable give up.  */
> > +      if (VAR_P (obj2)
> > +     && (TREE_STATIC (obj2) || DECL_EXTERNAL (obj2)))
> > +   {
> > +     varpool_node *node = varpool_node::get (obj2);
> > +     if (! node
> > +         || ! node->analyzed
> > +         || ! decl_binds_to_current_def_p (obj2))
> > +       return false;
> > +   }
> >        return !pt_solution_includes (&pi->pt, obj2);
> >      }
> >  
> > @@ -545,7 +569,12 @@ dump_points_to_solution (FILE *file, str
> >           comma = ", ";
> >         }
> >       if (pt->vars_contains_restrict)
> > -       fprintf (file, "%srestrict", comma);
> > +       {
> > +         fprintf (file, "%srestrict", comma);
> > +         comma = ", ";
> > +       }
> > +     if (pt->vars_contains_interposable)
> > +       fprintf (file, "%sinterposable", comma);
> >       fprintf (file, ")");
> >     }
> >      }
> > Index: gcc/tree-ssa-alias.h
> > ===================================================================
> > --- gcc/tree-ssa-alias.h    (revision 241362)
> > +++ gcc/tree-ssa-alias.h    (working copy)
> > @@ -57,6 +57,8 @@ struct GTY(()) pt_solution
> >    /* Nonzero if the vars bitmap includes a anonymous variable used to
> >       represent storage pointed to by a restrict qualified pointer.  */
> >    unsigned int vars_contains_restrict : 1;
> > +  /* Nonzero if the vars bitmap includes an interposable variable.  */
> > +  unsigned int vars_contains_interposable : 1;
> >  
> >    /* Set of variables that this pointer may point to.  */
> >    bitmap vars;
> > Index: gcc/gimple-pretty-print.c
> > ===================================================================
> > --- gcc/gimple-pretty-print.c       (revision 241362)
> > +++ gcc/gimple-pretty-print.c       (working copy)
> > @@ -728,6 +728,12 @@ pp_points_to_solution (pretty_printer *b
> >         {
> >           pp_string (buffer, comma);
> >           pp_string (buffer, "restrict");
> > +         comma = ", ";
> > +       }
> > +     if (pt->vars_contains_interposable)
> > +       {
> > +         pp_string (buffer, comma);
> > +         pp_string (buffer, "interposable");
> >         }
> >       pp_string (buffer, ")");
> >     }
> > Index: gcc/tree-ssa-structalias.c
> > ===================================================================
> > --- gcc/tree-ssa-structalias.c      (revision 241362)
> > +++ gcc/tree-ssa-structalias.c      (working copy)
> > @@ -39,6 +39,8 @@
> >  #include "tree-dfa.h"
> >  #include "params.h"
> >  #include "gimple-walk.h"
> > +#include "varasm.h"
> > +
> >  
> >  /* The idea behind this analyzer is to generate set constraints from the
> >     program, then solve the resulting constraints in order to generate the
> > @@ -6344,6 +6346,18 @@ set_uids_in_ptset (bitmap into, bitmap f
> >               && fndecl
> >               && ! auto_var_in_fn_p (vi->decl, fndecl)))
> >         pt->vars_contains_nonlocal = true;
> > +
> > +     /* If we have a variable that is interposable record that fact
> > +        for pointer comparison simplification.  */
> > +     if (VAR_P (vi->decl)
> > +         && (DECL_EXTERNAL (vi->decl) || TREE_PUBLIC (vi->decl)))
> > +       {
> > +         varpool_node *node = varpool_node::get (vi->decl);
> > +         if (! node
> > +             || ! node->analyzed
> > +             || ! decl_binds_to_current_def_p (node->decl))
> > +           pt->vars_contains_interposable = true;
> > +       }
> >     }
> >  
> >        else if (TREE_CODE (vi->decl) == FUNCTION_DECL
> > @@ -7576,7 +7590,8 @@ make_pass_build_ealias (gcc::context *ct
> >  
> >  /* IPA PTA solutions for ESCAPED.  */
> >  struct pt_solution ipa_escaped_pt
> > -  = { true, false, false, false, false, false, false, false, false, NULL };
> > +  = { true, false, false, false, false,
> > +      false, false, false, false, false, NULL };
> >  
> >  /* Associate node with varinfo DATA. Worker for
> >     cgraph_for_symbol_thunks_and_aliases.  */
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to