This is an automated email from the git hooks/post-receive script.
unknown user pushed a commit to branch aoliva/pr64164 in repository gcc.
commit 3672f750fe682bc50bbdb4113ec93f81f8617451 Author: Alexandre Oliva aoliva@redhat.com Date: Sat Aug 1 22:04:17 2015 -0300
try special handlling of byref parms
for gcc/ChangeLog
PR middle-end/67034 * cfgexpand.c (parm_maybe_byref_p): New. (expand_one_ssa_partition): Call it. Expand maybe-byref parms with a placeholder for the mem addr. * function.c (assign_parm_setup_reg): Replace the placeholder with a newly-created pseudo. Arrange for the pseudo to be initialized from the incoming passed pointer. Don't copy the BLKmode data, just check that it was a maybe_byref parm. * cfgexpand.h (parm_maybe_byref_p): Declare. * tree-ssa-coalesce.c: Include cfgexpand.h. (gimple_can_coalesce_p): Do not coalesce maybe-byref parms with SSA_NAMEs of other variables, or anonymous SSA_NAMEs. --- gcc/cfgexpand.c | 33 +++++++++++++++++++++++++++++++- gcc/cfgexpand.h | 1 + gcc/function.c | 51 ++++++++++++++++++++++--------------------------- gcc/tree-ssa-coalesce.c | 12 +++++++++--- 4 files changed, 65 insertions(+), 32 deletions(-)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 9577ad6d..5b89359 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -172,6 +172,26 @@ leader_merge (tree cur, tree next) return cur; }
+/* Return true if VAR is a PARM_DECL or a RESULT_DECL of type BLKmode. + 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_maybe_byref_p (tree var) +{ + if (!var || VAR_P (var)) + return false; + + gcc_assert (TREE_CODE (var) == PARM_DECL + || TREE_CODE (var) == RESULT_DECL); + + return TYPE_MODE (TREE_TYPE (var)) == BLKmode; +}
/* Return the RTL for the default SSA def of a PARM or RESULT, if there is one. */ @@ -1315,7 +1335,18 @@ expand_one_ssa_partition (tree var)
if (!use_register_for_decl (var)) { - if (defer_stack_allocation (var, true)) + if (parm_maybe_byref_p (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 (GET_MODE (x) == BLKmode); + 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; + } + else if (defer_stack_allocation (var, true)) add_stack_var (var); else expand_one_stack_var_1 (var); diff --git a/gcc/cfgexpand.h b/gcc/cfgexpand.h index 602579d..987cf356 100644 --- a/gcc/cfgexpand.h +++ b/gcc/cfgexpand.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern tree gimple_assign_rhs_to_tree (gimple); extern HOST_WIDE_INT estimated_stack_frame_size (struct cgraph_node *); +extern bool parm_maybe_byref_p (tree); extern rtx get_rtl_for_parm_ssa_default_def (tree var);
diff --git a/gcc/function.c b/gcc/function.c index 390b81e..84ab365 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3103,24 +3103,34 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tr [...] = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp, TREE_TYPE (current_function_decl), 2);
- rtx from_expand = rtl_for_parm (all, parm); + rtx from_expand = parmreg = rtl_for_parm (all, parm);
- if (from_expand) + if (from_expand && !data->passed_pointer) { - parmreg = from_expand; - if (!data->passed_pointer && GET_MODE (parmreg) != promoted_nominal_mode) + if (GET_MODE (parmreg) != promoted_nominal_mode) parmreg = gen_lowpart (promoted_nominal_mode, parmreg); } - else + else if (!from_expand || parm_maybe_byref_p (parm)) { parmreg = gen_reg_rtx (promoted_nominal_mode); if (!DECL_ARTIFICIAL (parm)) mark_user_reg (parmreg); + + if (from_expand) + { + gcc_assert (data->passed_pointer); + gcc_assert (GET_CODE (from_expand) == MEM + && GET_MODE (from_expand) == BLKmode + && XEXP (from_expand, 0) == NULL_RTX); + XEXP (from_expand, 0) = parmreg; + } }
/* If this was an item that we received a pointer to, set DECL_RTL appropriately. */ - if (!from_expand && data->passed_pointer) + if (from_expand) + SET_DECL_RTL (parm, from_expand); + else if (data->passed_pointer) { rtx x = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data->passed_type)), parmreg); set_mem_attributes (x, parm, 1); @@ -3141,8 +3151,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
need_conversion = (data->nominal_mode != data->passed_mode || promoted_nominal_mode != data->promoted_mode); - gcc_assert (!(need_conversion && data->passed_pointer)); - moved = from_expand && data->passed_pointer; + moved = false;
if (need_conversion && GET_MODE_CLASS (data->nominal_mode) == MODE_INT @@ -3281,15 +3290,12 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tr [...] if (data->passed_pointer && (from_expand || TYPE_MODE (TREE_TYPE (parm)) != BLKmode)) { - rtx src = DECL_RTL (parm); - /* We can't use nominal_mode, because it will have been set to Pmode above. We must use the actual mode of the parm. */ if (from_expand) { + parmreg = from_expand; gcc_assert (GET_MODE (parmreg) == TYPE_MODE (TREE_TYPE (parm))); - src = gen_rtx_MEM (GET_MODE (parmreg), validated_mem); - set_mem_attributes (src, parm, 1); } else if (use_register_for_decl (parm)) { @@ -3308,14 +3314,14 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tr [...] set_mem_attributes (parmreg, parm, 1); }
- if (GET_MODE (parmreg) != GET_MODE (src)) + if (GET_MODE (parmreg) != GET_MODE (DECL_RTL (parm))) { - rtx tempreg = gen_reg_rtx (GET_MODE (src)); + rtx tempreg = gen_reg_rtx (GET_MODE (DECL_RTL (parm))); int unsigned_p = TYPE_UNSIGNED (TREE_TYPE (parm));
push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn); - emit_move_insn (tempreg, src); + emit_move_insn (tempreg, DECL_RTL (parm)); tempreg = convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p); emit_move_insn (parmreg, tempreg); all->first_conversion_insn = get_insns (); @@ -3325,20 +3331,9 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, did_conversion = true; } else if (GET_MODE (parmreg) == BLKmode) - { - push_to_sequence2 (all->first_conversion_insn, - all->last_conversion_insn); - gcc_assert (TREE_CODE (data->passed_type) == POINTER_TYPE); - gcc_assert (TREE_TYPE (data->passed_type) == TREE_TYPE (parm)); - emit_block_move (parmreg, src, - GEN_INT (int_size_in_bytes (TREE_TYPE (parm))), - BLOCK_OP_NORMAL);; - all->first_conversion_insn = get_insns (); - all->last_conversion_insn = get_last_insn (); - end_sequence (); - } + gcc_assert (parm_maybe_byref_p (parm)); else - emit_move_insn (parmreg, src); + emit_move_insn (parmreg, DECL_RTL (parm));
SET_DECL_RTL (parm, parmreg);
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index a622728..08ce72c 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-iterator.h" #include "tree-ssa-live.h" #include "tree-ssa-coalesce.h" +#include "cfgexpand.h" #include "explow.h" #include "diagnostic-core.h"
@@ -1379,10 +1380,15 @@ gimple_can_coalesce_p (tree name1, tree name2) /* Check that the promoted modes are the same. We don't want to coalesce if the promoted modes would be different. Only PARM_DECLs and RESULT_DECLs have different promotion rules, - so skip the test if we both are variables or anonymous - SSA_NAMEs. */ + so skip the test if both are variables, or both are anonymous + SSA_NAMEs. Now, if a parm or result has BLKmode, do not + coalesce its SSA versions with those of any other variables, + because it may be passed by reference. */ return ((!var1 || VAR_P (var1)) && (!var2 || VAR_P (var2))) - || promote_ssa_mode (name1, NULL) == promote_ssa_mode (name2, NULL); + || (/* The case var1 == var2 is already covered above. */ + !parm_maybe_byref_p (var1) + && !parm_maybe_byref_p (var2) + && promote_ssa_mode (name1, NULL) == promote_ssa_mode (name2, NULL)); }
/* If the types are not the same, check for a canonical type match. This