]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ipa-prop.h
Update copyright years.
[thirdparty/gcc.git] / gcc / ipa-prop.h
index 103594dcdc27ccdc41d10793169393ace54dbb9e..6aad0c4a147904e7df9e3a3f4954a543e51b45b7 100644 (file)
@@ -1,5 +1,5 @@
 /* Interprocedural analyses.
-   Copyright (C) 2005-2015 Free Software Foundation, Inc.
+   Copyright (C) 2005-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -39,6 +39,15 @@ along with GCC; see the file COPYING3.  If not see
                   argument.
    Unknown      - neither of the above.
 
+   IPA_JF_LOAD_AGG is a compound pass-through jump function, in which primary
+   operation on formal parameter is memory dereference that loads a value from
+   a part of an aggregate, which is represented or pointed to by the formal
+   parameter.  Moreover, an additional unary/binary operation can be applied on
+   the loaded value, and final result is passed as actual argument of callee
+   (e.g. *(param_1(D) + 4) op 24 ).  It is meant to describe usage of aggregate
+   parameter or by-reference parameter referenced in argument passing, commonly
+   found in C++ and Fortran.
+
    IPA_JF_ANCESTOR is a special pass-through jump function, which means that
    the result is an address of a part of the object pointed to by the formal
    parameter to which the function refers.  It is mainly intended to represent
@@ -60,6 +69,7 @@ enum jump_func_type
   IPA_JF_UNKNOWN = 0,  /* newly allocated and zeroed jump functions default */
   IPA_JF_CONST,             /* represented by field costant */
   IPA_JF_PASS_THROUGH,     /* represented by field pass_through */
+  IPA_JF_LOAD_AGG,         /* represented by field load_agg */
   IPA_JF_ANCESTOR          /* represented by field ancestor */
 };
 
@@ -97,6 +107,26 @@ struct GTY(()) ipa_pass_through_data
   unsigned agg_preserved : 1;
 };
 
+/* Structure holding data required to describe a load-value-from-aggregate
+   jump function.  */
+
+struct GTY(()) ipa_load_agg_data
+{
+  /* Inherit from pass through jump function, describing unary/binary
+     operation on the value loaded from aggregate that is represented or
+     pointed to by the formal parameter, specified by formal_id in this
+     pass_through jump function data structure.  */
+  struct ipa_pass_through_data pass_through;
+  /* Type of the value loaded from the aggregate.  */
+  tree type;
+  /* Offset at which the value is located within the aggregate.  */
+  HOST_WIDE_INT offset;
+  /* True if loaded by reference (the aggregate is pointed to by the formal
+     parameter) or false if loaded by value (the aggregate is represented
+     by the formal parameter).  */
+  bool by_ref;
+};
+
 /* Structure holding data required to describe an ancestor pass-through
    jump function.  */
 
@@ -110,48 +140,165 @@ struct GTY(()) ipa_ancestor_jf_data
   unsigned agg_preserved : 1;
 };
 
-/* An element in an aggegate part of a jump function describing a known value
-   at a given offset.  When it is part of a pass-through jump function with
-   agg_preserved set or an ancestor jump function with agg_preserved set, all
-   unlisted positions are assumed to be preserved but the value can be a type
-   node, which means that the particular piece (starting at offset and having
-   the size of the type) is clobbered with an unknown value.  When
-   agg_preserved is false or the type of the containing jump function is
-   different, all unlisted parts are assumed to be unknown and all values must
-   fulfill is_gimple_ip_invariant.  */
+/* A jump function for an aggregate part at a given offset, which describes how
+   it content value is generated.  All unlisted positions are assumed to have a
+   value defined in an unknown way.  */
 
 struct GTY(()) ipa_agg_jf_item
 {
-  /* The offset at which the known value is located within the aggregate.  */
+  /* The offset for the aggregate part.  */
   HOST_WIDE_INT offset;
 
-  /* The known constant or type if this is a clobber.  */
-  tree value;
-};
+  /* Data type of the aggregate part.  */
+  tree type;
+
+  /* Jump function type.  */
+  enum jump_func_type jftype;
 
+  /* Represents a value of jump function. constant represents the actual constant
+     in constant jump function content.  pass_through is used only in simple pass
+     through jump function context.  load_agg is for load-value-from-aggregate
+     jump function context.  */
+  union jump_func_agg_value
+  {
+    tree GTY ((tag ("IPA_JF_CONST"))) constant;
+    struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;
+    struct ipa_load_agg_data GTY ((tag ("IPA_JF_LOAD_AGG"))) load_agg;
+  } GTY ((desc ("%1.jftype"))) value;
+};
 
-/* Aggregate jump function - i.e. description of contents of aggregates passed
-   either by reference or value.  */
+/* Jump functions describing a set of aggregate contents.  */
 
 struct GTY(()) ipa_agg_jump_function
 {
-  /* Description of the individual items.  */
+  /* Description of the individual jump function item.  */
   vec<ipa_agg_jf_item, va_gc> *items;
-  /* True if the data was passed by reference (as opposed to by value). */
+  /* True if the data was passed by reference (as opposed to by value).  */
   bool by_ref;
 };
 
-typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p;
+/* An element in an aggregate part describing a known value at a given offset.
+   All unlisted positions are assumed to be unknown and all listed values must
+   fulfill is_gimple_ip_invariant.  */
+
+struct ipa_agg_value
+{
+  /* The offset at which the known value is located within the aggregate.  */
+  HOST_WIDE_INT offset;
+
+  /* The known constant.  */
+  tree value;
+
+  /* Return true if OTHER describes same agg value.  */
+  bool equal_to (const ipa_agg_value &other);
+};
+
+/* Structure describing a set of known offset/value for aggregate.  */
 
-/* Info about pointer alignments. */
-struct GTY(()) ipa_alignment
+struct ipa_agg_value_set
 {
+  /* Description of the individual item.  */
+  vec<ipa_agg_value> items;
+  /* True if the data was passed by reference (as opposed to by value).  */
+  bool by_ref;
+
+  /* Return true if OTHER describes same agg values.  */
+  bool equal_to (const ipa_agg_value_set &other)
+  {
+    if (by_ref != other.by_ref)
+      return false;
+    if (items.length () != other.items.length ())
+      return false;
+    for (unsigned int i = 0; i < items.length (); i++)
+      if (!items[i].equal_to (other.items[i]))
+       return false;
+    return true;
+  }
+
+  /* Return true if there is any value for aggregate.  */
+  bool is_empty () const
+  {
+    return items.is_empty ();
+  }
+
+  ipa_agg_value_set copy () const
+  {
+    ipa_agg_value_set new_copy;
+
+    new_copy.items = items.copy ();
+    new_copy.by_ref = by_ref;
+
+    return new_copy;
+  }
+
+  void release ()
+  {
+    items.release ();
+  }
+};
+
+/* Return copy of a vec<ipa_agg_value_set>.  */
+
+static inline vec<ipa_agg_value_set>
+ipa_copy_agg_values (const vec<ipa_agg_value_set> &aggs)
+{
+  vec<ipa_agg_value_set> aggs_copy = vNULL;
+
+  if (!aggs.is_empty ())
+    {
+      ipa_agg_value_set *agg;
+      int i;
+
+      aggs_copy.reserve_exact (aggs.length ());
+
+      FOR_EACH_VEC_ELT (aggs, i, agg)
+       aggs_copy.quick_push (agg->copy ());
+    }
+
+  return aggs_copy;
+}
+
+/* For vec<ipa_agg_value_set>, DO NOT call release(), use below function
+   instead.  Because ipa_agg_value_set contains a field of vector type, we
+   should release this child vector in each element before reclaiming the
+   whole vector.  */
+
+static inline void
+ipa_release_agg_values (vec<ipa_agg_value_set> &aggs,
+                       bool release_vector = true)
+{
+  ipa_agg_value_set *agg;
+  int i;
+
+  FOR_EACH_VEC_ELT (aggs, i, agg)
+    agg->release ();
+  if (release_vector)
+    aggs.release ();
+}
+
+/* Information about zero/non-zero bits.  */
+class GTY(()) ipa_bits
+{
+public:
+  /* The propagated value.  */
+  widest_int value;
+  /* Mask corresponding to the value.
+     Similar to ccp_lattice_t, if xth bit of mask is 0,
+     implies xth bit of value is constant.  */
+  widest_int mask;
+};
+
+/* Info about value ranges.  */
+
+class GTY(()) ipa_vr
+{
+public:
   /* The data fields below are valid only if known is true.  */
   bool known;
-  /* See ptr_info_def and get_pointer_alignment_1 for description of these
-     two.  */
-  unsigned align;
-  unsigned misalign;
+  enum value_range_kind type;
+  wide_int min;
+  wide_int max;
+  bool nonzero_p (tree) const;
 };
 
 /* A jump function for a callsite represents the values passed as actual
@@ -159,12 +306,19 @@ struct GTY(()) ipa_alignment
    types of jump functions supported.  */
 struct GTY (()) ipa_jump_func
 {
-  /* Aggregate contants description.  See struct ipa_agg_jump_function and its
-     description.  */
+  /* Aggregate jump function description.  See struct ipa_agg_jump_function
+     and its description.  */
   struct ipa_agg_jump_function agg;
 
-  /* Information about alignment of pointers. */
-  struct ipa_alignment alignment;
+  /* 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.  */
+  class ipa_bits *bits;
+
+  /* Information about value range, containing valid data only when vr_known is
+     true.  The pointed to structure is shared betweed different jump
+     functions.  Use ipa_set_jfunc_vr to set this field.  */
+  class value_range *m_vr;
 
   enum jump_func_type type;
   /* Represents a value of a jump function.  pass_through is used only in jump
@@ -281,42 +435,53 @@ ipa_get_jf_ancestor_type_preserved (struct ipa_jump_func *jfunc)
 
 /* Summary describing a single formal parameter.  */
 
-struct ipa_param_descriptor
+struct GTY(()) ipa_param_descriptor
 {
-  /* PARAM_DECL of this parameter.  */
-  tree decl;
+  /* In analysis and modification phase, this is the PARAM_DECL of this
+     parameter, in IPA LTO phase, this is the type of the the described
+     parameter or NULL if not known.  Do not read this field directly but
+     through ipa_get_param and ipa_get_type as appropriate.  */
+  tree decl_or_type;
   /* If all uses of the parameter are described by ipa-prop structures, this
      says how many there are.  If any use could not be described by means of
      ipa-prop structures, this is IPA_UNDESCRIBED_USE.  */
   int controlled_uses;
-  unsigned int move_cost : 31;
+  unsigned int move_cost : 28;
   /* The parameter is used.  */
   unsigned used : 1;
+  unsigned used_by_ipa_predicates : 1;
+  unsigned used_by_indirect_call : 1;
+  unsigned used_by_polymorphic_call : 1;
 };
 
 /* ipa_node_params stores information related to formal parameters of functions
    and some other information for interprocedural passes that operate on
    parameters (such as ipa-cp).  */
 
-struct ipa_node_params
+class GTY((for_user)) ipa_node_params
 {
+public:
+  /* Default constructor.  */
+  ipa_node_params ();
+
+  /* Default destructor.  */
   ~ipa_node_params ();
 
   /* Information about individual formal parameters that are gathered when
      summaries are generated. */
-  vec<ipa_param_descriptordescriptors;
+  vec<ipa_param_descriptor, va_gc> *descriptors;
   /* Pointer to an array of structures describing individual formal
      parameters.  */
-  struct ipcp_param_lattices *lattices;
+  class ipcp_param_lattices * GTY((skip)) lattices;
   /* Only for versioned nodes this field would not be NULL,
      it points to the node that IPA cp cloned from.  */
-  struct cgraph_node *ipcp_orig_node;
+  struct cgraph_node * GTY((skip)) ipcp_orig_node;
   /* If this node is an ipa-cp clone, these are the known constants that
      describe what it has been specialized for.  */
-  vec<tree> known_csts;
+  vec<tree> GTY((skip)) known_csts;
   /* If this node is an ipa-cp clone, these are the known polymorphic contexts
      that describe what it has been specialized for.  */
-  vec<ipa_polymorphic_call_context> known_contexts;
+  vec<ipa_polymorphic_call_context> GTY((skip)) known_contexts;
   /* Whether the param uses analysis and jump function computation has already
      been performed.  */
   unsigned analysis_done : 1;
@@ -332,10 +497,32 @@ struct ipa_node_params
   unsigned node_dead : 1;
   /* Node is involved in a recursion, potentionally indirect.  */
   unsigned node_within_scc : 1;
+  /* Node contains only direct recursion.  */
+  unsigned node_is_self_scc : 1;
   /* Node is calling a private function called only once.  */
   unsigned node_calling_single_call : 1;
+  /* False when there is something makes versioning impossible.  */
+  unsigned versionable : 1;
 };
 
+inline
+ipa_node_params::ipa_node_params ()
+: descriptors (NULL), lattices (NULL), ipcp_orig_node (NULL),
+  known_csts (vNULL), known_contexts (vNULL), analysis_done (0),
+  node_enqueued (0), do_clone_for_all_contexts (0), is_all_contexts_clone (0),
+  node_dead (0), node_within_scc (0), node_calling_single_call (0),
+  versionable (0)
+{
+}
+
+inline
+ipa_node_params::~ipa_node_params ()
+{
+  free (lattices);
+  known_csts.release ();
+  known_contexts.release ();
+}
+
 /* Intermediate information that we get from alias analysis about a particular
    parameter in a particular basic_block.  When a parameter or the memory it
    references is marked modified, we use that information in all dominated
@@ -375,7 +562,7 @@ struct ipa_func_body_info
   cgraph_node *node;
 
   /* Its info.  */
-  struct ipa_node_params *info;
+  class ipa_node_params *info;
 
   /* Information about individual BBs. */
   vec<ipa_bb_info> bb_infos;
@@ -383,8 +570,9 @@ struct ipa_func_body_info
   /* Number of parameters.  */
   int param_count;
 
-  /* Number of statements already walked by when analyzing this function.  */
-  unsigned int aa_walked;
+  /* Number of statements we are still allowed to walked by when analyzing this
+     function.  */
+  unsigned int aa_walk_budget;
 };
 
 /* ipa_node_params access functions.  Please use these to access fields that
@@ -393,67 +581,151 @@ struct ipa_func_body_info
 /* Return the number of formal parameters. */
 
 static inline int
