[PR 78140] Reuse same IPA bits and VR info
authorMartin Jambor <mjambor@suse.cz>
Wed, 1 Mar 2017 09:37:27 +0000 (10:37 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Wed, 1 Mar 2017 09:37:27 +0000 (10:37 +0100)
2017-03-01  Martin Jambor  <mjambor@suse.cz>

PR lto/78140
* ipa-prop.h (ipa_bits): Removed field known.
(ipa_jump_func): Removed field vr_known.  Changed fields bits and m_vr
to pointers.  Adjusted their comments to warn about their sharing.
(ipcp_transformation_summary): Change bits to a vector of pointers.
(ipa_check_create_edge_args): Moved to ipa-prop.c, declare.
(ipa_get_ipa_bits_for_value): Declare.
* tree-vrp.h (value_range): Mark as GTY((for_user)).
* ipa-prop.c (ipa_bit_ggc_hash_traits): New.
(ipa_bits_hash_table): Likewise.
(ipa_vr_ggc_hash_traits): Likewise.
(ipa_vr_hash_table): Likewise.
(ipa_print_node_jump_functions_for_edge): Adjust for bits and m_vr
being pointers and vr_known being removed.
(ipa_set_jf_unknown): Likewise.
(ipa_get_ipa_bits_for_value): New function.
(ipa_set_jfunc_bits): Likewise.
(ipa_get_value_range): New overloaded functions.
(ipa_set_jfunc_vr): Likewise.
(ipa_compute_jump_functions_for_edge): Use the above functions to
construct bits and vr parts of jump functions.
(ipa_check_create_edge_args): Move here from ipa-prop.h, also allocate
ipa_bits_hash_table and ipa_vr_hash_table if they do not already
exist.
(ipcp_grow_transformations_if_necessary): Also allocate
ipa_bits_hash_table and ipa_vr_hash_table if they do not already
exist.
(ipa_node_params_t::duplicate): Do not copy bits, just pointers to
them.  Fix too long lines.
(ipa_write_jump_function): Adjust for bits and m_vr being pointers and
vr_known being removed.
(ipa_read_jump_function): Use new setter functions to construct bits
and vr parts of jump functions or set them to NULL.
(write_ipcp_transformation_info): Adjust for bits being pointers.
(read_ipcp_transformation_info): Likewise.
(ipcp_update_bits): Likewise.  Fix excessively long lines a trailing
space.
Include gt-ipa-prop.h.
* ipa-cp.c (propagate_bits_across_jump_function): Adjust for bits
being pointers.
(ipcp_store_bits_results): Likewise.
(propagate_vr_across_jump_function): Adjust for m_vr being a pointer.
Do not write to existing jump functions but use a temporary instead.

From-SVN: r245805

gcc/ChangeLog
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/tree-vrp.h

index 4873ae8eb9d6b982cd8d5c0bb52f78b300f2f333..087e4cf3b5458615549ff946f90cd0fbb7d3fa59 100644 (file)
@@ -1,3 +1,49 @@
+2017-03-01  Martin Jambor  <mjambor@suse.cz>
+
+       PR lto/78140
+       * ipa-prop.h (ipa_bits): Removed field known.
+       (ipa_jump_func): Removed field vr_known.  Changed fields bits and m_vr
+       to pointers.  Adjusted their comments to warn about their sharing.
+       (ipcp_transformation_summary): Change bits to a vector of pointers.
+       (ipa_check_create_edge_args): Moved to ipa-prop.c, declare.
+       (ipa_get_ipa_bits_for_value): Declare.
+       * tree-vrp.h (value_range): Mark as GTY((for_user)).
+       * ipa-prop.c (ipa_bit_ggc_hash_traits): New.
+       (ipa_bits_hash_table): Likewise.
+       (ipa_vr_ggc_hash_traits): Likewise.
+       (ipa_vr_hash_table): Likewise.
+       (ipa_print_node_jump_functions_for_edge): Adjust for bits and m_vr
+       being pointers and vr_known being removed.
+       (ipa_set_jf_unknown): Likewise.
+       (ipa_get_ipa_bits_for_value): New function.
+       (ipa_set_jfunc_bits): Likewise.
+       (ipa_get_value_range): New overloaded functions.
+       (ipa_set_jfunc_vr): Likewise.
+       (ipa_compute_jump_functions_for_edge): Use the above functions to
+       construct bits and vr parts of jump functions.
+       (ipa_check_create_edge_args): Move here from ipa-prop.h, also allocate
+       ipa_bits_hash_table and ipa_vr_hash_table if they do not already
+       exist.
+       (ipcp_grow_transformations_if_necessary): Also allocate
+       ipa_bits_hash_table and ipa_vr_hash_table if they do not already
+       exist.
+       (ipa_node_params_t::duplicate): Do not copy bits, just pointers to
+       them.  Fix too long lines.
+       (ipa_write_jump_function): Adjust for bits and m_vr being pointers and
+       vr_known being removed.
+       (ipa_read_jump_function): Use new setter functions to construct bits
+       and vr parts of jump functions or set them to NULL.
+       (write_ipcp_transformation_info): Adjust for bits being pointers.
+       (read_ipcp_transformation_info): Likewise.
+       (ipcp_update_bits): Likewise.  Fix excessively long lines a trailing
+       space.
+       Include gt-ipa-prop.h.
+       * ipa-cp.c (propagate_bits_across_jump_function): Adjust for bits
+       being pointers.
+       (ipcp_store_bits_results): Likewise.
+       (propagate_vr_across_jump_function): Adjust for m_vr being a pointer.
+       Do not write to existing jump functions but use a temporary instead.
+
 2017-03-01  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/79681
index aa3c9973a66b0f7e8266e610b5752c1302916428..16e7e2216ab96489a7985e0280cc637ff1954ea2 100644 (file)
@@ -1819,8 +1819,8 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
         and we store it in jump function during analysis stage.  */
 
       if (src_lats->bits_lattice.bottom_p ()
-         && jfunc->bits.known)
-       return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask,
+         && jfunc->bits)
+       return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
                                        precision);
       else
        return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn,
