re PR tree-optimization/86214 (Strongly increased stack usage)
PR tree-optimization/86214 * tree-inline.h (struct copy_body_data): Add add_clobbers_to_eh_landing_pads member. * tree-inline.c (add_clobbers_to_eh_landing_pad): New function. (copy_edges_for_bb): Call it if EH edge destination is < id->add_clobbers_to_eh_landing_pads. Fix a comment typo. (expand_call_inline): Set id->add_clobbers_to_eh_landing_pads if flag_stack_reuse != SR_NONE and clear it afterwards. * g++.dg/opt/pr86214-1.C: New test. * g++.dg/opt/pr86214-2.C: New test. From-SVN: r268067
This commit is contained in:
parent
6616a31808
commit
d0bf921f6a
|
@ -1,3 +1,14 @@
|
||||||
|
2019-01-18 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/86214
|
||||||
|
* tree-inline.h (struct copy_body_data): Add
|
||||||
|
add_clobbers_to_eh_landing_pads member.
|
||||||
|
* tree-inline.c (add_clobbers_to_eh_landing_pad): New function.
|
||||||
|
(copy_edges_for_bb): Call it if EH edge destination is <
|
||||||
|
id->add_clobbers_to_eh_landing_pads. Fix a comment typo.
|
||||||
|
(expand_call_inline): Set id->add_clobbers_to_eh_landing_pads
|
||||||
|
if flag_stack_reuse != SR_NONE and clear it afterwards.
|
||||||
|
|
||||||
2019-01-18 Christophe Lyon <christophe.lyon@linaro.org>
|
2019-01-18 Christophe Lyon <christophe.lyon@linaro.org>
|
||||||
|
|
||||||
PR target/85596
|
PR target/85596
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2019-01-18 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR tree-optimization/86214
|
||||||
|
* g++.dg/opt/pr86214-1.C: New test.
|
||||||
|
* g++.dg/opt/pr86214-2.C: New test.
|
||||||
|
|
||||||
2019-01-18 Christophe Lyon <christophe.lyon@linaro.org>
|
2019-01-18 Christophe Lyon <christophe.lyon@linaro.org>
|
||||||
|
|
||||||
* gcc.target/arm/pr77904.c: Add dg-warning for sp clobber.
|
* gcc.target/arm/pr77904.c: Add dg-warning for sp clobber.
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// PR tree-optimization/86214
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-O2 -Wstack-usage=15000" }
|
||||||
|
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
struct A { A (); ~A (); int a; void qux (const char *); };
|
||||||
|
int bar (char *);
|
||||||
|
|
||||||
|
static inline A
|
||||||
|
foo ()
|
||||||
|
{
|
||||||
|
char b[8192];
|
||||||
|
int x = bar (b);
|
||||||
|
A s;
|
||||||
|
if (x > 0 && (size_t) x < sizeof b)
|
||||||
|
s.qux (b);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
baz () // { dg-bogus "stack usage is" }
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
char c[1024];
|
||||||
|
bar (c);
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// PR tree-optimization/86214
|
||||||
|
// { dg-do compile }
|
||||||
|
// { dg-options "-O2 -Wstack-usage=15000" }
|
||||||
|
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
struct A { A (); ~A (); int a; void qux (const char *); };
|
||||||
|
int bar (char *);
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline)) A
|
||||||
|
foo ()
|
||||||
|
{
|
||||||
|
char b[8192];
|
||||||
|
int x = bar (b);
|
||||||
|
A s;
|
||||||
|
if (x > 0 && (size_t) x < sizeof b)
|
||||||
|
s.qux (b);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
baz () // { dg-bogus "stack usage is" }
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
foo (); foo (); foo (); foo (); foo ();
|
||||||
|
}
|
|
@ -2190,6 +2190,40 @@ update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Insert clobbers for automatic variables of inlined ID->src_fn
|
||||||
|
function at the start of basic block BB. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_clobbers_to_eh_landing_pad (basic_block bb, copy_body_data *id)
|
||||||
|
{
|
||||||
|
tree var;
|
||||||
|
unsigned int i;
|
||||||
|
FOR_EACH_VEC_SAFE_ELT (id->src_cfun->local_decls, i, var)
|
||||||
|
if (VAR_P (var)
|
||||||
|
&& !DECL_HARD_REGISTER (var)
|
||||||
|
&& !TREE_THIS_VOLATILE (var)
|
||||||
|
&& !DECL_HAS_VALUE_EXPR_P (var)
|
||||||
|
&& !is_gimple_reg (var)
|
||||||
|
&& auto_var_in_fn_p (var, id->src_fn))
|
||||||
|
{
|
||||||
|
tree *t = id->decl_map->get (var);
|
||||||
|
if (!t)
|
||||||
|
continue;
|
||||||
|
tree new_var = *t;
|
||||||
|
if (VAR_P (new_var)
|
||||||
|
&& !DECL_HARD_REGISTER (new_var)
|
||||||
|
&& !TREE_THIS_VOLATILE (new_var)
|
||||||
|
&& !DECL_HAS_VALUE_EXPR_P (new_var)
|
||||||
|
&& !is_gimple_reg (new_var)
|
||||||
|
&& auto_var_in_fn_p (new_var, id->dst_fn))
|
||||||
|
{
|
||||||
|
gimple_stmt_iterator gsi = gsi_after_labels (bb);
|
||||||
|
tree clobber = build_clobber (TREE_TYPE (new_var));
|
||||||
|
gimple *clobber_stmt = gimple_build_assign (new_var, clobber);
|
||||||
|
gsi_insert_before (&gsi, clobber_stmt, GSI_NEW_STMT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy edges from BB into its copy constructed earlier, scale profile
|
/* Copy edges from BB into its copy constructed earlier, scale profile
|
||||||
accordingly. Edges will be taken care of later. Assume aux
|
accordingly. Edges will be taken care of later. Assume aux
|
||||||
|
@ -2232,7 +2266,7 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
|
||||||
if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
|
if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* When doing function splitting, we must decreate count of the return block
|
/* When doing function splitting, we must decrease count of the return block
|
||||||
which was previously reachable by block we did not copy. */
|
which was previously reachable by block we did not copy. */
|
||||||
if (single_succ_p (bb) && single_succ_edge (bb)->dest->index == EXIT_BLOCK)
|
if (single_succ_p (bb) && single_succ_edge (bb)->dest->index == EXIT_BLOCK)
|
||||||
FOR_EACH_EDGE (old_edge, ei, bb->preds)
|
FOR_EACH_EDGE (old_edge, ei, bb->preds)
|
||||||
|
@ -2317,8 +2351,16 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den,
|
||||||
e->probability = old_edge->probability;
|
e->probability = old_edge->probability;
|
||||||
|
|
||||||
FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
|
FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
|
||||||
if ((e->flags & EDGE_EH) && !e->probability.initialized_p ())
|
if (e->flags & EDGE_EH)
|
||||||
e->probability = profile_probability::never ();
|
{
|
||||||
|
if (!e->probability.initialized_p ())
|
||||||
|
e->probability = profile_probability::never ();
|
||||||
|
if (e->dest->index < id->add_clobbers_to_eh_landing_pads)
|
||||||
|
{
|
||||||
|
add_clobbers_to_eh_landing_pad (e->dest, id);
|
||||||
|
id->add_clobbers_to_eh_landing_pads = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4565,6 +4607,8 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
|
||||||
id->decl_map = new hash_map<tree, tree>;
|
id->decl_map = new hash_map<tree, tree>;
|
||||||
dst = id->debug_map;
|
dst = id->debug_map;
|
||||||
id->debug_map = NULL;
|
id->debug_map = NULL;
|
||||||
|
if (flag_stack_reuse != SR_NONE)
|
||||||
|
id->add_clobbers_to_eh_landing_pads = last_basic_block_for_fn (cfun);
|
||||||
|
|
||||||
/* Record the function we are about to inline. */
|
/* Record the function we are about to inline. */
|
||||||
id->src_fn = fn;
|
id->src_fn = fn;
|
||||||
|
@ -4872,6 +4916,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
id->assign_stmts.release ();
|
id->assign_stmts.release ();
|
||||||
|
id->add_clobbers_to_eh_landing_pads = 0;
|
||||||
|
|
||||||
/* Output the inlining info for this abstract function, since it has been
|
/* Output the inlining info for this abstract function, since it has been
|
||||||
inlined. If we don't do this now, we can lose the information about the
|
inlined. If we don't do this now, we can lose the information about the
|
||||||
|
|
|
@ -155,6 +155,12 @@ struct copy_body_data
|
||||||
/* A list of addressable local variables remapped into the caller
|
/* A list of addressable local variables remapped into the caller
|
||||||
when inlining a call within an OpenMP SIMD-on-SIMT loop. */
|
when inlining a call within an OpenMP SIMD-on-SIMT loop. */
|
||||||
vec<tree> *dst_simt_vars;
|
vec<tree> *dst_simt_vars;
|
||||||
|
|
||||||
|
/* If clobbers for local variables from the inline function
|
||||||
|
that need to live in memory should be added to EH landing pads
|
||||||
|
outside of the inlined function, this should be the number
|
||||||
|
of basic blocks in the caller before inlining. Zero otherwise. */
|
||||||
|
int add_clobbers_to_eh_landing_pads;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Weights of constructions for estimate_num_insns. */
|
/* Weights of constructions for estimate_num_insns. */
|
||||||
|
|
Loading…
Reference in New Issue