diff options
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r-- | gcc/cfgexpand.c | 332 |
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); } } |