/* Definitions for computing resource usage of specific insns.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
+#include "backend.h"
#include "rtl.h"
+#include "df.h"
+#include "diagnostic-core.h"
#include "tm_p.h"
-#include "hard-reg-set.h"
-#include "function.h"
#include "regs.h"
#include "flags.h"
#include "output.h"
#include "except.h"
#include "insn-attr.h"
#include "params.h"
-#include "df.h"
+#include "emit-rtl.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 HARD_REG_SET pending_dead_regs;
\f
static void update_live_status (rtx, const_rtx, void *);
-static int find_basic_block (rtx, int);
-static rtx next_insn_no_annul (rtx);
-static rtx find_dead_or_set_registers (rtx, struct resources*,
- rtx*, int, struct resources,
- struct resources);
+static int find_basic_block (rtx_insn *, int);
+static rtx_insn *next_insn_no_annul (rtx_insn *);
+static rtx_insn *find_dead_or_set_registers (rtx_insn *, struct resources*,
+ rtx *, int, struct resources,
+ struct resources);
\f
/* Utility function called from mark_target_live_regs via note_stores.
It deadens any CLOBBERed registers and livens any SET registers. */
else
{
first_regno = REGNO (dest);
- last_regno = END_HARD_REGNO (dest);
+ last_regno = END_REGNO (dest);
}
if (GET_CODE (x) == CLOBBER)
correct. */
static int
-find_basic_block (rtx insn, int search_limit)
+find_basic_block (rtx_insn *insn, int search_limit)
{
/* Scan backwards to the previous BARRIER. Then see if we can find a
label that starts a basic block. Return the basic block number. */
/* Similar to next_insn, but ignores insns in the delay slots of
an annulled branch. */
-static rtx
-next_insn_no_annul (rtx insn)
+static rtx_insn *
+next_insn_no_annul (rtx_insn *insn)
{
if (insn)
{
insn = NEXT_INSN (insn);
if (insn && NONJUMP_INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
- insn = XVECEXP (PATTERN (insn), 0, 0);
+ insn = as_a <rtx_sequence *> (PATTERN (insn))->insn (0);
}
return insn;
However, we may have moved some of the parameter loading insns
into the delay slot of this CALL. If so, the USE's for them
don't count and should be skipped. */
- rtx_insn *insn = PREV_INSN (x);
+ rtx_insn *insn = PREV_INSN (as_a <rtx_insn *> (x));
rtx_sequence *sequence = 0;
int seq_size = 0;
int i;
if (frame_pointer_needed)
{
SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
- SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
-#endif
+ if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
+ SET_HARD_REG_BIT (res->regs, HARD_FRAME_POINTER_REGNUM);
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
include_delayed_effects
? MARK_SRC_DEST_CALL : MARK_SRC_DEST);
-#ifdef INSN_REFERENCES_ARE_DELAYED
if (! include_delayed_effects
- && INSN_REFERENCES_ARE_DELAYED (x))
+ && INSN_REFERENCES_ARE_DELAYED (as_a <rtx_insn *> (x)))
return;
-#endif
/* No special processing, just speed up. */
mark_referenced_resources (PATTERN (x), res, include_delayed_effects);
Stop after passing a few conditional jumps, and/or a small
number of unconditional branches. */
-static rtx
-find_dead_or_set_registers (rtx target, struct resources *res,
+static rtx_insn *
+find_dead_or_set_registers (rtx_insn *target, struct resources *res,
rtx *jump_target, int jump_count,
struct resources set, struct resources needed)
{
HARD_REG_SET scratch;
- rtx insn, next;
- rtx jump_insn = 0;
+ rtx_insn *insn;
+ rtx_insn *next_insn;
+ rtx_insn *jump_insn = 0;
int i;
- for (insn = target; insn; insn = next)
+ for (insn = target; insn; insn = next_insn)
{
- rtx this_jump_insn = insn;
+ rtx_insn *this_insn = insn;
- next = NEXT_INSN (insn);
+ next_insn = NEXT_INSN (insn);
/* If this instruction can throw an exception, then we don't
know where we might end up next. That means that we have to
of a call, so search for a JUMP_INSN in any position. */
for (i = 0; i < seq->len (); i++)
{
- this_jump_insn = seq->element (i);
- if (JUMP_P (this_jump_insn))
+ this_insn = seq->insn (i);
+ if (JUMP_P (this_insn))
break;
}
}
break;
}
- if (JUMP_P (this_jump_insn))
+ if (rtx_jump_insn *this_jump_insn =
+ dyn_cast <rtx_jump_insn *> (this_insn))
{
if (jump_count++ < 10)
{
if (any_uncondjump_p (this_jump_insn)
|| ANY_RETURN_P (PATTERN (this_jump_insn)))
{
- next = JUMP_LABEL (this_jump_insn);
- if (ANY_RETURN_P (next))
- next = NULL_RTX;
+ rtx lab_or_return = this_jump_insn->jump_label ();
+ if (ANY_RETURN_P (lab_or_return))
+ next_insn = NULL;
+ else
+ next_insn = as_a <rtx_insn *> (lab_or_return);
if (jump_insn == 0)
{
jump_insn = insn;
AND_COMPL_HARD_REG_SET (scratch, needed.regs);
AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
- if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
- find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
- &target_res, 0, jump_count,
- target_set, needed);
- find_dead_or_set_registers (next,
+ if (!ANY_RETURN_P (this_jump_insn->jump_label ()))
+ find_dead_or_set_registers
+ (this_jump_insn->jump_target (),
+ &target_res, 0, jump_count, target_set, needed);
+ find_dead_or_set_registers (next_insn,
&fallthrough_res, 0, jump_count,
set, needed);
IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
if (mark_type == MARK_SRC_DEST_CALL)
{
+ rtx_call_insn *call_insn = as_a <rtx_call_insn *> (x);
rtx link;
HARD_REG_SET regs;
res->cc = res->memory = 1;
- get_call_reg_set_usage (x, ®s, regs_invalidated_by_call);
+ get_call_reg_set_usage (call_insn, ®s, regs_invalidated_by_call);
IOR_HARD_REG_SET (res->regs, regs);
- for (link = CALL_INSN_FUNCTION_USAGE (x);
+ for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
link; link = XEXP (link, 1))
if (GET_CODE (XEXP (link, 0)) == CLOBBER)
mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
/* Check for a REG_SETJMP. If it exists, then we must
assume that this call can clobber any register. */
- if (find_reg_note (x, REG_SETJMP, NULL))
+ if (find_reg_note (call_insn, REG_SETJMP, NULL))
SET_HARD_REG_SET (res->regs);
}
/* An insn consisting of just a CLOBBER (or USE) is just for flow
and doesn't actually do anything, so we ignore it. */
-#ifdef INSN_SETS_ARE_DELAYED
if (mark_type != MARK_SRC_DEST_CALL
- && INSN_SETS_ARE_DELAYED (x))
+ && INSN_SETS_ARE_DELAYED (as_a <rtx_insn *> (x)))
return;
-#endif
x = PATTERN (x);
if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
init_resource_info () was invoked before we are called. */
void
-mark_target_live_regs (rtx insns, rtx target, struct resources *res)
+mark_target_live_regs (rtx_insn *insns, rtx target_maybe_return, struct resources *res)
{
int b = -1;
unsigned int i;
struct target_info *tinfo = NULL;
- rtx insn;
- rtx jump_insn = 0;
+ rtx_insn *insn;
rtx jump_target;
HARD_REG_SET scratch;
struct resources set, needed;
/* Handle end of function. */
- if (target == 0 || ANY_RETURN_P (target))
+ if (target_maybe_return == 0 || ANY_RETURN_P (target_maybe_return))
{
*res = end_of_function_needs;
return;
}
+ /* We've handled the case of RETURN/SIMPLE_RETURN; we should now have an
+ instruction. */
+ rtx_insn *target = as_a <rtx_insn *> (target_maybe_return);
+
/* Handle return insn. */
- else if (return_insn_p (target))
+ if (return_insn_p (target))
{
*res = end_of_function_needs;
mark_referenced_resources (target, res, false);
information, we can get it from there unless the insn at the
start of the basic block has been deleted. */
if (tinfo && tinfo->block != -1
- && ! INSN_DELETED_P (BB_HEAD (BASIC_BLOCK_FOR_FN (cfun,
- tinfo->block))))
+ && ! BB_HEAD (BASIC_BLOCK_FOR_FN (cfun, tinfo->block))->deleted ())
b = tinfo->block;
}
if (b != -1)
{
regset regs_live = DF_LR_IN (BASIC_BLOCK_FOR_FN (cfun, b));
- rtx start_insn, stop_insn;
+ rtx_insn *start_insn, *stop_insn;
/* Compute hard regs live at start of block. */
REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
if (NONJUMP_INSN_P (start_insn)
&& GET_CODE (PATTERN (start_insn)) == SEQUENCE)
- start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
+ start_insn = as_a <rtx_sequence *> (PATTERN (start_insn))->insn (0);
if (NONJUMP_INSN_P (stop_insn)
&& GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
insn = next_insn_no_annul (insn))
{
rtx link;
- rtx real_insn = insn;
+ rtx_insn *real_insn = insn;
enum rtx_code code = GET_CODE (insn);
if (DEBUG_INSN_P (insn))
if (code == INSN
&& GET_CODE (PATTERN (insn)) == USE
&& INSN_P (XEXP (PATTERN (insn), 0)))
- real_insn = XEXP (PATTERN (insn), 0);
+ real_insn = as_a <rtx_insn *> (XEXP (PATTERN (insn), 0));
if (CALL_P (real_insn))
{
CLEAR_RESOURCE (&set);
CLEAR_RESOURCE (&needed);
- jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
- set, needed);
+ rtx_insn *jump_insn = find_dead_or_set_registers (target, res, &jump_target,
+ 0, set, needed);
/* If we hit an unconditional branch, we have another way of finding out
what is live: we can see what is live at the branch target and include
if (jump_insn)
{
struct resources new_resources;
- rtx stop_insn = next_active_insn (jump_insn);
+ rtx_insn *stop_insn = next_active_insn (jump_insn);
if (!ANY_RETURN_P (jump_target))
jump_target = next_active_insn (jump_target);
This should be invoked before the first call to mark_target_live_regs. */
void
-init_resource_info (rtx epilogue_insn)
+init_resource_info (rtx_insn *epilogue_insn)
{
int i;
basic_block bb;
if (frame_pointer_needed)
{
SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
- SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
-#endif
+ if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
+ SET_HARD_REG_BIT (end_of_function_needs.regs,
+ HARD_FRAME_POINTER_REGNUM);
}
if (!(frame_pointer_needed
&& EXIT_IGNORE_STACK
&end_of_function_needs, true);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i]
-#ifdef EPILOGUE_USES
- || EPILOGUE_USES (i)
-#endif
- )
+ if (global_regs[i] || EPILOGUE_USES (i))
SET_HARD_REG_BIT (end_of_function_needs.regs, i);
/* The registers required to be live at the end of the function are
/* Clear any hashed information that we have stored for INSN. */
void
-clear_hashed_info_for_insn (rtx insn)
+clear_hashed_info_for_insn (rtx_insn *insn)
{
struct target_info *tinfo;
/* Increment the tick count for the basic block that contains INSN. */
void
-incr_ticks_for_insn (rtx insn)
+incr_ticks_for_insn (rtx_insn *insn)
{
int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH);