/* Data flow analysis for GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This file contains the data flow analysis pass of the compiler.
/* Forward declarations */
static void find_basic_blocks PROTO((rtx, rtx));
-static int uses_reg_or_mem PROTO((rtx));
+static int jmp_uses_reg_or_mem PROTO((rtx));
static void mark_label_ref PROTO((rtx, rtx, int));
static void life_analysis PROTO((rtx, int));
void allocate_for_life_analysis PROTO((void));
for (i = len - 1; i >= 0; i--)
if (GET_CODE (XVECEXP (pat, 0, i)) == SET
&& SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
- && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
+ && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
computed_jump = 1;
}
else if (GET_CODE (pat) == SET
&& SET_DEST (pat) == pc_rtx
- && uses_reg_or_mem (SET_SRC (pat)))
+ && jmp_uses_reg_or_mem (SET_SRC (pat)))
computed_jump = 1;
if (computed_jump)
\f
/* Subroutines of find_basic_blocks. */
-/* Return 1 if X contain a REG or MEM that is not in the constant pool. */
+/* Return 1 if X, the SRC_SRC of SET of (pc) contain a REG or MEM that is
+ not in the constant pool and not in the condition of an IF_THEN_ELSE. */
static int
-uses_reg_or_mem (x)
+jmp_uses_reg_or_mem (x)
rtx x;
{
enum rtx_code code = GET_CODE (x);
int i, j;
char *fmt;
- if (code == REG
- || (code == MEM
- && ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))))
- return 1;
+ switch (code)
+ {
+ case CONST:
+ case LABEL_REF:
+ case PC:
+ return 0;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
+
+ case IF_THEN_ELSE:
+ return (jmp_uses_reg_or_mem (XEXP (x, 1))
+ || jmp_uses_reg_or_mem (XEXP (x, 2)));
+
+ case PLUS: case MINUS: case MULT:
+ return (jmp_uses_reg_or_mem (XEXP (x, 0))
+ || jmp_uses_reg_or_mem (XEXP (x, 1)));
+ }
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e'
- && uses_reg_or_mem (XEXP (x, i)))
+ && jmp_uses_reg_or_mem (XEXP (x, i)))
return 1;
if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
- if (uses_reg_or_mem (XVECEXP (x, i, j)))
+ if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
return 1;
}
final, insn);
/* Each call clobbers all call-clobbered regs that are not
- global. Note that the function-value reg is a
+ global or fixed. Note that the function-value reg is a
call-clobbered reg, and mark_set_regs has already had
a chance to handle it. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (call_used_regs[i] && ! global_regs[i])
+ if (call_used_regs[i] && ! global_regs[i]
+ && ! fixed_regs[i])
dead[i / REGSET_ELT_BITS]
|= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS));
/* Return 1 if register REGNO was used before it was set.
In other words, if it is live at function entry.
- Don't count global regster variables, though. */
+ Don't count global register variables, though. */
int
regno_uninitialized (regno)
register int offset = regno / REGSET_ELT_BITS;
register REGSET_ELT_TYPE bit
= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE all_needed = (needed[offset] & bit);
REGSET_ELT_TYPE some_needed = (needed[offset] & bit);
+ REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
/* Mark it as a significant register for this basic block. */
if (significant)
n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (--n > 0)
{
+ REGSET_ELT_TYPE n_bit
+ = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+
if (significant)
- significant[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
- dead[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+ significant[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+
+ dead[(regno + n) / REGSET_ELT_BITS] |= n_bit;
some_needed
- |= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
- all_needed
- &= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+ |= (needed[(regno + n) / REGSET_ELT_BITS] & n_bit);
+ some_not_needed
+ |= ((~ needed[(regno + n) / REGSET_ELT_BITS]) & n_bit);
}
}
/* Additional data to record if this is the final pass. */
reg_live_length[regno]++;
}
- if (all_needed)
+ if (! some_not_needed)
{
/* Make a logical link from the next following insn
that uses this register, back to this insn.
else if (GET_CODE (q) == REG
/* PREV_INSN used here to check the semi-open interval
[insn,incr). */
- && ! reg_used_between_p (q, PREV_INSN (insn), incr))
+ && ! reg_used_between_p (q, PREV_INSN (insn), incr)
+ /* We must also check for sets of q as q may be
+ a call clobbered hard register and there may
+ be a call between PREV_INSN (insn) and incr. */
+ && ! reg_set_between_p (q, PREV_INSN (insn), incr))
{
/* We have *p followed sometime later by q = p+size.
Both p and q must be live afterward,
register int offset = regno / REGSET_ELT_BITS;
register REGSET_ELT_TYPE bit
= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE all_needed = needed[offset] & bit;
REGSET_ELT_TYPE some_needed = needed[offset] & bit;
+ REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
live[offset] |= bit;
+
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
if (regno < FIRST_PSEUDO_REGISTER)
n = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (--n > 0)
{
- live[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
- some_needed
- |= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
- all_needed
- &= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+ REGSET_ELT_TYPE n_bit
+ = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+
+ live[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+ some_needed |= (needed[(regno + n) / REGSET_ELT_BITS] & n_bit);
+ some_not_needed
+ |= ((~ needed[(regno + n) / REGSET_ELT_BITS]) & n_bit);
}
}
if (final)
we do not make a REG_DEAD note; likewise if we already
made such a note. */
- if (! all_needed
+ if (some_not_needed
&& ! dead_or_set_p (insn, x)
#if 0
&& (regno >= FIRST_PSEUDO_REGISTER || ! fixed_regs[regno])