/* Compute register class preferences for pseudo-registers.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
- 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
#ifdef FORBIDDEN_INC_DEC_CLASSES
static int auto_inc_dec_reg_p (rtx, enum machine_mode);
#endif
-static void reg_scan_mark_refs (rtx, rtx, int);
+static void reg_scan_mark_refs (rtx, rtx, int, unsigned int);
/* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers. */
if (!reg_n_info)
{
reg_n_info = VEC_alloc (reg_info_p, heap, regno_allocated);
- VEC_safe_grow (reg_info_p, heap, reg_n_info, regno_allocated);
- memset (VEC_address (reg_info_p, reg_n_info), 0,
- sizeof (reg_info_p) * regno_allocated);
+ VEC_safe_grow_cleared (reg_info_p, heap, reg_n_info,
+ regno_allocated);
renumber = xmalloc (size_renumber);
reg_pref_buffer = XNEWVEC (struct reg_pref, regno_allocated);
}
size_t old_length = VEC_length (reg_info_p, reg_n_info);
if (old_length < regno_allocated)
{
- reg_info_p *addr;
- VEC_safe_grow (reg_info_p, heap, reg_n_info, regno_allocated);
- addr = VEC_address (reg_info_p, reg_n_info);
- memset (&addr[old_length], 0,
- sizeof (reg_info_p) * (regno_allocated - old_length));
+ VEC_safe_grow_cleared (reg_info_p, heap, reg_n_info,
+ regno_allocated);
}
else if (regno_allocated < old_length)
{
regno_allocated = 0;
reg_n_max = 0;
}
+
+/* Clear the information stored for REGNO. */
+void
+clear_reg_info_regno (unsigned int regno)
+{
+ if (regno < regno_allocated)
+ memset (VEC_index (reg_info_p, reg_n_info, regno), 0, sizeof (reg_info));
+}
\f
/* This is the `regscan' pass of the compiler, run just before cse
and again just before loop.
if (GET_CODE (pat) == PARALLEL
&& XVECLEN (pat, 0) > max_parallel)
max_parallel = XVECLEN (pat, 0);
- reg_scan_mark_refs (pat, insn, 0);
+ reg_scan_mark_refs (pat, insn, 0, 0);
if (REG_NOTES (insn))
- reg_scan_mark_refs (REG_NOTES (insn), insn, 1);
+ reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0);
}
max_parallel += max_set_parallel;
timevar_pop (TV_REG_SCAN);
}
+/* Update 'regscan' information by looking at the insns
+ from FIRST to LAST. Some new REGs have been created,
+ and any REG with number greater than OLD_MAX_REGNO is
+ such a REG. We only update information for those. */
+
+void
+reg_scan_update (rtx first, rtx last, unsigned int old_max_regno)
+{
+ rtx insn;
+
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+
+ for (insn = first; insn != last; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL
+ && XVECLEN (pat, 0) > max_parallel)
+ max_parallel = XVECLEN (pat, 0);
+ reg_scan_mark_refs (pat, insn, 0, old_max_regno);
+
+ if (REG_NOTES (insn))
+ reg_scan_mark_refs (REG_NOTES (insn), insn, 1, old_max_regno);
+ }
+}
+
/* X is the expression to scan. INSN is the insn it appears in.
- NOTE_FLAG is nonzero if X is from INSN's notes rather than its body. */
+ NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.
+ We should only record information for REGs with numbers
+ greater than or equal to MIN_REGNO. */
static void
-reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
+reg_scan_mark_refs (rtx x, rtx insn, int note_flag, unsigned int min_regno)
{
enum rtx_code code;
rtx dest;
{
unsigned int regno = REGNO (x);
- if (!note_flag)
- REGNO_LAST_UID (regno) = INSN_UID (insn);
- if (REGNO_FIRST_UID (regno) == 0)
- REGNO_FIRST_UID (regno) = INSN_UID (insn);
+ if (regno >= min_regno)
+ {
+ if (!note_flag)
+ REGNO_LAST_UID (regno) = INSN_UID (insn);
+ if (REGNO_FIRST_UID (regno) == 0)
+ REGNO_FIRST_UID (regno) = INSN_UID (insn);
+ /* If we are called by reg_scan_update() (indicated by min_regno
+ being set), we also need to update the reference count. */
+ if (min_regno)
+ REG_N_REFS (regno)++;
+ }
}
break;
case EXPR_LIST:
if (XEXP (x, 0))
- reg_scan_mark_refs (XEXP (x, 0), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 0), insn, note_flag, min_regno);
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
break;
case INSN_LIST:
if (XEXP (x, 1))
- reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
break;
case CLOBBER:
{
rtx reg = XEXP (x, 0);
- if (REG_P (reg))
+ if (REG_P (reg)
+ && REGNO (reg) >= min_regno)
{
REG_N_SETS (REGNO (reg))++;
REG_N_REFS (REGNO (reg))++;
}
else if (MEM_P (reg))
- reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag);
+ reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag, min_regno);
}
break;
if (GET_CODE (dest) == PARALLEL)
max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1);
- if (REG_P (dest))
+ if (REG_P (dest)
+ && REGNO (dest) >= min_regno)
{
REG_N_SETS (REGNO (dest))++;
REG_N_REFS (REGNO (dest))++;
if (REG_P (SET_DEST (x))
&& REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER
+ && REGNO (SET_DEST (x)) >= min_regno
/* If the destination pseudo is set more than once, then other
sets might not be to a pointer value (consider access to a
union in two threads of control in the presence of global
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- reg_scan_mark_refs (XEXP (x, i), insn, note_flag);
+ reg_scan_mark_refs (XEXP (x, i), insn, note_flag, min_regno);
else if (fmt[i] == 'E' && XVEC (x, i) != 0)
{
int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag);
+ reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag, min_regno);
}
}
}