for gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR debug/47106
PR debug/47402
* cfgexpand.c (account_used_vars_for_block): Disregard used flag.
(estimated_stack_frame_size): Prefer referenced vars over scope
block vars.
* tree-flow.h (referenced_var_lookup_in): Declare.
* tree-inline.c (remap_decl): Only mark VAR_DECLs as referenced
that were referenced in the original function.
(copy_decl_for_dup_finish): Likewise.
* tree-dfa.c (referenced_var_lookup_in): Split out of...
(referenced_var_lookup): ... this.
for gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR debug/47106
PR debug/47402
* g++.dg/debug/pr47106.C: New.
===================================================================
@@ -1325,8 +1325,7 @@ account_used_vars_for_block (tree block,
/* Expand all variables at this level. */
for (t = BLOCK_VARS (block); t ; t = DECL_CHAIN (t))
- if (var_ann (t) && is_used_p (t))
- size += expand_one_var (t, toplevel, false);
+ size += expand_one_var (t, toplevel, false);
/* Expand all variables at containing levels. */
for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
@@ -1381,20 +1380,38 @@ estimated_stack_frame_size (tree decl)
size_t i;
tree var, outer_block = DECL_INITIAL (current_function_decl);
unsigned ix;
+ referenced_var_iterator rvi;
tree old_cur_fun_decl = current_function_decl;
+
current_function_decl = decl;
push_cfun (DECL_STRUCT_FUNCTION (decl));
- init_vars_expansion ();
-
- FOR_EACH_LOCAL_DECL (cfun, ix, var)
+ /* We want to count only referenced vars, but if asked to estimate
+ stack size before we compute them, guess based on local decls and
+ scopes. We have to make sure we compute the same values for
+ debug and non-debug compilations, in spite of the removal of
+ unused variables from lexical blocks, but this removal never
+ occurs before referenced vars are computed. Even when we perform
+ inlining and versioning, we register referenced vars, and can
+ thus use them for further stack size estimation. */
+ if (gimple_in_ssa_p (cfun))
+ {
+ gcc_checking_assert (gimple_referenced_vars (cfun));
+ FOR_EACH_REFERENCED_VAR (var, rvi)
+ size += expand_one_var (var, true, false);
+ }
+ else
{
- /* TREE_USED marks local variables that do not appear in lexical
- blocks. We don't want to expand those that do twice. */
- if (TREE_USED (var))
- size += expand_one_var (var, true, false);
+ FOR_EACH_LOCAL_DECL (cfun, ix, var)
+ {
+ /* TREE_USED marks local variables that do not appear in
+ lexical blocks. We don't want to expand those that do
+ twice. */
+ if (TREE_USED (var))
+ size += expand_one_var (var, true, false);
+ }
+ size += account_used_vars_for_block (outer_block, true);
}
- size += account_used_vars_for_block (outer_block, true);
if (stack_vars_num > 0)
{
===================================================================
@@ -319,6 +319,7 @@ typedef struct
!end_referenced_vars_p (&(ITER)); \
(VAR) = next_referenced_var (&(ITER)))
+extern tree referenced_var_lookup_in (htab_t, unsigned int);
extern tree referenced_var_lookup (unsigned int);
extern bool referenced_var_check_and_insert (tree);
#define num_referenced_vars htab_elements (gimple_referenced_vars (cfun))
===================================================================
@@ -317,7 +317,12 @@ remap_decl (tree decl, copy_body_data *i
|| TREE_CODE (t) == RESULT_DECL || TREE_CODE (t) == PARM_DECL))
{
get_var_ann (t);
- add_referenced_var (t);
+ if (TREE_CODE (decl) != VAR_DECL
+ || !gimple_referenced_vars (DECL_STRUCT_FUNCTION (id->src_fn))
+ || referenced_var_lookup_in (gimple_referenced_vars
+ (DECL_STRUCT_FUNCTION (id->src_fn)),
+ DECL_UID (decl)))
+ add_referenced_var (t);
}
return t;
}
@@ -4753,6 +4758,14 @@ copy_decl_for_dup_finish (copy_body_data
new function. */
DECL_CONTEXT (copy) = id->dst_fn;
+ if (TREE_CODE (decl) == VAR_DECL
+ && gimple_referenced_vars (cfun)
+ && gimple_referenced_vars (DECL_STRUCT_FUNCTION (id->src_fn))
+ && referenced_var_lookup_in (gimple_referenced_vars
+ (DECL_STRUCT_FUNCTION (id->src_fn)),
+ DECL_UID (decl)))
+ add_referenced_var (copy);
+
return copy;
}
===================================================================
@@ -490,10 +490,18 @@ find_referenced_vars_in (gimple stmt)
tree
referenced_var_lookup (unsigned int uid)
{
+ return referenced_var_lookup_in (gimple_referenced_vars (cfun), uid);
+}
+
+/* Lookup UID in REFVARS and return the associated variable. */
+
+tree
+referenced_var_lookup_in (htab_t refvars, unsigned int uid)
+{
tree h;
struct tree_decl_minimal in;
in.uid = uid;
- h = (tree) htab_find_with_hash (gimple_referenced_vars (cfun), &in, uid);
+ h = (tree) htab_find_with_hash (refvars, &in, uid);
return h;
}
===================================================================
@@ -0,0 +1,37 @@
+// { dg-do compile }
+// { dg-options "-O -fpartial-inlining -flto -fconserve-stack -fcompare-debug" }
+
+void end (int, int) __attribute__ ((__noreturn__));
+
+struct S
+{
+ int i;
+ S *s;
+};
+
+inline bool f (S *s)
+{
+ if (!s->s)
+ end (0, 0);
+ return s->s == s;
+}
+
+inline bool
+baz (S s1, S)
+{
+ while (f (&s1));
+}
+
+inline bool
+bar (S s1, S s2, S)
+{
+ baz (s1, s2);
+}
+
+S getS ();
+
+bool
+foo ()
+{
+ bar (getS (), getS (), getS ());
+}