[Ada] Replace low-level Ekind membership tests with high-level Is_Formal
[gcc.git] / gcc / tree-ssa-structalias.c
index 75c6faedc1f6741b19b34c673d6943a1d9f24e8e..30a8c93b4ff82e519e7feed4fb2b246575ca03c7 100644 (file)
@@ -1,5 +1,5 @@
 /* Tree based points-to analysis
-   Copyright (C) 2005-2019 Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
    Contributed by Daniel Berlin <dberlin@dberlin.org>
 
    This file is part of GCC.
@@ -37,7 +37,6 @@
 #include "gimple-iterator.h"
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
-#include "params.h"
 #include "gimple-walk.h"
 #include "varasm.h"
 #include "stringpool.h"
    as a consequence.
 
    See  "Efficient Field-sensitive pointer analysis for C" by "David
-   J. Pearce and Paul H. J. Kelly and Chris Hankin, at
+   J. Pearce and Paul H. J. Kelly and Chris Hankin", at
    http://citeseer.ist.psu.edu/pearce04efficient.html
 
    Also see "Ultra-fast Aliasing Analysis using CLA: A Million Lines
-   of C Code in a Second" by ""Nevin Heintze and Olivier Tardieu" at
+   of C Code in a Second" by "Nevin Heintze and Olivier Tardieu" at
    http://citeseer.ist.psu.edu/heintze01ultrafast.html
 
    There are three types of real constraint expressions, DEREF,
@@ -85,7 +84,7 @@
    Each variable for a structure field has
 
    1. "size", that tells the size in bits of that field.
-   2. "fullsize, that tells the size in bits of the entire structure.
+   2. "fullsize", that tells the size in bits of the entire structure.
    3. "offset", that tells the offset in bits from the beginning of the
    structure to this field.
 
 
    We probably should compute a per-function unit-ESCAPE solution
    propagating it simply like the clobber / uses solutions.  The
-   solution can go alongside the non-IPA espaced solution and be
+   solution can go alongside the non-IPA escaped solution and be
    used to query which vars escape the unit through a function.
    This is also required to make the escaped-HEAP trick work in IPA mode.
 
@@ -1912,7 +1911,7 @@ typedef const struct equiv_class_label *const_equiv_class_label_t;
 
 /* Equiv_class_label hashtable helpers.  */
 
