diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index 63d0c3dc36d..e5407d32fbb 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -42,6 +42,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "value-prof.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "ipa-inline.h"
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 0ac8f73204b..473d8410bc9 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -51,6 +51,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "cfgloop.h"
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 6d7bc402a29..4fff6873a36 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -84,6 +84,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "alloc-pool.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "symtab-thunks.h"
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 5c405258ec3..d200166f7e9 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -191,6 +191,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "gimple-pretty-print.h"
 #include "plugin.h"
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 32eae49d4e9..29c899157e1 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -91,6 +91,8 @@
 #include "tree-pass.h"
 #include "cfgbuild.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "hash-map.h"
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index d5b83e9d90f..8b79d335c88 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "ifcvt.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 50f9fe2c0d7..a4d3369f01b 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "ifcvt.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index f1b1cf24233..d3b9ae81025 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "ifcvt.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 8f5ce817630..93a01146db7 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "ifcvt.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index dbb26e8f76a..53db72e95f9 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -86,6 +86,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "intl.h"
 #include "ifcvt.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 5d975dab921..a2a679d8eed 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -72,6 +72,8 @@
 #include "context.h"
 #include "tree-pass.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "except.h"
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index f182c26e78b..c857b2028f2 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -83,6 +83,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm-constrs.h"
 #include "tree-vrp.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "sched-int.h"
diff --git a/gcc/gengtype.cc b/gcc/gengtype.cc
index b1db727b958..a72249eacf8 100644
--- a/gcc/gengtype.cc
+++ b/gcc/gengtype.cc
@@ -1713,9 +1713,9 @@ open_base_files (void)
       "tree-dfa.h", "tree-ssa.h", "reload.h", "cpplib.h", "tree-chrec.h",
       "except.h", "output.h",  "cfgloop.h", "target.h", "lto-streamer.h",
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
-      "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
-      "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h", "diagnostic-spec.h", "ctfc.h",
+      "sreal.h", "ipa-cp.h", "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h",
+      "omp-general.h", "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h",
+      "symtab-thunks.h", "symtab-clones.h", "diagnostic-spec.h", "ctfc.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 0cc53199963..9c4ad1ee7b9 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -48,6 +48,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "alloc-pool.h"
 #include "symbol-summary.h"
 #include "ipa-utils.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 // Construct a fur_source, and set the m_query field.
 
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index e85477df32d..2a1da631e9c 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -109,6 +109,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-expr.h"
 #include "gimple.h"
 #include "predict.h"
+#include "sreal.h"
 #include "alloc-pool.h"
 #include "tree-pass.h"
 #include "cgraph.h"
@@ -118,6 +119,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "tree-pretty-print.h"
 #include "tree-inline.h"
@@ -130,274 +132,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "symtab-clones.h"
 #include "gimple-range.h"
 