@@ -1829,10 +1829,9 @@ propagate_bits_across_jump_function (cgraph_edge *cs, int idx,
 
   else if (jfunc->type == IPA_JF_ANCESTOR)
     return dest_lattice->set_to_bottom ();
-
-  else if (jfunc->bits.known)
-    return dest_lattice->meet_with (jfunc->bits.value, jfunc->bits.mask, precision);
-
+  else if (jfunc->bits)
+    return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask,
+                                   precision);
   else
     return dest_lattice->set_to_bottom ();
 }
@@ -1903,19 +1902,21 @@ propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc,
          val = fold_convert (param_type, val);
          if (TREE_OVERFLOW_P (val))
            val = drop_tree_overflow (val);
-         jfunc->vr_known = true;
-         jfunc->m_vr.type = VR_RANGE;
-         jfunc->m_vr.min = val;
-         jfunc->m_vr.max = val;
-         return dest_lat->meet_with (&jfunc->m_vr);
+
+         value_range tmpvr;
+         memset (&tmpvr, 0, sizeof (tmpvr));
+         tmpvr.type = VR_RANGE;
+         tmpvr.min = val;
+         tmpvr.max = val;
+         return dest_lat->meet_with (&tmpvr);
        }
     }
 
   value_range vr;
-  if (jfunc->vr_known
-      && ipa_vr_operation_and_type_effects (&vr, &jfunc->m_vr, NOP_EXPR,
+  if (jfunc->m_vr
+      && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR,
                                            param_type,
-                                           TREE_TYPE (jfunc->m_vr.min)))
+                                           TREE_TYPE (jfunc->m_vr->min)))
     return dest_lat->meet_with (&vr);
   else
     return dest_lat->set_to_bottom ();
@@ -4870,19 +4871,17 @@ ipcp_store_bits_results (void)
       for (unsigned i = 0; i < count; i++)
        {
          ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
-         ipa_bits bits_jfunc;
+         ipa_bits *jfbits;
 
          if (plats->bits_lattice.constant_p ())
-           {
-             bits_jfunc.known = true;
-             bits_jfunc.value = plats->bits_lattice.get_value ();
-             bits_jfunc.mask = plats->bits_lattice.get_mask ();
-           }
+           jfbits
+             = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (),
+                                           plats->bits_lattice.get_mask ());
          else
-           bits_jfunc.known = false;
+           jfbits = NULL;
 
-         ts->bits->quick_push (bits_jfunc);
-         if (!dump_file || !bits_jfunc.known)
+         ts->bits->quick_push (jfbits);
+         if (!dump_file || !jfbits)
            continue;
          if (!dumped_sth)
            {
@@ -4891,9 +4890,9 @@ ipcp_store_bits_results (void)
              dumped_sth = true;
            }
          fprintf (dump_file, " param %i: value = ", i);
-         print_hex (bits_jfunc.value, dump_file);
+         print_hex (jfbits->value, dump_file);
          fprintf (dump_file, ", mask = ");
-         print_hex (bits_jfunc.mask, dump_file);
+         print_hex (jfbits->mask, dump_file);
          fprintf (dump_file, "\n");
        }
     }
index 33503d4befcb3191ac11b3840273224e604e369e..d519cdfcbabae3578ffa62caf870941a6be47fef 100644 (file)
@@ -60,6 +60,93 @@ vec<ipcp_transformation_summary, va_gc> *ipcp_transformations;
 /* Vector where the parameter infos are actually stored. */
 vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
 
+/* Traits for a hash table for reusing already existing ipa_bits. */
+
+struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
+{
+  typedef ipa_bits *value_type;
+  typedef ipa_bits *compare_type;
+  static hashval_t
+  hash (const ipa_bits *p)
+  {
+    hashval_t t = (hashval_t) p->value.to_shwi ();
+    return iterative_hash_host_wide_int (p->mask.to_shwi (), t);
+  }
+  static bool
+  equal (const ipa_bits *a, const ipa_bits *b)
+    {
+      return a->value == b->value && a->mask == b->mask;
+    }
+  static void
+  mark_empty (ipa_bits *&p)
+    {
+      p = NULL;
+    }
+  static bool
+  is_empty (const ipa_bits *p)
+    {
+      return p == NULL;
+    }
+  static bool
+  is_deleted (const ipa_bits *p)
+    {
+      return p == reinterpret_cast<const ipa_bits *> (1);
+    }
+  static void
+  mark_deleted (ipa_bits *&p)
+    {
+      p = reinterpret_cast<ipa_bits *> (1);
+    }
+};
+
+/* Hash table for avoid repeated allocations of equal ipa_bits.  */
+static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table;
+
+/* Traits for a hash table for reusing value_ranges used for IPA.  Note that
+   the equiv bitmap is not hashed and is expected to be NULL.  */
+
+struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range *>
+{
+  typedef value_range *value_type;
+  typedef value_range *compare_type;
+  static hashval_t
+  hash (const value_range *p)
+  {
+    gcc_checking_assert (!p->equiv);
+    hashval_t t = (hashval_t) p->type;
+    t = iterative_hash_expr (p->min, t);
+    return iterative_hash_expr (p->max, t);
+  }
+  static bool
+  equal (const value_range *a, const value_range *b)
+    {
+      return a->type == b->type && a->min == b->min && a->max == b->max;
+    }
+  static void
+  mark_empty (value_range *&p)
+    {
+      p = NULL;
+    }
+  static bool
+  is_empty (const value_range *p)
+    {
+      return p == NULL;
+    }
+  static bool
+  is_deleted (const value_range *p)
+    {
+      return p == reinterpret_cast<const value_range *> (1);
+    }
+  static void
+  mark_deleted (value_range *&p)
+    {
+      p = reinterpret_cast<value_range *> (1);
+    }
+};
+
+/* Hash table for avoid repeated allocations of equal value_ranges.  */
+static GTY ((cache)) hash_table<ipa_vr_ggc_hash_traits> *ipa_vr_hash_table;
+
 /* Holders of ipa cgraph hooks: */
 static struct cgraph_edge_hook_list *edge_removal_hook_holder;
 static struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
@@ -298,23 +385,25 @@ ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
          ctx->dump (dump_file);
        }
 
-      if (jump_func->bits.known)
+      if (jump_func->bits)
        {
-         fprintf (f, "         value: "); print_hex (jump_func->bits.value, f);
-         fprintf (f, ", mask: "); print_hex (jump_func->bits.mask, f);
+         fprintf (f, "         value: ");
+         print_hex (jump_func->bits->value, f);
+         fprintf (f, ", mask: ");
+         print_hex (jump_func->bits->mask, f);
          fprintf (f, "\n");
        }
       else
        fprintf (f, "         Unknown bits\n");
 
-      if (jump_func->vr_known)
+      if (jump_func->m_vr)
        {
          fprintf (f, "         VR  ");
          fprintf (f, "%s[",
-                  (jump_func->m_vr.type == VR_ANTI_RANGE) ? "~" : "");
-         print_decs (jump_func->m_vr.min, f);
+                  (jump_func->m_vr->type == VR_ANTI_RANGE) ? "~" : "");
+         print_decs (jump_func->m_vr->min, f);
          fprintf (f, ", ");
-         print_decs (jump_func->m_vr.max, f);
+         print_decs (jump_func->m_vr->max, f);
          fprintf (f, "]\n");
        }
       else
