aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2015-09-27 09:02:00 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2015-09-27 09:02:00 +0000
commitf11a7b6d57f6fcba1bf2e5a0403dc49120195320 (patch)
tree0f5ba4acabc38f459581c262648b0feb65f83a32 /gcc/cfgexpand.c
parentedfc19ab2bf68516aa9697d11949637af884148e (diff)
downloadgcc-f11a7b6d57f6fcba1bf2e5a0403dc49120195320.zip
gcc-f11a7b6d57f6fcba1bf2e5a0403dc49120195320.tar.gz
gcc-f11a7b6d57f6fcba1bf2e5a0403dc49120195320.tar.bz2
revert to assign_parms assignments using default defs
Revert the fragile and complicated changes to assign_parms designed to enable it to use RTL assigments chosen by cfgexpand, and instead have cfgexpand use the RTL assignments by assign_parms, keying them off of the default defs that are now necessarily introduced for each parm and result. The possible lack of a default def was already a problem, and the fallbacks in place were not enough, as shown by PR67312. We now have checking asserts in set_rtl that verify that we're assigning to each var a piece of RTL that matches the expectations set forth by use_register_for_decl. for gcc/ChangeLog PR rtl-optimization/64164 PR tree-optimization/67312 PR middle-end/67340 PR middle-end/67490 PR bootstrap/67597 * cfgexpand.c (parm_in_stack_slot_p): Remove. (ssa_default_def_partition): Remove. (get_rtl_for_parm_ssa_default_def): Remove. (set_rtl): Check that RTL assignments match expectations. Loop on SUBREGs, CONCATs and PARALLELs subexprs. Set only the default def location for params and results. Record SSA names or types in REG and MEM attrs, respectively. (set_parm_rtl): New. (expand_one_ssa_partition): Drop logic that assigned MEMs with unassigned addresses. (adjust_one_expanded_partition_var): Don't accept NULL RTL on deferred stack alloc vars. (expand_used_vars): Skip partitions holding parm default defs. Move adjust_one_expanded_partition_var loop... (pass_expand::execute): ... here. Drop redundant assert. Adjust comments before the final loop over all ssa names. Require assigned rtl of parms and results to match exactly. Reset its attributes to match them, not any other variables in the same partition. (expand_debug_expr): Use entry value for PARM's default defs only iff they have zero nondebug uses. * cfgexpand.h (parm_in_stack_slot_p): Remove. (get_rtl_for_parm_ssa_default_def): Remove. (set_parm_rtl): Declare. * doc/invoke.texi: Improve wording. * explow.c (promote_decl_mode): Fix promote_function_mode for result decls not by reference. (promote_ssa_mode): Disregard BLKmode from promote_decl, and bypass TYPE_MODE to get the actual vector mode. * function.c: Include tree-dfa.h. Revert 2015-08-14's and 2015-08-19's changes as follows. Drop include of basic-block.h and df.h. (rtl_for_parm): Remove. (maybe_reset_rtl_for_parm): Remove. (parm_in_unassigned_mem_p): Remove. (use_register_for_decl): Add logic for RESULT_DECLs matching assign_parms' behavior. (split_complex_args): Revert. (assign_parms_augmented_arg_list): Revert. Add comment referencing the logic above. (assign_parm_adjust_stack_rtl): Revert. (assign_parm_setup_block): Revert. Use set_parm_rtl instead of SET_DECL_RTL. Set up a REG if the parm demands so. (assign_parm_setup_reg): Revert. Consolidated SET_DECL_RTL calls into a single set_parm_rtl. Set up a temporary RTL temporarily for expand_assignment. (assign_parm_setup_stack): Revert. Use set_parm_rtl. (assign_parms_unsplit_complex): Revert. Use set_parm_rtl. (assign_bounds): Revert. (assign_parms): Revert. Use set_parm_rtl. (allocate_struct_function): Relayout result and parms of non-abstruct functions. (expand_function_start): Revert. Use set_parm_rtl. If the result is not a hard reg, create a pseudo from the promoted mode of the default def. Promote static chain mode. * tree-outof-ssa.c (remove_ssa_form): Drop unused partition_has_default_def. Set up partitions_for_parm_default_defs. (finish_out_of_ssa): Remove partition_has_default_def. Release partitions_for_parm_default_defs. * tree-outof-ssa.h (struct ssaexpand): Remove partition_has_default_def. Add partitions_for_parm_default_defs. * tree-ssa-coalesce.c: Include tree-dfa.h, tm_p.h and stor-layout.h. (build_ssa_conflict_graph): Fix conflict-detection of default defs of even unused default defs of params and results. (for_all_parms): New. (create_default_def): New. (register_default_def): New. (coalesce_with_default): New. (create_outofssa_var_map): Create default defs for all parms and results, and register their partitions. Add GIMPLE_RETURN operands as coalesce candidates with results. Add default defs of each parm or result as coalesce candidates with its other defs. Mark each result def, and each default def of parms, as used_in_copy. (gimple_can_coalesce_p): Call it. Call use_register_for_decl with the ssa names, even anonymous ones. Drop parm_in_stack_slot_p calls. Require same signedness and alignment. (coalesce_ssa_name): Add coalesce candidates for all defs of each parm and result, even unused ones. (parm_default_def_partition_arg): New type. (set_parm_default_def_partition): New. (get_parm_default_def_partitions): New. * tree-ssa-coalesce.h (get_parm_default_def_partitions): New. * tree-ssa-live.c (partition_view_init): Regard unused defs of parms and results as used. (verify_live_on_entry): Don't error out just because they're not live. for gcc/testsuite/ChangeLog PR rtl-optimization/64164 PR tree-optimization/67312 * gcc.dg/pr67312.c: New. From Zdenek Sojka. * gcc.target/i386/stackalign/return-4.c: Add -O. From-SVN: r228175
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r--gcc/cfgexpand.c332
1 files changed, 171 insertions, 161 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 6c9284f..58e55d2 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -99,6 +99,8 @@ static rtx expand_debug_expr (tree);
static bool defer_stack_allocation (tree, bool);
+static void record_alignment_for_reg_var (unsigned int);
+
/* Return an expression tree corresponding to the RHS of GIMPLE
statement STMT. */
@@ -172,111 +174,86 @@ leader_merge (tree cur, tree next)
return cur;
}
-/* Return true if VAR is a PARM_DECL or a RESULT_DECL that ought to be
- assigned to a stack slot. We can't have expand_one_ssa_partition
- choose their address: the pseudo holding the address would be set
- up too late for assign_params to copy the parameter if needed.
-
- Such parameters are likely passed as a pointer to the value, rather
- than as a value, and so we must not coalesce them, nor allocate
- stack space for them before determining the calling conventions for
- them.
-
- For their SSA_NAMEs, expand_one_ssa_partition emits RTL as MEMs
- with pc_rtx as the address, and then it replaces the pc_rtx with
- NULL so as to make sure the MEM is not used before it is adjusted
- in assign_parm_setup_reg. */
-
-bool
-parm_in_stack_slot_p (tree var)
-{
- if (!var || VAR_P (var))
- return false;
-
- gcc_assert (TREE_CODE (var) == PARM_DECL
- || TREE_CODE (var) == RESULT_DECL);
-
- return !use_register_for_decl (var);
-}
-
-/* Return the partition of the default SSA_DEF for decl VAR. */
-
-static int
-ssa_default_def_partition (tree var)
-{
- tree name = ssa_default_def (cfun, var);
-
- if (!name)
- return NO_PARTITION;
-
- return var_to_partition (SA.map, name);
-}
-
-/* Return the RTL for the default SSA def of a PARM or RESULT, if
- there is one. */
-
-rtx
-get_rtl_for_parm_ssa_default_def (tree var)
-{
- gcc_assert (TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == RESULT_DECL);
-
- if (!is_gimple_reg (var))
- return NULL_RTX;
-
- /* If we've already determined RTL for the decl, use it. This is
- not just an optimization: if VAR is a PARM whose incoming value
- is unused, we won't find a default def to use its partition, but
- we still want to use the location of the parm, if it was used at
- all. During assign_parms, until a location is assigned for the
- VAR, RTL can only for a parm or result if we're not coalescing
- across variables, when we know we're coalescing all SSA_NAMEs of
- each parm or result, and we're not coalescing them with names
- pertaining to other variables, such as other parms' default
- defs. */
- if (DECL_RTL_SET_P (var))
- {
- gcc_assert (DECL_RTL (var) != pc_rtx);
- return DECL_RTL (var);
- }
-
- int part = ssa_default_def_partition (var);
- if (part == NO_PARTITION)
- return NULL_RTX;
-
- return SA.partition_to_pseudo[part];
-}
-
/* Associate declaration T with storage space X. If T is no
SSA name this is exactly SET_DECL_RTL, otherwise make the
partition of T associated with X. */
static inline void
set_rtl (tree t, rtx x)
{
- if (x && SSAVAR (t))
+ gcc_checking_assert (!x
+ || !(TREE_CODE (t) == SSA_NAME || is_gimple_reg (t))
+ || (use_register_for_decl (t)
+ ? (REG_P (x)
+ || (GET_CODE (x) == CONCAT
+ && (REG_P (XEXP (x, 0))
+ || SUBREG_P (XEXP (x, 0)))
+ && (REG_P (XEXP (x, 1))
+ || SUBREG_P (XEXP (x, 1))))
+ || (GET_CODE (x) == PARALLEL
+ && SSAVAR (t)
+ && TREE_CODE (SSAVAR (t)) == RESULT_DECL
+ && !flag_tree_coalesce_vars))
+ : (MEM_P (x) || x == pc_rtx
+ || (GET_CODE (x) == CONCAT
+ && MEM_P (XEXP (x, 0))
+ && MEM_P (XEXP (x, 1))))));
+ /* Check that the RTL for SSA_NAMEs and gimple-reg PARM_DECLs and
+ RESULT_DECLs has the expected mode. For memory, we accept
+ unpromoted modes, since that's what we're likely to get. For
+ PARM_DECLs and RESULT_DECLs, we'll have been called by
+ set_parm_rtl, which will give us the default def, so we don't
+ have to compute it ourselves. For RESULT_DECLs, we accept mode
+ mismatches too, as long as we're not coalescing across variables,
+ so that we don't reject BLKmode PARALLELs or unpromoted REGs. */
+ gcc_checking_assert (!x || x == pc_rtx || TREE_CODE (t) != SSA_NAME
+ || (SSAVAR (t) && TREE_CODE (SSAVAR (t)) == RESULT_DECL
+ && !flag_tree_coalesce_vars)
+ || !use_register_for_decl (t)
+ || GET_MODE (x) == promote_ssa_mode (t, NULL));
+
+ if (x)
{
bool skip = false;
tree cur = NULL_TREE;
-
- if (MEM_P (x))
- cur = MEM_EXPR (x);
- else if (REG_P (x))
- cur = REG_EXPR (x);
- else if (GET_CODE (x) == CONCAT
- && REG_P (XEXP (x, 0)))
- cur = REG_EXPR (XEXP (x, 0));
- else if (GET_CODE (x) == PARALLEL)
- cur = REG_EXPR (XVECEXP (x, 0, 0));
- else if (x == pc_rtx)
+ rtx xm = x;
+
+ retry:
+ if (MEM_P (xm))
+ cur = MEM_EXPR (xm);
+ else if (REG_P (xm))
+ cur = REG_EXPR (xm);
+ else if (SUBREG_P (xm))
+ {
+ gcc_assert (subreg_lowpart_p (xm));
+ xm = SUBREG_REG (xm);
+ goto retry;
+ }
+ else if (GET_CODE (xm) == CONCAT)
+ {
+ xm = XEXP (xm, 0);
+ goto retry;
+ }
+ else if (GET_CODE (xm) == PARALLEL)
+ {
+ xm = XVECEXP (xm, 0, 0);
+ gcc_assert (GET_CODE (xm) == EXPR_LIST);
+ xm = XEXP (xm, 0);
+ goto retry;
+ }
+ else if (xm == pc_rtx)
skip = true;
else
gcc_unreachable ();
- tree next = skip ? cur : leader_merge (cur, SSAVAR (t));
+ tree next = skip ? cur : leader_merge (cur, SSAVAR (t) ? SSAVAR (t) : t);
if (cur != next)
{
if (MEM_P (x))
- set_mem_attributes (x, next, true);
+ set_mem_attributes (x,
+ next && TREE_CODE (next) == SSA_NAME
+ ? TREE_TYPE (next)
+ : next, true);
else
set_reg_attrs_for_decl_rtl (next, x);
}
@@ -294,13 +271,11 @@ set_rtl (tree t, rtx x)
}
/* For the benefit of debug information at -O0 (where
vartracking doesn't run) record the place also in the base
- DECL. For PARMs and RESULTs, we may end up resetting these
- in function.c:maybe_reset_rtl_for_parm, but in some rare
- cases we may need them (unused and overwritten incoming
- value, that at -O0 must share the location with the other
- uses in spite of the missing default def), and this may be
- the only chance to preserve them. */
- if (x && x != pc_rtx && SSA_NAME_VAR (t))
+ DECL. For PARMs and RESULTs, do so only when setting the
+ default def. */
+ if (x && x != pc_rtx && SSA_NAME_VAR (t)
+ && (VAR_P (SSA_NAME_VAR (t))
+ || SSA_NAME_IS_DEFAULT_DEF (t)))
{
tree var = SSA_NAME_VAR (t);
/* If we don't yet have something recorded, just record it now. */
@@ -1242,6 +1217,49 @@ account_stack_vars (void)
return size;
}
+/* Record the RTL assignment X for the default def of PARM. */
+
+extern void
+set_parm_rtl (tree parm, rtx x)
+{
+ gcc_assert (TREE_CODE (parm) == PARM_DECL
+ || TREE_CODE (parm) == RESULT_DECL);
+
+ if (x && !MEM_P (x))
+ {
+ unsigned int align = MINIMUM_ALIGNMENT (TREE_TYPE (parm),
+ TYPE_MODE (TREE_TYPE (parm)),
+ TYPE_ALIGN (TREE_TYPE (parm)));
+
+ /* If the variable alignment is very large we'll dynamicaly
+ allocate it, which means that in-frame portion is just a
+ pointer. ??? We've got a pseudo for sure here, do we
+ actually dynamically allocate its spilling area if needed?
+ ??? Isn't it a problem when POINTER_SIZE also exceeds
+ MAX_SUPPORTED_STACK_ALIGNMENT, as on cris and lm32? */
+ if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
+ align = POINTER_SIZE;
+
+ record_alignment_for_reg_var (align);
+ }
+
+ if (!is_gimple_reg (parm))
+ return set_rtl (parm, x);
+
+ tree ssa = ssa_default_def (cfun, parm);
+ if (!ssa)
+ return set_rtl (parm, x);
+
+ int part = var_to_partition (SA.map, ssa);
+ gcc_assert (part != NO_PARTITION);
+
+ bool changed = bitmap_bit_p (SA.partitions_for_parm_default_defs, part);
+ gcc_assert (changed);
+
+ set_rtl (ssa, x);
+ gcc_assert (DECL_RTL (parm) == x);
+}
+
/* A subroutine of expand_one_var. Called to immediately assign rtl
to a variable to be allocated in the stack frame. */
@@ -1349,37 +1367,7 @@ expand_one_ssa_partition (tree var)
if (!use_register_for_decl (var))
{
- /* We can't risk having the parm assigned to a MEM location
- whose address references a pseudo, for the pseudo will only
- be set up after arguments are copied to the stack slot.
-
- If the parm doesn't have a default def (e.g., because its
- incoming value is unused), then we want to let assign_params
- do the allocation, too. In this case we want to make sure
- SSA_NAMEs associated with the parm don't get assigned to more
- than one partition, lest we'd create two unassigned stac
- slots for the same parm, thus the assert at the end of the
- block. */
- if (parm_in_stack_slot_p (SSA_NAME_VAR (var))
- && (ssa_default_def_partition (SSA_NAME_VAR (var)) == part
- || !ssa_default_def (cfun, SSA_NAME_VAR (var))))
- {
- expand_one_stack_var_at (var, pc_rtx, 0, 0);
- rtx x = SA.partition_to_pseudo[part];
- gcc_assert (GET_CODE (x) == MEM);
- gcc_assert (XEXP (x, 0) == pc_rtx);
- /* Reset the address, so that any attempt to use it will
- ICE. It will be adjusted in assign_parm_setup_reg. */
- XEXP (x, 0) = NULL_RTX;
- /* If the RTL associated with the parm is not what we have
- just created, the parm has been split over multiple
- partitions. In order for this to work, we must have a
- default def for the parm, otherwise assign_params won't
- know what to do. */
- gcc_assert (DECL_RTL_IF_SET (SSA_NAME_VAR (var)) == x
- || ssa_default_def (cfun, SSA_NAME_VAR (var)));
- }
- else if (defer_stack_allocation (var, true))
+ if (defer_stack_allocation (var, true))
add_stack_var (var);
else
expand_one_stack_var_1 (var);
@@ -1393,8 +1381,8 @@ expand_one_ssa_partition (tree var)
set_rtl (var, x);
}
-/* Record the association between the RTL generated for a partition
- and the underlying variable of the SSA_NAME. */
+/* Record the association between the RTL generated for partition PART
+ and the underlying variable of the SSA_NAME VAR. */
static void
adjust_one_expanded_partition_var (tree var)
@@ -1410,12 +1398,7 @@ adjust_one_expanded_partition_var (tree var)
rtx x = SA.partition_to_pseudo[part];
- if (!x)
- {
- /* This var will get a stack slot later. */
- gcc_assert (defer_stack_allocation (var, true));
- return;
- }
+ gcc_assert (x);
set_rtl (var, x);
@@ -2040,6 +2023,9 @@ expand_used_vars (void)
for (i = 0; i < SA.map->num_partitions; i++)
{
+ if (bitmap_bit_p (SA.partitions_for_parm_default_defs, i))
+ continue;
+
tree var = partition_to_var (SA.map, i);
gcc_assert (!virtual_operand_p (var));
@@ -2047,9 +2033,6 @@ expand_used_vars (void)
expand_one_ssa_partition (var);
}
- for (i = 1; i < num_ssa_names; i++)
- adjust_one_expanded_partition_var (ssa_name (i));
-
if (flag_stack_protect == SPCT_FLAG_STRONG)
gen_stack_protect_signal
= stack_protect_decl_p () || stack_protect_return_slot_p ();
@@ -4947,26 +4930,27 @@ expand_debug_expr (tree exp)
}
else
{
+ /* If this is a reference to an incoming value of
+ parameter that is never used in the code or where the
+ incoming value is never used in the code, use
+ PARM_DECL's DECL_RTL if set. */
+ if (SSA_NAME_IS_DEFAULT_DEF (exp)
+ && SSA_NAME_VAR (exp)
+ && TREE_CODE (SSA_NAME_VAR (exp)) == PARM_DECL
+ && has_zero_uses (exp))
+ {
+ op0 = expand_debug_parm_decl (SSA_NAME_VAR (exp));
+ if (op0)
+ goto adjust_mode;
+ op0 = expand_debug_expr (SSA_NAME_VAR (exp));
+ if (op0)
+ goto adjust_mode;
+ }
+
int part = var_to_partition (SA.map, exp);
if (part == NO_PARTITION)
- {
- /* If this is a reference to an incoming value of parameter
- that is never used in the code or where the incoming
- value is never used in the code, use PARM_DECL's
- DECL_RTL if set. */
- if (SSA_NAME_IS_DEFAULT_DEF (exp)
- && TREE_CODE (SSA_NAME_VAR (exp)) == PARM_DECL)
- {
- op0 = expand_debug_parm_decl (SSA_NAME_VAR (exp));
- if (op0)
- goto adjust_mode;
- op0 = expand_debug_expr (SSA_NAME_VAR (exp));
- if (op0)
- goto adjust_mode;
- }
- return NULL;
- }
+ return NULL;
gcc_assert (part >= 0 && (unsigned)part < SA.map->num_partitions);
@@ -6216,9 +6200,26 @@ pass_expand::execute (function *fun)
parm_birth_insn = var_seq;
}
- /* If we have a class containing differently aligned pointers
- we need to merge those into the corresponding RTL pointer
- alignment. */
+ /* Now propagate the RTL assignment of each partition to the
+ underlying var of each SSA_NAME. */
+ for (i = 1; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+
+ if (!name
+ /* We might have generated new SSA names in
+ update_alias_info_with_stack_vars. They will have a NULL
+ defining statements, and won't be part of the partitioning,
+ so ignore those. */
+ || !SSA_NAME_DEF_STMT (name))
+ continue;
+
+ adjust_one_expanded_partition_var (name);
+ }
+
+ /* Clean up RTL of variables that straddle across multiple
+ partitions, and check that the rtl of any PARM_DECLs that are not
+ cleaned up is that of their default defs. */
for (i = 1; i < num_ssa_names; i++)
{
tree name = ssa_name (i);
@@ -6235,9 +6236,6 @@ pass_expand::execute (function *fun)
if (part == NO_PARTITION)
continue;
- gcc_assert (SA.partition_to_pseudo[part]
- || defer_stack_allocation (name, true));
-
/* If this decl was marked as living in multiple places, reset
this now to NULL. */
tree var = SSA_NAME_VAR (name);
@@ -6252,7 +6250,19 @@ pass_expand::execute (function *fun)
rtx in = DECL_RTL_IF_SET (var);
gcc_assert (in);
rtx out = SA.partition_to_pseudo[part];
- gcc_assert (in == out || rtx_equal_p (in, out));
+ gcc_assert (in == out);
+
+ /* Now reset VAR's RTL to IN, so that the _EXPR attrs match
+ those expected by debug backends for each parm and for
+ the result. This is particularly important for stabs,
+ whose register elimination from parm's DECL_RTL may cause
+ -fcompare-debug differences as SET_DECL_RTL changes reg's
+ attrs. So, make sure the RTL already has the parm as the
+ EXPR, so that it won't change. */
+ SET_DECL_RTL (var, NULL_RTX);
+ if (MEM_P (in))
+ set_mem_attributes (in, var, true);
+ SET_DECL_RTL (var, in);
}
}