-template <typename valtype> class ipcp_value;
-
-/* Describes a particular source for an IPA-CP value.  */
-
-template <typename valtype>
-struct ipcp_value_source
-{
-public:
-  /* Aggregate offset of the source, negative if the source is scalar value of
-     the argument itself.  */
-  HOST_WIDE_INT offset;
-  /* The incoming edge that brought the value.  */
-  cgraph_edge *cs;
-  /* If the jump function that resulted into his value was a pass-through or an
-     ancestor, this is the ipcp_value of the caller from which the described
-     value has been derived.  Otherwise it is NULL.  */
-  ipcp_value<valtype> *val;
-  /* Next pointer in a linked list of sources of a value.  */
-  ipcp_value_source *next;
-  /* If the jump function that resulted into his value was a pass-through or an
-     ancestor, this is the index of the parameter of the caller the jump
-     function references.  */
-  int index;
-};
-
-/* Common ancestor for all ipcp_value instantiations.  */
-
-class ipcp_value_base
-{
-public:
-  /* Time benefit and that specializing the function for this value would bring
-     about in this function alone.  */
-  sreal local_time_benefit;
-  /* Time benefit that specializing the function for this value can bring about
-     in it's callees.  */
-  sreal prop_time_benefit;
-  /* Size cost that specializing the function for this value would bring about
-     in this function alone.  */
-  int local_size_cost;
-  /* Size cost that specializing the function for this value can bring about in
-     it's callees.  */
-  int prop_size_cost;
-
-  ipcp_value_base ()
-    : local_time_benefit (0), prop_time_benefit (0),
-      local_size_cost (0), prop_size_cost (0) {}
-};
-
-/* Describes one particular value stored in struct ipcp_lattice.  */
-
-template <typename valtype>
-class ipcp_value : public ipcp_value_base
-{
-public:
-  /* The actual value for the given parameter.  */
-  valtype value;
-  /* The list of sources from which this value originates.  */
-  ipcp_value_source <valtype> *sources = nullptr;
-  /* Next pointers in a linked list of all values in a lattice.  */
-  ipcp_value *next = nullptr;
-  /* Next pointers in a linked list of values in a strongly connected component
-     of values. */
-  ipcp_value *scc_next = nullptr;
-  /* Next pointers in a linked list of SCCs of values sorted topologically
-     according their sources.  */
-  ipcp_value  *topo_next = nullptr;
-  /* A specialized node created for this value, NULL if none has been (so far)
-     created.  */
-  cgraph_node *spec_node = nullptr;
-  /* Depth first search number and low link for topological sorting of
-     values.  */
-  int dfs = 0;
-  int low_link = 0;
-  /* SCC number to identify values which recursively feed into each other.
-     Values in the same SCC have the same SCC number.  */
-  int scc_no = 0;
-  /* Non zero if the value is generated from another value in the same lattice
-     for a self-recursive call, the actual number is how many times the
-     operation has been performed.  In the unlikely event of the value being
-     present in two chains fo self-recursive value generation chains, it is the
-     maximum.  */
-  unsigned self_recursion_generated_level = 0;
-  /* True if this value is currently on the topo-sort stack.  */
-  bool on_stack = false;
-
-  void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
-		   HOST_WIDE_INT offset);
-
-  /* Return true if both THIS value and O feed into each other.  */
-
-  bool same_scc (const ipcp_value<valtype> *o)
-  {
-    return o->scc_no == scc_no;
-  }
-
-/* Return true, if a this value has been generated for a self-recursive call as
-   a result of an arithmetic pass-through jump-function acting on a value in
-   the same lattice function.  */
-
-  bool self_recursion_generated_p ()
-  {
-    return self_recursion_generated_level > 0;
-  }
-};
-
-/* Lattice describing potential values of a formal parameter of a function, or
-   a part of an aggregate.  TOP is represented by a lattice with zero values
-   and with contains_variable and bottom flags cleared.  BOTTOM is represented
-   by a lattice with the bottom flag set.  In that case, values and
-   contains_variable flag should be disregarded.  */
-
-template <typename valtype>
-struct ipcp_lattice
-{
-public:
-  /* The list of known values and types in this lattice.  Note that values are
-     not deallocated if a lattice is set to bottom because there may be value
-     sources referencing them.  */
-  ipcp_value<valtype> *values;
-  /* Number of known values and types in this lattice.  */
-  int values_count;
-  /* The lattice contains a variable component (in addition to values).  */
-  bool contains_variable;
-  /* The value of the lattice is bottom (i.e. variable and unusable for any
-     propagation).  */
-  bool bottom;
-
-  inline bool is_single_const ();
-  inline bool set_to_bottom ();
-  inline bool set_contains_variable ();
-  bool add_value (valtype newval, cgraph_edge *cs,
-		  ipcp_value<valtype> *src_val = NULL,
-		  int src_idx = 0, HOST_WIDE_INT offset = -1,
-		  ipcp_value<valtype> **val_p = NULL,
-		  unsigned same_lat_gen_level = 0);
-  void print (FILE * f, bool dump_sources, bool dump_benefits);
-};
-
-/* Lattice of tree values with an offset to describe a part of an
-   aggregate.  */
-
-struct ipcp_agg_lattice : public ipcp_lattice<tree>
-{
-public:
-  /* Offset that is being described by this lattice. */
-  HOST_WIDE_INT offset;
-  /* Size so that we don't have to re-compute it every time we traverse the
-     list.  Must correspond to TYPE_SIZE of all lat values.  */
-  HOST_WIDE_INT size;
-  /* Next element of the linked list.  */
-  struct ipcp_agg_lattice *next;
-};
-
-/* Lattice of known bits, only capable of holding one value.
-   Bitwise constant propagation propagates which bits of a
-   value are constant.
-   For eg:
-   int f(int x)
-   {
-     return some_op (x);
-   }
-
-   int f1(int y)
-   {
-     if (cond)
-      return f (y & 0xff);
-     else
-      return f (y & 0xf);
-   }
-
-   In the above case, the param 'x' will always have all
-   the bits (except the bits in lsb) set to 0.
-   Hence the mask of 'x' would be 0xff. The mask
-   reflects that the bits in lsb are unknown.
-   The actual propagated value is given by m_value & ~m_mask.  */
-
-class ipcp_bits_lattice
-{
-public:
-  bool bottom_p () const { return m_lattice_val == IPA_BITS_VARYING; }
-  bool top_p () const { return m_lattice_val == IPA_BITS_UNDEFINED; }
-  bool constant_p () const { return m_lattice_val == IPA_BITS_CONSTANT; }
-  bool set_to_bottom ();
-  bool set_to_constant (widest_int, widest_int);
-  bool known_nonzero_p () const;
-
-  widest_int get_value () const { return m_value; }
-  widest_int get_mask () const { return m_mask; }
-
-  bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
-		  enum tree_code, tree, bool);
-
-  bool meet_with (widest_int, widest_int, unsigned);
-
-  void print (FILE *);
-
-private:
-  enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val;
-
-  /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
-     If a bit in mask is set to 0, then the corresponding bit in
-     value is known to be constant.  */
-  widest_int m_value, m_mask;
-
-  bool meet_with_1 (widest_int, widest_int, unsigned, bool);
-  void get_value_and_mask (tree, widest_int *, widest_int *);
-};
-
-/* Lattice of value ranges.  */
-
-class ipcp_vr_lattice
-{
-public:
-  Value_Range m_vr;
-
-  inline bool bottom_p () const;
-  inline bool top_p () const;
-  inline bool set_to_bottom ();
-  bool meet_with (const vrange &p_vr);
-  bool meet_with (const ipcp_vr_lattice &other);
-  void init (tree type);
-  void print (FILE * f);
-
-private:
-  bool meet_with_1 (const vrange &other_vr);
-};
-
-inline void
-ipcp_vr_lattice::init (tree type)
-{
-  if (type)
-    m_vr.set_type (type);
-
-  // Otherwise m_vr will default to unsupported_range.
-}
-
-/* Structure containing lattices for a parameter itself and for pieces of
-   aggregates that are passed in the parameter or by a reference in a parameter
-   plus some other useful flags.  */
-
-class ipcp_param_lattices
-{
-public:
-  /* Lattice describing the value of the parameter itself.  */
-  ipcp_lattice<tree> itself;
-  /* Lattice describing the polymorphic contexts of a parameter.  */
-  ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
-  /* Lattices describing aggregate parts.  */
-  ipcp_agg_lattice *aggs;
-  /* Lattice describing known bits.  */
-  ipcp_bits_lattice bits_lattice;
-  /* Lattice describing value range.  */
-  ipcp_vr_lattice m_value_range;
-  /* Number of aggregate lattices */
-  int aggs_count;
-  /* True if aggregate data were passed by reference (as opposed to by
-     value).  */
-  bool aggs_by_ref;
-  /* All aggregate lattices contain a variable component (in addition to
-     values).  */
-  bool aggs_contain_variable;
-  /* The value of all aggregate lattices is bottom (i.e. variable and unusable
-     for any propagation).  */
-  bool aggs_bottom;
-
-  /* There is a virtual call based on this parameter.  */
-  bool virt_call;
-};
 
 /* Allocation pools for values and their sources in ipa-cp.  */
 