-ipa_get_param_count (struct ipa_node_params *info)
+ipa_get_param_count (class ipa_node_params *info)
 {
-  return info->descriptors.length ();
+  return vec_safe_length (info->descriptors);
 }
 
 /* Return the declaration of Ith formal parameter of the function corresponding
    to INFO.  Note there is no setter function as this array is built just once
-   using ipa_initialize_node_params. */
+   using ipa_initialize_node_params.  This function should not be called in
+   WPA.  */
 
 static inline tree
-ipa_get_param (struct ipa_node_params *info, int i)
+ipa_get_param (class ipa_node_params *info, int i)
 {
-  gcc_checking_assert (!flag_wpa);
-  return info->descriptors[i].decl;
+  gcc_checking_assert (info->descriptors);
+  tree t = (*info->descriptors)[i].decl_or_type;
+  gcc_checking_assert (TREE_CODE (t) == PARM_DECL);
+  return t;
+}
+
+/* Return the type of Ith formal parameter of the function corresponding
+   to INFO if it is known or NULL if not.  */
+
+static inline tree
+ipa_get_type (class ipa_node_params *info, int i)
+{
+  if (vec_safe_length (info->descriptors) <= (unsigned) i)
+    return NULL;
+  tree t = (*info->descriptors)[i].decl_or_type;
+  if (!t)
+    return NULL;
+  if (TYPE_P (t))
+    return t;
+  gcc_checking_assert (TREE_CODE (t) == PARM_DECL);
+  return TREE_TYPE (t);
 }
 
 /* Return the move cost of Ith formal parameter of the function corresponding
    to INFO.  */
 
 static inline int
