aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-analysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa-inline-analysis.c')
-rw-r--r--gcc/ipa-inline-analysis.c305
1 files changed, 185 insertions, 120 deletions
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index f8ca825e24f..5d6721813d8 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -216,13 +216,14 @@ struct agg_position_info
bool by_ref;
};
-/* Add condition to condition list CONDS. AGGPOS describes whether the used
- oprand is loaded from an aggregate and where in the aggregate it is. It can
- be NULL, which means this not a load from an aggregate. */
+/* Add condition to condition list SUMMARY. OPERAND_NUM, SIZE, CODE and VAL
+ correspond to fields of condition structure. AGGPOS describes whether the
+ used operand is loaded from an aggregate and where in the aggregate it is.
+ It can be NULL, which means this not a load from an aggregate. */
static struct predicate
add_condition (struct inline_summary *summary, int operand_num,
- struct agg_position_info *aggpos,
+ HOST_WIDE_INT size, struct agg_position_info *aggpos,
enum tree_code code, tree val)
{
int i;
@@ -248,6 +249,7 @@ add_condition (struct inline_summary *summary, int operand_num,
for (i = 0; vec_safe_iterate (summary->conds, i, &c); i++)
{
if (c->operand_num == operand_num
+ && c->size == size
&& c->code == code
&& c->val == val
&& c->agg_contents == agg_contents
@@ -264,6 +266,7 @@ add_condition (struct inline_summary *summary, int operand_num,
new_cond.agg_contents = agg_contents;
new_cond.by_ref = by_ref;
new_cond.offset = offset;
+ new_cond.size = size;
vec_safe_push (summary->conds, new_cond);
return single_cond_predicate (i + predicate_first_dynamic_condition);
}
@@ -850,7 +853,8 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
if (known_aggs.exists ())
{
agg = known_aggs[c->operand_num];
- val = ipa_find_agg_cst_for_param (agg, c->offset, c->by_ref);
+ val = ipa_find_agg_cst_for_param (agg, known_vals[c->operand_num],
+ c->offset, c->by_ref);
}
else
val = NULL_TREE;
@@ -867,21 +871,25 @@ evaluate_conditions_for_known_args (struct cgraph_node *node,
clause |= 1 << (i + predicate_first_dynamic_condition);
continue;
}
- if (c->code == IS_NOT_CONSTANT || c->code == CHANGED)
+ if (c->code == CHANGED)
continue;
- if (operand_equal_p (TYPE_SIZE (TREE_TYPE (c->val)),
- TYPE_SIZE (TREE_TYPE (val)), 0))
+ if (tree_to_shwi (TYPE_SIZE (TREE_TYPE (val))) != c->size)
{
- val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (c->val), val);
+ clause |= 1 << (i + predicate_first_dynamic_condition);
+ continue;
+ }
+ if (c->code == IS_NOT_CONSTANT)
+ continue;
- res = val
- ? fold_binary_to_constant (c->code, boolean_type_node, val, c->val)
- : NULL;
+ val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (c->val), val);
+ res = val
+ ? fold_binary_to_constant (c->code, boolean_type_node, val, c->val)
+ : NULL;
+
+ if (res && integer_zerop (res))
+ continue;
- if (res && integer_zerop (res))
- continue;
- }
clause |= 1 << (i + predicate_first_dynamic_condition);
}
return clause;
@@ -1069,6 +1077,7 @@ reset_inline_summary (struct cgraph_node *node,
reset_inline_edge_summary (e);
for (e = node->indirect_calls; e; e = e->next_callee)
reset_inline_edge_summary (e);
+ info->fp_expressions = false;
}
/* Hook that is called by cgraph.c when a node is removed. */
@@ -1423,6 +1432,8 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
fprintf (f, " inlinable");
if (s->contains_cilk_spawn)
fprintf (f, " contains_cilk_spawn");
+ if (s->fp_expressions)
+ fprintf (f, " fp_expression");
fprintf (f, "\n self time: %i\n", s->self_time);
fprintf (f, " global time: %i\n", s->time);
fprintf (f, " self size: %i\n", s->self_size);
@@ -1487,19 +1498,23 @@ initialize_inline_failed (struct cgraph_edge *e)
{
struct cgraph_node *callee = e->callee;
- if (e->indirect_unknown_callee)
+ if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE
+ && cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+ ;
+ else if (e->indirect_unknown_callee)
e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
else if (!callee->definition)
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
else if (callee->local.redefined_extern_inline)
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
- else if (e->call_stmt_cannot_inline_p)
- e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
else if (cfun && fn_contains_cilk_spawn_p (cfun))
/* We can't inline if the function is spawing a function. */
- e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
+ e->inline_failed = CIF_CILK_SPAWN;
else
e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+ gcc_checking_assert (!e->call_stmt_cannot_inline_p
+ || cgraph_inline_failed_type (e->inline_failed)
+ == CIF_FINAL_ERROR);
}
/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
@@ -1515,16 +1530,21 @@ mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
}
/* If OP refers to value of function parameter, return the corresponding
- parameter. */
+ parameter. If non-NULL, the size of the memory load (or the SSA_NAME of the
+ PARM_DECL) will be stored to *SIZE_P in that case too. */
static tree
-unmodified_parm_1 (gimple *stmt, tree op)
+unmodified_parm_1 (gimple *stmt, tree op, HOST_WIDE_INT *size_p)
{
/* SSA_NAME referring to parm default def? */
if (TREE_CODE (op) == SSA_NAME
&& SSA_NAME_IS_DEFAULT_DEF (op)
&& TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
- return SSA_NAME_VAR (op);
+ {
+ if (size_p)
+ *size_p = tree_to_shwi (TYPE_SIZE (TREE_TYPE (op)));
+ return SSA_NAME_VAR (op);
+ }
/* Non-SSA parm reference? */
if (TREE_CODE (op) == PARM_DECL)
{
@@ -1535,18 +1555,24 @@ unmodified_parm_1 (gimple *stmt, tree op)
walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified, &modified,
NULL);
if (!modified)
- return op;
+ {
+ if (size_p)
+ *size_p = tree_to_shwi (TYPE_SIZE (TREE_TYPE (op)));
+ return op;
+ }
}
return NULL_TREE;
}
/* If OP refers to value of function parameter, return the corresponding
- parameter. Also traverse chains of SSA register assignments. */
+ parameter. Also traverse chains of SSA register assignments. If non-NULL,
+ the size of the memory load (or the SSA_NAME of the PARM_DECL) will be
+ stored to *SIZE_P in that case too. */
static tree
-unmodified_parm (gimple *stmt, tree op)
+unmodified_parm (gimple *stmt, tree op, HOST_WIDE_INT *size_p)
{
- tree res = unmodified_parm_1 (stmt, op);
+ tree res = unmodified_parm_1 (stmt, op, size_p);
if (res)
return res;
@@ -1554,23 +1580,25 @@ unmodified_parm (gimple *stmt, tree op)
&& !SSA_NAME_IS_DEFAULT_DEF (op)
&& gimple_assign_single_p (SSA_NAME_DEF_STMT (op)))
return unmodified_parm (SSA_NAME_DEF_STMT (op),
- gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op)));
+ gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op)),
+ size_p);
return NULL_TREE;
}
/* If OP refers to a value of a function parameter or value loaded from an
aggregate passed to a parameter (either by value or reference), return TRUE
- and store the number of the parameter to *INDEX_P and information whether
- and how it has been loaded from an aggregate into *AGGPOS. INFO describes
- the function parameters, STMT is the statement in which OP is used or
- loaded. */
+ and store the number of the parameter to *INDEX_P, the access size into
+ *SIZE_P, and information whether and how it has been loaded from an
+ aggregate into *AGGPOS. INFO describes the function parameters, STMT is the
+ statement in which OP is used or loaded. */
static bool
unmodified_parm_or_parm_agg_item (struct ipa_func_body_info *fbi,
gimple *stmt, tree op, int *index_p,
+ HOST_WIDE_INT *size_p,
struct agg_position_info *aggpos)
{
- tree res = unmodified_parm_1 (stmt, op);
+ tree res = unmodified_parm_1 (stmt, op, size_p);
gcc_checking_assert (aggpos);
if (res)
@@ -1591,14 +1619,14 @@ unmodified_parm_or_parm_agg_item (struct ipa_func_body_info *fbi,
stmt = SSA_NAME_DEF_STMT (op);
op = gimple_assign_rhs1 (stmt);
if (!REFERENCE_CLASS_P (op))
- return unmodified_parm_or_parm_agg_item (fbi, stmt, op, index_p,
+ return unmodified_parm_or_parm_agg_item (fbi, stmt, op, index_p, size_p,
aggpos);
}
aggpos->agg_contents = true;
return ipa_load_from_parm_agg (fbi, fbi->info->descriptors,
stmt, op, index_p, &aggpos->offset,
- NULL, &aggpos->by_ref);
+ size_p, &aggpos->by_ref);
}
/* See if statement might disappear after inlining.
@@ -1649,7 +1677,7 @@ eliminated_by_inlining_prob (gimple *stmt)
inner_lhs = lhs;
/* Reads of parameter are expected to be free. */
- if (unmodified_parm (stmt, inner_rhs))
+ if (unmodified_parm (stmt, inner_rhs, NULL))
rhs_free = true;
/* Match expressions of form &this->field. Those will most likely
combine with something upstream after inlining. */
@@ -1659,7 +1687,7 @@ eliminated_by_inlining_prob (gimple *stmt)
if (TREE_CODE (op) == PARM_DECL)
rhs_free = true;
else if (TREE_CODE (op) == MEM_REF
- && unmodified_parm (stmt, TREE_OPERAND (op, 0)))
+ && unmodified_parm (stmt, TREE_OPERAND (op, 0), NULL))
rhs_free = true;
}
@@ -1672,7 +1700,7 @@ eliminated_by_inlining_prob (gimple *stmt)
/* Reads of parameters passed by reference
expected to be free (i.e. optimized out after inlining). */
if (TREE_CODE (inner_rhs) == MEM_REF
- && unmodified_parm (stmt, TREE_OPERAND (inner_rhs, 0)))
+ && unmodified_parm (stmt, TREE_OPERAND (inner_rhs, 0), NULL))
rhs_free = true;
/* Copying parameter passed by reference into gimple register is
@@ -1713,7 +1741,7 @@ eliminated_by_inlining_prob (gimple *stmt)
if (TREE_CODE (inner_lhs) == PARM_DECL
|| TREE_CODE (inner_lhs) == RESULT_DECL
|| (TREE_CODE (inner_lhs) == MEM_REF
- && (unmodified_parm (stmt, TREE_OPERAND (inner_lhs, 0))
+ && (unmodified_parm (stmt, TREE_OPERAND (inner_lhs, 0), NULL)
|| (TREE_CODE (TREE_OPERAND (inner_lhs, 0)) == SSA_NAME
&& SSA_NAME_VAR (TREE_OPERAND (inner_lhs, 0))
&& TREE_CODE (SSA_NAME_VAR (TREE_OPERAND
@@ -1744,6 +1772,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
gimple *last;
tree op;
int index;
+ HOST_WIDE_INT size;
struct agg_position_info aggpos;
enum tree_code code, inverted_code;
edge e;
@@ -1760,7 +1789,7 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
/* TODO: handle conditionals like
var = op0 < 4;
if (var != 0). */
- if (unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
+ if (unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &size, &aggpos))
{
code = gimple_cond_code (last);
inverted_code = invert_tree_comparison (code, HONOR_NANS (op));
@@ -1774,9 +1803,10 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
unordered one. Be sure it is not confused with NON_CONSTANT. */
if (this_code != ERROR_MARK)
{
- struct predicate p = add_condition
- (summary, index, &aggpos, this_code,
- unshare_expr_without_location (gimple_cond_rhs (last)));
+ struct predicate p
+ = add_condition (summary, index, size, &aggpos, this_code,
+ unshare_expr_without_location
+ (gimple_cond_rhs (last)));
e->aux = edge_predicate_pool.allocate ();
*(struct predicate *) e->aux = p;
}
@@ -1803,11 +1833,12 @@ set_cond_stmt_execution_predicate (struct ipa_func_body_info *fbi,
|| gimple_call_num_args (set_stmt) != 1)
return;
op2 = gimple_call_arg (set_stmt, 0);
- if (!unmodified_parm_or_parm_agg_item (fbi, set_stmt, op2, &index, &aggpos))
+ if (!unmodified_parm_or_parm_agg_item (fbi, set_stmt, op2, &index, &size,
+ &aggpos))
return;
FOR_EACH_EDGE (e, ei, bb->succs) if (e->flags & EDGE_FALSE_VALUE)
{
- struct predicate p = add_condition (summary, index, &aggpos,
+ struct predicate p = add_condition (summary, index, size, &aggpos,
IS_NOT_CONSTANT, NULL_TREE);
e->aux = edge_predicate_pool.allocate ();
*(struct predicate *) e->aux = p;
@@ -1826,6 +1857,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
gimple *lastg;
tree op;
int index;
+ HOST_WIDE_INT size;
struct agg_position_info aggpos;
edge e;
edge_iterator ei;
@@ -1837,7 +1869,7 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
return;
gswitch *last = as_a <gswitch *> (lastg);
op = gimple_switch_index (last);
- if (!unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &aggpos))
+ if (!unmodified_parm_or_parm_agg_item (fbi, last, op, &index, &size, &aggpos))
return;
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1862,14 +1894,14 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
if (!min && !max)
p = true_predicate ();
else if (!max)
- p = add_condition (summary, index, &aggpos, EQ_EXPR,
+ p = add_condition (summary, index, size, &aggpos, EQ_EXPR,
unshare_expr_without_location (min));
else
{
struct predicate p1, p2;
- p1 = add_condition (summary, index, &aggpos, GE_EXPR,
+ p1 = add_condition (summary, index, size, &aggpos, GE_EXPR,
unshare_expr_without_location (min));
- p2 = add_condition (summary, index, &aggpos, LE_EXPR,
+ p2 = add_condition (summary, index, size, &aggpos, LE_EXPR,
unshare_expr_without_location (max));
p = and_predicates (summary->conds, &p1, &p2);
}
@@ -1970,13 +2002,14 @@ will_be_nonconstant_expr_predicate (struct ipa_node_params *info,
{
tree parm;
int index;
+ HOST_WIDE_INT size;
while (UNARY_CLASS_P (expr))
expr = TREE_OPERAND (expr, 0);
- parm = unmodified_parm (NULL, expr);
+ parm = unmodified_parm (NULL, expr, &size);
if (parm && (index = ipa_get_param_decl_index (info, parm)) >= 0)
- return add_condition (summary, index, NULL, CHANGED, NULL_TREE);
+ return add_condition (summary, index, size, NULL, CHANGED, NULL_TREE);
if (is_gimple_min_invariant (expr))
return false_predicate ();
if (TREE_CODE (expr) == SSA_NAME)
@@ -2037,6 +2070,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
struct predicate op_non_const;
bool is_load;
int base_index;
+ HOST_WIDE_INT size;
struct agg_position_info aggpos;
/* What statments might be optimized away
@@ -2060,7 +2094,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
tree op;
gcc_assert (gimple_assign_single_p (stmt));
op = gimple_assign_rhs1 (stmt);
- if (!unmodified_parm_or_parm_agg_item (fbi, stmt, op, &base_index,
+ if (!unmodified_parm_or_parm_agg_item (fbi, stmt, op, &base_index, &size,
&aggpos))
return p;
}
@@ -2071,7 +2105,7 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
adding conditionals. */
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
- tree parm = unmodified_parm (stmt, use);
+ tree parm = unmodified_parm (stmt, use, NULL);
/* For arguments we can build a condition. */
if (parm && ipa_get_param_decl_index (fbi->info, parm) >= 0)
continue;
@@ -2086,18 +2120,19 @@ will_be_nonconstant_predicate (struct ipa_func_body_info *fbi,
if (is_load)
op_non_const =
- add_condition (summary, base_index, &aggpos, CHANGED, NULL);
+ add_condition (summary, base_index, size, &aggpos, CHANGED, NULL);
else
op_non_const = false_predicate ();
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
- tree parm = unmodified_parm (stmt, use);
+ HOST_WIDE_INT size;
+ tree parm = unmodified_parm (stmt, use, &size);
int index;
if (parm && (index = ipa_get_param_decl_index (fbi->info, parm)) >= 0)
{
if (index != base_index)
- p = add_condition (summary, index, NULL, CHANGED, NULL_TREE);
+ p = add_condition (summary, index, size, NULL, CHANGED, NULL_TREE);
else
continue;
}
@@ -2459,6 +2494,21 @@ clobber_only_eh_bb_p (basic_block bb, bool need_eh = true)
return true;
}
+/* Return true if STMT compute a floating point expression that may be affected
+ by -ffast-math and similar flags. */
+
+static bool
+fp_expression_p (gimple *stmt)
+{
+ ssa_op_iter i;
+ tree op;
+
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF|SSA_OP_USE)
+ if (FLOAT_TYPE_P (TREE_TYPE (op)))
+ return true;
+ return false;
+}
+
/* Compute function body size parameters for NODE.
When EARLY is true, we compute only simple summaries without
non-trivial predicates to drive the early inliner. */
@@ -2733,6 +2783,13 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
this_time * (2 - prob), &p);
}
+ if (!info->fp_expressions && fp_expression_p (stmt))
+ {
+ info->fp_expressions = true;
+ if (dump_file)
+ fprintf (dump_file, " fp_expression set\n");
+ }
+
gcc_assert (time >= 0);
gcc_assert (size >= 0);
}
@@ -2891,67 +2948,78 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
info = inline_summaries->get (node);
reset_inline_summary (node, info);
- /* FIXME: Thunks are inlinable, but tree-inline don't know how to do that.
- Once this happen, we will need to more curefully predict call
- statement size. */
- if (node->thunk.thunk_p)
- {
- struct inline_edge_summary *es = inline_edge_summary (node->callees);
- struct predicate t = true_predicate ();
-
- info->inlinable = 0;
- node->callees->call_stmt_cannot_inline_p = true;
- node->local.can_change_signature = false;
- es->call_stmt_time = 1;
- es->call_stmt_size = 1;
- account_size_time (info, 0, 0, &t);
- return;
- }
-
- /* Even is_gimple_min_invariant rely on current_function_decl. */
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
-
/* Estimate the stack size for the function if we're optimizing. */
- self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
+ self_stack_size = optimize && !node->thunk.thunk_p
+ ? estimated_stack_frame_size (node) : 0;
info->estimated_self_stack_size = self_stack_size;
info->estimated_stack_size = self_stack_size;
info->stack_frame_offset = 0;
- /* Can this function be inlined at all? */
- if (!opt_for_fn (node->decl, optimize)
- && !lookup_attribute ("always_inline",
- DECL_ATTRIBUTES (node->decl)))
- info->inlinable = false;
- else
- info->inlinable = tree_inlinable_function_p (node->decl);
-
- info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
-
- /* Type attributes can use parameter indices to describe them. */
- if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
- node->local.can_change_signature = false;
- else
+ if (node->thunk.thunk_p)
{
- /* Otherwise, inlinable functions always can change signature. */
- if (info->inlinable)
- node->local.can_change_signature = true;
- else
+ struct inline_edge_summary *es = inline_edge_summary (node->callees);
+ struct predicate t = true_predicate ();
+
+ node->local.can_change_signature = false;
+ es->call_stmt_size = eni_size_weights.call_cost;
+ es->call_stmt_time = eni_time_weights.call_cost;
+ account_size_time (info, INLINE_SIZE_SCALE * 2,
+ INLINE_TIME_SCALE * 2, &t);
+ t = not_inlined_predicate ();
+ account_size_time (info, 2 * INLINE_SIZE_SCALE, 0, &t);
+ inline_update_overall_summary (node);
+ info->self_size = info->size;
+ info->self_time = info->time;
+ /* We can not inline instrumetnation clones. */
+ if (node->thunk.add_pointer_bounds_args)
{
- /* Functions calling builtin_apply can not change signature. */
- for (e = node->callees; e; e = e->next_callee)
- {
- tree cdecl = e->callee->decl;
- if (DECL_BUILT_IN (cdecl)
- && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
- && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
- || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
- break;
- }
- node->local.can_change_signature = !e;
+ info->inlinable = false;
+ node->callees->inline_failed = CIF_CHKP;
}
+ else
+ info->inlinable = true;
}
- estimate_function_body_sizes (node, early);
-
+ else
+ {
+ /* Even is_gimple_min_invariant rely on current_function_decl. */
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+
+ /* Can this function be inlined at all? */
+ if (!opt_for_fn (node->decl, optimize)
+ && !lookup_attribute ("always_inline",
+ DECL_ATTRIBUTES (node->decl)))
+ info->inlinable = false;
+ else
+ info->inlinable = tree_inlinable_function_p (node->decl);
+
+ info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
+
+ /* Type attributes can use parameter indices to describe them. */
+ if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
+ node->local.can_change_signature = false;
+ else
+ {
+ /* Otherwise, inlinable functions always can change signature. */
+ if (info->inlinable)
+ node->local.can_change_signature = true;
+ else
+ {
+ /* Functions calling builtin_apply can not change signature. */
+ for (e = node->callees; e; e = e->next_callee)
+ {
+ tree cdecl = e->callee->decl;
+ if (DECL_BUILT_IN (cdecl)
+ && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
+ && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
+ || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
+ break;
+ }
+ node->local.can_change_signature = !e;
+ }
+ }
+ estimate_function_body_sizes (node, early);
+ pop_cfun ();
+ }
for (e = node->callees; e; e = e->next_callee)
if (e->callee->comdat_local_p ())
break;
@@ -2968,8 +3036,6 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
gcc_assert (info->time == info->self_time
&& info->size == info->self_size);
}
-
- pop_cfun ();
}
@@ -3377,7 +3443,8 @@ remap_predicate (struct inline_summary *info,
ap.by_ref = c->by_ref;
cond_predicate = add_condition (info,
operand_map[c->operand_num],
- &ap, c->code, c->val);
+ c->size, &ap, c->code,
+ c->val);
}
}
/* Fixed conditions remains same, construct single
@@ -3577,6 +3644,8 @@ inline_merge_summary (struct cgraph_edge *edge)
else
toplev_predicate = true_predicate ();
+ info->fp_expressions |= callee_info->fp_expressions;
+
if (callee_info->conds)
evaluate_properties_for_edge (edge, true, &clause, NULL, NULL, NULL);
if (ipa_node_params_sum && callee_info->conds)
@@ -4080,17 +4149,9 @@ inline_analyze_function (struct cgraph_node *node)
{
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
- {
- if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
- e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
- e->call_stmt_cannot_inline_p = true;
- }
+ e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
for (e = node->indirect_calls; e; e = e->next_callee)
- {
- if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
- e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
- e->call_stmt_cannot_inline_p = true;
- }
+ e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
}
pop_cfun ();
@@ -4229,6 +4290,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
bp = streamer_read_bitpack (&ib);
info->inlinable = bp_unpack_value (&bp, 1);
info->contains_cilk_spawn = bp_unpack_value (&bp, 1);
+ info->fp_expressions = bp_unpack_value (&bp, 1);
count2 = streamer_read_uhwi (&ib);
gcc_assert (!info->conds);
@@ -4236,6 +4298,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
{
struct condition c;
c.operand_num = streamer_read_uhwi (&ib);
+ c.size = streamer_read_uhwi (&ib);
c.code = (enum tree_code) streamer_read_uhwi (&ib);
c.val = stream_read_tree (&ib, data_in);
bp = streamer_read_bitpack (&ib);
@@ -4395,11 +4458,13 @@ inline_write_summary (void)
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, info->inlinable, 1);
bp_pack_value (&bp, info->contains_cilk_spawn, 1);
+ bp_pack_value (&bp, info->fp_expressions, 1);
streamer_write_bitpack (&bp);
streamer_write_uhwi (ob, vec_safe_length (info->conds));
for (i = 0; vec_safe_iterate (info->conds, i, &c); i++)
{
streamer_write_uhwi (ob, c->operand_num);
+ streamer_write_uhwi (ob, c->size);
streamer_write_uhwi (ob, c->code);
stream_write_tree (ob, c->val, true);
bp = bitpack_create (ob->main_stream);