@@ -397,8 +486,8 @@ static void
 ipa_set_jf_unknown (struct ipa_jump_func *jfunc)
 {
   jfunc->type = IPA_JF_UNKNOWN;
-  jfunc->bits.known = false;
-  jfunc->vr_known = false;
+  jfunc->bits = NULL;
+  jfunc->m_vr = NULL;
 }
 
 /* Set JFUNC to be a copy of another jmp (to be used by jump function
@@ -1658,6 +1747,91 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i)
   return NULL;
 }
 
+/* Return ipa_bits with VALUE and MASK values, which can be either a newly
+   allocated structure or a previously existing one shared with other jump
+   functions and/or transformation summaries.  */
+
+ipa_bits *
+ipa_get_ipa_bits_for_value (const widest_int &value, const widest_int &mask)
+{
+  ipa_bits tmp;
+  tmp.value = value;
+  tmp.mask = mask;
+
+  ipa_bits **slot = ipa_bits_hash_table->find_slot (&tmp, INSERT);
+  if (*slot)
+    return *slot;
+
+  ipa_bits *res = ggc_alloc<ipa_bits> ();
+  res->value = value;
+  res->mask = mask;
+  *slot = res;
+
+  return res;
+}
+
+/* Assign to JF a pointer to ipa_bits structure with VALUE and MASK.  Use hash
+   table in order to avoid creating multiple same ipa_bits structures.  */
+
+static void
+ipa_set_jfunc_bits (ipa_jump_func *jf, const widest_int &value,
+                   const widest_int &mask)
+{
+  jf->bits = ipa_get_ipa_bits_for_value (value, mask);
+}
+
+/* Return a pointer to a value_range just like *TMP, but either find it in
+   ipa_vr_hash_table or allocate it in GC memory.  TMP->equiv must be NULL.  */
+
+static value_range *
+ipa_get_value_range (value_range *tmp)
+{
+  value_range **slot = ipa_vr_hash_table->find_slot (tmp, INSERT);
+  if (*slot)
+    return *slot;
+
+  value_range *vr = ggc_alloc<value_range> ();
+  *vr = *tmp;
+  *slot = vr;
+
+  return vr;
+}
+
+/* Return a pointer to a value range consisting of TYPE, MIN, MAX and an empty
+   equiv set. Use hash table in order to avoid creating multiple same copies of
+   value_ranges.  */
+
+static value_range *
+ipa_get_value_range (enum value_range_type type, tree min, tree max)
+{
+  value_range tmp;
+  tmp.type = type;
+  tmp.min = min;
+  tmp.max = max;
+  tmp.equiv = NULL;
+  return ipa_get_value_range (&tmp);
+}
+
+/* Assign to JF a pointer to a value_range structure with TYPE, MIN and MAX and
+   a NULL equiv bitmap.  Use hash table in order to avoid creating multiple
+   same value_range structures.  */
+
+static void
+ipa_set_jfunc_vr (ipa_jump_func *jf, enum value_range_type type,
+                 tree min, tree max)
+{
+  jf->m_vr = ipa_get_value_range (type, min, max);
+}
+
+/* Assign to JF a pointer to a value_range just liek TMP but either fetch a
+   copy from ipa_vr_hash_table or allocate a new on in GC memory.  */
+
+static void
+ipa_set_jfunc_vr (ipa_jump_func *jf, value_range *tmp)
+{
+  jf->m_vr = ipa_get_value_range (tmp);
+}
+
 /* Compute jump function for all arguments of callsite CS and insert the
    information in the jump_functions array in the ipa_edge_args corresponding
    to this callsite.  */
@@ -1714,14 +1888,11 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
 
          if (addr_nonzero)
            {
-             jfunc->vr_known = true;
-             jfunc->m_vr.type = VR_ANTI_RANGE;
-             jfunc->m_vr.min = build_int_cst (TREE_TYPE (arg), 0);
-             jfunc->m_vr.max = build_int_cst (TREE_TYPE (arg), 0);
-             jfunc->m_vr.equiv = NULL;
+             tree z = build_int_cst (TREE_TYPE (arg), 0);
+             ipa_set_jfunc_vr (jfunc, VR_ANTI_RANGE, z, z);
            }
          else
-           gcc_assert (!jfunc->vr_known);
+           gcc_assert (!jfunc->m_vr);
        }
       else
        {
@@ -1732,56 +1903,48 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
              && (type = get_range_info (arg, &min, &max))
              && (type == VR_RANGE || type == VR_ANTI_RANGE))
            {
-             value_range vr;
-
-             vr.type = type;
-             vr.min = wide_int_to_tree (TREE_TYPE (arg), min);
-             vr.max = wide_int_to_tree (TREE_TYPE (arg), max);
-             vr.equiv = NULL;
-             extract_range_from_unary_expr (&jfunc->m_vr,
-                                            NOP_EXPR,
-                                            param_type,
-                                            &vr, TREE_TYPE (arg));
-             if (jfunc->m_vr.type == VR_RANGE
-                 || jfunc->m_vr.type == VR_ANTI_RANGE)
-               jfunc->vr_known = true;
+             value_range tmpvr,resvr;
+
+             tmpvr.type = type;
+             tmpvr.min = wide_int_to_tree (TREE_TYPE (arg), min);
+             tmpvr.max = wide_int_to_tree (TREE_TYPE (arg), max);
+             tmpvr.equiv = NULL;
+             memset (&resvr, 0, sizeof (resvr));
+             extract_range_from_unary_expr (&resvr, NOP_EXPR, param_type,
+                                            &tmpvr, TREE_TYPE (arg));
+             if (resvr.type == VR_RANGE || resvr.type == VR_ANTI_RANGE)
+               ipa_set_jfunc_vr (jfunc, &resvr);
              else
-               jfunc->vr_known = false;
+               gcc_assert (!jfunc->m_vr);
            }
          else
-           gcc_assert (!jfunc->vr_known);
+           gcc_assert (!jfunc->m_vr);
        }
 
       if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
          && (TREE_CODE (arg) == SSA_NAME || TREE_CODE (arg) == INTEGER_CST))
        {
-         jfunc->bits.known = true;
-         
          if (TREE_CODE (arg) == SSA_NAME)
-           {
-             jfunc->bits.value = 0;
-             jfunc->bits.mask = widest_int::from (get_nonzero_bits (arg),
-                                                  TYPE_SIGN (TREE_TYPE (arg)));
-           }
+           ipa_set_jfunc_bits (jfunc, 0,
+                               widest_int::from (get_nonzero_bits (arg),
+                                                 TYPE_SIGN (TREE_TYPE (arg))));
          else
-           {
-             jfunc->bits.value = wi::to_widest (arg);
-             jfunc->bits.mask = 0;
-           }
+           ipa_set_jfunc_bits (jfunc, wi::to_widest (arg), 0);
        }
       else if (POINTER_TYPE_P (TREE_TYPE (arg)))
        {
          unsigned HOST_WIDE_INT bitpos;
          unsigned align;
 
-         jfunc->bits.known = true;
          get_pointer_alignment_1 (arg, &align, &bitpos);
-         jfunc->bits.mask = wi::mask<widest_int>(TYPE_PRECISION (TREE_TYPE (arg)), false)
-                            .and_not (align / BITS_PER_UNIT - 1);
-         jfunc->bits.value = bitpos / BITS_PER_UNIT;
+         widest_int mask
+           = wi::mask<widest_int>(TYPE_PRECISION (TREE_TYPE (arg)), false)
+           .and_not (align / BITS_PER_UNIT - 1);
+         widest_int value = bitpos / BITS_PER_UNIT;
+         ipa_set_jfunc_bits (jfunc, value, mask);
        }
       else
-       gcc_assert (!jfunc->bits.known);
+       gcc_assert (!jfunc->bits);
 
       if (is_gimple_ip_invariant (arg)
          || (VAR_P (arg)
@@ -3545,6 +3708,22 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
   return changed;
 }
 
+/* Ensure that array of edge arguments infos is big enough to accommodate a
+   structure for all edges and reallocates it if not.  Also, allocate
+   associated hash tables is they do not already exist.  */
+
+void
+ipa_check_create_edge_args (void)
+{
+  if (vec_safe_length (ipa_edge_args_vector)
+      <= (unsigned) symtab->edges_max_uid)
+    vec_safe_grow_cleared (ipa_edge_args_vector, symtab->edges_max_uid + 1);
+  if (!ipa_bits_hash_table)
+    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
+  if (!ipa_vr_hash_table)
+    ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
+}
+
 /* Frees all dynamically allocated structures that the argument info points
    to.  */
 
@@ -3581,7 +3760,8 @@ ipa_free_all_node_params (void)
   ipa_node_params_sum = NULL;
 }
 
-/* Grow ipcp_transformations if necessary.  */
+/* Grow ipcp_transformations if necessary.  Also allocate any necessary hash
+   tables if they do not already exist.  */
 
 void
 ipcp_grow_transformations_if_necessary (void)
@@ -3589,6 +3769,10 @@ ipcp_grow_transformations_if_necessary (void)
   if (vec_safe_length (ipcp_transformations)
       <= (unsigned) symtab->cgraph_max_uid)
     vec_safe_grow_cleared (ipcp_transformations, symtab->cgraph_max_uid + 1);
