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
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?

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?)

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

Reply via email to