-ipa_get_param_move_cost (struct ipa_node_params *info, int i)
+ipa_get_param_move_cost (class ipa_node_params *info, int i)
 {
-  return info->descriptors[i].move_cost;
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].move_cost;
 }
 
 /* Set the used flag corresponding to the Ith formal parameter of the function
    associated with INFO to VAL.  */
 
 static inline void
-ipa_set_param_used (struct ipa_node_params *info, int i, bool val)
+ipa_set_param_used (class ipa_node_params *info, int i, bool val)
 {
-  info->descriptors[i].used = val;
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used = val;
+}
+
+/* Set the used_by_ipa_predicates flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_ipa_predicates (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_ipa_predicates = val;
+}
+
+/* Set the used_by_indirect_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_indirect_call (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_indirect_call = val;
+}
+
+/* Set the .used_by_polymorphic_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO to VAL.  */
+
+static inline void
+ipa_set_param_used_by_polymorphic_call (class ipa_node_params *info, int i, bool val)
+{
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].used_by_polymorphic_call = val;
 }
 
 /* Return how many uses described by ipa-prop a parameter has or
    IPA_UNDESCRIBED_USE if there is a use that is not described by these
    structures.  */
 static inline int
-ipa_get_controlled_uses (struct ipa_node_params *info, int i)
+ipa_get_controlled_uses (class ipa_node_params *info, int i)
 {
-  /* FIXME: introducing speuclation causes out of bounds access here.  */
-  if (info->descriptors.length () > (unsigned)i)
-    return info->descriptors[i].controlled_uses;
+  /* FIXME: introducing speculation causes out of bounds access here.  */
+  if (vec_safe_length (info->descriptors) > (unsigned)i)
+    return (*info->descriptors)[i].controlled_uses;
   return IPA_UNDESCRIBED_USE;
 }
 
 /* Set the controlled counter of a given parameter.  */
 
 static inline void
