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>
|
||||
|
||||
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>
|
||||
|
||||
* gcc.target/arm/pr77904.c: Add dg-warning for sp clobber.
|
||||
|
30
gcc/testsuite/g++.dg/opt/pr86214-1.C
Normal file
30
gcc/testsuite/g++.dg/opt/pr86214-1.C
Normal file
@ -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 ();
|
||||
}
|
28
gcc/testsuite/g++.dg/opt/pr86214-2.C
Normal file
28
gcc/testsuite/g++.dg/opt/pr86214-2.C
Normal file
@ -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
|
||||
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)
|
||||
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. */
|
||||
if (single_succ_p (bb) && single_succ_edge (bb)->dest->index == EXIT_BLOCK)
|
||||
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;
|
||||
|
||||
FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
|
||||
if ((e->flags & EDGE_EH) && !e->probability.initialized_p ())
|
||||
e->probability = profile_probability::never ();
|
||||
if (e->flags & EDGE_EH)
|
||||
{
|
||||
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>;
|
||||
dst = id->debug_map;
|
||||
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. */
|
||||
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->add_clobbers_to_eh_landing_pads = 0;
|
||||
|
||||
/* 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
|
||||
|
@ -155,6 +155,12 @@ struct copy_body_data
|
||||
/* A list of addressable local variables remapped into the caller
|
||||
when inlining a call within an OpenMP SIMD-on-SIMT loop. */
|
||||
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. */
|
||||
|
Loading…
Reference in New Issue
Block a user