aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2021-05-17 16:35:38 +0200
committerRichard Biener <rguenther@suse.de>2021-05-18 13:55:37 +0200
commitd3a0208e433dc5aed7ef8deab8d74b6da55e1985 (patch)
tree2e65420ea3648c9aa6d0a5c0f7623792d5eb3fe4
parentb5c3145ad9ac04654d4947d34d1e9dc5c26f4c53 (diff)
Avoid setting TREE_ADDRESSABLE on stack vars during RTL expansion
This avoids setting TREE_ADDRESSABLE on variables we want to force to the stack. Instead track those in a temporary bitmap and force stack expansion that way, leaving TREE_ADDRESSABLE alone, not pessimizing future alias queries. 2021-05-17 Richard Biener <rguenther@suse.de> * cfgexpand.c (expand_one_var): Pass in forced_stack_var and honor it when expanding. (expand_used_vars_for_block): Pass through forced_stack_var. (expand_used_vars): Likewise. (discover_nonconstant_array_refs_r): Set bits in forced_stack_vars instead of marking vars TREE_ADDRESSABLE. (avoid_type_punning_on_regs): Likewise. (discover_nonconstant_array_refs): Likewise. (pass_expand::execute): Create and pass down forced_stack_var bitmap. For parameters and returns temporarily set TREE_ADDRESSABLE when expand_function_start.
-rw-r--r--gcc/cfgexpand.c107
1 files changed, 75 insertions, 32 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index e3814ee9d06..3e6f7cafc4c 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1719,7 +1719,8 @@ defer_stack_allocation (tree var, bool toplevel)
*/
static poly_uint64
-expand_one_var (tree var, bool toplevel, bool really_expand)
+expand_one_var (tree var, bool toplevel, bool really_expand,
+ bitmap forced_stack_var = NULL)
{
unsigned int align = BITS_PER_UNIT;
tree origvar = var;
@@ -1797,7 +1798,9 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
expand_one_error_var (var);
}
}
- else if (use_register_for_decl (var))
+ else if (use_register_for_decl (var)
+ && (!forced_stack_var
+ || !bitmap_bit_p (forced_stack_var, DECL_UID (var))))
{
if (really_expand)
expand_one_register_var (origvar);
@@ -1842,7 +1845,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
TOPLEVEL is true if this is the outermost BLOCK. */
static void
-expand_used_vars_for_block (tree block, bool toplevel)
+expand_used_vars_for_block (tree block, bool toplevel, bitmap forced_stack_vars)
{
tree t;
@@ -1851,11 +1854,11 @@ expand_used_vars_for_block (tree block, bool toplevel)
if (TREE_USED (t)
&& ((!VAR_P (t) && TREE_CODE (t) != RESULT_DECL)
|| !DECL_NONSHAREABLE (t)))
- expand_one_var (t, toplevel, true);
+ expand_one_var (t, toplevel, true, forced_stack_vars);
/* Expand all variables at containing levels. */
for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
- expand_used_vars_for_block (t, false);
+ expand_used_vars_for_block (t, false, forced_stack_vars);
}
/* A subroutine of expand_used_vars. Walk down through the BLOCK tree
@@ -2139,7 +2142,7 @@ stack_protect_return_slot_p ()
/* Expand all variables used in the function. */
static rtx_insn *
-expand_used_vars (void)
+expand_used_vars (bitmap forced_stack_vars)
{
tree var, outer_block = DECL_INITIAL (current_function_decl);
auto_vec<tree> maybe_local_decls;
@@ -2216,7 +2219,7 @@ expand_used_vars (void)
TREE_USED (var) = 1;
if (expand_now)
- expand_one_var (var, true, true);
+ expand_one_var (var, true, true, forced_stack_vars);
next:
if (DECL_ARTIFICIAL (var) && !DECL_IGNORED_P (var))
@@ -2251,7 +2254,7 @@ expand_used_vars (void)
/* At this point, all variables within the block tree with TREE_USED
set are actually used by the optimized function. Lay them out. */
- expand_used_vars_for_block (outer_block, true);
+ expand_used_vars_for_block (outer_block, true, forced_stack_vars);
tree attribs = DECL_ATTRIBUTES (current_function_decl);
if (stack_vars_num > 0)
@@ -6241,9 +6244,10 @@ construct_exit_block (void)
static tree
discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
- void *data ATTRIBUTE_UNUSED)
+ void *data)
{
tree t = *tp;
+ bitmap forced_stack_vars = (bitmap)((walk_stmt_info *)data)->info;
if (IS_TYPE_OR_DECL_P (t))
*walk_subtrees = 0;
@@ -6267,8 +6271,9 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
{
t = get_base_address (t);
if (t && DECL_P (t)
- && DECL_MODE (t) != BLKmode)
- TREE_ADDRESSABLE (t) = 1;
+ && DECL_MODE (t) != BLKmode
+ && !TREE_ADDRESSABLE (t))
+ bitmap_set_bit (forced_stack_vars, DECL_UID (t));
}
*walk_subtrees = 0;
@@ -6283,9 +6288,10 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
tree base = get_base_address (t);
if (base
&& DECL_P (base)
+ && !TREE_ADDRESSABLE (base)
&& DECL_MODE (base) != BLKmode
&& GET_MODE_SIZE (DECL_MODE (base)).is_constant ())
- TREE_ADDRESSABLE (base) = 1;
+ bitmap_set_bit (forced_stack_vars, DECL_UID (base));
*walk_subtrees = 0;
}
@@ -6298,7 +6304,7 @@ discover_nonconstant_array_refs_r (tree * tp, int *walk_subtrees,
suitable for raw bits processing (like XFmode on i?86). */
static void
-avoid_type_punning_on_regs (tree t)
+avoid_type_punning_on_regs (tree t, bitmap forced_stack_vars)
{
machine_mode access_mode = TYPE_MODE (TREE_TYPE (t));
if (access_mode != BLKmode
@@ -6312,7 +6318,7 @@ avoid_type_punning_on_regs (tree t)
GET_MODE_BITSIZE (GET_MODE_INNER (DECL_MODE (base))))
/* Double check in the expensive way we really would get a pseudo. */
&& use_register_for_decl (base))
- TREE_ADDRESSABLE (base) = 1;
+ bitmap_set_bit (forced_stack_vars, DECL_UID (base));
}
/* RTL expansion is not able to compile array references with variable
@@ -6321,38 +6327,49 @@ avoid_type_punning_on_regs (tree t)
scenario. */
static void
-discover_nonconstant_array_refs (void)
+discover_nonconstant_array_refs (bitmap forced_stack_vars)
{
basic_block bb;
gimple_stmt_iterator gsi;
+ walk_stmt_info wi = {};
+ wi.info = forced_stack_vars;
FOR_EACH_BB_FN (bb, cfun)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
if (!is_gimple_debug (stmt))
{
- walk_gimple_op (stmt, discover_nonconstant_array_refs_r, NULL);
+ walk_gimple_op (stmt, discover_nonconstant_array_refs_r, &wi);
gcall *call = dyn_cast <gcall *> (stmt);
if (call && gimple_call_internal_p (call))
- switch (gimple_call_internal_fn (call))
- {
- case IFN_LOAD_LANES:
- /* The source must be a MEM. */
- mark_addressable (gimple_call_arg (call, 0));
- break;
- case IFN_STORE_LANES:
- /* The destination must be a MEM. */
- mark_addressable (gimple_call_lhs (call));
- break;
- default:
- break;
- }
+ {
+ tree cand = NULL_TREE;
+ switch (gimple_call_internal_fn (call))
+ {
+ case IFN_LOAD_LANES:
+ /* The source must be a MEM. */
+ cand = gimple_call_arg (call, 0);
+ break;
+ case IFN_STORE_LANES:
+ /* The destination must be a MEM. */
+ cand = gimple_call_lhs (call);
+ break;
+ default:
+ break;
+ }
+ if (cand)
+ cand = get_base_address (cand);
+ if (cand
+ && DECL_P (cand)
+ && use_register_for_decl (cand))
+ bitmap_set_bit (forced_stack_vars, DECL_UID (cand));
+ }
if (gimple_vdef (stmt))
{
tree t = gimple_get_lhs (stmt);
if (t && REFERENCE_CLASS_P (t))
- avoid_type_punning_on_regs (t);
+ avoid_type_punning_on_regs (t, forced_stack_vars);
}
}
}
@@ -6553,7 +6570,8 @@ pass_expand::execute (function *fun)
}
/* Mark arrays indexed with non-constant indices with TREE_ADDRESSABLE. */
- discover_nonconstant_array_refs ();
+ auto_bitmap forced_stack_vars;
+ discover_nonconstant_array_refs (forced_stack_vars);
/* Make sure all values used by the optimization passes have sane
defaults. */
@@ -6601,7 +6619,7 @@ pass_expand::execute (function *fun)
timevar_push (TV_VAR_EXPAND);
start_sequence ();
- var_ret_seq = expand_used_vars ();
+ var_ret_seq = expand_used_vars (forced_stack_vars);
var_seq = get_insns ();
end_sequence ();
@@ -6621,9 +6639,34 @@ pass_expand::execute (function *fun)
(int) param_ssp_buffer_size);
}
+ /* Temporarily mark PARM_DECLs and RESULT_DECLs we need to expand to
+ memory addressable so expand_function_start can emit the required
+ copies. */
+ auto_vec<tree, 16> marked_parms;
+ for (tree parm = DECL_ARGUMENTS (current_function_decl); parm;
+ parm = DECL_CHAIN (parm))
+ if (!TREE_ADDRESSABLE (parm)
+ && bitmap_bit_p (forced_stack_vars, DECL_UID (parm)))
+ {
+ TREE_ADDRESSABLE (parm) = 1;
+ marked_parms.safe_push (parm);
+ }
+ if (DECL_RESULT (current_function_decl)
+ && !TREE_ADDRESSABLE (DECL_RESULT (current_function_decl))
+ && bitmap_bit_p (forced_stack_vars,
+ DECL_UID (DECL_RESULT (current_function_decl))))
+ {
+ TREE_ADDRESSABLE (DECL_RESULT (current_function_decl)) = 1;
+ marked_parms.safe_push (DECL_RESULT (current_function_decl));
+ }
+
/* Set up parameters and prepare for return, for the function. */
expand_function_start (current_function_decl);
+ /* Clear TREE_ADDRESSABLE again. */
+ while (!marked_parms.is_empty ())
+ TREE_ADDRESSABLE (marked_parms.pop ()) = 0;
+
/* If we emitted any instructions for setting up the variables,
emit them before the FUNCTION_START note. */
if (var_seq)