-ipa_set_controlled_uses (struct ipa_node_params *info, int i, int val)
+ipa_set_controlled_uses (class ipa_node_params *info, int i, int val)
 {
-  info->descriptors[i].controlled_uses = val;
+  gcc_checking_assert (info->descriptors);
+  (*info->descriptors)[i].controlled_uses = val;
 }
 
 /* Return the used flag corresponding to the Ith formal parameter of the
    function associated with INFO.  */
 
 static inline bool
-ipa_is_param_used (struct ipa_node_params *info, int i)
+ipa_is_param_used (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used;
+}
+
+/* Return the used_by_ipa_predicates flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_ipa_predicates (class ipa_node_params *info, int i)
 {
-  return info->descriptors[i].used;
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_ipa_predicates;
+}
+
+/* Return the used_by_indirect_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_indirect_call (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_indirect_call;
+}
+
+/* Return the used_by_polymorphic_call flag corresponding to the Ith formal
+   parameter of the function associated with INFO.  */
+
+static inline bool
+ipa_is_param_used_by_polymorphic_call (class ipa_node_params *info, int i)
+{
+  gcc_checking_assert (info->descriptors);
+  return (*info->descriptors)[i].used_by_polymorphic_call;
 }
 
 /* Information about replacements done in aggregates for a given node (each
@@ -474,23 +746,60 @@ struct GTY(()) ipa_agg_replacement_value
 
 /* Structure holding information for the transformation phase of IPA-CP.  */
 
-struct GTY(()) ipcp_transformation_summary
+struct GTY(()) ipcp_transformation
 {
   /* Linked list of known aggregate values.  */
   ipa_agg_replacement_value *agg_values;
-  /* Alignment information for pointers.  */
-  vec<ipa_alignment, va_gc> *alignments;
+  /* Known bits information.  */
+  vec<ipa_bits *, va_gc> *bits;
+  /* Value range information.  */
+  vec<ipa_vr, va_gc> *m_vr;
+
+  /* Default constructor.  */
+  ipcp_transformation ()
+  : agg_values (NULL), bits (NULL), m_vr (NULL)
+  { }
+
+  /* Default destructor.  */
+  ~ipcp_transformation ()
+  {
+    ipa_agg_replacement_value *agg = agg_values;
+    while (agg)
+      {
+       ipa_agg_replacement_value *next = agg->next;
+       ggc_free (agg);
+       agg = next;
+      }
+    vec_free (bits);
+    vec_free (m_vr);
+  }
 };
 
 void ipa_set_node_agg_value_chain (struct cgraph_node *node,
                                   struct ipa_agg_replacement_value *aggvals);
-void ipcp_grow_transformations_if_necessary (void);
+void ipcp_transformation_initialize (void);
+void ipcp_free_transformation_sum (void);
 
 /* ipa_edge_args stores information related to a callsite and particularly its
    arguments.  It can be accessed by the IPA_EDGE_REF macro.  */
-struct GTY(()) ipa_edge_args
+
+class GTY((for_user)) ipa_edge_args
 {
-  /* Vector of the callsite's jump function of each parameter.  */
+ public:
+
+  /* Default constructor.  */
+  ipa_edge_args () : jump_functions (NULL), polymorphic_call_contexts (NULL)
+    {}
+
+  /* Destructor.  */
+  ~ipa_edge_args ()
+    {
+      vec_free (jump_functions);
+      vec_free (polymorphic_call_contexts);
+    }
+
+  /* Vectors of the callsite's jump function and polymorphic context
+     information of each parameter.  */
   vec<ipa_jump_func, va_gc> *jump_functions;
   vec<ipa_polymorphic_call_context, va_gc> *polymorphic_call_contexts;
 };
@@ -501,7 +810,7 @@ struct GTY(()) ipa_edge_args
 /* Return the number of actual arguments. */
 
 static inline int
-ipa_get_cs_argument_count (struct ipa_edge_args *args)
+ipa_get_cs_argument_count (class ipa_edge_args *args)
 {
   return vec_safe_length (args->jump_functions);
 }
@@ -511,15 +820,15 @@ ipa_get_cs_argument_count (struct ipa_edge_args *args)
    ipa_compute_jump_functions. */
 
 static inline struct ipa_jump_func *
-ipa_get_ith_jump_func (struct ipa_edge_args *args, int i)
+ipa_get_ith_jump_func (class ipa_edge_args *args, int i)
 {
   return &(*args->jump_functions)[i];
 }
 
 /* Returns a pointer to the polymorphic call context for the ith argument.
    NULL if contexts are not computed.  */
-static inline struct ipa_polymorphic_call_context *
-ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i)
+static inline class ipa_polymorphic_call_context *
+ipa_get_ith_polymorhic_call_context (class ipa_edge_args *args, int i)
 {
   if (!args->polymorphic_call_contexts)
     return NULL;
@@ -527,11 +836,11 @@ ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i)
 }
 
 /* Function summary for ipa_node_params.  */
-class ipa_node_params_t: public function_summary <ipa_node_params *>
+class GTY((user)) ipa_node_params_t: public function_summary <ipa_node_params *>
 {
 public:
-  ipa_node_params_t (symbol_table *table):
-    function_summary<ipa_node_params *> (table) { }
+  ipa_node_params_t (symbol_table *table, bool ggc):
+    function_summary<ipa_node_params *> (table, ggc) { }
 
   /* Hook that is called by summary when a node is duplicated.  */
   virtual void duplicate (cgraph_node *node,
@@ -540,17 +849,66 @@ public:
                          ipa_node_params *data2);
 };
 
+/* Summary to manange ipa_edge_args structures.  */
+
+class GTY((user)) ipa_edge_args_sum_t : public call_summary <ipa_edge_args *>
+{
+ public:
+  ipa_edge_args_sum_t (symbol_table *table, bool ggc)
+    : call_summary<ipa_edge_args *> (table, ggc) { }
+
+  void remove (cgraph_edge *edge)
+  {
+    call_summary <ipa_edge_args *>::remove (edge);
+  }
+
+  /* Hook that is called by summary when an edge is removed.  */
+  virtual void remove (cgraph_edge *cs, ipa_edge_args *args);
+  /* Hook that is called by summary when an edge is duplicated.  */
+  virtual void duplicate (cgraph_edge *src,
+                         cgraph_edge *dst,
+                         ipa_edge_args *old_args,
+                         ipa_edge_args *new_args);
+};
+
 /* Function summary where the parameter infos are actually stored. */
-extern ipa_node_params_t *ipa_node_params_sum;
-/* Vector of IPA-CP transformation data for each clone.  */
-extern GTY(()) vec<ipcp_transformation_summary, va_gc> *ipcp_transformations;
-/* Vector where the parameter infos are actually stored. */
-extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
+extern GTY(()) ipa_node_params_t * ipa_node_params_sum;
+/* Call summary to store information about edges such as jump functions.  */
+extern GTY(()) ipa_edge_args_sum_t *ipa_edge_args_sum;
+
+/* Function summary for IPA-CP transformation.  */
+class ipcp_transformation_t
+: public function_summary<ipcp_transformation *>
+{
+public:
+  ipcp_transformation_t (symbol_table *table, bool ggc):
+    function_summary<ipcp_transformation *> (table, ggc) {}
+
+  ~ipcp_transformation_t () {}
+
+  static ipcp_transformation_t *create_ggc (symbol_table *symtab)
+  {
+    ipcp_transformation_t *summary
+      = new (ggc_alloc_no_dtor <ipcp_transformation_t> ())
+      ipcp_transformation_t (symtab, true);
+    return summary;
+  }
+  /* Hook that is called by summary when a node is duplicated.  */
+  virtual void duplicate (cgraph_node *node,
+                         cgraph_node *node2,
+                         ipcp_transformation *data,
+                         ipcp_transformation *data2);
+};
+
+/* Function summary where the IPA CP transformations are actually stored.  */
+extern GTY(()) function_summary <ipcp_transformation *> *ipcp_transformation_sum;
 
 /* Return the associated parameter/argument info corresponding to the given
    node/edge.  */
 #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE))
-#define IPA_EDGE_REF(EDGE) (&(*ipa_edge_args_vector)[(EDGE)->uid])
+#define IPA_NODE_REF_GET_CREATE(NODE) (ipa_node_params_sum->get_create (NODE))
+#define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE))
+#define IPA_EDGE_REF_GET_CREATE(EDGE) (ipa_edge_args_sum->get_create (EDGE))
 /* This macro checks validity of index returned by
    ipa_get_param_decl_index function.  */
 #define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1)
@@ -558,7 +916,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_free_edge_args_substructures (struct ipa_edge_args *);
+void ipa_check_create_edge_args (void);
 void ipa_free_all_node_params (void);
 void ipa_free_all_edge_args (void);
 void ipa_free_all_structures_after_ipa_cp (void);