@@ -431,7 +165,6 @@ ipa_get_parm_lattices (class ipa_node_params *info, int i)
 {
   gcc_assert (i >= 0 && i < ipa_get_param_count (info));
   gcc_checking_assert (!info->ipcp_orig_node);
-  gcc_checking_assert (info->lattices);
   return &(info->lattices[i]);
 }
 
@@ -1821,7 +1554,7 @@ ipa_value_from_jfunc (class ipa_node_params *info, struct ipa_jump_func *jfunc,
 	{
 	  ipcp_lattice<tree> *lat;
 
-	  if (!info->lattices
+	  if (info->lattices.is_empty ()
 	      || idx >= ipa_get_param_count (info))
 	    return NULL_TREE;
 	  lat = ipa_get_scalar_lat (info, idx);
@@ -1884,7 +1617,7 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx,
 	}
       else
 	{
-	  if (!info->lattices
+	  if (info->lattices.is_empty ()
 	      || srcidx >= ipa_get_param_count (info))
 	    return ctx;
 	  ipcp_lattice<ipa_polymorphic_call_context> *lat;
@@ -2056,7 +1789,7 @@ ipa_agg_value_from_jfunc (ipa_node_params *info, cgraph_node *node,
 				 item->value.load_agg.by_ref);
 	}
     }
-  else if (info->lattices)
+  else if (!info->lattices.is_empty ())
     {
       class ipcp_param_lattices *src_plats
 	= ipa_get_parm_lattices (info, src_idx);
@@ -2937,7 +2670,6 @@ merge_agg_lats_step (class ipcp_param_lattices *dest_plats,
 	return false;
       dest_plats->aggs_count++;
       new_al = ipcp_agg_lattice_pool.allocate ();
-      memset (new_al, 0, sizeof (*new_al));
 
       new_al->offset = offset;
       new_al->size = val_size;
@@ -4295,8 +4027,7 @@ ipcp_propagate_stage (class ipa_topo_info *topo)
         determine_versionability (node, info);
 
 	unsigned nlattices = ipa_get_param_count (info);
-	void *chunk = XCNEWVEC (class ipcp_param_lattices, nlattices);
-	info->lattices = new (chunk) ipcp_param_lattices[nlattices];
+	info->lattices.safe_grow_cleared (nlattices, true);
 	initialize_node_lattices (node);
       }
     ipa_size_summary *s = ipa_size_summaries->get (node);
@@ -6568,7 +6299,7 @@ ipcp_store_vr_results (void)
 
       if (info->ipcp_orig_node)
 	info = ipa_node_params_sum->get (info->ipcp_orig_node);
-      if (!info->lattices)
+      if (info->lattices.is_empty ())
 	/* Newly expanded artificial thunks do not have lattices.  */
 	continue;
 
diff --git a/gcc/ipa-cp.h b/gcc/ipa-cp.h
new file mode 100644
index 00000000000..0b3cfe4b526
--- /dev/null
+++ b/gcc/ipa-cp.h
@@ -0,0 +1,292 @@
+/* Interprocedural constant propagation
+   Copyright (C) 2024 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef IPA_CP_H
+#define IPA_CP_H
+
+template <typename valtype> class ipcp_value;
+
+/* Describes a particular source for an IPA-CP value.  */
+
+template <typename valtype>
+struct ipcp_value_source
+{
+public:
+  /* Aggregate offset of the source, negative if the source is scalar value of
+     the argument itself.  */
+  HOST_WIDE_INT offset;
+  /* The incoming edge that brought the value.  */
+  cgraph_edge *cs;
+  /* If the jump function that resulted into his value was a pass-through or an
+     ancestor, this is the ipcp_value of the caller from which the described
+     value has been derived.  Otherwise it is NULL.  */
+  ipcp_value<valtype> *val;
+  /* Next pointer in a linked list of sources of a value.  */
+  ipcp_value_source *next;
+  /* If the jump function that resulted into his value was a pass-through or an
+     ancestor, this is the index of the parameter of the caller the jump
+     function references.  */
+  int index;
+};
+
+/* Common ancestor for all ipcp_value instantiations.  */
+
+class ipcp_value_base
+{
+public:
+  /* Time benefit and that specializing the function for this value would bring
+     about in this function alone.  */
+  sreal local_time_benefit = 0;
+  /* Time benefit that specializing the function for this value can bring about
+     in it's callees.  */
+  sreal prop_time_benefit = 0;
+  /* Size cost that specializing the function for this value would bring about
+     in this function alone.  */
+  int local_size_cost = 0;
+  /* Size cost that specializing the function for this value can bring about in
+     it's callees.  */
+  int prop_size_cost = 0;
+};
+
+/* Describes one particular value stored in struct ipcp_lattice.  */
+
+template <typename valtype>
+class ipcp_value : public ipcp_value_base
+{
+public:
+  /* The actual value for the given parameter.  */
+  valtype value;
+  /* The list of sources from which this value originates.  */
+  ipcp_value_source <valtype> *sources = nullptr;
+  /* Next pointers in a linked list of all values in a lattice.  */
+  ipcp_value *next = nullptr;
+  /* Next pointers in a linked list of values in a strongly connected component
+     of values. */
+  ipcp_value *scc_next = nullptr;
+  /* Next pointers in a linked list of SCCs of values sorted topologically
+     according their sources.  */
+  ipcp_value  *topo_next = nullptr;
+  /* A specialized node created for this value, NULL if none has been (so far)
+     created.  */
+  cgraph_node *spec_node = nullptr;
+  /* Depth first search number and low link for topological sorting of
+     values.  */
+  int dfs = 0;
+  int low_link = 0;
+  /* SCC number to identify values which recursively feed into each other.
+     Values in the same SCC have the same SCC number.  */
+  int scc_no = 0;
+  /* Non zero if the value is generated from another value in the same lattice
+     for a self-recursive call, the actual number is how many times the
+     operation has been performed.  In the unlikely event of the value being
+     present in two chains fo self-recursive value generation chains, it is the
+     maximum.  */
+  unsigned self_recursion_generated_level = 0;
+  /* True if this value is currently on the topo-sort stack.  */
+  bool on_stack = false;
+
+  void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
+		   HOST_WIDE_INT offset);
+
+  /* Return true if both THIS value and O feed into each other.  */
+
+  bool same_scc (const ipcp_value<valtype> *o)
+  {
+    return o->scc_no == scc_no;
+  }
+
+/* Return true, if a this value has been generated for a self-recursive call as
+   a result of an arithmetic pass-through jump-function acting on a value in
+   the same lattice function.  */
+
+  bool self_recursion_generated_p ()
+  {
+    return self_recursion_generated_level > 0;
+  }
+};
+
+/* Lattice describing potential values of a formal parameter of a function, or
+   a part of an aggregate.  TOP is represented by a lattice with zero values
+   and with contains_variable and bottom flags cleared.  BOTTOM is represented
+   by a lattice with the bottom flag set.  In that case, values and
+   contains_variable flag should be disregarded.  */
+
+template <typename valtype>
+struct ipcp_lattice
+{
+public:
+  /* The list of known values and types in this lattice.  Note that values are
+     not deallocated if a lattice is set to bottom because there may be value
+     sources referencing them.  */
+  ipcp_value<valtype> *values = nullptr;
+  /* Number of known values and types in this lattice.  */
+  int values_count = 0;
+  /* The lattice contains a variable component (in addition to values).  */
+  bool contains_variable = false;
+  /* The value of the lattice is bottom (i.e. variable and unusable for any
+     propagation).  */
+  bool bottom = false;
+
+  inline bool is_single_const ();
+  inline bool set_to_bottom ();
+  inline bool set_contains_variable ();
+  bool add_value (valtype newval, cgraph_edge *cs,
+		  ipcp_value<valtype> *src_val = NULL,
+		  int src_idx = 0, HOST_WIDE_INT offset = -1,
+		  ipcp_value<valtype> **val_p = NULL,
+		  unsigned same_lat_gen_level = 0);
+  void print (FILE * f, bool dump_sources, bool dump_benefits);
+};
+
+/* Lattice of tree values with an offset to describe a part of an
+   aggregate.  */
+
+struct ipcp_agg_lattice : public ipcp_lattice<tree>
+{
+public:
+  /* Offset that is being described by this lattice. */
+  HOST_WIDE_INT offset = 0;
+  /* Size so that we don't have to re-compute it every time we traverse the
+     list.  Must correspond to TYPE_SIZE of all lat values.  */
+  HOST_WIDE_INT size = 0;
+  /* Next element of the linked list.  */
+  struct ipcp_agg_lattice *next = nullptr;
+};
+
+/* Lattice of known bits, only capable of holding one value.
+   Bitwise constant propagation propagates which bits of a
+   value are constant.
+   For eg:
+   int f(int x)
+   {
+     return some_op (x);
+   }
+
+   int f1(int y)
+   {
+     if (cond)
+      return f (y & 0xff);
+     else
+      return f (y & 0xf);
+   }
+
+   In the above case, the param 'x' will always have all
+   the bits (except the bits in lsb) set to 0.
+   Hence the mask of 'x' would be 0xff. The mask
+   reflects that the bits in lsb are unknown.
+   The actual propagated value is given by m_value & ~m_mask.  */
+
+class ipcp_bits_lattice
+{
+public:
+  bool bottom_p () const { return m_lattice_val == IPA_BITS_VARYING; }
+  bool top_p () const { return m_lattice_val == IPA_BITS_UNDEFINED; }
+  bool constant_p () const { return m_lattice_val == IPA_BITS_CONSTANT; }
+  bool set_to_bottom ();
+  bool set_to_constant (widest_int, widest_int);
+  bool known_nonzero_p () const;
+
+  widest_int get_value () const { return m_value; }
+  widest_int get_mask () const { return m_mask; }
+
+  bool meet_with (ipcp_bits_lattice& other, unsigned, signop,
+		  enum tree_code, tree, bool);
+
+  bool meet_with (widest_int, widest_int, unsigned);
+
+  void print (FILE *);
+
+private:
+  enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING }
+    m_lattice_val = IPA_BITS_UNDEFINED;
+
+  /* Similar to ccp_lattice_t, mask represents which bits of value are constant.
+     If a bit in mask is set to 0, then the corresponding bit in
+     value is known to be constant.  */
+  widest_int m_value, m_mask;
+
+  bool meet_with_1 (widest_int, widest_int, unsigned, bool);
+  void get_value_and_mask (tree, widest_int *, widest_int *);
+};
+
+/* Lattice of value ranges.  */
+
+class ipcp_vr_lattice
+{
+public:
+  Value_Range m_vr;
+
+  inline bool bottom_p () const;
+  inline bool top_p () const;
+  inline bool set_to_bottom ();
+  bool meet_with (const vrange &p_vr);
+  bool meet_with (const ipcp_vr_lattice &other);
+  void init (tree type);
+  void print (FILE * f);
+
+private:
+  bool meet_with_1 (const vrange &other_vr);
+};
+
+inline void
+ipcp_vr_lattice::init (tree type)
+{
+  if (type)
+    m_vr.set_type (type);
+
+  // Otherwise m_vr will default to unsupported_range.
+}
+
+/* Structure containing lattices for a parameter itself and for pieces of
+   aggregates that are passed in the parameter or by a reference in a parameter
+   plus some other useful flags.
+
+   Even after construction, m_value_range parts still need to be initialized
+   with the type they represent with the init method.  */
+
+class ipcp_param_lattices
+{
+public:
+  /* Lattice describing the value of the parameter itself.  */
+  ipcp_lattice<tree> itself;
+  /* Lattice describing the polymorphic contexts of a parameter.  */
+  ipcp_lattice<ipa_polymorphic_call_context> ctxlat;
+  /* Lattices describing aggregate parts.  */
+  ipcp_agg_lattice *aggs = nullptr;
+  /* Lattice describing known bits.  */
+  ipcp_bits_lattice bits_lattice;
+  /* Lattice describing value range.  */
+  ipcp_vr_lattice m_value_range;
+  /* Number of aggregate lattices */
+  int aggs_count = 0;
+  /* True if aggregate data were passed by reference (as opposed to by
+     value).  */
+  bool aggs_by_ref = false;
+  /* All aggregate lattices contain a variable component (in addition to
+     values).  */
+  bool aggs_contain_variable = false;
+  /* The value of all aggregate lattices is bottom (i.e. variable and unusable
+     for any propagation).  */
+  bool aggs_bottom = false;
+
+  /* There is a virtual call based on this parameter.  */
+  bool virt_call = false;
+};
+
+#endif /* IPA_CP_H */
diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
index caf8548fbc9..a7ce434bffb 100644
--- a/gcc/ipa-devirt.cc
+++ b/gcc/ipa-devirt.cc
@@ -124,6 +124,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "demangle.h"
diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index 74c9b4e1d1e..dff40cd8aa5 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -75,6 +75,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop-niter.h"
 #include "tree-ssa-loop.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "cfgloop.h"
diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc
index f56891325f3..5d5a42f9c6c 100644
--- a/gcc/ipa-icf.cc
+++ b/gcc/ipa-icf.cc
@@ -73,6 +73,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "except.h"
diff --git a/gcc/ipa-inline-analysis.cc b/gcc/ipa-inline-analysis.cc
index 24ac4cbafc0..a190cb6501b 100644
--- a/gcc/ipa-inline-analysis.cc
+++ b/gcc/ipa-inline-analysis.cc
@@ -40,6 +40,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-loop-niter.h"
 #include "tree-ssa-loop.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "ipa-inline.h"
diff --git a/gcc/ipa-inline-transform.cc b/gcc/ipa-inline-transform.cc
index a05631a085d..73ae4e68ef3 100644
--- a/gcc/ipa-inline-transform.cc
+++ b/gcc/ipa-inline-transform.cc
@@ -40,6 +40,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-cfg.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "ipa-inline.h"
diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
index be2ca58c7dd..cc509b0c4a4 100644
--- a/gcc/ipa-inline.cc
+++ b/gcc/ipa-inline.cc
@@ -108,11 +108,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "profile.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "ipa-inline.h"
 #include "ipa-utils.h"
-#include "sreal.h"
 #include "auto-profile.h"
 #include "builtins.h"
 #include "fibonacci_heap.h"
diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index cec730dfa4b..a5adce8ea39 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -75,6 +75,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-modref-tree.h"
 #include "ipa-modref.h"
 #include "value-range.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "attr-fnspec.h"
diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc
index 02f71a42237..3e0df6a6f77 100644
--- a/gcc/ipa-param-manipulation.cc
+++ b/gcc/ipa-param-manipulation.cc
@@ -47,6 +47,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-phinodes.h"
 #include "cfgexpand.h"
 #include "attribs.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 
 /* Actual prefixes of different newly synthetized parameters.  Keep in sync
diff --git a/gcc/ipa-predicate.cc b/gcc/ipa-predicate.cc
index d3b3227b0fe..164aba4a126 100644
--- a/gcc/ipa-predicate.cc
+++ b/gcc/ipa-predicate.cc
@@ -27,6 +27,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-vrp.h"
 #include "alloc-pool.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "real.h"
diff --git a/gcc/ipa-profile.cc b/gcc/ipa-profile.cc
index 5e89f677c3e..27f411ce81a 100644
--- a/gcc/ipa-profile.cc
+++ b/gcc/ipa-profile.cc
@@ -55,6 +55,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index bec0ebd210c..e22c4f78405 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -41,6 +41,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "gimple-walk.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "tree-cfg.h"
 #include "tree-dfa.h"
@@ -4561,7 +4563,7 @@ ipa_node_params_t::duplicate(cgraph_node *, cgraph_node *,
 			     ipa_node_params *new_info)
 {
   new_info->descriptors = vec_safe_copy (old_info->descriptors);
-  new_info->lattices = NULL;
+  gcc_assert (new_info->lattices.is_empty ());
   new_info->ipcp_orig_node = old_info->ipcp_orig_node;
   new_info->known_csts = old_info->known_csts.copy ();
   new_info->known_contexts = old_info->known_contexts.copy ();
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 9c78dc9f486..ee3c0006add 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -627,7 +627,7 @@ public:
   vec<ipa_param_descriptor, va_gc> *descriptors;
   /* Pointer to an array of structures describing individual formal
      parameters.  */
-  class ipcp_param_lattices * GTY((skip)) lattices;
+  vec<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 * GTY((skip)) ipcp_orig_node;
@@ -662,7 +662,7 @@ public:
 
 inline
 ipa_node_params::ipa_node_params ()
-: descriptors (NULL), lattices (NULL), ipcp_orig_node (NULL),
+: descriptors (NULL), lattices (vNULL), 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_is_self_scc (0),
@@ -673,8 +673,8 @@ ipa_node_params::ipa_node_params ()
 inline
 ipa_node_params::~ipa_node_params ()
 {
-  free (lattices);
   vec_free (descriptors);
+  lattices.release ();
   known_csts.release ();
   known_contexts.release ();
 }
diff --git a/gcc/ipa-pure-const.cc b/gcc/ipa-pure-const.cc
index 7e9ece21b22..d285462b6cf 100644
--- a/gcc/ipa-pure-const.cc
+++ b/gcc/ipa-pure-const.cc
@@ -59,6 +59,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ssa.h"
 #include "alloc-pool.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "symtab-thunks.h"
diff --git a/gcc/ipa-split.cc b/gcc/ipa-split.cc
index 8e6aa018a7d..39ad822608b 100644
--- a/gcc/ipa-split.cc
+++ b/gcc/ipa-split.cc
@@ -95,6 +95,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "gimple-walk.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "tree-cfg.h"
 #include "tree-into-ssa.h"
diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
index 14c2a344e6d..6d6da408925 100644
--- a/gcc/ipa-sra.cc
+++ b/gcc/ipa-sra.cc
@@ -84,6 +84,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "symtab-clones.h"
 #include "attribs.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 
 static void ipa_sra_summarize_function (cgraph_node *);
diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
index 0ee063c9edd..09db1e04431 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -43,6 +43,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "alloc-pool.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "gimple-fold.h"
diff --git a/gcc/ipa-utils.cc b/gcc/ipa-utils.cc
index 1567874882f..3be0ddb8e96 100644
--- a/gcc/ipa-utils.cc
+++ b/gcc/ipa-utils.cc
@@ -33,6 +33,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "tree-eh.h"
diff --git a/gcc/ipa.cc b/gcc/ipa.cc
index 82d8c59d660..c453fca5d9b 100644
--- a/gcc/ipa.cc
+++ b/gcc/ipa.cc
@@ -33,6 +33,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "dbgcnt.h"
diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
index e54ddf2ca41..2ce94cc3282 100644
--- a/gcc/lto/lto-common.cc
+++ b/gcc/lto/lto-common.cc
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "common.h"
 #include "debug.h"
diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc
index 7165747d57e..19f91e5d660 100644
--- a/gcc/lto/lto-partition.cc
+++ b/gcc/lto/lto-partition.cc
@@ -31,10 +31,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-streamer.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "lto-partition.h"
-#include "sreal.h"
 
 vec<ltrans_partition> ltrans_partitions;
 
diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc
index f7c0623f6b2..91aa2fbddb4 100644
--- a/gcc/lto/lto.cc
+++ b/gcc/lto/lto.cc
@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "debug.h"
 #include "lto.h"
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 175d4cd18fa..2cd4096558e 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -74,6 +74,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-reference.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "ipa-utils.h"
 #include "gcse.h"
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index ad3b9b87c9d..f6a5cd0ee6e 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -150,6 +150,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "alloc-pool.h"
 #include "symbol-summary.h"
 #include "ipa-utils.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "internal-fn.h"
 
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 8792cd07901..97c6d5895f0 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -76,6 +76,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-sccvn.h"
 #include "alloc-pool.h"
 #include "symbol-summary.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "target.h"
 
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 978025b51de..b0f21e3aa60 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "symbol-summary.h"
 #include "ipa-utils.h"
+#include "sreal.h"
+#include "ipa-cp.h"
 #include "ipa-prop.h"
 #include "attribs.h"
 
