/* Interprocedural analyses.
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
+ Copyright (C) 2005-2021 Free Software Foundation, Inc.
This file is part of GCC.
/* Number of the caller's formal parameter being passed. */
int formal_id;
/* Operation that is performed on the argument before it is passed on.
- NOP_EXPR means no operation. Otherwise oper must be a simple binary
- arithmetic operation where the caller's parameter is the first operand and
- operand field from this structure is the second one. */
+ Special values which have other meaning than in normal contexts:
+ - NOP_EXPR means no operation, not even type conversion.
+ - ASSERT_EXPR means that only the value in operand is allowed to pass
+ through (without any change), for all other values the result is
+ unknown.
+ Otherwise operation must be a simple binary or unary arithmetic operation
+ where the caller's parameter is the first operand and (for binary
+ operations) the operand field from this structure is the second one. */
enum tree_code operation;
/* When the passed value is a pointer, it is set to true only when we are
certain that no write to the object it points to has occurred since the
whole vector. */
static inline void
-ipa_release_agg_values (vec<ipa_agg_value_set> &aggs)
+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 ();
- aggs.release ();
+ if (release_vector)
+ aggs.release ();
}
/* Information about zero/non-zero 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;
+ value_range *m_vr;
enum jump_func_type type;
/* Represents a value of a jump function. pass_through is used only in jump
return jfunc->value.ancestor.agg_preserved;
}
+/* Class for allocating a bundle of various potentially known properties about
+ actual arguments of a particular call on stack for the usual case and on
+ heap only if there are unusually many arguments. The data is deallocated
+ when the instance of this class goes out of scope or is otherwise
+ destructed. */
+
+class ipa_auto_call_arg_values
+{
+public:
+ ~ipa_auto_call_arg_values ();
+
+ /* If m_known_vals (vector of known "scalar" values) is sufficiantly long,
+ return its element at INDEX, otherwise return NULL. */
+ tree safe_sval_at (int index)
+ {
+ /* TODO: Assert non-negative index here and test. */
+ if ((unsigned) index < m_known_vals.length ())
+ return m_known_vals[index];
+ return NULL;
+ }
+
+ /* If m_known_aggs is sufficiantly long, return the pointer rto its element
+ at INDEX, otherwise return NULL. */
+ ipa_agg_value_set *safe_aggval_at (int index)
+ {
+ /* TODO: Assert non-negative index here and test. */
+ if ((unsigned) index < m_known_aggs.length ())
+ return &m_known_aggs[index];
+ return NULL;
+ }
+
+ /* Vector describing known values of parameters. */
+ auto_vec<tree, 32> m_known_vals;
+
+ /* Vector describing known polymorphic call contexts. */
+ auto_vec<ipa_polymorphic_call_context, 32> m_known_contexts;
+
+ /* Vector describing known aggregate values. */
+ auto_vec<ipa_agg_value_set, 32> m_known_aggs;
+
+ /* Vector describing known value ranges of arguments. */
+ auto_vec<value_range, 32> m_known_value_ranges;
+};
+
+/* Class bundling the various potentially known properties about actual
+ arguments of a particular call. This variant does not deallocate the
+ bundled data in any way. */
+
+class ipa_call_arg_values
+{
+public:
+ /* Default constructor, setting the vectors to empty ones. */
+ ipa_call_arg_values ()
+ {}
+
+ /* Construct this general variant of the bundle from the variant which uses
+ auto_vecs to hold the vectors. This means that vectors of objects
+ constructed with this constructor should not be changed because if they
+ get reallocated, the member vectors and the underlying auto_vecs would get
+ out of sync. */
+ ipa_call_arg_values (ipa_auto_call_arg_values *aavals)
+ : m_known_vals (aavals->m_known_vals.to_vec_legacy ()),
+ m_known_contexts (aavals->m_known_contexts.to_vec_legacy ()),
+ m_known_aggs (aavals->m_known_aggs.to_vec_legacy ()),
+ m_known_value_ranges (aavals->m_known_value_ranges.to_vec_legacy ())
+ {}
+
+ /* If m_known_vals (vector of known "scalar" values) is sufficiantly long,
+ return its element at INDEX, otherwise return NULL. */
+ tree safe_sval_at (int index)
+ {
+ /* TODO: Assert non-negative index here and test. */
+ if ((unsigned) index < m_known_vals.length ())
+ return m_known_vals[index];
+ return NULL;
+ }
+
+ /* If m_known_aggs is sufficiantly long, return the pointer rto its element
+ at INDEX, otherwise return NULL. */
+ ipa_agg_value_set *safe_aggval_at (int index)
+ {
+ /* TODO: Assert non-negative index here and test. */
+ if ((unsigned) index < m_known_aggs.length ())
+ return &m_known_aggs[index];
+ return NULL;
+ }
+
+ /* Vector describing known values of parameters. */
+ vec<tree> m_known_vals = vNULL;
+
+ /* Vector describing known polymorphic call contexts. */
+ vec<ipa_polymorphic_call_context> m_known_contexts = vNULL;
+
+ /* Vector describing known aggregate values. */
+ vec<ipa_agg_value_set> m_known_aggs = vNULL;
+
+ /* Vector describing known value ranges of arguments. */
+ vec<value_range> m_known_value_ranges = vNULL;
+};
+
+
/* Summary describing a single formal parameter. */
struct GTY(()) ipa_param_descriptor
{
/* 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, in IPA LTO phase, this is the type of 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. */
+ ipa-prop structures (which include flag dereferenced below), this is
+ IPA_UNDESCRIBED_USE. */
int controlled_uses;
- unsigned int move_cost : 28;
+ unsigned int move_cost : 27;
/* 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;
+ /* Set to true when in addition to being used in call statements, the
+ parameter has also been used for loads (but not for writes, does not
+ escape, etc.). This allows us to identify parameters p which are only
+ used as *p, and so when we propagate a constant to them, we can generate a
+ LOAD and not ADDR reference to them. */
+ unsigned load_dereferenced : 1;
};
/* ipa_node_params stores information related to formal parameters of functions
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. */
ipa_node_params::~ipa_node_params ()
{
free (lattices);
+ vec_free (descriptors);
known_csts.release ();
known_contexts.release ();
}
(*info->descriptors)[i].controlled_uses = val;
}
+/* Assuming a parameter does not have IPA_UNDESCRIBED_USE controlled uses,
+ return flag which indicates it has been dereferenced but only in a load. */
+static inline int
+ipa_get_param_load_dereferenced (class ipa_node_params *info, int i)
+{
+ gcc_assert (ipa_get_controlled_uses (info, i) != IPA_UNDESCRIBED_USE);
+ return (*info->descriptors)[i].load_dereferenced;
+}
+
+/* Set the load_dereferenced flag of a given parameter. */
+
+static inline void
+ipa_set_param_load_dereferenced (class ipa_node_params *info, int i, bool val)
+{
+ gcc_checking_assert (info->descriptors);
+ (*info->descriptors)[i].load_dereferenced = val;
+}
+
/* Return the used flag corresponding to the Ith formal parameter of the
function associated with INFO. */
HOST_WIDE_INT offset;
/* The constant value. */
tree value;
- /* The paramter index. */
+ /* The parameter index. */
int index;
/* Whether the value was passed by reference. */
bool by_ref;
/* Destructor. */
~ipa_edge_args ()
{
+ unsigned int i;
+ ipa_jump_func *jf;
+ FOR_EACH_VEC_SAFE_ELT (jump_functions, i, jf)
+ vec_free (jf->agg.items);
vec_free (jump_functions);
vec_free (polymorphic_call_contexts);
}
{
public:
ipa_node_params_t (symbol_table *table, bool ggc):
- function_summary<ipa_node_params *> (table, ggc) { }
+ function_summary<ipa_node_params *> (table, ggc)
+ {
+ disable_insertion_hook ();
+ }
/* Hook that is called by summary when a node is duplicated. */
virtual void duplicate (cgraph_node *node,
/* 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_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)
-
/* Creating and freeing ipa_node_params and ipa_edge_args. */
void ipa_create_all_node_params (void);
void ipa_create_all_edge_args (void);
bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
vec<cgraph_edge *> *new_edges);
-/* Indirect edge and binfo processing. */
+/* Indirect edge processing and target discovery. */
+tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
+ ipa_call_arg_values *avals,
+ bool *speculative);
tree ipa_get_indirect_edge_target (struct cgraph_edge *ie,
- vec<tree>,
- vec<ipa_polymorphic_call_context>,
- vec<ipa_agg_value_set>,
- bool *);
+ ipa_auto_call_arg_values *avals,
+ bool *speculative);
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);
void ipa_analyze_node (struct cgraph_node *);
/* Aggregate jump function related functions. */
-tree ipa_find_agg_cst_for_param (struct ipa_agg_value_set *agg, tree scalar,
+tree ipa_find_agg_cst_for_param (const 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,
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 *);
+bool unadjusted_ptr_and_unit_offset (tree op, tree *ret,
+ poly_int64 *offset_ret);
/* From tree-sra.c: */
tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree,