#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
+/* The contents of the current function definition are allocated
+ in this obstack, and all are freed at the end of the function.
+ For top-level functions, this is temporary_obstack.
+ Separate obstacks are made for nested functions. */
+
+extern struct obstack *function_obstack;
+
/* List of labels that must never be deleted. */
extern rtx forced_labels;
static void mark_label_ref PROTO((rtx, rtx, int));
static void life_analysis PROTO((rtx, int));
void allocate_for_life_analysis PROTO((void));
-static void init_regset_vector PROTO((regset *, regset, int, int));
+static void init_regset_vector PROTO((regset *, int, int, struct obstack *));
static void propagate_block PROTO((regset, rtx, rtx, int,
regset, int));
static rtx flow_delete_insn PROTO((rtx));
/* List of label_refs to all labels whose addresses are taken
and used as data. */
rtx label_value_list;
+ int label_value_list_marked_live;
rtx x, note;
enum rtx_code prev_code, code;
int depth, pass;
restart:
label_value_list = 0;
+ label_value_list_marked_live = 0;
block_live_static = block_live;
bzero (block_live, n_basic_blocks);
bzero (block_marked, n_basic_blocks);
abort ();
n_basic_blocks = i + 1;
- /* Don't delete the labels (in this function)
- that are referenced by non-jump instructions. */
-
- for (x = label_value_list; x; x = XEXP (x, 1))
- if (! LABEL_REF_NONLOCAL_P (x))
- block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
-
for (x = forced_labels; x; x = XEXP (x, 1))
if (! LABEL_REF_NONLOCAL_P (x))
block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
if (computed_jump)
{
+ if (label_value_list_marked_live == 0)
+ {
+ label_value_list_marked_live = 1;
+
+ /* This could be made smarter by only considering
+ these live, if the computed goto is live. */
+
+ /* Don't delete the labels (in this function) that
+ are referenced by non-jump instructions. */
+
+ for (x = label_value_list; x; x = XEXP (x, 1))
+ if (! LABEL_REF_NONLOCAL_P (x))
+ block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
+ }
+
for (x = label_value_list; x; x = XEXP (x, 1))
mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
insn, 0);
gotos. */
}
+ /* All blocks associated with labels in label_value_list are
+ trivially considered as marked live, if the list is empty.
+ We do this to speed up the below code. */
+
+ if (label_value_list == 0)
+ label_value_list_marked_live = 1;
+
/* Pass over all blocks, marking each block that is reachable
and has not yet been marked.
Keep doing this until, in one pass, no blocks have been marked.
insn = basic_block_end[i];
if (GET_CODE (insn) == JUMP_INSN)
mark_label_ref (PATTERN (insn), insn, 0);
+
+ if (label_value_list_marked_live == 0)
+ /* Now that we know that this block is live, mark as
+ live, all the blocks that we might be able to get
+ to as live. */
+
+ for (insn = basic_block_head[i];
+ insn != NEXT_INSN (basic_block_end[i]);
+ insn = NEXT_INSN (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ for (note = REG_NOTES (insn);
+ note;
+ note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL)
+ {
+ x = XEXP (note, 0);
+ block_live[BLOCK_NUM (x)] = 1;
+ }
+ }
+ }
}
}
rtx f;
int nregs;
{
- register regset tem;
int first_pass;
int changed;
/* For each basic block, a bitmask of regs
if there isn't enough space.
Don't use oballoc since we may need to allocate other things during
this function on the temporary obstack. */
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_live_at_end, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_live_at_end, n_basic_blocks, regset_bytes,
+ &flow_obstack);
basic_block_new_live_at_end
= (regset *) alloca (n_basic_blocks * sizeof (regset));
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_new_live_at_end, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_new_live_at_end, n_basic_blocks, regset_bytes,
+ &flow_obstack);
basic_block_significant
= (regset *) alloca (n_basic_blocks * sizeof (regset));
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_significant, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_significant, n_basic_blocks, regset_bytes,
+ &flow_obstack);
/* Record which insns refer to any volatile memory
or for any reason can't be deleted just because they are dead stores.
{
/* If exiting needs the right stack value,
consider the stack pointer live at the end of the function. */
- basic_block_live_at_end[n_basic_blocks - 1]
- [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ STACK_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ STACK_POINTER_REGNUM);
}
/* Mark the frame pointer is needed at the end of the function. If
if (n_basic_blocks > 0)
{
- basic_block_live_at_end[n_basic_blocks - 1]
- [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live */
- basic_block_live_at_end[n_basic_blocks - 1]
- [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
- % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
- % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ HARD_FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ HARD_FRAME_POINTER_REGNUM);
#endif
}
#endif
)
{
- basic_block_live_at_end[n_basic_blocks - 1]
- [i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1], i);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1], i);
}
/* Propagate life info through the basic blocks
reg that is live at the end now but was not live there before
is one of the significant regs of this basic block). */
- for (j = 0; j < regset_size; j++)
- {
- register REGSET_ELT_TYPE x
- = (basic_block_new_live_at_end[i][j]
- & ~basic_block_live_at_end[i][j]);
- if (x)
- consider = 1;
- if (x & basic_block_significant[i][j])
- {
- must_rescan = 1;
- consider = 1;
- break;
- }
- }
-
+ EXECUTE_IF_AND_COMPL_IN_REG_SET (basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i],
+ 0, j,
+ {
+ consider = 1;
+ if (REGNO_REG_SET_P (basic_block_significant[i], j))
+ {
+ must_rescan = 1;
+ goto done;
+ }
+ });
+ done:
if (! consider)
continue;
}
/* No complete rescan needed;
just record those variables newly known live at end
as live at start as well. */
- for (j = 0; j < regset_size; j++)
- {
- register REGSET_ELT_TYPE x
- = (basic_block_new_live_at_end[i][j]
- & ~basic_block_live_at_end[i][j]);
- basic_block_live_at_start[i][j] |= x;
- basic_block_live_at_end[i][j] |= x;
- }
+ IOR_AND_COMPL_REG_SET (basic_block_live_at_start[i],
+ basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i]);
+
+ IOR_AND_COMPL_REG_SET (basic_block_live_at_end[i],
+ basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i]);
}
else
{
/* Update the basic_block_live_at_start
by propagation backwards through the block. */
- bcopy ((char *) basic_block_new_live_at_end[i],
- (char *) basic_block_live_at_end[i], regset_bytes);
- bcopy ((char *) basic_block_live_at_end[i],
- (char *) basic_block_live_at_start[i], regset_bytes);
+ COPY_REG_SET (basic_block_live_at_end[i],
+ basic_block_new_live_at_end[i]);
+ COPY_REG_SET (basic_block_live_at_start[i],
+ basic_block_live_at_end[i]);
propagate_block (basic_block_live_at_start[i],
basic_block_head[i], basic_block_end[i], 0,
first_pass ? basic_block_significant[i]
that falls through into this one (if any). */
head = basic_block_head[i];
if (basic_block_drops_in[i])
- {
- register int j;
- for (j = 0; j < regset_size; j++)
- basic_block_new_live_at_end[i-1][j]
- |= basic_block_live_at_start[i][j];
- }
+ IOR_REG_SET (basic_block_new_live_at_end[i-1],
+ basic_block_live_at_start[i]);
/* Update the basic_block_new_live_at_end's of
all the blocks that jump to this one. */
jump = LABEL_NEXTREF (jump))
{
register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
- register int j;
- for (j = 0; j < regset_size; j++)
- basic_block_new_live_at_end[from_block][j]
- |= basic_block_live_at_start[i][j];
+ IOR_REG_SET (basic_block_new_live_at_end[from_block],
+ basic_block_live_at_start[i]);
}
}
#ifdef USE_C_ALLOCA
one basic block. */
if (n_basic_blocks > 0)
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (basic_block_live_at_start[0][i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
- REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+ EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[0],
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+ });
/* Now the life information is accurate.
Make one more pass over each basic block
But we don't need to do this for the user's variables, since
ANSI says only volatile variables need this. */
#ifdef LONGJMP_RESTORE_FROM_STACK
- for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
- if (regs_live_at_setjmp[i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))
- && regno_reg_rtx[i] != 0 && ! REG_USERVAR_P (regno_reg_rtx[i]))
- {
- REG_LIVE_LENGTH (i) = -1;
- REG_BASIC_BLOCK (i) = -1;
- }
+ EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ if (regno_reg_rtx[i] != 0
+ && ! REG_USERVAR_P (regno_reg_rtx[i]))
+ {
+ REG_LIVE_LENGTH (i) = -1;
+ REG_BASIC_BLOCK (i) = -1;
+ }
+ });
#endif
#endif
If the pseudo goes in a hard reg, some other value may occupy
that hard reg where this pseudo is dead, thus clobbering the pseudo.
Conclusion: such a pseudo must not go in a hard reg. */
- for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
- if ((regs_live_at_setjmp[i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
- && regno_reg_rtx[i] != 0)
- {
- REG_LIVE_LENGTH (i) = -1;
- REG_BASIC_BLOCK (i) = -1;
- }
+ EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ if (regno_reg_rtx[i] != 0)
+ {
+ REG_LIVE_LENGTH (i) = -1;
+ REG_BASIC_BLOCK (i) = -1;
+ }
+ });
obstack_free (&flow_obstack, NULL_PTR);
}
allocate_for_life_analysis ()
{
register int i;
- register regset tem;
regset_size = ((max_regno + REGSET_ELT_BITS - 1) / REGSET_ELT_BITS);
regset_bytes = regset_size * sizeof (*(regset) 0);
basic_block_live_at_start
= (regset *) oballoc (n_basic_blocks * sizeof (regset));
- tem = (regset) oballoc (n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_live_at_start, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_live_at_start, n_basic_blocks, regset_bytes,
+ function_obstack);
- regs_live_at_setjmp = (regset) oballoc (regset_bytes);
- bzero ((char *) regs_live_at_setjmp, regset_bytes);
+ regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
+ CLEAR_REG_SET (regs_live_at_setjmp);
}
/* Make each element of VECTOR point at a regset,
BYTES_PER_ELT is the number of bytes in one regset. */
static void
-init_regset_vector (vector, space, nelts, bytes_per_elt)
+init_regset_vector (vector, nelts, bytes_per_elt, alloc_obstack)
regset *vector;
- regset space;
int nelts;
int bytes_per_elt;
+ struct obstack *alloc_obstack;
{
register int i;
- register regset p = space;
for (i = 0; i < nelts; i++)
{
- vector[i] = p;
- p += bytes_per_elt / sizeof (*p);
+ vector[i] = OBSTACK_ALLOC_REG_SET (alloc_obstack);
+ CLEAR_REG_SET (vector[i]);
}
}
/* The following variables are used only if FINAL is nonzero. */
/* This vector gets one element for each reg that has been live
at any point in the basic block that has been scanned so far.
- SOMETIMES_MAX says how many elements are in use so far.
- In each element, OFFSET is the byte-number within a regset
- for the register described by the element, and BIT is a mask
- for that register's bit within the byte. */
- register struct sometimes { short offset; short bit; } *regs_sometimes_live;
+ SOMETIMES_MAX says how many elements are in use so far. */
+ register int *regs_sometimes_live;
int sometimes_max = 0;
/* This regset has 1 for each reg that we have seen live so far.
It and REGS_SOMETIMES_LIVE are updated together. */
current basic block, and adjust as we pass ends and starts of loops. */
loop_depth = basic_block_loop_depth[bnum];
- dead = (regset) alloca (regset_bytes);
- live = (regset) alloca (regset_bytes);
+ dead = ALLOCA_REG_SET ();
+ live = ALLOCA_REG_SET ();
cc0_live = 0;
last_mem_set = 0;
if (final)
{
- register int i, offset;
- REGSET_ELT_TYPE bit;
+ register int i;
num_scratch = 0;
- maxlive = (regset) alloca (regset_bytes);
- bcopy ((char *) old, (char *) maxlive, regset_bytes);
- regs_sometimes_live
- = (struct sometimes *) alloca (max_regno * sizeof (struct sometimes));
+ maxlive = ALLOCA_REG_SET ();
+ COPY_REG_SET (maxlive, old);
+ regs_sometimes_live = (int *) alloca (max_regno * sizeof (int));
/* Process the regs live at the end of the block.
Enter them in MAXLIVE and REGS_SOMETIMES_LIVE.
- Also mark them as not local to any one basic block. */
-
- for (offset = 0, i = 0; offset < regset_size; offset++)
- for (bit = 1; bit; bit <<= 1, i++)
- {
- if (i == max_regno)
- break;
- if (old[offset] & bit)
- {
- REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
- regs_sometimes_live[sometimes_max].offset = offset;
- regs_sometimes_live[sometimes_max].bit = i % REGSET_ELT_BITS;
- sometimes_max++;
- }
- }
+ Also mark them as not local to any one basic block. */
+ EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
+ {
+ REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+ regs_sometimes_live[sometimes_max] = i;
+ sometimes_max++;
+ });
}
/* Scan the block an insn at a time from end to beginning. */
warn if any non-volatile datum is live. */
if (final && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
- {
- int i;
- for (i = 0; i < regset_size; i++)
- regs_live_at_setjmp[i] |= old[i];
- }
+ IOR_REG_SET (regs_live_at_setjmp, old);
}
/* Update the life-status of regs for this insn.
goto flushed;
}
- for (i = 0; i < regset_size; i++)
- {
- dead[i] = 0; /* Faster than bzero here */
- live[i] = 0; /* since regset_size is usually small */
- }
+ CLEAR_REG_SET (dead);
+ CLEAR_REG_SET (live);
/* See if this is an increment or decrement that can be
merged into a following memory address. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; 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));
+ SET_REGNO_REG_SET (dead, i);
/* The stack ptr is used (honorarily) by a CALL insn. */
- live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= ((REGSET_ELT_TYPE) 1
- << (STACK_POINTER_REGNUM % REGSET_ELT_BITS));
+ SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
/* Calls may also reference any of the global registers,
so they are made live. */
}
/* Update OLD for the registers used or set. */
- for (i = 0; i < regset_size; i++)
- {
- old[i] &= ~dead[i];
- old[i] |= live[i];
- }
+ AND_COMPL_REG_SET (old, dead);
+ IOR_REG_SET (old, live);
if (GET_CODE (insn) == CALL_INSN && final)
{
must not go in a register clobbered by calls.
Find all regs now live and record this for them. */
- register struct sometimes *p = regs_sometimes_live;
+ register int *p = regs_sometimes_live;
for (i = 0; i < sometimes_max; i++, p++)
- if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
- REG_N_CALLS_CROSSED (p->offset * REGSET_ELT_BITS + p->bit)++;
+ if (REGNO_REG_SET_P (old, *p))
+ REG_N_CALLS_CROSSED (*p)++;
}
}
if (final)
{
- for (i = 0; i < regset_size; i++)
- {
- register REGSET_ELT_TYPE diff = live[i] & ~maxlive[i];
+ register int regno;
+ register int *p;
- if (diff)
- {
- register int regno;
- maxlive[i] |= diff;
- for (regno = 0; diff && regno < REGSET_ELT_BITS; regno++)
- if (diff & ((REGSET_ELT_TYPE) 1 << regno))
- {
- regs_sometimes_live[sometimes_max].offset = i;
- regs_sometimes_live[sometimes_max].bit = regno;
- diff &= ~ ((REGSET_ELT_TYPE) 1 << regno);
- sometimes_max++;
- }
- }
- }
+ EXECUTE_IF_AND_COMPL_IN_REG_SET (live, maxlive, 0, regno,
+ {
+ regs_sometimes_live[sometimes_max++] = regno;
+ SET_REGNO_REG_SET (maxlive, regno);
+ });
- {
- register struct sometimes *p = regs_sometimes_live;
- for (i = 0; i < sometimes_max; i++, p++)
- {
- if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
- REG_LIVE_LENGTH (p->offset * REGSET_ELT_BITS + p->bit)++;
- }
- }
+ p = regs_sometimes_live;
+ for (i = 0; i < sometimes_max; i++)
+ {
+ regno = *p++;
+ if (REGNO_REG_SET_P (old, regno))
+ REG_LIVE_LENGTH (regno)++;
+ }
}
}
flushed: ;
if (GET_CODE (r) == REG)
{
register int regno = REGNO (r);
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
/* Don't delete insns to set global regs. */
if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
it, so we can treat it normally). */
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
- || (needed[offset] & bit) != 0)
+ || REGNO_REG_SET_P (needed, regno))
return 0;
/* If this is a hard register, verify that subsequent words are
int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
while (--n > 0)
- if ((needed[(regno + n) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + n) % REGSET_ELT_BITS))) != 0)
+ if (REGNO_REG_SET_P (needed, regno+n))
return 0;
}
&& (global_regs[regno] || FUNCTION_ARG_REGNO_P (regno))))
return 0;
- return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)));
+ return REGNO_REG_SET_P (basic_block_live_at_start[0], regno);
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
return 0;
return ((REG_N_SETS (regno) > 1
- || (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))))
- && (regs_live_at_setjmp[regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))));
+ || REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+ && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
}
\f
/* Process the registers that are set within X.
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
/* && regno != STACK_POINTER_REGNUM) -- let's try without this. */
{
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE some_needed = (needed[offset] & bit);
- REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
+ int some_needed = REGNO_REG_SET_P (needed, regno);
+ int some_not_needed = ! some_needed;
/* Mark it as a significant register for this basic block. */
if (significant)
- significant[offset] |= bit;
+ SET_REGNO_REG_SET (significant, regno);
/* Mark it as as dead before this insn. */
- dead[offset] |= bit;
+ SET_REGNO_REG_SET (dead, regno);
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
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);
-
+ int regno_n = regno + n;
+ int needed_regno = REGNO_REG_SET_P (needed, regno_n);
if (significant)
- significant[(regno + n) / REGSET_ELT_BITS] |= n_bit;
+ SET_REGNO_REG_SET (significant, regno_n);
- dead[(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);
+ SET_REGNO_REG_SET (dead, regno_n);
+ some_needed |= needed_regno;
+ some_not_needed |= ! needed_regno;
}
}
/* Additional data to record if this is the final pass. */
for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
i >= 0; i--)
- if ((needed[(regno + i) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + i) % REGSET_ELT_BITS))) == 0)
+ if (!REGNO_REG_SET_P (needed, regno + i))
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_UNUSED,
gen_rtx (REG, reg_raw_mode[regno + i],
it previously wasn't live here. If we don't mark
it as needed, we'll put a REG_DEAD note for it
on this insn, which is incorrect. */
- needed[regno / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (needed, regno);
/* If there are any calls between INSN and INCR, show
that REGNO now crosses them. */
return;
case MEM:
- /* Invalidate the data for the last MEM stored. We could do this only
- if the addresses conflict, but this doesn't seem worthwhile. */
- last_mem_set = 0;
+ /* CYGNUS LOCAL dje/8176 */
+ /* Invalidate the data for the last MEM stored, but only if MEM is
+ something that can be stored into. */
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+ ; /* needn't clear last_mem_set */
+ else
+ last_mem_set = 0;
+ /* END CYGNUS LOCAL */
#ifdef AUTO_INC_DEC
if (final)
regno = REGNO (x);
{
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE some_needed = needed[offset] & bit;
- REGSET_ELT_TYPE some_not_needed = (~ needed[offset]) & bit;
+ REGSET_ELT_TYPE some_needed = REGNO_REG_SET_P (needed, regno);
+ REGSET_ELT_TYPE some_not_needed = ! some_needed;
- live[offset] |= bit;
+ SET_REGNO_REG_SET (live, regno);
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
n = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (--n > 0)
{
- REGSET_ELT_TYPE n_bit
- = (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
+ int regno_n = regno + n;
+ int needed_regno = REGNO_REG_SET_P (needed, regno_n);
- 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);
+ SET_REGNO_REG_SET (live, regno_n);
+ some_needed |= needed_regno;
+ some_not_needed |= ! needed_regno;
}
}
if (final)
for (i = HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1;
i >= 0; i--)
- if ((needed[(regno + i) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + i) % REGSET_ELT_BITS))) == 0
+ if (!REGNO_REG_SET_P (needed, regno + i)
&& ! dead_or_set_regno_p (insn, regno + i))
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_DEAD,
if (! EXIT_IGNORE_STACK
|| (! FRAME_POINTER_REQUIRED && flag_omit_frame_pointer))
#endif
- live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i]
|| EPILOGUE_USES (i)
#endif
)
- live[i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (live, i);
break;
}
}
fprintf (file, "\nRegisters live at start:");
for (regno = 0; regno < max_regno; regno++)
- {
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- if (basic_block_live_at_start[i][offset] & bit)
- fprintf (file, " %d", regno);
- }
+ if (REGNO_REG_SET_P (basic_block_live_at_start[i], regno))
+ fprintf (file, " %d", regno);
fprintf (file, "\n");
}
fprintf (file, "\n");