@@ -574,36 +932,28 @@ static inline void
 ipa_check_create_node_params (void)
 {
   if (!ipa_node_params_sum)
-    ipa_node_params_sum = new ipa_node_params_t (symtab);
-}
-
-/* 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);
+    ipa_node_params_sum
+      = (new (ggc_alloc_no_dtor <ipa_node_params_t> ())
+        ipa_node_params_t (symtab, true));
 }
 
-/* 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.  */
+/* Returns true if edge summary contains a record for EDGE.  The main purpose
+   of this function is that debug dumping function can check info availability
+   without causing allocations.  */
 
 static inline bool
 ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge)
 {
-  return ((unsigned) edge->uid < vec_safe_length (ipa_edge_args_vector));
+  return ipa_edge_args_sum->exists (edge);
 }
 
-static inline ipcp_transformation_summary *
+static inline ipcp_transformation *
 ipcp_get_transformation_summary (cgraph_node *node)
 {
-  if ((unsigned) node->uid >= vec_safe_length (ipcp_transformations))
+  if (ipcp_transformation_sum == NULL)
     return NULL;
-  return &(*ipcp_transformations)[node->uid];
+
+  return ipcp_transformation_sum->get (node);
 }
 
 /* Return the aggregate replacements for NODE, if there are any.  */
@@ -611,7 +961,7 @@ ipcp_get_transformation_summary (cgraph_node *node)
 static inline struct ipa_agg_replacement_value *
 ipa_get_agg_replacements_for_node (cgraph_node *node)
 {
-  ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node);
+  ipcp_transformation *ts = ipcp_get_transformation_summary (node);
   return ts ? ts->agg_values : NULL;
 }
 
@@ -622,23 +972,29 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 
 /* Indirect edge and binfo processing.  */
 tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
-                                  vec<tree> ,
+                                  vec<tree>,
                                   vec<ipa_polymorphic_call_context>,
-                                  vec<ipa_agg_jump_function_p>,
+                                  vec<ipa_agg_value_set>,
                                   bool *);
 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 *);
 
 /* Aggregate jump function related functions.  */
-tree ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *, HOST_WIDE_INT,
-                                bool);
-bool ipa_load_from_parm_agg (struct ipa_func_body_info *,
-                            vec<ipa_param_descriptor>, gimple, tree, int *,
-                            HOST_WIDE_INT *, HOST_WIDE_INT *, bool *);
+tree ipa_find_agg_cst_for_param (struct ipa_agg_value_set *agg, tree scalar,
+                                HOST_WIDE_INT offset, bool by_ref,
+                                bool *from_global_constant = NULL);
+bool ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
+                            vec<ipa_param_descriptor, va_gc> *descriptors,
+                            gimple *stmt, tree op, int *index_p,
+                            HOST_WIDE_INT *offset_p, poly_int64 *size_p,
+                            bool *by_ref, bool *guaranteed_unmodified = NULL);
 
 /* Debugging interface.  */
 void ipa_print_node_params (FILE *, struct cgraph_node *node);
@@ -655,124 +1011,40 @@ extern object_allocator<ipcp_value<ipa_polymorphic_call_context> >
   ipcp_poly_ctx_values_pool;
 
 template <typename valtype>
-class ipcp_value_source;
+struct ipcp_value_source;
 
 extern object_allocator<ipcp_value_source<tree> > ipcp_sources_pool;
 
-class ipcp_agg_lattice;
+struct ipcp_agg_lattice;
 
 extern object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool;
 
