aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>1996-06-08 17:49:13 +0000
committerRichard Kenner <kenner@vlsi1.ultra.nyu.edu>1996-06-08 17:49:13 +0000
commit9d4794cb80afb6c4ee5fade5cf1a5d8229b2e11c (patch)
tree479cd63556d7ce770fccffb8e5dd5e186d9e50d8 /gcc/function.c
parent5cc87bff9b94ebb557909f79c22596d3a1419bbf (diff)
(fixup_var_refs_1, case SIGN_EXTEND): Handle paradoxical SUBREGs as first
operand. (fixup_var_regs_1, case SET): Handle paradoxical SUBREGs as first operand of a ZERO_EXTRACT in SET_DEST. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@12243 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/gcc/function.c b/gcc/function.c
index e4d73d0b1bb..27a01c1aea5 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -1755,8 +1755,20 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
tem = XEXP (x, 0);
if (GET_CODE (tem) == SUBREG)
- tem = fixup_memory_subreg (tem, insn, 1);
- tem = fixup_stack_1 (tem, insn);
+ {
+ if (GET_MODE_BITSIZE (GET_MODE (tem))
+ > GET_MODE_BITSIZE (GET_MODE (var)))
+ {
+ replacement = find_fixup_replacement (replacements, var);
+ if (replacement->new == 0)
+ replacement->new = gen_reg_rtx (GET_MODE (var));
+ SUBREG_REG (tem) = replacement->new;
+ }
+
+ tem = fixup_memory_subreg (tem, insn, 0);
+ }
+ else
+ tem = fixup_stack_1 (tem, insn);
/* Unless we want to load from memory, get TEM into the proper mode
for an extract from memory. This can only be done if the
@@ -1885,6 +1897,22 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
|| GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
optimize_bit_field (x, insn, NULL_PTR);
+ /* For a paradoxical SUBREG inside a ZERO_EXTRACT, load the object
+ into a register and then store it back out. */
+ if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
+ && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG
+ && SUBREG_REG (XEXP (SET_DEST (x), 0)) == var
+ && (GET_MODE_SIZE (GET_MODE (XEXP (SET_DEST (x), 0)))
+ > GET_MODE_SIZE (GET_MODE (var))))
+ {
+ replacement = find_fixup_replacement (replacements, var);
+ if (replacement->new == 0)
+ replacement->new = gen_reg_rtx (GET_MODE (var));
+
+ SUBREG_REG (XEXP (SET_DEST (x), 0)) = replacement->new;
+ emit_insn_after (gen_move_insn (var, replacement->new), insn);
+ }
+
/* If SET_DEST is now a paradoxical SUBREG, put the result of this
insn into a pseudo and store the low part of the pseudo into VAR. */
if (GET_CODE (SET_DEST (x)) == SUBREG
@@ -1940,7 +1968,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
This was legitimate when the MEM was a REG. */
if (GET_CODE (tem) == SUBREG
&& SUBREG_REG (tem) == var)
- tem = fixup_memory_subreg (tem, insn, 1);
+ tem = fixup_memory_subreg (tem, insn, 0);
else
tem = fixup_stack_1 (tem, insn);
@@ -2158,7 +2186,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
If any insns must be emitted to compute NEWADDR, put them before INSN.
UNCRITICAL nonzero means accept paradoxical subregs.
- This is used for subregs found inside of ZERO_EXTRACTs and in REG_NOTES. */
+ This is used for subregs found inside REG_NOTES. */
static rtx
fixup_memory_subreg (x, insn, uncritical)