From: Richard Kenner Date: Sat, 19 Sep 1992 19:47:00 +0000 (-0400) Subject: (fixup_var_refs{,_insns}): Add new parms for promoted mode and signedness; X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00d8a4c187af94bc3ff1753c3ab06b9e25ba2c6f;p=gcc.git (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 --- diff --git a/gcc/function.c b/gcc/function.c index dbc90043d7f..9295cb1121c 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -495,7 +495,7 @@ pop_function_context () { struct var_refs_queue *queue = p->fixup_var_refs_queue; for (; queue; queue = queue->next) - fixup_var_refs (queue->modified); + fixup_var_refs (queue->modified, queue->promoted_mode, queue->unsignedp); } free (p); @@ -812,11 +812,17 @@ put_var_into_stack (decl) { register rtx reg; register rtx new = 0; + enum machine_mode promoted_mode, decl_mode; struct function *function = 0; 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); + 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, find that function's saved context. */ @@ -847,7 +853,7 @@ put_var_into_stack (decl) new = function->parm_reg_stack_loc[REGNO (reg)]; if (new == 0) new = assign_outer_stack_local (GET_MODE (reg), - GET_MODE_SIZE (GET_MODE (reg)), + GET_MODE_SIZE (decl_mode), 0, function); } else @@ -856,14 +862,14 @@ put_var_into_stack (decl) new = parm_reg_stack_loc[REGNO (reg)]; if (new == 0) new = assign_stack_local (GET_MODE (reg), - GET_MODE_SIZE (GET_MODE (reg)), - 0); + GET_MODE_SIZE (decl_mode), 0); } XEXP (reg, 0) = XEXP (new, 0); /* `volatil' bit means one thing for MEMs, another entirely for REGs. */ REG_USERVAR_P (reg) = 0; PUT_CODE (reg, MEM); + PUT_MODE (reg, decl_mode); /* If this is a memory ref that contains aggregate components, mark it as such for cse and loop optimize. */ @@ -884,18 +890,22 @@ put_var_into_stack (decl) temp = (struct var_refs_queue *) oballoc (sizeof (struct var_refs_queue)); temp->modified = reg; + temp->promoted_mode = promoted_mode; + temp->unsignedp = TREE_UNSIGNED (TREE_TYPE (decl)); temp->next = function->fixup_var_refs_queue; function->fixup_var_refs_queue = temp; pop_obstacks (); } else /* Variable is local; fix it up now. */ - fixup_var_refs (reg); + fixup_var_refs (reg, promoted_mode, TREE_UNSIGNED (TREE_TYPE (decl))); } static void -fixup_var_refs (var) +fixup_var_refs (var, promoted_mode, unsignedp) rtx var; + enum machine_mode promoted_mode; + int unsignedp; { tree pending; rtx first_insn = get_insns (); @@ -903,13 +913,14 @@ fixup_var_refs (var) tree rtl_exps = rtl_expr_chain; /* 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. */ for (; stack; stack = stack->next) { 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 in case we added an insn at the end. */ stack->last = get_last_insn (); @@ -923,7 +934,7 @@ fixup_var_refs (var) if (seq != const0_rtx && seq != 0) { push_to_sequence (seq); - fixup_var_refs_insns (var, seq, 0); + fixup_var_refs_insns (var, promoted_mode, unsignedp, seq, 0); end_sequence (); } } @@ -974,8 +985,10 @@ find_replacement (replacements, x) main chain of insns for the current function. */ static void -fixup_var_refs_insns (var, insn, toplevel) +fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel) rtx var; + enum machine_mode promoted_mode; + int unsignedp; rtx insn; int toplevel; { @@ -1012,13 +1025,15 @@ fixup_var_refs_insns (var, insn, toplevel) 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) { if (GET_CODE (replacements->new) == REG) { rtx insert_before; + rtx seq; /* OLD might be a (subreg (mem)). */ if (GET_CODE (replacements->old) == SUBREG) @@ -1042,9 +1057,24 @@ fixup_var_refs_insns (var, insn, toplevel) else insert_before = insn; - emit_insn_before (gen_move_insn (replacements->new, - replacements->old), - insert_before); + /* If we are changing the mode, do a conversion. + This might be wasteful, but combine.c will + 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; @@ -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 - at *LOC in INSN needs to be changed. +/* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE. + 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 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) or the SUBREG, as appropriate, to the pseudo. */ static void -fixup_var_refs_1 (var, loc, insn, replacements) +fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) register rtx var; + enum machine_mode promoted_mode; register rtx *loc; rtx insn; struct fixup_replacement **replacements; @@ -1104,14 +1135,15 @@ fixup_var_refs_1 (var, loc, insn, replacements) *loc = replacement->new = x = fixup_stack_1 (x, insn); - /* Unless we are forcing memory to register, we can leave things - the way they are if the insn is valid. */ + /* Unless we are forcing memory to register or we changed the mode, + we can leave things the way they are if the insn is valid. */ 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; - *loc = replacement->new = gen_reg_rtx (GET_MODE (x)); + *loc = replacement->new = gen_reg_rtx (promoted_mode); return; } @@ -1230,6 +1262,18 @@ fixup_var_refs_1 (var, loc, insn, replacements) case SUBREG: 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 SUBREG with VAR in memory, but these aren't allowed at this stage of the compilation. So load VAR into a pseudo and take @@ -1314,9 +1358,12 @@ fixup_var_refs_1 (var, loc, insn, replacements) { /* Since this case will return, ensure we fixup all the operands here. */ - fixup_var_refs_1 (var, &XEXP (outerdest, 1), insn, replacements); - fixup_var_refs_1 (var, &XEXP (outerdest, 2), insn, replacements); - fixup_var_refs_1 (var, &SET_SRC (x), insn, replacements); + fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1), + 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); @@ -1439,24 +1486,37 @@ fixup_var_refs_1 (var, loc, insn, replacements) /* Otherwise, storing into VAR must be handled specially 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) { rtx temp; - rtx fixeddest; - tem = SET_DEST (x); + rtx fixeddest = SET_DEST (x); + /* STRICT_LOW_PART can be discarded, around a MEM. */ - if (GET_CODE (tem) == STRICT_LOW_PART) - tem = XEXP (tem, 0); + if (GET_CODE (fixeddest) == STRICT_LOW_PART) + fixeddest = XEXP (fixeddest, 0); /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ - if (GET_CODE (tem) == SUBREG) - fixeddest = fixup_memory_subreg (tem, insn, 0); + if (GET_CODE (fixeddest) == SUBREG) + fixeddest = fixup_memory_subreg (fixeddest, insn, 0); 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; } } @@ -1468,12 +1528,13 @@ fixup_var_refs_1 (var, loc, insn, replacements) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { 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') { register int 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) register rtx stack_parm = 0; CUMULATIVE_ARGS args_so_far; enum machine_mode passed_mode, nominal_mode; + int unsignedp; /* Total space needed so far for args on the stack, given as a constant and a tree-expression. */ struct args_size stack_args_size; @@ -2889,9 +2951,24 @@ assign_parms (fndecl, second_time) by invisible reference. */ || passed_pointer || parm == function_result_decl) { - /* Store the parm in a pseudoregister during the function. */ - register rtx parmreg = gen_reg_rtx (nominal_mode); + /* Store the parm in a pseudoregister during the function, but we + 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; /* If this was an item that we received a pointer to, set DECL_RTL @@ -2917,9 +2994,9 @@ assign_parms (fndecl, second_time) && REGNO (entry_parm) < FIRST_PSEUDO_REGISTER && ! HARD_REGNO_MODE_OK (REGNO (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 - convert_move (parmreg, validize_mem (entry_parm), 0); + convert_move (parmreg, validize_mem (entry_parm), unsignedp); } else emit_move_insn (parmreg, validize_mem (entry_parm));