-/* Operation to be performed for the parameter in ipa_parm_adjustment
-   below.  */
-enum ipa_parm_op {
-  IPA_PARM_OP_NONE,
-
-  /* This describes a brand new parameter.
-
-     The field `type' should be set to the new type, `arg_prefix'
-     should be set to the string prefix for the new DECL_NAME, and
-     `new_decl' will ultimately hold the newly created argument.  */
-  IPA_PARM_OP_NEW,
-
-  /* This new parameter is an unmodified parameter at index base_index. */
-  IPA_PARM_OP_COPY,
-
-  /* This adjustment describes a parameter that is about to be removed
-     completely.  Most users will probably need to book keep those so that they
-     don't leave behinfd any non default def ssa names belonging to them.  */
-  IPA_PARM_OP_REMOVE
-};
-
-/* Structure to describe transformations of formal parameters and actual
-   arguments.  Each instance describes one new parameter and they are meant to
-   be stored in a vector.  Additionally, most users will probably want to store
-   adjustments about parameters that are being removed altogether so that SSA
-   names belonging to them can be replaced by SSA names of an artificial
-   variable.  */
-struct ipa_parm_adjustment
-{
-  /* The original PARM_DECL itself, helpful for processing of the body of the
-     function itself.  Intended for traversing function bodies.
-     ipa_modify_formal_parameters, ipa_modify_call_arguments and
-     ipa_combine_adjustments ignore this and use base_index.
-     ipa_modify_formal_parameters actually sets this.  */
-  tree base;
-
-  /* Type of the new parameter.  However, if by_ref is true, the real type will
-     be a pointer to this type.  */
-  tree type;
-
-  /* Alias refrerence type to be used in MEM_REFs when adjusting caller
-     arguments.  */
-  tree alias_ptr_type;
-
-  /* The new declaration when creating/replacing a parameter.  Created
-     by ipa_modify_formal_parameters, useful for functions modifying
-     the body accordingly.  For brand new arguments, this is the newly
-     created argument.  */
-  tree new_decl;
-
-  /* New declaration of a substitute variable that we may use to replace all
-     non-default-def ssa names when a parm decl is going away.  */
-  tree new_ssa_base;
-
-  /* If non-NULL and the original parameter is to be removed (copy_param below
-     is NULL), this is going to be its nonlocalized vars value.  */
-  tree nonlocal_value;
-
-  /* This holds the prefix to be used for the new DECL_NAME.  */
-  const char *arg_prefix;
-
-  /* Offset into the original parameter (for the cases when the new parameter
-     is a component of an original one).  */
-  HOST_WIDE_INT offset;
-
-  /* Zero based index of the original parameter this one is based on.  */
-  int base_index;
-
-  /* Whether this parameter is a new parameter, a copy of an old one,
-     or one about to be removed.  */
-  enum ipa_parm_op op;
-
-  /* The parameter is to be passed by reference.  */
-  unsigned by_ref : 1;
-};
-
-typedef vec<ipa_parm_adjustment> ipa_parm_adjustment_vec;
-
-vec<tree> ipa_get_vector_of_formal_parms (tree fndecl);
-vec<tree> ipa_get_vector_of_formal_parm_types (tree fntype);
-void ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec);
-void ipa_modify_call_arguments (struct cgraph_edge *, gcall *,
-                               ipa_parm_adjustment_vec);
-ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec,
-                                                ipa_parm_adjustment_vec);
-void ipa_dump_param_adjustments (FILE *, ipa_parm_adjustment_vec, tree);
 void ipa_dump_agg_replacement_values (FILE *f,
                                      struct ipa_agg_replacement_value *av);
 void ipa_prop_write_jump_functions (void);
 void ipa_prop_read_jump_functions (void);
 void ipcp_write_transformation_summaries (void);
 void ipcp_read_transformation_summaries (void);
-void ipa_update_after_lto_read (void);
-int ipa_get_param_decl_index (struct ipa_node_params *, tree);
-tree ipa_value_from_jfunc (struct ipa_node_params *info,
-                          struct ipa_jump_func *jfunc);
+int ipa_get_param_decl_index (class ipa_node_params *, tree);
+tree ipa_value_from_jfunc (class ipa_node_params *info,
+                          struct ipa_jump_func *jfunc, tree type);
 unsigned int ipcp_transform_function (struct cgraph_node *node);
 ipa_polymorphic_call_context ipa_context_from_jfunc (ipa_node_params *,
                                                     cgraph_edge *,
                                                     int,
                                                     ipa_jump_func *);
-void ipa_dump_param (FILE *, struct ipa_node_params *info, int i);
-bool ipa_modify_expr (tree *, bool, ipa_parm_adjustment_vec);
-ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
-                                                  ipa_parm_adjustment_vec,
-                                                  bool);
-
+value_range ipa_value_range_from_jfunc (ipa_node_params *, cgraph_edge *,
+                                       ipa_jump_func *, tree);
+ipa_agg_value_set ipa_agg_value_set_from_jfunc (ipa_node_params *,
+                                               cgraph_node *,
+                                               ipa_agg_jump_function *);
+void ipa_dump_param (FILE *, class ipa_node_params *info, int i);
+void ipa_release_body_info (struct ipa_func_body_info *);
+tree ipa_get_callee_param_type (struct cgraph_edge *e, int i);
+bool ipcp_get_parm_bits (tree, tree *, widest_int *);
 
 /* From tree-sra.c:  */
-tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree,
+tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree,
                           gimple_stmt_iterator *, bool);
 
 /* In ipa-cp.c  */