-struct equiv_class_hasher : free_ptr_hash <equiv_class_label>
+struct equiv_class_hasher : nofree_ptr_hash <equiv_class_label>
 {
   static inline hashval_t hash (const equiv_class_label *);
   static inline bool equal (const equiv_class_label *,
@@ -1945,6 +1944,8 @@ static hash_table<equiv_class_hasher> *pointer_equiv_class_table;
    classes.  */
 static hash_table<equiv_class_hasher> *location_equiv_class_table;
 
+struct obstack equiv_class_obstack;
+
 /* Lookup a equivalence class in TABLE by the bitmap of LABELS with
    hash HAS it contains.  Sets *REF_LABELS to the bitmap LABELS
    is equivalent to.  */
@@ -1961,7 +1962,7 @@ equiv_class_lookup_or_add (hash_table<equiv_class_hasher> *table,
   slot = table->find_slot (&ecl, INSERT);
   if (!*slot)
     {
-      *slot = XNEW (struct equiv_class_label);
+      *slot = XOBNEW (&equiv_class_obstack, struct equiv_class_label);
       (*slot)->labels = labels;
       (*slot)->hashcode = ecl.hashcode;
       (*slot)->equivalence_class = 0;
@@ -2335,6 +2336,7 @@ perform_var_substitution (constraint_graph_t graph)
   scc_info *si = new scc_info (size);
 
   bitmap_obstack_initialize (&iteration_obstack);
+  gcc_obstack_init (&equiv_class_obstack);
   pointer_equiv_class_table = new hash_table<equiv_class_hasher> (511);
   location_equiv_class_table
     = new hash_table<equiv_class_hasher> (511);
@@ -2474,6 +2476,7 @@ free_var_substitution_info (class scc_info *si)
   pointer_equiv_class_table = NULL;
   delete location_equiv_class_table;
   location_equiv_class_table = NULL;
+  obstack_free (&equiv_class_obstack, NULL);
   bitmap_obstack_release (&iteration_obstack);
 }
 
@@ -4854,6 +4857,14 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
         point for reachable memory of their arguments.  */
       else if (flags & (ECF_PURE|ECF_LOOPING_CONST_OR_PURE))
        handle_pure_call (t, &rhsc);
+      /* If the call is to a replaceable operator delete and results
+        from a delete expression as opposed to a direct call to
+        such operator, then the effects for PTA (in particular
+        the escaping of the pointer) can be ignored.  */
+      else if (fndecl
+              && DECL_IS_OPERATOR_DELETE_P (fndecl)
+              && gimple_call_from_new_or_delete (t))
+       ;
       else
        handle_rhs_call (t, &rhsc);
       if (gimple_call_lhs (t))
@@ -5005,11 +5016,12 @@ find_func_aliases (struct function *fn, gimple *origt)
                   || code == FLOOR_MOD_EXPR
                   || code == ROUND_MOD_EXPR)
            /* Division and modulo transfer the pointer from the LHS.  */
-           get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
-         else if ((CONVERT_EXPR_CODE_P (code)
-                   && !(POINTER_TYPE_P (gimple_expr_type (t))
-                        && !POINTER_TYPE_P (TREE_TYPE (rhsop))))
+           get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
+                                          NULL_TREE, &rhsc);
+         else if (CONVERT_EXPR_CODE_P (code)
                   || gimple_assign_single_p (t))
+           /* See through conversions, single RHS are handled by
+              get_constraint_for_rhs.  */
            get_constraint_for_rhs (rhsop, &rhsc);
          else if (code == COND_EXPR)
            {
@@ -5028,14 +5040,16 @@ find_func_aliases (struct function *fn, gimple *origt)
            ;
          else
            {
-             /* All other operations are merges.  */
+             /* All other operations are possibly offsetting merges.  */
              auto_vec<ce_s, 4> tmp;
              struct constraint_expr *rhsp;
              unsigned i, j;
-             get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
+             get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
+                                            NULL_TREE, &rhsc);
              for (i = 2; i < gimple_num_ops (t); ++i)
                {
-                 get_constraint_for_rhs (gimple_op (t, i), &tmp);
+                 get_constraint_for_ptr_offset (gimple_op (t, i),
+                                                NULL_TREE, &tmp);
                  FOR_EACH_VEC_ELT (tmp, j, rhsp)
                    rhsc.safe_push (*rhsp);
                  tmp.truncate (0);
@@ -5691,9 +5705,9 @@ push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
     return false;
 
   /* If the vector of fields is growing too big, bail out early.
-     Callers check for vec::length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
+     Callers check for vec::length <= param_max_fields_for_field_sensitive, make
      sure this fails.  */
-  if (fieldstack->length () > MAX_FIELDS_FOR_FIELD_SENSITIVE)
+  if (fieldstack->length () > (unsigned)param_max_fields_for_field_sensitive)
     return false;
 
   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
@@ -6114,7 +6128,7 @@ create_variable_info_for_1 (tree decl, const char *name, bool add_id,
   /* If we didn't end up collecting sub-variables create a full
      variable for the decl.  */
   if (fieldstack.length () == 0
-      || fieldstack.length () > MAX_FIELDS_FOR_FIELD_SENSITIVE)
+      || fieldstack.length () > (unsigned)param_max_fields_for_field_sensitive)
     {
       vi = new_var_info (decl, name, add_id);
       vi->offset = 0;
@@ -6801,7 +6815,7 @@ pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
 /* Return true if the points-to solution *PT is empty.  */
 
 bool
-pt_solution_empty_p (struct pt_solution *pt)
+pt_solution_empty_p (const pt_solution *pt)
 {
   if (pt->anything
       || pt->nonlocal)
@@ -7179,7 +7193,7 @@ init_base_vars (void)
 static void
 init_alias_vars (void)
 {
-  use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1);
+  use_field_sensitive = (param_max_fields_for_field_sensitive > 1);
 
   bitmap_obstack_initialize (&pta_obstack);
   bitmap_obstack_initialize (&oldpta_obstack);
@@ -7959,7 +7973,7 @@ associate_varinfo_to_alias (struct cgraph_node *node, void *data)
 {
   if ((node->alias
        || (node->thunk.thunk_p
-          && ! node->global.inlined_to))
+          && ! node->inlined_to))
       && node->analyzed
       && !node->ifunc_resolver)
     insert_vi_for_tree (node->decl, (varinfo_t)data);
@@ -8079,7 +8093,8 @@ refered_from_nonlocal_fn (struct cgraph_node *node, void *data)
 {
   bool *nonlocal_p = (bool *)data;
   *nonlocal_p |= (node->used_from_other_partition
-                 || node->externally_visible
+                 || DECL_EXTERNAL (node->decl)
+                 || TREE_PUBLIC (node->decl)
                  || node->force_output
                  || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)));
   return false;
@@ -8091,7 +8106,8 @@ refered_from_nonlocal_var (struct varpool_node *node, void *data)
 {
   bool *nonlocal_p = (bool *)data;
   *nonlocal_p |= (node->used_from_other_partition
-                 || node->externally_visible
+                 || DECL_EXTERNAL (node->decl)
+                 || TREE_PUBLIC (node->decl)
                  || node->force_output);
   return false;
 }
@@ -8129,7 +8145,7 @@ ipa_pta_execute (void)
       /* Nodes without a body are not interesting.  Especially do not
          visit clones at this point for now - we get duplicate decls
         there for inline clones at least.  */
-      if (!node->has_gimple_body_p () || node->global.inlined_to)
+      if (!node->has_gimple_body_p () || node->inlined_to)
        continue;
       node->get_body ();
 
@@ -8140,7 +8156,8 @@ ipa_pta_execute (void)
         For local functions we see all callers and thus do not need initial
         constraints for parameters.  */
       bool nonlocal_p = (node->used_from_other_partition
-                        || node->externally_visible
+                        || DECL_EXTERNAL (node->decl)
+                        || TREE_PUBLIC (node->decl)
                         || node->force_output
                         || lookup_attribute ("noipa",
                                              DECL_ATTRIBUTES (node->decl)));
@@ -8154,7 +8171,8 @@ ipa_pta_execute (void)
          && from != constraints.length ())
        {
          fprintf (dump_file,
-                  "Generating intial constraints for %s", node->name ());
+                  "Generating initial constraints for %s",
+                  node->dump_name ());
          if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
            fprintf (dump_file, " (%s)",
                     IDENTIFIER_POINTER
@@ -8180,8 +8198,9 @@ ipa_pta_execute (void)
 
       /* For the purpose of IPA PTA unit-local globals are not
          escape points.  */
-      bool nonlocal_p = (var->used_from_other_partition
-                        || var->externally_visible
+      bool nonlocal_p = (DECL_EXTERNAL (var->decl)
+                        || TREE_PUBLIC (var->decl)
+                        || var->used_from_other_partition
                         || var->force_output);
       var->call_for_symbol_and_aliases (refered_from_nonlocal_var,
                                        &nonlocal_p, true);
@@ -8211,7 +8230,7 @@ ipa_pta_execute (void)
       if (dump_file)
        {
          fprintf (dump_file,
-                  "Generating constraints for %s", node->name ());
+                  "Generating constraints for %s", node->dump_name ());
          if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
            fprintf (dump_file, " (%s)",
                     IDENTIFIER_POINTER