Commit 27e29549 by Richard Henderson Committed by Richard Henderson

calls.c (precompute_register_parameters): Force all PARALLELs into pseudo registers.

        * calls.c (precompute_register_parameters): Force all PARALLELs
        into pseudo registers.
        (load_register_parameters): Copy PARALLELs into hard registers.
        * function.c (assign_parm_setup_block): Copy PARALLELS into
        pseudo registers.  Do emit_group_store in conversion_insns.
        * expr.c (emit_group_load_1): Rename from emit_group_load, take
        tmps as an argument.  Move final copy loop ...
        (emit_group_load): ... here.  New function.
        (emit_group_load_into_temps, emit_group_move_into_temps): New.
        * expr.h: Declare them.

From-SVN: r90613
parent eaf0dc02
2004-11-13 Richard Henderson <rth@redhat.com>
* calls.c (precompute_register_parameters): Force all PARALLELs
into pseudo registers.
(load_register_parameters): Copy PARALLELs into hard registers.
* function.c (assign_parm_setup_block): Copy PARALLELS into
pseudo registers. Do emit_group_store in conversion_insns.
* expr.c (emit_group_load_1): Rename from emit_group_load, take
tmps as an argument. Move final copy loop ...
(emit_group_load): ... here. New function.
(emit_group_load_into_temps, emit_group_move_into_temps): New.
* expr.h: Declare them.
2004-11-14 Kazu Hirata <kazu@cs.umass.edu>
* tree-cfg.c, tree-if-conv.c, tree-ssa-loop-ivopts.c,
......
......@@ -644,7 +644,8 @@ call_expr_flags (tree t)
Set REG_PARM_SEEN if we encounter a register parameter. */
static void
precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg_parm_seen)
precompute_register_parameters (int num_actuals, struct arg_data *args,
int *reg_parm_seen)
{
int i;
......@@ -679,6 +680,17 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
args[i].value, args[i].unsignedp);
/* If we're going to have to load the value by parts, pull the
parts into pseudos. The part extraction process can involve
non-trivial computation. */
if (GET_CODE (args[i].reg) == PARALLEL)
{
tree type = TREE_TYPE (args[i].tree_value);
args[i].value
= emit_group_load_into_temps (args[i].reg, args[i].value,
type, int_size_in_bytes (type));
}
/* If the value is expensive, and we are inside an appropriately
short loop, put the value into a pseudo and then put the pseudo
into the hard reg.
......@@ -687,13 +699,13 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg
register parameters. This is to avoid reload conflicts while
loading the parameters registers. */
if ((! (REG_P (args[i].value)
|| (GET_CODE (args[i].value) == SUBREG
&& REG_P (SUBREG_REG (args[i].value)))))
&& args[i].mode != BLKmode
&& rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
&& ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
|| optimize))
else if ((! (REG_P (args[i].value)
|| (GET_CODE (args[i].value) == SUBREG
&& REG_P (SUBREG_REG (args[i].value)))))
&& args[i].mode != BLKmode
&& rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
&& ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
|| optimize))
args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
}
}
......@@ -1454,11 +1466,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
locations. The Irix 6 ABI has examples of this. */
if (GET_CODE (reg) == PARALLEL)
{
tree type = TREE_TYPE (args[i].tree_value);
emit_group_load (reg, args[i].value, type,
int_size_in_bytes (type));
}
emit_group_move (reg, args[i].value);
/* If simple case, just do move. If normal partial, store_one_arg
has already loaded the register for us. In all other cases,
......
......@@ -1557,15 +1557,14 @@ gen_group_rtx (rtx orig)
return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
}
/* Emit code to move a block ORIG_SRC of type TYPE to a block DST,
where DST is non-consecutive registers represented by a PARALLEL.
SSIZE represents the total size of block ORIG_SRC in bytes, or -1
if not known. */
/* A subroutine of emit_group_load. Arguments as for emit_group_load,
except that values are placed in TMPS[i], and must later be moved
into corrosponding XEXP (XVECEXP (DST, 0, i), 0) element. */
void
emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
static void
emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
{
rtx *tmps, src;
rtx src;
int start, i;
enum machine_mode m = GET_MODE (orig_src);
......@@ -1585,7 +1584,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
/* ...and back again. */
if (imode != BLKmode)
src = gen_lowpart (imode, src);
emit_group_load (dst, src, type, ssize);
emit_group_load_1 (tmps, dst, src, type, ssize);
return;
}
......@@ -1596,8 +1595,6 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
else
start = 1;
tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0));
/* Process the pieces. */
for (i = start; i < XVECLEN (dst, 0); i++)
{
......@@ -1709,10 +1706,61 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
build_int_cst (NULL_TREE, shift), tmps[i], 0);
}
}
/* Emit code to move a block SRC of type TYPE to a block DST,
where DST is non-consecutive registers represented by a PARALLEL.
SSIZE represents the total size of block ORIG_SRC in bytes, or -1
if not known. */
void
emit_group_load (rtx dst, rtx src, tree type, int ssize)
{
rtx *tmps;
int i;
tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0));
emit_group_load_1 (tmps, dst, src, type, ssize);
/* Copy the extracted pieces into the proper (probable) hard regs. */
for (i = start; i < XVECLEN (dst, 0); i++)
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
for (i = 0; i < XVECLEN (dst, 0); i++)
{
rtx d = XEXP (XVECEXP (dst, 0, i), 0);
if (d == NULL)
continue;
emit_move_insn (d, tmps[i]);
}
}
/* Similar, but load SRC into new pseudos in a format that looks like
PARALLEL. This can later be fed to emit_group_move to get things
in the right place. */
rtx
emit_group_load_into_temps (rtx parallel, rtx src, tree type, int ssize)
{
rtvec vec;
int i;
vec = rtvec_alloc (XVECLEN (parallel, 0));
emit_group_load_1 (&RTVEC_ELT (vec, 0), parallel, src, type, ssize);
/* Convert the vector to look just like the original PARALLEL, except
with the computed values. */
for (i = 0; i < XVECLEN (parallel, 0); i++)
{
rtx e = XVECEXP (parallel, 0, i);
rtx d = XEXP (e, 0);
if (d)
{
d = force_reg (GET_MODE (d), RTVEC_ELT (vec, i));
e = alloc_EXPR_LIST (REG_NOTE_KIND (e), d, XEXP (e, 1));
}
RTVEC_ELT (vec, i) = e;
}
return gen_rtx_PARALLEL (GET_MODE (parallel), vec);
}
/* Emit code to move a block SRC to block DST, where SRC and DST are
......@@ -1733,6 +1781,27 @@ emit_group_move (rtx dst, rtx src)
XEXP (XVECEXP (src, 0, i), 0));
}
/* Move a group of registers represented by a PARALLEL into pseudos. */
rtx
emit_group_move_into_temps (rtx src)
{
rtvec vec = rtvec_alloc (XVECLEN (src, 0));
int i;
for (i = 0; i < XVECLEN (src, 0); i++)
{
rtx e = XVECEXP (src, 0, i);
rtx d = XEXP (e, 0);
if (d)
e = alloc_EXPR_LIST (REG_NOTE_KIND (e), copy_to_reg (d), XEXP (e, 1));
RTVEC_ELT (vec, i) = e;
}
return gen_rtx_PARALLEL (GET_MODE (src), vec);
}
/* Emit code to move a block SRC to a block ORIG_DST of type TYPE,
where SRC is non-consecutive registers represented by a PARALLEL.
SSIZE represents the total size of block ORIG_DST, or -1 if not
......
......@@ -387,10 +387,16 @@ extern rtx gen_group_rtx (rtx);
PARALLEL. */
extern void emit_group_load (rtx, rtx, tree, int);
/* Similarly, but load into new temporaries. */
extern rtx emit_group_load_into_temps (rtx, rtx, tree, int);
/* Move a non-consecutive group of registers represented by a PARALLEL into
a non-consecutive group of registers represented by a PARALLEL. */
extern void emit_group_move (rtx, rtx);
/* Move a group of registers represented by a PARALLEL into pseudos. */
extern rtx emit_group_move_into_temps (rtx);
/* Store a BLKmode value from non-consecutive registers represented by a
PARALLEL. */
extern void emit_group_store (rtx, rtx, tree, int);
......
......@@ -2536,11 +2536,15 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data)
present and valid in DATA->STACK_RTL. */
static void
assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
assign_parm_setup_block (struct assign_parm_data_all *all,
tree parm, struct assign_parm_data_one *data)
{
rtx entry_parm = data->entry_parm;
rtx stack_parm = data->stack_parm;
if (GET_CODE (entry_parm) == PARALLEL)
entry_parm = emit_group_move_into_temps (entry_parm);
/* If we've a non-block object that's nevertheless passed in parts,
reconstitute it in register operations rather than on the stack. */
if (GET_CODE (entry_parm) == PARALLEL
......@@ -2550,6 +2554,8 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
{
rtx parmreg = gen_reg_rtx (data->nominal_mode);
push_to_sequence (all->conversion_insns);
/* For values returned in multiple registers, handle possible
incompatible calls to emit_group_store.
......@@ -2572,6 +2578,10 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
else
emit_group_store (parmreg, entry_parm, data->nominal_type,
int_size_in_bytes (data->nominal_type));
all->conversion_insns = get_insns ();
end_sequence ();
SET_DECL_RTL (parm, parmreg);
return;
}
......@@ -2609,7 +2619,12 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
/* Handle values in multiple non-contiguous locations. */
if (GET_CODE (entry_parm) == PARALLEL)
emit_group_store (mem, entry_parm, data->passed_type, size);
{
push_to_sequence (all->conversion_insns);
emit_group_store (mem, entry_parm, data->passed_type, size);
all->conversion_insns = get_insns ();
end_sequence ();
}
else if (size == 0)
;
......@@ -2648,7 +2663,7 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
{
rtx tem, x;
int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
rtx reg = gen_rtx_REG (word_mode, REGNO (data->entry_parm));
rtx reg = gen_lowpart (word_mode, entry_parm);
x = expand_shift (LSHIFT_EXPR, word_mode, reg,
build_int_cst (NULL_TREE, by),
......@@ -2657,11 +2672,11 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
emit_move_insn (tem, x);
}
else
move_block_from_reg (REGNO (data->entry_parm), mem,
move_block_from_reg (REGNO (entry_parm), mem,
size_stored / UNITS_PER_WORD);
}
else
move_block_from_reg (REGNO (data->entry_parm), mem,
move_block_from_reg (REGNO (entry_parm), mem,
size_stored / UNITS_PER_WORD);
}
......@@ -2782,7 +2797,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
emit_move_insn (tempreg, DECL_RTL (parm));
tempreg = convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p);
emit_move_insn (parmreg, tempreg);
all->conversion_insns = get_insns();
all->conversion_insns = get_insns ();
end_sequence ();
did_conversion = true;
......@@ -3083,7 +3098,7 @@ assign_parms (tree fndecl)
assign_parm_adjust_stack_rtl (&data);
if (assign_parm_setup_block_p (&data))
assign_parm_setup_block (parm, &data);
assign_parm_setup_block (&all, parm, &data);
else if (data.passed_pointer || use_register_for_decl (parm))
assign_parm_setup_reg (&all, parm, &data);
else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment