aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
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);
}
}