Commit 00d8a4c1 by Richard Kenner

(fixup_var_refs{,_insns}): Add new parms for promoted mode and signedness;

all callers changed.
Insert mode conversions when required.
(fixup_var_refs_1): Add new parms for mode and signedness; handle SUBREGs
for promoted values.
(assign_parms): Promote the mode of parameters when useful for the target
machine.

From-SVN: r2175
parent 1499e0a8
...@@ -495,7 +495,7 @@ pop_function_context () ...@@ -495,7 +495,7 @@ pop_function_context ()
{ {
struct var_refs_queue *queue = p->fixup_var_refs_queue; struct var_refs_queue *queue = p->fixup_var_refs_queue;
for (; queue; queue = queue->next) for (; queue; queue = queue->next)
fixup_var_refs (queue->modified); fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp);
} }
free (p); free (p);
...@@ -812,11 +812,17 @@ put_var_into_stack (decl) ...@@ -812,11 +812,17 @@ put_var_into_stack (decl)
{ {
register rtx reg; register rtx reg;
register rtx new = 0; register rtx new = 0;
enum machine_mode promoted_mode, decl_mode;
struct function *function = 0; struct function *function = 0;
tree context = decl_function_context (decl); tree context = decl_function_context (decl);
/* Get the current rtl used for this object. */ /* Get the current rtl used for this object and it's original mode. */
reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl); reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl);
promoted_mode = GET_MODE (reg);
/* Get the declared mode for this object. */
decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
: DECL_MODE (decl));
/* If this variable comes from an outer function, /* If this variable comes from an outer function,
find that function's saved context. */ find that function's saved context. */
...@@ -847,7 +853,7 @@ put_var_into_stack (decl) ...@@ -847,7 +853,7 @@ put_var_into_stack (decl)
new = function->parm_reg_stack_loc[REGNO (reg)]; new = function->parm_reg_stack_loc[REGNO (reg)];
if (new == 0) if (new == 0)
new = assign_outer_stack_local (GET_MODE (reg), new = assign_outer_stack_local (GET_MODE (reg),
GET_MODE_SIZE (GET_MODE (reg)), GET_MODE_SIZE (decl_mode),
0, function); 0, function);
} }
else else
...@@ -856,14 +862,14 @@ put_var_into_stack (decl) ...@@ -856,14 +862,14 @@ put_var_into_stack (decl)
new = parm_reg_stack_loc[REGNO (reg)]; new = parm_reg_stack_loc[REGNO (reg)];
if (new == 0) if (new == 0)
new = assign_stack_local (GET_MODE (reg), new = assign_stack_local (GET_MODE (reg),
GET_MODE_SIZE (GET_MODE (reg)), GET_MODE_SIZE (decl_mode), 0);
0);
} }
XEXP (reg, 0) = XEXP (new, 0); XEXP (reg, 0) = XEXP (new, 0);
/* `volatil' bit means one thing for MEMs, another entirely for REGs. */ /* `volatil' bit means one thing for MEMs, another entirely for REGs. */
REG_USERVAR_P (reg) = 0; REG_USERVAR_P (reg) = 0;
PUT_CODE (reg, MEM); PUT_CODE (reg, MEM);
PUT_MODE (reg, decl_mode);
/* If this is a memory ref that contains aggregate components, /* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */ mark it as such for cse and loop optimize. */
...@@ -884,18 +890,22 @@ put_var_into_stack (decl) ...@@ -884,18 +890,22 @@ put_var_into_stack (decl)
temp temp
= (struct var_refs_queue *) oballoc (sizeof (struct var_refs_queue)); = (struct var_refs_queue *) oballoc (sizeof (struct var_refs_queue));
temp->modified = reg; temp->modified = reg;
temp->promoted_mode = promoted_mode;
temp->unsignedp = TREE_UNSIGNED (TREE_TYPE (decl));
temp->next = function->fixup_var_refs_queue; temp->next = function->fixup_var_refs_queue;
function->fixup_var_refs_queue = temp; function->fixup_var_refs_queue = temp;
pop_obstacks (); pop_obstacks ();
} }
else else
/* Variable is local; fix it up now. */ /* Variable is local; fix it up now. */
fixup_var_refs (reg); fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (TREE_TYPE (decl)));
} }
static void static void
fixup_var_refs (var) fixup_var_refs (var, promoted_mode, unsignedp)
rtx var; rtx var;
enum machine_mode promoted_mode;
int unsignedp;
{ {
tree pending; tree pending;
rtx first_insn = get_insns (); rtx first_insn = get_insns ();
...@@ -903,13 +913,14 @@ fixup_var_refs (var) ...@@ -903,13 +913,14 @@ fixup_var_refs (var)
tree rtl_exps = rtl_expr_chain; tree rtl_exps = rtl_expr_chain;
/* Must scan all insns for stack-refs that exceed the limit. */ /* Must scan all insns for stack-refs that exceed the limit. */
fixup_var_refs_insns (var, first_insn, stack == 0); fixup_var_refs_insns (var, promoted_mode, unsignedp, first_insn, stack == 0);
/* Scan all pending sequences too. */ /* Scan all pending sequences too. */
for (; stack; stack = stack->next) for (; stack; stack = stack->next)
{ {
push_to_sequence (stack->first); push_to_sequence (stack->first);
fixup_var_refs_insns (var, stack->first, stack->next != 0); fixup_var_refs_insns (var, promoted_mode, unsignedp,
stack->first, stack->next != 0);
/* Update remembered end of sequence /* Update remembered end of sequence
in case we added an insn at the end. */ in case we added an insn at the end. */
stack->last = get_last_insn (); stack->last = get_last_insn ();
...@@ -923,7 +934,7 @@ fixup_var_refs (var) ...@@ -923,7 +934,7 @@ fixup_var_refs (var)
if (seq != const0_rtx && seq != 0) if (seq != const0_rtx && seq != 0)
{ {
push_to_sequence (seq); push_to_sequence (seq);
fixup_var_refs_insns (var, seq, 0); fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0);
end_sequence (); end_sequence ();
} }
} }
...@@ -974,8 +985,10 @@ find_replacement (replacements, x) ...@@ -974,8 +985,10 @@ find_replacement (replacements, x)
main chain of insns for the current function. */ main chain of insns for the current function. */
static void static void
fixup_var_refs_insns (var, insn, toplevel) fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
rtx var; rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx insn; rtx insn;
int toplevel; int toplevel;
{ {
...@@ -1012,13 +1025,15 @@ fixup_var_refs_insns (var, insn, toplevel) ...@@ -1012,13 +1025,15 @@ fixup_var_refs_insns (var, insn, toplevel)
struct fixup_replacement *replacements = 0; struct fixup_replacement *replacements = 0;
fixup_var_refs_1 (var, &PATTERN (insn), insn, &replacements); fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
&replacements);
while (replacements) while (replacements)
{ {
if (GET_CODE (replacements->new) == REG) if (GET_CODE (replacements->new) == REG)
{ {
rtx insert_before; rtx insert_before;
rtx seq;
/* OLD might be a (subreg (mem)). */ /* OLD might be a (subreg (mem)). */
if (GET_CODE (replacements->old) == SUBREG) if (GET_CODE (replacements->old) == SUBREG)
...@@ -1042,9 +1057,24 @@ fixup_var_refs_insns (var, insn, toplevel) ...@@ -1042,9 +1057,24 @@ fixup_var_refs_insns (var, insn, toplevel)
else else
insert_before = insn; insert_before = insn;
emit_insn_before (gen_move_insn (replacements->new, /* If we are changing the mode, do a conversion.
replacements->old), This might be wasteful, but combine.c will
insert_before); eliminate much of the waste. */
if (GET_MODE (replacements->new)
!= GET_MODE (replacements->old))
{
start_sequence ();
convert_move (replacements->new,
replacements->old, unsignedp);
seq = gen_sequence ();
end_sequence ();
}
else
seq = gen_move_insn (replacements->new,
replacements->old);
emit_insn_before (seq, insert_before);
} }
replacements = replacements->next; replacements = replacements->next;
...@@ -1062,8 +1092,8 @@ fixup_var_refs_insns (var, insn, toplevel) ...@@ -1062,8 +1092,8 @@ fixup_var_refs_insns (var, insn, toplevel)
} }
} }
/* VAR is a MEM that used to be a pseudo register. See if the rtx expression /* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE.
at *LOC in INSN needs to be changed. See if the rtx expression at *LOC in INSN needs to be changed.
REPLACEMENTS is a pointer to a list head that starts out zero, but may REPLACEMENTS is a pointer to a list head that starts out zero, but may
contain a list of original rtx's and replacements. If we find that we need contain a list of original rtx's and replacements. If we find that we need
...@@ -1074,8 +1104,9 @@ fixup_var_refs_insns (var, insn, toplevel) ...@@ -1074,8 +1104,9 @@ fixup_var_refs_insns (var, insn, toplevel)
or the SUBREG, as appropriate, to the pseudo. */ or the SUBREG, as appropriate, to the pseudo. */
static void static void
fixup_var_refs_1 (var, loc, insn, replacements) fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
register rtx var; register rtx var;
enum machine_mode promoted_mode;
register rtx *loc; register rtx *loc;
rtx insn; rtx insn;
struct fixup_replacement **replacements; struct fixup_replacement **replacements;
...@@ -1104,14 +1135,15 @@ fixup_var_refs_1 (var, loc, insn, replacements) ...@@ -1104,14 +1135,15 @@ fixup_var_refs_1 (var, loc, insn, replacements)
*loc = replacement->new = x = fixup_stack_1 (x, insn); *loc = replacement->new = x = fixup_stack_1 (x, insn);
/* Unless we are forcing memory to register, we can leave things /* Unless we are forcing memory to register or we changed the mode,
the way they are if the insn is valid. */ we can leave things the way they are if the insn is valid. */
INSN_CODE (insn) = -1; INSN_CODE (insn) = -1;
if (! flag_force_mem && recog_memoized (insn) >= 0) if (! flag_force_mem && GET_MODE (x) == promoted_mode
&& recog_memoized (insn) >= 0)
return; return;
*loc = replacement->new = gen_reg_rtx (GET_MODE (x)); *loc = replacement->new = gen_reg_rtx (promoted_mode);
return; return;
} }
...@@ -1230,6 +1262,18 @@ fixup_var_refs_1 (var, loc, insn, replacements) ...@@ -1230,6 +1262,18 @@ fixup_var_refs_1 (var, loc, insn, replacements)
case SUBREG: case SUBREG:
if (SUBREG_REG (x) == var) if (SUBREG_REG (x) == var)
{ {
/* If this is a special SUBREG made because VAR was promoted
from a wider mode, replace it with VAR and call ourself
recursively, this time saying that the object previously
had its current mode (by virtue of the SUBREG). */
if (SUBREG_PROMOTED_VAR_P (x))
{
*loc = var;
fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements);
return;
}
/* If this SUBREG makes VAR wider, it has become a paradoxical /* If this SUBREG makes VAR wider, it has become a paradoxical
SUBREG with VAR in memory, but these aren't allowed at this SUBREG with VAR in memory, but these aren't allowed at this
stage of the compilation. So load VAR into a pseudo and take stage of the compilation. So load VAR into a pseudo and take
...@@ -1314,9 +1358,12 @@ fixup_var_refs_1 (var, loc, insn, replacements) ...@@ -1314,9 +1358,12 @@ fixup_var_refs_1 (var, loc, insn, replacements)
{ {
/* Since this case will return, ensure we fixup all the /* Since this case will return, ensure we fixup all the
operands here. */ operands here. */
fixup_var_refs_1 (var, &XEXP (outerdest, 1), insn, replacements); fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
fixup_var_refs_1 (var, &XEXP (outerdest, 2), insn, replacements); insn, replacements);
fixup_var_refs_1 (var, &SET_SRC (x), insn, replacements); fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
insn, replacements);
fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
insn, replacements);
tem = XEXP (outerdest, 0); tem = XEXP (outerdest, 0);
...@@ -1439,24 +1486,37 @@ fixup_var_refs_1 (var, loc, insn, replacements) ...@@ -1439,24 +1486,37 @@ fixup_var_refs_1 (var, loc, insn, replacements)
/* Otherwise, storing into VAR must be handled specially /* Otherwise, storing into VAR must be handled specially
by storing into a temporary and copying that into VAR by storing into a temporary and copying that into VAR
with a new insn after this one. */ with a new insn after this one. Note that this case
will be used when storing into a promoted scalar since
the insn will now have different modes on the input
and output and hence will be invalid (except for the case
of setting it to a constant, which does not need any
change if it is valid). We generate extra code in that case,
but combine.c will eliminate it. */
if (dest == var) if (dest == var)
{ {
rtx temp; rtx temp;
rtx fixeddest; rtx fixeddest = SET_DEST (x);
tem = SET_DEST (x);
/* STRICT_LOW_PART can be discarded, around a MEM. */ /* STRICT_LOW_PART can be discarded, around a MEM. */
if (GET_CODE (tem) == STRICT_LOW_PART) if (GET_CODE (fixeddest) == STRICT_LOW_PART)
tem = XEXP (tem, 0); fixeddest = XEXP (fixeddest, 0);
/* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
if (GET_CODE (tem) == SUBREG) if (GET_CODE (fixeddest) == SUBREG)
fixeddest = fixup_memory_subreg (tem, insn, 0); fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
else else
fixeddest = fixup_stack_1 (tem, insn); fixeddest = fixup_stack_1 (fixeddest, insn);
temp = gen_reg_rtx (GET_MODE (SET_SRC (x)) == VOIDmode
? GET_MODE (fixeddest)
: GET_MODE (SET_SRC (x)));
emit_insn_after (gen_move_insn (fixeddest,
gen_lowpart (GET_MODE (fixeddest),
temp)),
insn);
temp = gen_reg_rtx (GET_MODE (tem));
emit_insn_after (gen_move_insn (fixeddest, temp), insn);
SET_DEST (x) = temp; SET_DEST (x) = temp;
} }
} }
...@@ -1468,12 +1528,13 @@ fixup_var_refs_1 (var, loc, insn, replacements) ...@@ -1468,12 +1528,13 @@ fixup_var_refs_1 (var, loc, insn, replacements)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
fixup_var_refs_1 (var, &XEXP (x, i), insn, replacements); fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements);
if (fmt[i] == 'E') if (fmt[i] == 'E')
{ {
register int j; register int j;
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
fixup_var_refs_1 (var, &XVECEXP (x, i, j), insn, replacements); fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
insn, replacements);
} }
} }
} }
...@@ -2493,6 +2554,7 @@ assign_parms (fndecl, second_time) ...@@ -2493,6 +2554,7 @@ assign_parms (fndecl, second_time)
register rtx stack_parm = 0; register rtx stack_parm = 0;
CUMULATIVE_ARGS args_so_far; CUMULATIVE_ARGS args_so_far;
enum machine_mode passed_mode, nominal_mode; enum machine_mode passed_mode, nominal_mode;
int unsignedp;
/* Total space needed so far for args on the stack, /* Total space needed so far for args on the stack,
given as a constant and a tree-expression. */ given as a constant and a tree-expression. */
struct args_size stack_args_size; struct args_size stack_args_size;
...@@ -2889,9 +2951,24 @@ assign_parms (fndecl, second_time) ...@@ -2889,9 +2951,24 @@ assign_parms (fndecl, second_time)
by invisible reference. */ by invisible reference. */
|| passed_pointer || parm == function_result_decl) || passed_pointer || parm == function_result_decl)
{ {
/* Store the parm in a pseudoregister during the function. */ /* Store the parm in a pseudoregister during the function, but we
register rtx parmreg = gen_reg_rtx (nominal_mode); may need to do it in a wider mode. */
register rtx parmreg;
unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
if (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == BOOLEAN_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == CHAR_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE
|| TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE)
{
PROMOTE_MODE (nominal_mode, unsignedp, TREE_TYPE (parm));
}
parmreg = gen_reg_rtx (nominal_mode);
REG_USERVAR_P (parmreg) = 1; REG_USERVAR_P (parmreg) = 1;
/* If this was an item that we received a pointer to, set DECL_RTL /* If this was an item that we received a pointer to, set DECL_RTL
...@@ -2917,9 +2994,9 @@ assign_parms (fndecl, second_time) ...@@ -2917,9 +2994,9 @@ assign_parms (fndecl, second_time)
&& REGNO (entry_parm) < FIRST_PSEUDO_REGISTER && REGNO (entry_parm) < FIRST_PSEUDO_REGISTER
&& ! HARD_REGNO_MODE_OK (REGNO (entry_parm), && ! HARD_REGNO_MODE_OK (REGNO (entry_parm),
GET_MODE (entry_parm))) GET_MODE (entry_parm)))
convert_move (parmreg, copy_to_reg (entry_parm), 0); convert_move (parmreg, copy_to_reg (entry_parm), unsignedp);
else else
convert_move (parmreg, validize_mem (entry_parm), 0); convert_move (parmreg, validize_mem (entry_parm), unsignedp);
} }
else else
emit_move_insn (parmreg, validize_mem (entry_parm)); emit_move_insn (parmreg, validize_mem (entry_parm));
......
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