/* Definitions for computing resource usage of specific insns.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
This file is part of GCC.
static int
find_basic_block (rtx insn, int search_limit)
{
- basic_block bb;
-
/* Scan backwards to the previous BARRIER. Then see if we can find a
label that starts a basic block. Return the basic block number. */
for (insn = prev_nonnote_insn (insn);
for (insn = next_nonnote_insn (insn);
insn && LABEL_P (insn);
insn = next_nonnote_insn (insn))
- {
- FOR_EACH_BB (bb)
- if (insn == BB_HEAD (bb))
- return bb->index;
- }
+ if (BLOCK_FOR_INSN (insn))
+ return BLOCK_FOR_INSN (insn)->index;
return -1;
}
void
mark_referenced_resources (rtx x, struct resources *res,
- int include_delayed_effects)
+ bool include_delayed_effects)
{
enum rtx_code code = GET_CODE (x);
int i, j;
case SUBREG:
if (!REG_P (SUBREG_REG (x)))
- mark_referenced_resources (SUBREG_REG (x), res, 0);
+ mark_referenced_resources (SUBREG_REG (x), res, false);
else
{
unsigned int regno = subreg_regno (x);
res->volatil |= MEM_VOLATILE_P (x);
/* Mark registers used to access memory. */
- mark_referenced_resources (XEXP (x, 0), res, 0);
+ mark_referenced_resources (XEXP (x, 0), res, false);
return;
case CC0:
traditional asms unlike their normal usage. */
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
- mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
+ mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, false);
return;
case CALL:
/* The first operand will be a (MEM (xxx)) but doesn't really reference
memory. The second operand may be referenced, though. */
- mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
- mark_referenced_resources (XEXP (x, 1), res, 0);
+ mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, false);
+ mark_referenced_resources (XEXP (x, 1), res, false);
return;
case SET:
registers used to access memory are referenced. SET_DEST is
also referenced if it is a ZERO_EXTRACT. */
- mark_referenced_resources (SET_SRC (x), res, 0);
+ mark_referenced_resources (SET_SRC (x), res, false);
x = SET_DEST (x);
if (GET_CODE (x) == ZERO_EXTRACT
|| GET_CODE (x) == STRICT_LOW_PART)
- mark_referenced_resources (x, res, 0);
+ mark_referenced_resources (x, res, false);
else if (GET_CODE (x) == SUBREG)
x = SUBREG_REG (x);
if (MEM_P (x))
- mark_referenced_resources (XEXP (x, 0), res, 0);
+ mark_referenced_resources (XEXP (x, 0), res, false);
return;
case CLOBBER:
}
if (i >= seq_size)
mark_referenced_resources (XEXP (XEXP (link, 0), 0),
- res, 0);
+ res, false);
}
}
}
if (jump_count >= 10)
break;
- mark_referenced_resources (insn, &needed, 1);
+ mark_referenced_resources (insn, &needed, true);
/* For an annulled branch, mark_set_resources ignores slots
filled by instructions from the target. This is correct
}
}
- mark_referenced_resources (insn, &needed, 1);
+ mark_referenced_resources (insn, &needed, true);
mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
COPY_HARD_REG_SET (scratch, set.regs);
(with no intervening active insns) to see if any of them start a basic
block. If we hit the start of the function first, we use block 0.
- Once we have found a basic block and a corresponding first insns, we can
- accurately compute the live status from basic_block_live_regs and
- reg_renumber. (By starting at a label following a BARRIER, we are immune
- to actions taken by reload and jump.) Then we scan all insns between
- that point and our target. For each CLOBBER (or for call-clobbered regs
- when we pass a CALL_INSN), mark the appropriate registers are dead. For
- a SET, mark them as live.
+ Once we have found a basic block and a corresponding first insn, we can
+ accurately compute the live status (by starting at a label following a
+ BARRIER, we are immune to actions taken by reload and jump.) Then we
+ scan all insns between that point and our target. For each CLOBBER (or
+ for call-clobbered regs when we pass a CALL_INSN), mark the appropriate
+ registers are dead. For a SET, mark them as live.
We have to be careful when using REG_DEAD notes because they are not
updated by such things as find_equiv_reg. So keep track of registers
else if (return_insn_p (target))
{
*res = end_of_function_needs;
- mark_referenced_resources (target, res, 0);
+ mark_referenced_resources (target, res, false);
return;
}
/* If we found a basic block, get the live registers from it and update
them with anything set or killed between its start and the insn before
- TARGET. Otherwise, we must assume everything is live. */
+ TARGET; this custom life analysis is really about registers so we need
+ to use the LR problem. Otherwise, we must assume everything is live. */
if (b != -1)
{
regset regs_live = DF_LR_IN (BASIC_BLOCK (b));
rtx start_insn, stop_insn;
- /* Compute hard regs live at start of block -- this is the real hard regs
- marked live, plus live pseudo regs that have been renumbered to
- hard regs. */
-
+ /* Compute hard regs live at start of block. */
REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
/* Get starting and ending insn, handling the case where each might
rtx real_insn = insn;
enum rtx_code code = GET_CODE (insn);
+ if (DEBUG_INSN_P (insn))
+ continue;
+
/* If this insn is from the target of a branch, it isn't going to
be used in the sequel. If it is used in both cases, this
test will not be true. */
else if (LABEL_P (real_insn))
{
+ basic_block bb;
+
/* A label clobbers the pending dead registers since neither
reload nor jump will propagate a value across a label. */
AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
CLEAR_HARD_REG_SET (pending_dead_regs);
+
+ /* We must conservatively assume that all registers that used
+ to be live here still are. The fallthrough edge may have
+ left a live register uninitialized. */
+ bb = BLOCK_FOR_INSN (real_insn);
+ if (bb)
+ {
+ HARD_REG_SET extra_live;
+
+ REG_SET_TO_HARD_REG_SET (extra_live, DF_LR_IN (bb));
+ IOR_HARD_REG_SET (current_live_regs, extra_live);
+ }
}
/* The beginning of the epilogue corresponds to the end of the
/* Include JUMP_INSN in the needed registers. */
for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
{
- mark_referenced_resources (insn, &needed, 1);
+ mark_referenced_resources (insn, &needed, true);
COPY_HARD_REG_SET (scratch, needed.regs);
AND_COMPL_HARD_REG_SET (scratch, set.regs);
init_resource_info (rtx epilogue_insn)
{
int i;
+ basic_block bb;
/* Indicate what resources are required to be valid at the end of the current
function. The condition code never is and memory always is. If the
if (crtl->return_rtx != 0)
mark_referenced_resources (crtl->return_rtx,
- &end_of_function_needs, 1);
+ &end_of_function_needs, true);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i]
/* Allocate and initialize the tables used by mark_target_live_regs. */
target_hash_table = XCNEWVEC (struct target_info *, TARGET_HASH_PRIME);
bb_ticks = XCNEWVEC (int, last_basic_block);
+
+ /* Set the BLOCK_FOR_INSN of each label that starts a basic block. */
+ FOR_EACH_BB (bb)
+ if (LABEL_P (BB_HEAD (bb)))
+ BLOCK_FOR_INSN (BB_HEAD (bb)) = bb;
}
\f
/* Free up the resources allocated to mark_target_live_regs (). This
void
free_resource_info (void)
{
+ basic_block bb;
+
if (target_hash_table != NULL)
{
int i;
free (bb_ticks);
bb_ticks = NULL;
}
+
+ FOR_EACH_BB (bb)
+ if (LABEL_P (BB_HEAD (bb)))
+ BLOCK_FOR_INSN (BB_HEAD (bb)) = NULL;
}
\f
/* Clear any hashed information that we have stored for INSN. */
/* Add TRIAL to the set of resources used at the end of the current
function. */
void
-mark_end_of_function_resources (rtx trial, int include_delayed_effects)
+mark_end_of_function_resources (rtx trial, bool include_delayed_effects)
{
mark_referenced_resources (trial, &end_of_function_needs,
include_delayed_effects);