/* Definitions for computing resource usage of specific insns.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "flags.h"
#include "output.h"
#include "resource.h"
+#include "except.h"
#include "insn-attr.h"
+#include "params.h"
/* This structure is used to record liveness information at the targets or
fallthrough insns of branches. We will most likely need the information
static int *bb_ticks;
/* Marks registers possibly live at the current place being scanned by
- mark_target_live_regs. Used only by next two function. */
+ mark_target_live_regs. Also used by update_live_status. */
static HARD_REG_SET current_live_regs;
static HARD_REG_SET pending_dead_regs;
\f
static void update_live_status PARAMS ((rtx, rtx, void *));
-static int find_basic_block PARAMS ((rtx));
+static int find_basic_block PARAMS ((rtx, int));
static rtx next_insn_no_annul PARAMS ((rtx));
static rtx find_dead_or_set_registers PARAMS ((rtx, struct resources*,
rtx*, int, struct resources,
CLEAR_HARD_REG_BIT (pending_dead_regs, i);
}
}
-/* Find the number of the basic block that starts closest to INSN. Return -1
- if we couldn't find such a basic block. */
+
+/* Find the number of the basic block with correct live register
+ information that starts closest to INSN. Return -1 if we couldn't
+ find such a basic block or the beginning is more than
+ SEARCH_LIMIT instructions before INSN. Use SEARCH_LIMIT = -1 for
+ an unlimited search.
+
+ The delay slot filling code destroys the control-flow graph so,
+ instead of finding the basic block containing INSN, we search
+ backwards toward a BARRIER where the live register information is
+ correct. */
static int
-find_basic_block (insn)
+find_basic_block (insn, search_limit)
rtx insn;
+ int search_limit;
{
int i;
/* 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);
- insn && GET_CODE (insn) != BARRIER;
- insn = prev_nonnote_insn (insn))
+ insn && GET_CODE (insn) != BARRIER && search_limit != 0;
+ insn = prev_nonnote_insn (insn), --search_limit)
;
+ /* The closest BARRIER is too far away. */
+ if (search_limit == 0)
+ return -1;
+
/* The start of the function is basic block zero. */
- if (insn == 0)
+ else if (insn == 0)
return 0;
/* See if any of the upcoming CODE_LABELs start a basic block. If we reach
}
\f
/* Given X, some rtl, and RES, a pointer to a `struct resource', mark
- which resources are references by the insn. If INCLUDE_DELAYED_EFFECTS
+ which resources are referenced by the insn. If INCLUDE_DELAYED_EFFECTS
is TRUE, resources used by the called routine will be included for
CALL_INSNs. */
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ if (last_regno > FIRST_PSEUDO_REGISTER)
+ abort ();
for (r = regno; r < last_regno; r++)
SET_HARD_REG_BIT (res->regs, r);
}
return;
case REG:
- for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
- SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
+ {
+ unsigned int regno = REGNO (x);
+ unsigned int last_regno
+ = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+ if (last_regno > FIRST_PSEUDO_REGISTER)
+ abort ();
+ for (r = regno; r < last_regno; r++)
+ SET_HARD_REG_BIT (res->regs, r);
+ }
return;
case MEM:
/* If INSN is a USE made by update_block, we care about the
underlying insn. Any registers set by the underlying insn
are live since the insn is being done somewhere else. */
- if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+ if (INSN_P (XEXP (PATTERN (insn), 0)))
mark_set_resources (XEXP (PATTERN (insn), 0), res, 0,
MARK_SRC_DEST_CALL);
mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
return;
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
+ mark_set_resources (XEXP (XEXP (x, 1), 0), res, 0, MARK_SRC_DEST);
+ mark_set_resources (XEXP (XEXP (x, 1), 1), res, 0, MARK_SRC_DEST);
+ return;
+
case SIGN_EXTRACT:
case ZERO_EXTRACT:
if (! (mark_type == MARK_DEST && in_dest))
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ if (last_regno > FIRST_PSEUDO_REGISTER)
+ abort ();
for (r = regno; r < last_regno; r++)
SET_HARD_REG_BIT (res->regs, r);
}
case REG:
if (in_dest)
- for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
- SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
+ {
+ unsigned int regno = REGNO (x);
+ unsigned int last_regno
+ = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+ if (last_regno > FIRST_PSEUDO_REGISTER)
+ abort ();
+ for (r = regno; r < last_regno; r++)
+ SET_HARD_REG_BIT (res->regs, r);
+ }
return;
case STRICT_LOW_PART:
}
if (b == -1)
- b = find_basic_block (target);
+ b = find_basic_block (target, MAX_DELAY_SLOT_LIVE_SEARCH);
if (target_hash_table != NULL)
{
{
/* Allocate a place to put our results and chain it into the
hash table. */
- tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
+ tinfo = (struct target_info *) xmalloc (sizeof (struct target_info));
tinfo->uid = INSN_UID (target);
tinfo->block = b;
tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
/* If this insn is a USE made by update_block, we care about the
underlying insn. */
if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
- && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+ && INSN_P (XEXP (PATTERN (insn), 0)))
real_insn = XEXP (PATTERN (insn), 0);
if (GET_CODE (real_insn) == CALL_INSN)
#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
#endif
-#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
+#if !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
&& ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
#endif
)
{
if (target_hash_table != NULL)
{
+ int i;
+
+ for (i = 0; i < TARGET_HASH_PRIME; ++i)
+ {
+ struct target_info *ti = target_hash_table[i];
+
+ while (ti)
+ {
+ struct target_info *next = ti->next;
+ free (ti);
+ ti = next;
+ }
+ }
+
free (target_hash_table);
target_hash_table = NULL;
}
incr_ticks_for_insn (insn)
rtx insn;
{
- int b = find_basic_block (insn);
+ int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH);
if (b != -1)
bb_ticks[b]++;