+  if (!ipa_bits_hash_table)
+    ipa_bits_hash_table = hash_table<ipa_bit_ggc_hash_traits>::create_ggc (37);
+  if (!ipa_vr_hash_table)
+    ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37);
 }
 
 /* Set the aggregate replacements of NODE to be AGGVALS.  */
@@ -3775,12 +3959,18 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst,
       ipa_set_node_agg_value_chain (dst, new_av);
     }
 
-  ipcp_transformation_summary *src_trans = ipcp_get_transformation_summary (src);
+  ipcp_transformation_summary *src_trans
+    = ipcp_get_transformation_summary (src);
 
   if (src_trans)
     {
       ipcp_grow_transformations_if_necessary ();
       src_trans = ipcp_get_transformation_summary (src);
+      ipcp_transformation_summary *dst_trans
+       = ipcp_get_transformation_summary (dst);
+
+      dst_trans->bits = vec_safe_copy (src_trans->bits);
+
       const vec<ipa_vr, va_gc> *src_vr = src_trans->m_vr;
       vec<ipa_vr, va_gc> *&dst_vr
        = ipcp_get_transformation_summary (dst)->m_vr;
@@ -3791,18 +3981,6 @@ ipa_node_params_t::duplicate(cgraph_node *src, cgraph_node *dst,
            dst_vr->quick_push ((*src_vr)[i]);
        }
     }
-
-  if (src_trans && vec_safe_length (src_trans->bits) > 0)
-    {
-      ipcp_grow_transformations_if_necessary ();
-      src_trans = ipcp_get_transformation_summary (src);
-      const vec<ipa_bits, va_gc> *src_bits = src_trans->bits;
-      vec<ipa_bits, va_gc> *&dst_bits
-       = ipcp_get_transformation_summary (dst)->bits;
-      vec_safe_reserve_exact (dst_bits, src_bits->length ());
-      for (unsigned i = 0; i < src_bits->length (); ++i)
-       dst_bits->quick_push ((*src_bits)[i]);
-    }
 }
 
 /* Register our cgraph hooks if they are not already there.  */
@@ -4718,21 +4896,21 @@ ipa_write_jump_function (struct output_block *ob,
     }
 
   bp = bitpack_create (ob->main_stream);
-  bp_pack_value (&bp, jump_func->bits.known, 1);
+  bp_pack_value (&bp, !!jump_func->bits, 1);
   streamer_write_bitpack (&bp);
-  if (jump_func->bits.known)
+  if (jump_func->bits)
     {
-      streamer_write_widest_int (ob, jump_func->bits.value);
-      streamer_write_widest_int (ob, jump_func->bits.mask);
+      streamer_write_widest_int (ob, jump_func->bits->value);
+      streamer_write_widest_int (ob, jump_func->bits->mask);
     }
-  bp_pack_value (&bp, jump_func->vr_known, 1);
+  bp_pack_value (&bp, !!jump_func->m_vr, 1);
   streamer_write_bitpack (&bp);
-  if (jump_func->vr_known)
+  if (jump_func->m_vr)
     {
       streamer_write_enum (ob->main_stream, value_rang_type,
-                          VR_LAST, jump_func->m_vr.type);
-      stream_write_tree (ob, jump_func->m_vr.min, true);
-      stream_write_tree (ob, jump_func->m_vr.max, true);
+                          VR_LAST, jump_func->m_vr->type);
+      stream_write_tree (ob, jump_func->m_vr->min, true);
+      stream_write_tree (ob, jump_func->m_vr->max, true);
     }
 }
 
