aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@cygnus.com>1999-11-05 10:11:40 +0000
committerNick Clifton <nickc@gcc.gnu.org>1999-11-05 10:11:40 +0000
commit8c36698e5207d286292375e844faf9c95c35ce42 (patch)
tree430f1e20192cbb2ad005a7f482d2aa53b09d1313 /gcc/function.c
parentce82ff5c170684904ab924965c1ed6e1b4b30853 (diff)
downloadgcc-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.c88
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 (&REG_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 (&REG_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. */