diff options
author | Nick Clifton <nickc@cygnus.com> | 1999-11-05 10:11:40 +0000 |
---|---|---|
committer | Nick Clifton <nickc@gcc.gnu.org> | 1999-11-05 10:11:40 +0000 |
commit | 8c36698e5207d286292375e844faf9c95c35ce42 (patch) | |
tree | 430f1e20192cbb2ad005a7f482d2aa53b09d1313 /gcc/function.c | |
parent | ce82ff5c170684904ab924965c1ed6e1b4b30853 (diff) | |
download | gcc-8c36698e5207d286292375e844faf9c95c35ce42.zip gcc-8c36698e5207d286292375e844faf9c95c35ce42.tar.gz gcc-8c36698e5207d286292375e844faf9c95c35ce42.tar.bz2 |
If purge_addressof_1 fails to remove addressofs in notes, remove the notes
instead.
From-SVN: r30414
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 88 |
1 files changed, 65 insertions, 23 deletions
diff --git a/gcc/function.c b/gcc/function.c index 07dd0b1..c9b4e20 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -268,8 +268,9 @@ static int all_blocks PROTO((tree, tree *)); static int *record_insns PROTO((rtx)) ATTRIBUTE_UNUSED; static int contains PROTO((rtx, int *)); static void put_addressof_into_stack PROTO((rtx, struct hash_table *)); -static void purge_addressof_1 PROTO((rtx *, rtx, int, int, +static boolean purge_addressof_1 PROTO((rtx *, rtx, int, int, struct hash_table *)); +static int is_addressof PROTO ((rtx *, void *)); static struct hash_entry *insns_for_mem_newfunc PROTO((struct hash_entry *, struct hash_table *, hash_table_key)); @@ -2765,9 +2766,10 @@ static rtx purge_addressof_replacements; /* Helper function for purge_addressof. See if the rtx expression at *LOC in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into - the stack. */ + the stack. If the function returns FALSE then the replacement could not + be made. */ -static void +static boolean purge_addressof_1 (loc, insn, force, store, ht) rtx *loc; rtx insn; @@ -2778,13 +2780,14 @@ purge_addressof_1 (loc, insn, force, store, ht) RTX_CODE code; int i, j; const char *fmt; + boolean result = true; /* Re-start here to avoid recursion in common cases. */ restart: x = *loc; if (x == 0) - return; + return true; code = GET_CODE (x); @@ -2793,9 +2796,9 @@ purge_addressof_1 (loc, insn, force, store, ht) memory. */ if (code == SET) { - purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); - purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); - return; + result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); + result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); + return result; } else if (code == ADDRESSOF && GET_CODE (XEXP (x, 0)) == MEM) @@ -2807,7 +2810,7 @@ purge_addressof_1 (loc, insn, force, store, ht) if (validate_change (insn, loc, sub, 0) || validate_replace_rtx (x, sub, insn)) - return; + return true; start_sequence (); sub = force_operand (sub, NULL_RTX); @@ -2818,7 +2821,7 @@ purge_addressof_1 (loc, insn, force, store, ht) insns = gen_sequence (); end_sequence (); emit_insn_before (insns, insn); - return; + return true; } else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force) @@ -2853,7 +2856,7 @@ purge_addressof_1 (loc, insn, force, store, ht) if (rtx_equal_p (x, XEXP (tem, 0))) { *loc = XEXP (XEXP (tem, 1), 0); - return; + return true; } /* See comment for purge_addressof_replacements. */ @@ -2896,8 +2899,14 @@ purge_addressof_1 (loc, insn, force, store, ht) return; } - /* There should always be such a replacement. */ - abort (); + /* Sometimes we may not be able to find the replacement. For + example when the original insn was a MEM in a wider mode, + and the note is part of a sign extension of a narrowed + version of that MEM. Gcc testcase compile/990829-1.c can + generate an example of this siutation. Rather than complain + we return false, which will prompt our caller to remove the + offending note. */ + return false; } size_x = GET_MODE_BITSIZE (GET_MODE (x)); @@ -2989,7 +2998,7 @@ purge_addressof_1 (loc, insn, force, store, ht) purge_bitfield_addressof_replacements)); /* We replaced with a reg -- all done. */ - return; + return true; } } @@ -3007,13 +3016,13 @@ purge_addressof_1 (loc, insn, force, store, ht) if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0))) { XEXP (XEXP (tem, 1), 0) = sub; - return; + return true; } purge_addressof_replacements = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0), gen_rtx_EXPR_LIST (VOIDmode, sub, purge_addressof_replacements)); - return; + return true; } goto restart; } @@ -3028,9 +3037,9 @@ purge_addressof_1 (loc, insn, force, store, ht) } else if (code == SET) { - purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); - purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); - return; + result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); + result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); + return result; } /* Scan all subexpressions. */ @@ -3038,11 +3047,13 @@ purge_addressof_1 (loc, insn, force, store, ht) for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) { if (*fmt == 'e') - purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht); + result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht); else if (*fmt == 'E') for (j = 0; j < XVECLEN (x, i); j++) - purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht); + result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht); } + + return result; } /* Return a new hash table entry in HT. */ @@ -3162,6 +3173,16 @@ compute_insns_for_mem (insns, last_insn, ht) } } +/* Helper function for purge_addressof called through for_each_rtx. + Returns true iff the rtl is an ADDRESSOF. */ +static int +is_addressof (rtl, data) + rtx * rtl; + void * data ATTRIBUTE_UNUSED; +{ + return GET_CODE (* rtl) == ADDRESSOF; +} + /* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining (MEM (ADDRESSOF)) patterns, and force any needed registers into the stack. */ @@ -3190,9 +3211,30 @@ purge_addressof (insns) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN) { - purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0, 0, &ht); - purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht); + if (! purge_addressof_1 (&PATTERN (insn), insn, + asm_noperands (PATTERN (insn)) > 0, 0, &ht)) + /* If we could not replace the ADDRESSOFs in the insn, + something is wrong. */ + abort (); + + if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht)) + { + /* If we could not replace the ADDRESSOFs in the insn's notes, + we can just remove the offending notes instead. */ + rtx note; + + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + { + /* If we find a REG_RETVAL note then the insn is a libcall. + Such insns must have REG_EQUAL notes as well, in order + for later passes of the compiler to work. So it is not + safe to delete the notes here, and instead we abort. */ + if (REG_NOTE_KIND (note) == REG_RETVAL) + abort (); + if (for_each_rtx (& note, is_addressof, NULL)) + remove_note (insn, note); + } + } } /* Clean up. */ |