@@ -4809,26 +4987,25 @@ ipa_read_jump_function (struct lto_input_block *ib,
   bool bits_known = bp_unpack_value (&bp, 1);
   if (bits_known)
     {
-      jump_func->bits.known = true;
-      jump_func->bits.value = streamer_read_widest_int (ib);
-      jump_func->bits.mask = streamer_read_widest_int (ib);
+      widest_int value = streamer_read_widest_int (ib);
+      widest_int mask = streamer_read_widest_int (ib);
+      ipa_set_jfunc_bits (jump_func, value, mask);
     }
   else
-    jump_func->bits.known = false;
+    jump_func->bits = NULL;
 
   struct bitpack_d vr_bp = streamer_read_bitpack (ib);
   bool vr_known = bp_unpack_value (&vr_bp, 1);
   if (vr_known)
     {
-      jump_func->vr_known = true;
-      jump_func->m_vr.type = streamer_read_enum (ib,
-                                                value_range_type,
-                                                VR_LAST);
-      jump_func->m_vr.min = stream_read_tree (ib, data_in);
-      jump_func->m_vr.max = stream_read_tree (ib, data_in);
+      enum value_range_type type = streamer_read_enum (ib, value_range_type,
+                                                      VR_LAST);
+      tree min = stream_read_tree (ib, data_in);
+      tree max = stream_read_tree (ib, data_in);
+      ipa_set_jfunc_vr (jump_func, type, min, max);
     }
   else
-    jump_func->vr_known = false;
+    jump_func->m_vr = NULL;
 }
 
 /* Stream out parts of cgraph_indirect_call_info corresponding to CS that are
@@ -5207,14 +5384,14 @@ write_ipcp_transformation_info (output_block *ob, cgraph_node *node)
 
       for (unsigned i = 0; i < count; ++i)
        {
-         const ipa_bitsbits_jfunc = (*ts->bits)[i];
+         const ipa_bits *bits_jfunc = (*ts->bits)[i];
          struct bitpack_d bp = bitpack_create (ob->main_stream);
-         bp_pack_value (&bp, bits_jfunc.known, 1);
+         bp_pack_value (&bp, !!bits_jfunc, 1);
          streamer_write_bitpack (&bp);
-         if (bits_jfunc.known)
+         if (bits_jfunc)
            {
-             streamer_write_widest_int (ob, bits_jfunc.value);
-             streamer_write_widest_int (ob, bits_jfunc.mask);
+             streamer_write_widest_int (ob, bits_jfunc->value);
+             streamer_write_widest_int (ob, bits_jfunc->mask);
            }
        }
     }
@@ -5281,13 +5458,14 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node,
 
       for (i = 0; i < count; i++)
        {
-         ipa_bits& bits_jfunc = (*ts->bits)[i];
          struct bitpack_d bp = streamer_read_bitpack (ib);
-         bits_jfunc.known = bp_unpack_value (&bp, 1);
-         if (bits_jfunc.known)
+         bool known = bp_unpack_value (&bp, 1);
+         if (known)
            {
-             bits_jfunc.value = streamer_read_widest_int (ib);
-             bits_jfunc.mask = streamer_read_widest_int (ib);
+             ipa_bits *bits
+               = ipa_get_ipa_bits_for_value (streamer_read_widest_int (ib),
+                                             streamer_read_widest_int (ib));
+             (*ts->bits)[i] = bits;
            }
        }
     }
@@ -5554,7 +5732,7 @@ ipcp_update_bits (struct cgraph_node *node)
   if (!ts || vec_safe_length (ts->bits) == 0)
     return;
 
-  vec<ipa_bits, va_gc> &bits = *ts->bits;
+  vec<ipa_bits *, va_gc> &bits = *ts->bits;
   unsigned count = bits.length ();
 
   for (unsigned i = 0; i < count; ++i, parm = next_parm)
@@ -5566,10 +5744,11 @@ ipcp_update_bits (struct cgraph_node *node)
       gcc_checking_assert (parm);
       next_parm = DECL_CHAIN (parm);
 
-      if (!bits[i].known
-         || !(INTEGRAL_TYPE_P (TREE_TYPE (parm)) || POINTER_TYPE_P (TREE_TYPE (parm)))
+      if (!bits[i]
+         || !(INTEGRAL_TYPE_P (TREE_TYPE (parm))
+              || POINTER_TYPE_P (TREE_TYPE (parm)))
          || !is_gimple_reg (parm))
-       continue;       
+       continue;
 
       tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm);
       if (!ddef)
@@ -5577,8 +5756,8 @@ ipcp_update_bits (struct cgraph_node *node)
 
       if (dump_file)
        {
-         fprintf (dump_file, "Adjusting mask for param %u to ", i); 
-         print_hex (bits[i].mask, dump_file);
+         fprintf (dump_file, "Adjusting mask for param %u to ", i);
+         print_hex (bits[i]->mask, dump_file);
          fprintf (dump_file, "\n");
        }
 
@@ -5587,14 +5766,14 @@ ipcp_update_bits (struct cgraph_node *node)
          unsigned prec = TYPE_PRECISION (TREE_TYPE (ddef));
          signop sgn = TYPE_SIGN (TREE_TYPE (ddef));
 
-         wide_int nonzero_bits = wide_int::from (bits[i].mask, prec, UNSIGNED)
-                                 | wide_int::from (bits[i].value, prec, sgn);
+         wide_int nonzero_bits = wide_int::from (bits[i]->mask, prec, UNSIGNED)
+                                 | wide_int::from (bits[i]->value, prec, sgn);
          set_nonzero_bits (ddef, nonzero_bits);
        }
       else
        {
-         unsigned tem = bits[i].mask.to_uhwi ();
-         unsigned HOST_WIDE_INT bitpos = bits[i].value.to_uhwi (); 
+         unsigned tem = bits[i]->mask.to_uhwi ();
+         unsigned HOST_WIDE_INT bitpos = bits[i]->value.to_uhwi ();
          unsigned align = tem & -tem;
          unsigned misalign = bitpos & (align - 1);
 
@@ -5757,3 +5936,5 @@ ipcp_transform_function (struct cgraph_node *node)
   else
     return TODO_update_ssa_only_virtuals;
 }
+
+#include "gt-ipa-prop.h"
index 8f7eb088813dfb0c78cf26d12c10df7117938d39..74234eb470debe001fb83195aec5a873ce73ff67 100644 (file)
@@ -152,11 +152,10 @@ struct GTY(()) ipa_bits
      Similar to ccp_lattice_t, if xth bit of mask is 0,
      implies xth bit of value is constant.  */
   widest_int mask;
-  /* True if jump function is known.  */
-  bool known;
 };
 
 /* Info about value ranges.  */
+
 struct GTY(()) ipa_vr
 {
   /* The data fields below are valid only if known is true.  */
@@ -175,13 +174,15 @@ struct GTY (()) ipa_jump_func
      description.  */
   struct ipa_agg_jump_function agg;
 
-  /* Information about zero/non-zero bits.  */
-  struct ipa_bits bits;
+  /* Information about zero/non-zero bits.  The pointed to structure is shared
+     betweed different jump functions.  Use ipa_set_jfunc_bits to set this
+     field.  */
+  struct ipa_bits *bits;
 
   /* Information about value range, containing valid data only when vr_known is
-     true.  */
-  value_range m_vr;
-  bool vr_known;
+     true.  The pointed to structure is shared betweed different jump
+     functions.  Use ipa_set_jfunc_vr to set this field.  */
+  struct value_range *m_vr;
 
   enum jump_func_type type;
   /* Represents a value of a jump function.  pass_through is used only in jump
@@ -547,7 +548,7 @@ struct GTY(()) ipcp_transformation_summary
   /* Linked list of known aggregate values.  */
   ipa_agg_replacement_value *agg_values;
   /* Known bits information.  */
-  vec<ipa_bits, va_gc> *bits;
+  vec<ipa_bits *, va_gc> *bits;
   /* Value range information.  */
   vec<ipa_vr, va_gc> *m_vr;
 };
@@ -630,6 +631,7 @@ extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
 /* Creating and freeing ipa_node_params and ipa_edge_args.  */
 void ipa_create_all_node_params (void);
 void ipa_create_all_edge_args (void);
+void ipa_check_create_edge_args (void);
 void ipa_free_edge_args_substructures (struct ipa_edge_args *);
 void ipa_free_all_node_params (void);
 void ipa_free_all_edge_args (void);
@@ -651,17 +653,6 @@ ipa_check_create_node_params (void)
         ipa_node_params_t (symtab, true));
 }
 
-/* This function ensures the array of edge arguments infos is big enough to
-   accommodate a structure for all edges and reallocates it if not.  */
-
-static inline void
-ipa_check_create_edge_args (void)
-{
-  if (vec_safe_length (ipa_edge_args_vector)
-      <= (unsigned) symtab->edges_max_uid)
-    vec_safe_grow_cleared (ipa_edge_args_vector, symtab->edges_max_uid + 1);
-}
-
 /* Returns true if the array of edge infos is large enough to accommodate an
    info for EDGE.  The main purpose of this function is that debug dumping
    function can check info availability without causing reallocations.  */
@@ -703,6 +694,9 @@ tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
 struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
                                                    bool speculative = false);
 tree ipa_impossible_devirt_target (struct cgraph_edge *, tree);
+ipa_bits *ipa_get_ipa_bits_for_value (const widest_int &value,
+                                     const widest_int &mask);
+
 
 /* Functions related to both.  */
 void ipa_analyze_node (struct cgraph_node *);
index 4fed978d0aa204579e20bad01faf687e1955b6db..ef2c68a752beccaca91f58b0667060ad3df72c04 100644 (file)
@@ -24,7 +24,7 @@ enum value_range_type { VR_UNDEFINED, VR_RANGE,
 
 /* Range of values that can be associated with an SSA_NAME after VRP
    has executed.  */
-struct GTY(()) value_range
+struct GTY((for_user)) value_range
 {
   /* Lattice value represented by this range.  */
   enum value_range_type type;