diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-30 18:03:48 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-09-30 18:03:48 +0000 |
commit | 41969bd39774ecb1f9b8bf59ac8246d1f1d50118 (patch) | |
tree | aa12f02c904c0630f987c5e88c9123d4dca0eded | |
parent | 1841879478554257855407f0623f9f88c45095b7 (diff) | |
download | gcc-41969bd39774ecb1f9b8bf59ac8246d1f1d50118.tar.gz |
* function.c (purge_addressof_1): Use bitfield manipulation
routines to handle mem mode < reg mode.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22686 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/function.c | 92 |
2 files changed, 85 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44721e7fa54..4075787acd7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Wed Sep 30 18:03:22 1998 Richard Henderson <rth@cygnus.com> + + * function.c (purge_addressof_1): Use bitfield manipulation + routines to handle mem mode < reg mode. + Wed Sep 30 18:43:32 1998 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl> * reorg.c (try_merge_delay_insns): Account for resources referenced diff --git a/gcc/function.c b/gcc/function.c index 54407fdb156..3361fd85729 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -457,7 +457,7 @@ static int *record_insns PROTO((rtx)); static int contains PROTO((rtx, int *)); #endif /* HAVE_prologue || HAVE_epilogue */ static void put_addressof_into_stack PROTO((rtx)); -static void purge_addressof_1 PROTO((rtx *, rtx, int)); +static void purge_addressof_1 PROTO((rtx *, rtx, int, int)); /* Pointer to chain of `struct function' for containing functions. */ struct function *outer_function_chain; @@ -2812,10 +2812,10 @@ put_addressof_into_stack (r) the stack. */ static void -purge_addressof_1 (loc, insn, force) +purge_addressof_1 (loc, insn, force, store) rtx *loc; rtx insn; - int force; + int force, store; { rtx x; RTX_CODE code; @@ -2847,7 +2847,7 @@ purge_addressof_1 (loc, insn, force) 0)) abort (); - insns = get_insns (); + insns = gen_sequence (); end_sequence (); emit_insns_before (insns, insn); return; @@ -2867,11 +2867,73 @@ purge_addressof_1 (loc, insn, force) } else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub)) { - if (! BYTES_BIG_ENDIAN && ! WORDS_BIG_ENDIAN) + int size_x, size_sub; + + size_x = GET_MODE_BITSIZE (GET_MODE (x)); + size_sub = GET_MODE_BITSIZE (GET_MODE (sub)); + + /* Don't even consider working with paradoxical subregs, + or the moral equivalent seen here. */ + if (size_x < size_sub) { - rtx sub2 = gen_rtx_SUBREG (GET_MODE (x), sub, 0); - if (validate_change (insn, loc, sub2, 0)) - goto restart; + /* Do a bitfield insertion to mirror what would happen + in memory. */ + + int bitpos; + rtx val, seq; + + bitpos = 0; + if (WORDS_BIG_ENDIAN) + { + bitpos += (size_sub / BITS_PER_WORD) * BITS_PER_WORD; + bitpos += (size_x / BITS_PER_WORD) * BITS_PER_WORD; + } + if (BYTES_BIG_ENDIAN) + { + bitpos += size_sub % BITS_PER_WORD; + bitpos -= size_x % BITS_PER_WORD; + } + + if (store) + { + /* If we can't replace with a register, be afraid. */ + + start_sequence (); + val = gen_reg_rtx (GET_MODE (x)); + if (! validate_change (insn, loc, val, 0)) + abort (); + seq = gen_sequence (); + end_sequence (); + emit_insn_before (seq, insn); + + start_sequence (); + store_bit_field (sub, size_x, bitpos, GET_MODE (x), + val, GET_MODE_SIZE (GET_MODE (sub)), + GET_MODE_SIZE (GET_MODE (sub))); + + seq = gen_sequence (); + end_sequence (); + emit_insn_after (seq, insn); + } + else + { + start_sequence (); + val = extract_bit_field (sub, size_x, bitpos, 1, NULL_RTX, + GET_MODE (x), GET_MODE (x), + GET_MODE_SIZE (GET_MODE (sub)), + GET_MODE_SIZE (GET_MODE (sub))); + + /* If we can't replace with a register, be afraid. */ + if (! validate_change (insn, loc, val, 0)) + abort (); + + seq = gen_sequence (); + end_sequence (); + emit_insn_before (seq, insn); + } + + /* We replaced with a reg -- all done. */ + return; } } else if (validate_change (insn, loc, sub, 0)) @@ -2883,16 +2945,22 @@ purge_addressof_1 (loc, insn, force) put_addressof_into_stack (x); return; } + else if (code == SET) + { + purge_addressof_1 (&SET_DEST (x), insn, force, 1); + purge_addressof_1 (&SET_SRC (x), insn, force, 0); + return; + } /* Scan all subexpressions. */ fmt = GET_RTX_FORMAT (code); for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) { if (*fmt == 'e') - purge_addressof_1 (&XEXP (x, i), insn, force); + purge_addressof_1 (&XEXP (x, i), insn, force, 0); else if (*fmt == 'E') for (j = 0; j < XVECLEN (x, i); j++) - purge_addressof_1 (&XVECEXP (x, i, j), insn, force); + purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0); } } @@ -2910,8 +2978,8 @@ purge_addressof (insns) || GET_CODE (insn) == CALL_INSN) { purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0); - purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0); + asm_noperands (PATTERN (insn)) > 0, 0); + purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0); } } |