+ lat = ipa_get_lattice (info, idx);
+ if (!ipa_lat_is_single_const (lat))
+ return NULL_TREE;
+ input = lat->values->value;
+ }
+
+ if (!input)
+ return NULL_TREE;
+
+ if (jfunc->type == IPA_JF_PASS_THROUGH)
+ {
+ if (jfunc->value.pass_through.operation == NOP_EXPR)
+ return input;
+ else if (TREE_CODE (input) == TREE_BINFO)
+ return NULL_TREE;
+ else
+ return ipa_get_jf_pass_through_result (jfunc, input);
+ }
+ else
+ {
+ if (TREE_CODE (input) == TREE_BINFO)
+ return get_binfo_at_offset (input, jfunc->value.ancestor.offset,
+ jfunc->value.ancestor.type);
+ else
+ return ipa_get_jf_ancestor_result (jfunc, input);
+ }
+ }
+ else
+ return NULL_TREE;
+}
+
+/* Determine whether JFUNC evaluates to a constant and if so, return it.
+ Otherwise return NULL. INFO describes the caller node so that pass-through
+ jump functions can be evaluated. */
+
+tree
+ipa_cst_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
+{
+ tree res = ipa_value_from_jfunc (info, jfunc);
+
+ if (res && TREE_CODE (res) == TREE_BINFO)
+ return NULL_TREE;
+ else
+ return res;
+}
+
+
+/* If checking is enabled, verify that no lattice is in the TOP state, i.e. not
+ bottom, not containing a variable component and without any known value at
+ the same time. */
+
+DEBUG_FUNCTION void
+ipcp_verify_propagated_values (void)
+{
+ struct cgraph_node *node;
+
+ FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+ {
+ struct ipa_node_params *info = IPA_NODE_REF (node);
+ int i, count = ipa_get_param_count (info);
+
+ for (i = 0; i < count; i++)
+ {
+ struct ipcp_lattice *lat = ipa_get_lattice (info, i);
+
+ if (!lat->bottom
+ && !lat->contains_variable
+ && lat->values_count == 0)
+ {
+ if (dump_file)
+ {
+ fprintf (dump_file, "\nIPA lattices after constant "
+ "propagation:\n");
+ print_all_lattices (dump_file, true, false);
+ }
+
+ gcc_unreachable ();
+ }
+ }
+ }
+}
+
+/* Return true iff X and Y should be considered equal values by IPA-CP. */
+
+static bool
+values_equal_for_ipcp_p (tree x, tree y)
+{
+ gcc_checking_assert (x != NULL_TREE && y != NULL_TREE);
+
+ if (x == y)
+ return true;
+
+ if (TREE_CODE (x) == TREE_BINFO || TREE_CODE (y) == TREE_BINFO)
+ return false;
+
+ if (TREE_CODE (x) == ADDR_EXPR
+ && TREE_CODE (y) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL
+ && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL)
+ return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)),
+ DECL_INITIAL (TREE_OPERAND (y, 0)), 0);
+ else
+ return operand_equal_p (x, y, 0);
+}
+
+/* Add a new value source to VAL, marking that a value comes from edge CS and
+ (if the underlying jump function is a pass-through or an ancestor one) from
+ a caller value SRC_VAL of a caller parameter described by SRC_INDEX. */
+
+static void
+add_value_source (struct ipcp_value *val, struct cgraph_edge *cs,
+ struct ipcp_value *src_val, int src_idx)
+{
+ struct ipcp_value_source *src;
+
+ src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool);
+ src->cs = cs;
+ src->val = src_val;
+ src->index = src_idx;
+
+ src->next = val->sources;
+ val->sources = src;
+}
+
+
+/* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for
+ it. CS, SRC_VAL and SRC_INDEX are meant for add_value_source and have the
+ same meaning. */
+
+static bool
+add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
+ struct cgraph_edge *cs, struct ipcp_value *src_val,
+ int src_idx)
+{
+ struct ipcp_value *val;
+
+ if (lat->bottom)
+ return false;
+
+
+ for (val = lat->values; val; val = val->next)
+ if (values_equal_for_ipcp_p (val->value, newval))
+ {
+ if (edge_within_scc (cs))
+ {
+ struct ipcp_value_source *s;
+ for (s = val->sources; s ; s = s->next)
+ if (s->cs == cs)
+ break;
+ if (s)
+ return false;
+ }
+
+ add_value_source (val, cs, src_val, src_idx);
+ return false;
+ }
+
+ if (lat->values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
+ {
+ /* We can only free sources, not the values themselves, because sources
+ of other values in this this SCC might point to them. */
+ for (val = lat->values; val; val = val->next)
+ {
+ while (val->sources)
+ {
+ struct ipcp_value_source *src = val->sources;
+ val->sources = src->next;
+ pool_free (ipcp_sources_pool, src);
+ }
+ }
+
+ lat->values = NULL;
+ return set_lattice_to_bottom (lat);
+ }
+
+ lat->values_count++;
+ val = (struct ipcp_value *) pool_alloc (ipcp_values_pool);
+ memset (val, 0, sizeof (*val));
+
+ add_value_source (val, cs, src_val, src_idx);
+ val->value = newval;
+ val->next = lat->values;
+ lat->values = val;
+ return true;
+}
+
+/* Propagate values through a pass-through jump function JFUNC associated with
+ edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
+ is the index of the source parameter. */
+
+static bool
+propagate_vals_accross_pass_through (struct cgraph_edge *cs,
+ struct ipa_jump_func *jfunc,
+ struct ipcp_lattice *src_lat,
+ struct ipcp_lattice *dest_lat,
+ int src_idx)
+{
+ struct ipcp_value *src_val;
+ bool ret = false;
+
+ if (jfunc->value.pass_through.operation == NOP_EXPR)
+ for (src_val = src_lat->values; src_val; src_val = src_val->next)
+ ret |= add_value_to_lattice (dest_lat, src_val->value, cs,
+ src_val, src_idx);
+ /* Do not create new values when propagating within an SCC because if there
+ arithmetic functions with circular dependencies, there is infinite number
+ of them and we would just make lattices bottom. */
+ else if (edge_within_scc (cs))
+ ret = set_lattice_contains_variable (dest_lat);
+ else
+ for (src_val = src_lat->values; src_val; src_val = src_val->next)
+ {
+ tree cstval = src_val->value;
+
+ if (TREE_CODE (cstval) == TREE_BINFO)
+ {
+ ret |= set_lattice_contains_variable (dest_lat);
+ continue;
+ }
+ cstval = ipa_get_jf_pass_through_result (jfunc, cstval);
+
+ if (cstval)
+ ret |= add_value_to_lattice (dest_lat, cstval, cs, src_val, src_idx);
+ else
+ ret |= set_lattice_contains_variable (dest_lat);
+ }
+
+ return ret;
+}
+
+/* Propagate values through an ancestor jump function JFUNC associated with
+ edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
+ is the index of the source parameter. */
+
+static bool
+propagate_vals_accross_ancestor (struct cgraph_edge *cs,
+ struct ipa_jump_func *jfunc,
+ struct ipcp_lattice *src_lat,
+ struct ipcp_lattice *dest_lat,
+ int src_idx)
+{
+ struct ipcp_value *src_val;
+ bool ret = false;
+
+ if (edge_within_scc (cs))
+ return set_lattice_contains_variable (dest_lat);
+
+ for (src_val = src_lat->values; src_val; src_val = src_val->next)
+ {
+ tree t = src_val->value;
+
+ if (TREE_CODE (t) == TREE_BINFO)
+ t = get_binfo_at_offset (t, jfunc->value.ancestor.offset,
+ jfunc->value.ancestor.type);
+ else
+ t = ipa_get_jf_ancestor_result (jfunc, t);
+
+ if (t)
+ ret |= add_value_to_lattice (dest_lat, t, cs, src_val, src_idx);
+ else
+ ret |= set_lattice_contains_variable (dest_lat);
+ }
+
+ return ret;
+}
+
+/* Propagate values across jump function JFUNC that is associated with edge CS
+ and put the values into DEST_LAT. */
+
+static bool
+propagate_accross_jump_function (struct cgraph_edge *cs,
+ struct ipa_jump_func *jfunc,
+ struct ipcp_lattice *dest_lat)
+{
+ if (dest_lat->bottom)
+ return false;
+
+ if (jfunc->type == IPA_JF_CONST
+ || jfunc->type == IPA_JF_KNOWN_TYPE)
+ {
+ tree val;
+
+ if (jfunc->type == IPA_JF_KNOWN_TYPE)
+ {
+ val = ipa_value_from_known_type_jfunc (jfunc);
+ if (!val)
+ return set_lattice_contains_variable (dest_lat);