From 941c63ac30be855420bc79b702355594712cff90 Mon Sep 17 00:00:00 2001 From: Jeffrey A Law Date: Sat, 12 Dec 1998 23:03:54 +0000 Subject: [PATCH] rtlanal.c (multiple_sets): New function. * rtlanal.c (multiple_sets): New function. * rtl.h (multiple_sets): Declare it. * local-alloc.c (wipe_dead_reg): Use it. * global.c (global_conflicts): Likewise. Should fix the m68k bootstrap problems. From-SVN: r24283 --- gcc/ChangeLog | 7 +++++++ gcc/global.c | 13 ++++++++++--- gcc/local-alloc.c | 11 +++++++++-- gcc/rtl.h | 1 + gcc/rtlanal.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2a101bda07..b0e12f6249f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Sat Dec 12 23:39:10 1998 Jeffrey A Law (law@cygnus.com) + + * rtlanal.c (multiple_sets): New function. + * rtl.h (multiple_sets): Declare it. + * local-alloc.c (wipe_dead_reg): Use it. + * global.c (global_conflicts): Likewise. + Sat Dec 12 22:13:02 1998 Mark Mitchell * global.c (record_conflicts): Don't use an array of shorts to diff --git a/gcc/global.c b/gcc/global.c index 67201726e3c..06277ee5365 100644 --- a/gcc/global.c +++ b/gcc/global.c @@ -739,9 +739,16 @@ global_conflicts () /* If INSN has multiple outputs, then any reg that dies here and is used inside of an output - must conflict with the other outputs. */ - - if (GET_CODE (PATTERN (insn)) == PARALLEL && !single_set (insn)) + must conflict with the other outputs. + + It is unsafe to use !single_set here since it will ignore an + unused output. Just because an output is unused does not mean + the compiler can assume the side effect will not occur. + Consider if REG appears in the address of an output and we + reload the output. If we allocate REG to the same hard + register as an unused output we could set the hard register + before the output reload insn. */ + if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn)) for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_DEAD) { diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index f7d12d2e1e0..85cb8af555b 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -1876,9 +1876,16 @@ wipe_dead_reg (reg, output_p) /* If this insn has multiple results, and the dead reg is used in one of the results, extend its life to after this insn, - so it won't get allocated together with any other result of this insn. */ + so it won't get allocated together with any other result of this insn. + + It is unsafe to use !single_set here since it will ignore an unused + output. Just because an output is unused does not mean the compiler + can assume the side effect will not occur. Consider if REG appears + in the address of an output and we reload the output. If we allocate + REG to the same hard register as an unused output we could set the hard + register before the output reload insn. */ if (GET_CODE (PATTERN (this_insn)) == PARALLEL - && !single_set (this_insn)) + && multiple_sets (this_insn)) { int i; for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--) diff --git a/gcc/rtl.h b/gcc/rtl.h index 940de7305e1..95ddbd1617c 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -988,6 +988,7 @@ extern int no_labels_between_p PROTO((rtx, rtx)); extern int modified_in_p PROTO((rtx, rtx)); extern int reg_set_p PROTO((rtx, rtx)); extern rtx single_set PROTO((rtx)); +extern rtx multiple_sets PROTO((rtx)); extern rtx find_last_value PROTO((rtx, rtx *, rtx)); extern int refers_to_regno_p PROTO((int, int, rtx, rtx *)); extern int reg_overlap_mentioned_p PROTO((rtx, rtx)); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 0abe2447165..f298ab2f5ef 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -690,6 +690,38 @@ single_set (insn) return 0; } + +/* Given an INSN, return nonzero if it has more than one SET, else return + zero. */ + +rtx +multiple_sets (insn) + rtx insn; +{ + rtx found; + int i; + + /* INSN must be an insn. */ + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + return 0; + + /* Only a PARALLEL can have multiple SETs. */ + if (GET_CODE (PATTERN (insn)) == PARALLEL) + { + for (i = 0, found = 0; i < XVECLEN (PATTERN (insn), 0); i++) + if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) + { + /* If we have already found a SET, then return now. */ + if (found) + return 1; + else + found = 1; + } + } + + /* Either zero or one SET. */ + return 0; +} /* Return the last thing that X was assigned from before *PINSN. Verify that the object is not modified up to VALID_TO. If it was, if we hit -- 2.30.2