/* Register to Stack convert for GNU compiler.
- Copyright (C) 1992-2013 Free Software Foundation, Inc.
+ Copyright (C) 1992-2016 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
#include "tree.h"
-#include "rtl-error.h"
-#include "tm_p.h"
-#include "function.h"
+#include "df.h"
#include "insn-config.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "flags.h"
+#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
#include "recog.h"
-#include "basic-block.h"
+#include "varasm.h"
+#include "rtl-error.h"
+#include "cfgrtl.h"
+#include "cfganal.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
#include "reload.h"
-#include "ggc.h"
#include "tree-pass.h"
-#include "target.h"
-#include "df.h"
-#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
+#include "rtl-iter.h"
#ifdef STACK_REGS
static void pop_stack (stack_ptr, int);
static rtx *get_true_reg (rtx *);
-static int check_asm_stack_operands (rtx);
+static int check_asm_stack_operands (rtx_insn *);
static void get_asm_operands_in_out (rtx, int *, int *);
static rtx stack_result (tree);
static void replace_reg (rtx *, int);
-static void remove_regno_note (rtx, enum reg_note, unsigned int);
+static void remove_regno_note (rtx_insn *, enum reg_note, unsigned int);
static int get_hard_regnum (stack_ptr, rtx);
-static rtx emit_pop_insn (rtx, stack_ptr, rtx, enum emit_where);
-static void swap_to_top(rtx, stack_ptr, rtx, rtx);
-static bool move_for_stack_reg (rtx, stack_ptr, rtx);
-static bool move_nan_for_stack_reg (rtx, stack_ptr, rtx);
+static rtx_insn *emit_pop_insn (rtx_insn *, stack_ptr, rtx, enum emit_where);
+static void swap_to_top (rtx_insn *, stack_ptr, rtx, rtx);
+static bool move_for_stack_reg (rtx_insn *, stack_ptr, rtx);
+static bool move_nan_for_stack_reg (rtx_insn *, stack_ptr, rtx);
static int swap_rtx_condition_1 (rtx);
-static int swap_rtx_condition (rtx);
-static void compare_for_stack_reg (rtx, stack_ptr, rtx);
-static bool subst_stack_regs_pat (rtx, stack_ptr, rtx);
-static void subst_asm_stack_regs (rtx, stack_ptr);
-static bool subst_stack_regs (rtx, stack_ptr);
-static void change_stack (rtx, stack_ptr, stack_ptr, enum emit_where);
+static int swap_rtx_condition (rtx_insn *);
+static void compare_for_stack_reg (rtx_insn *, stack_ptr, rtx);
+static bool subst_stack_regs_pat (rtx_insn *, stack_ptr, rtx);
+static void subst_asm_stack_regs (rtx_insn *, stack_ptr);
+static bool subst_stack_regs (rtx_insn *, stack_ptr);
+static void change_stack (rtx_insn *, stack_ptr, stack_ptr, enum emit_where);
static void print_stack (FILE *, stack_ptr);
-static rtx next_flags_user (rtx);
+static rtx_insn *next_flags_user (rtx_insn *);
\f
/* Return nonzero if any stack register is mentioned somewhere within PAT. */
\f
static rtx ix86_flags_rtx;
-static rtx
-next_flags_user (rtx insn)
+static rtx_insn *
+next_flags_user (rtx_insn *insn)
{
/* Search forward looking for the first use of this value.
Stop at block boundaries. */
return insn;
if (CALL_P (insn))
- return NULL_RTX;
+ return NULL;
}
- return NULL_RTX;
+ return NULL;
}
\f
/* Reorganize the stack into ascending numbers, before this insn. */
static void
-straighten_stack (rtx insn, stack_ptr regstack)
+straighten_stack (rtx_insn *insn, stack_ptr regstack)
{
struct stack_def temp_stack;
int top;
case UNSPEC:
if (XINT (*pat, 1) == UNSPEC_TRUNC_NOOP
- || XINT (*pat, 1) == UNSPEC_LDA)
+ || XINT (*pat, 1) == UNSPEC_FILD_ATOMIC)
pat = & XVECEXP (*pat, 0, 0);
return pat;
numbers below refer to that explanation. */
static int
-check_asm_stack_operands (rtx insn)
+check_asm_stack_operands (rtx_insn *insn)
{
int i;
int n_clobbers;
char reg_used_as_output[FIRST_PSEUDO_REGISTER];
char implicitly_dies[FIRST_PSEUDO_REGISTER];
- int alt;
rtx *clobber_reg = 0;
int n_inputs, n_outputs;
/* Find out what the constraints require. If no constraint
alternative matches, this asm is malformed. */
- extract_insn (insn);
- constrain_operands (1);
- alt = which_alternative;
+ extract_constrain_insn (insn);
- preprocess_constraints ();
+ preprocess_constraints (insn);
get_asm_operands_in_out (body, &n_outputs, &n_inputs);
- if (alt < 0)
+ if (which_alternative < 0)
{
malformed_asm = 1;
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
return 0;
}
+ const operand_alternative *op_alt = which_op_alt ();
/* Strip SUBREGs here to make the following code simpler. */
for (i = 0; i < recog_data.n_operands; i++)
for (i = 0; i < n_outputs; i++)
if (STACK_REG_P (recog_data.operand[i]))
{
- if (reg_class_size[(int) recog_op_alt[i][alt].cl] != 1)
+ if (reg_class_size[(int) op_alt[i].cl] != 1)
{
error_for_asm (insn, "output constraint %d must specify a single register", i);
malformed_asm = 1;
if (operands_match_p (clobber_reg[j], recog_data.operand[i]))
break;
- if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
+ if (j < n_clobbers || op_alt[i].matches >= 0)
implicitly_dies[REGNO (recog_data.operand[i])] = 1;
}
record any earlyclobber. */
for (i = n_outputs; i < n_outputs + n_inputs; i++)
- if (recog_op_alt[i][alt].matches == -1)
+ if (op_alt[i].matches == -1)
{
int j;
number REGNO from INSN. Remove only one such note. */
static void
-remove_regno_note (rtx insn, enum reg_note note, unsigned int regno)
+remove_regno_note (rtx_insn *insn, enum reg_note note, unsigned int regno)
{
rtx *note_link, this_rtx;
and source is the top of stack. A death note for the top of stack
cases the movdf pattern to pop. */
-static rtx
-emit_pop_insn (rtx insn, stack_ptr regstack, rtx reg, enum emit_where where)
+static rtx_insn *
+emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where where)
{
- rtx pop_insn, pop_rtx;
+ rtx_insn *pop_insn;
+ rtx pop_rtx;
int hard_regno;
/* For complex types take care to pop both halves. These may survive in
rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
- pop_insn = NULL_RTX;
+ pop_insn = NULL;
if (get_hard_regnum (regstack, reg1) >= 0)
pop_insn = emit_pop_insn (insn, regstack, reg1, where);
if (get_hard_regnum (regstack, reg2) >= 0)
gcc_assert (hard_regno >= FIRST_STACK_REG);
- pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode),
+ pop_rtx = gen_rtx_SET (FP_MODE_REG (hard_regno, DFmode),
FP_MODE_REG (FIRST_STACK_REG, DFmode));
if (where == EMIT_AFTER)
If REG is already at the top of the stack, no insn is emitted. */
static void
-emit_swap_insn (rtx insn, stack_ptr regstack, rtx reg)
+emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
{
int hard_regno;
rtx swap_rtx;
- int tmp, other_reg; /* swap regno temps */
- rtx i1; /* the stack-reg insn prior to INSN */
+ int other_reg; /* swap regno temps */
+ rtx_insn *i1; /* the stack-reg insn prior to INSN */
rtx i1set = NULL_RTX; /* the SET rtx within I1 */
hard_regno = get_hard_regnum (regstack, reg);
gcc_assert (hard_regno >= FIRST_STACK_REG);
other_reg = regstack->top - (hard_regno - FIRST_STACK_REG);
-
- tmp = regstack->reg[other_reg];
- regstack->reg[other_reg] = regstack->reg[regstack->top];
- regstack->reg[regstack->top] = tmp;
+ std::swap (regstack->reg[regstack->top], regstack->reg[other_reg]);
/* Find the previous insn involving stack regs, but don't pass a
block boundary. */
i1 = NULL;
if (current_block && insn != BB_HEAD (current_block))
{
- rtx tmp = PREV_INSN (insn);
- rtx limit = PREV_INSN (BB_HEAD (current_block));
+ rtx_insn *tmp = PREV_INSN (insn);
+ rtx_insn *limit = PREV_INSN (BB_HEAD (current_block));
while (tmp != limit)
{
if (LABEL_P (tmp)
is emitted. */
static void
-swap_to_top (rtx insn, stack_ptr regstack, rtx src1, rtx src2)
+swap_to_top (rtx_insn *insn, stack_ptr regstack, rtx src1, rtx src2)
{
struct stack_def temp_stack;
- int regno, j, k, temp;
+ int regno, j, k;
temp_stack = *regstack;
k = temp_stack.top - (regno - FIRST_STACK_REG);
j = temp_stack.top;
- temp = temp_stack.reg[k];
- temp_stack.reg[k] = temp_stack.reg[j];
- temp_stack.reg[j] = temp;
+ std::swap (temp_stack.reg[j], temp_stack.reg[k]);
}
/* Place operand 2 next on the stack. */
k = temp_stack.top - (regno - FIRST_STACK_REG);
j = temp_stack.top - 1;
- temp = temp_stack.reg[k];
- temp_stack.reg[k] = temp_stack.reg[j];
- temp_stack.reg[j] = temp;
+ std::swap (temp_stack.reg[j], temp_stack.reg[k]);
}
change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
was deleted in the process. */
static bool
-move_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat)
+move_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat)
{
rtx *psrc = get_true_reg (&SET_SRC (pat));
rtx *pdest = get_true_reg (&SET_DEST (pat));
a NaN into DEST, then invokes move_for_stack_reg. */
static bool
-move_nan_for_stack_reg (rtx insn, stack_ptr regstack, rtx dest)
+move_nan_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx dest)
{
rtx pat;
dest = FP_MODE_REG (REGNO (dest), SFmode);
- pat = gen_rtx_SET (VOIDmode, dest, not_a_num);
+ pat = gen_rtx_SET (dest, not_a_num);
PATTERN (insn) = pat;
INSN_CODE (insn) = -1;
}
static int
-swap_rtx_condition (rtx insn)
+swap_rtx_condition (rtx_insn *insn)
{
rtx pat = PATTERN (insn);
set up. */
static void
-compare_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat_src)
+compare_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat_src)
{
rtx *src1, *src2;
rtx src1_note, src2_note;
&& get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))
&& swap_rtx_condition (insn))
{
- rtx temp;
- temp = XEXP (pat_src, 0);
- XEXP (pat_src, 0) = XEXP (pat_src, 1);
- XEXP (pat_src, 1) = temp;
+ std::swap (XEXP (pat_src, 0), XEXP (pat_src, 1));
src1 = get_true_reg (&XEXP (pat_src, 0));
src2 = get_true_reg (&XEXP (pat_src, 1));
}
}
\f
-/* Substitute new registers in LOC, which is part of a debug insn.
- REGSTACK is the current register layout. */
-
-static int
-subst_stack_regs_in_debug_insn (rtx *loc, void *data)
-{
- stack_ptr regstack = (stack_ptr)data;
- int hard_regno;
-
- if (!STACK_REG_P (*loc))
- return 0;
-
- hard_regno = get_hard_regnum (regstack, *loc);
-
- /* If we can't find an active register, reset this debug insn. */
- if (hard_regno == -1)
- return 1;
-
- gcc_assert (hard_regno >= FIRST_STACK_REG);
-
- replace_reg (loc, hard_regno);
-
- return -1;
-}
-
/* Substitute hardware stack regs in debug insn INSN, using stack
layout REGSTACK. If we can't find a hardware stack reg for any of
the REGs in it, reset the debug insn. */
static void
-subst_all_stack_regs_in_debug_insn (rtx insn, struct stack_def *regstack)
+subst_all_stack_regs_in_debug_insn (rtx_insn *insn, struct stack_def *regstack)
{
- int ret = for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
- subst_stack_regs_in_debug_insn,
- regstack);
+ subrtx_ptr_iterator::array_type array;
+ FOR_EACH_SUBRTX_PTR (iter, array, &INSN_VAR_LOCATION_LOC (insn), NONCONST)
+ {
+ rtx *loc = *iter;
+ rtx x = *loc;
+ if (STACK_REG_P (x))
+ {
+ int hard_regno = get_hard_regnum (regstack, x);
- if (ret == 1)
- INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
- else
- gcc_checking_assert (ret == 0);
+ /* If we can't find an active register, reset this debug insn. */
+ if (hard_regno == -1)
+ {
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+ return;
+ }
+
+ gcc_assert (hard_regno >= FIRST_STACK_REG);
+ replace_reg (loc, hard_regno);
+ iter.skip_subrtxes ();
+ }
+ }
}
/* Substitute new registers in PAT, which is part of INSN. REGSTACK
was deleted in the process. */
static bool
-subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
+subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
{
rtx *dest, *src;
bool control_flow_insn_deleted = false;
if (get_hard_regnum (regstack, u) == -1)
{
rtx pat2 = gen_rtx_CLOBBER (VOIDmode, u);
- rtx insn2 = emit_insn_before (pat2, insn);
+ rtx_insn *insn2 = emit_insn_before (pat2, insn);
control_flow_insn_deleted
|= move_nan_for_stack_reg (insn2, regstack, u);
}
case CALL:
{
int count;
- for (count = hard_regno_nregs[REGNO (*dest)][GET_MODE (*dest)];
- --count >= 0;)
+ for (count = REG_NREGS (*dest); --count >= 0;)
{
regstack->reg[++regstack->top] = REGNO (*dest) + count;
SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);
if (src1_hard_regnum == -1)
{
rtx pat2 = gen_rtx_CLOBBER (VOIDmode, *src1);
- rtx insn2 = emit_insn_before (pat2, insn);
+ rtx_insn *insn2 = emit_insn_before (pat2, insn);
control_flow_insn_deleted
|= move_nan_for_stack_reg (insn2, regstack, *src1);
}
if (src2_hard_regnum == -1)
{
rtx pat2 = gen_rtx_CLOBBER (VOIDmode, *src2);
- rtx insn2 = emit_insn_before (pat2, insn);
+ rtx_insn *insn2 = emit_insn_before (pat2, insn);
control_flow_insn_deleted
|= move_nan_for_stack_reg (insn2, regstack, *src2);
}
case UNSPEC:
switch (XINT (pat_src, 1))
{
- case UNSPEC_STA:
case UNSPEC_FIST:
+ case UNSPEC_FIST_ATOMIC:
case UNSPEC_FIST_FLOOR:
case UNSPEC_FIST_CEIL:
requirements, since record_asm_stack_regs removes any problem asm. */
static void
-subst_asm_stack_regs (rtx insn, stack_ptr regstack)
+subst_asm_stack_regs (rtx_insn *insn, stack_ptr regstack)
{
rtx body = PATTERN (insn);
- int alt;
rtx *note_reg; /* Array of note contents */
rtx **note_loc; /* Address of REG field of each note */
/* Find out what the constraints required. If no constraint
alternative matches, that is a compiler bug: we should have caught
such an insn in check_asm_stack_operands. */
- extract_insn (insn);
- constrain_operands (1);
- alt = which_alternative;
+ extract_constrain_insn (insn);
- preprocess_constraints ();
+ preprocess_constraints (insn);
+ const operand_alternative *op_alt = which_op_alt ();
get_asm_operands_in_out (body, &n_outputs, &n_inputs);
- gcc_assert (alt >= 0);
-
/* Strip SUBREGs here to make the following code simpler. */
for (i = 0; i < recog_data.n_operands; i++)
if (GET_CODE (recog_data.operand[i]) == SUBREG
n_notes = 0;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{
+ if (GET_CODE (note) != EXPR_LIST)
+ continue;
rtx reg = XEXP (note, 0);
rtx *loc = & XEXP (note, 0);
for (i = n_outputs; i < n_outputs + n_inputs; i++)
if (STACK_REG_P (recog_data.operand[i])
- && reg_class_subset_p (recog_op_alt[i][alt].cl,
- FLOAT_REGS)
- && recog_op_alt[i][alt].cl != FLOAT_REGS)
+ && reg_class_subset_p (op_alt[i].cl, FLOAT_REGS)
+ && op_alt[i].cl != FLOAT_REGS)
{
/* If an operand needs to be in a particular reg in
FLOAT_REGS, the constraint was either 't' or 'u'. Since
it and swap it with whatever is already in I's place.
K is where recog_data.operand[i] is now. J is where it
should be. */
- int j, k, temp;
+ int j, k;
k = temp_stack.top - (regno - FIRST_STACK_REG);
j = (temp_stack.top
- (REGNO (recog_data.operand[i]) - FIRST_STACK_REG));
- temp = temp_stack.reg[k];
- temp_stack.reg[k] = temp_stack.reg[j];
- temp_stack.reg[j] = temp;
+ std::swap (temp_stack.reg[j], temp_stack.reg[k]);
}
}
if (operands_match_p (clobber_reg[j], recog_data.operand[i]))
break;
- if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
+ if (j < n_clobbers || op_alt[i].matches >= 0)
{
/* recog_data.operand[i] might not be at the top of stack.
But that's OK, because all we need to do is pop the
a control flow insn was deleted in the process. */
static bool
-subst_stack_regs (rtx insn, stack_ptr regstack)
+subst_stack_regs (rtx_insn *insn, stack_ptr regstack)
{
rtx *note_link, note;
bool control_flow_insn_deleted = false;
/* subst_stack_regs_pat may have deleted a no-op insn. If so, any
REG_UNUSED will already have been dealt with, so just return. */
- if (NOTE_P (insn) || INSN_DELETED_P (insn))
+ if (NOTE_P (insn) || insn->deleted ())
return control_flow_insn_deleted;
/* If this a noreturn call, we can't insert pop insns after it.
is no longer needed once this has executed. */
static void
-change_stack (rtx insn, stack_ptr old, stack_ptr new_stack, enum emit_where where)
+change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
+ enum emit_where where)
{
int reg;
int update_end = 0;
{
old->reg[++old->top] = i;
SET_HARD_REG_BIT (old->reg_set, i);
- emit_insn_before (gen_rtx_SET (VOIDmode,
- FP_MODE_REG (i, SFmode), not_a_num), insn);
+ emit_insn_before (gen_rtx_SET (FP_MODE_REG (i, SFmode), not_a_num),
+ insn);
}
/* Pop any registers that are not needed in the new block. */
/* If the destination block's stack already has a specified layout
and contains two or more registers, use a more intelligent algorithm
- to pop registers that minimizes the number number of fxchs below. */
+ to pop registers that minimizes the number of fxchs below. */
if (new_stack->top > 0)
{
bool slots[REG_STACK_SIZE];
Note that we are inserting converted code here. This code is
never seen by the convert_regs pass. */
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
+ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
{
basic_block block = e->dest;
block_info bi = BLOCK_INFO (block);
bi->stack_in.reg[++top] = reg;
- init = gen_rtx_SET (VOIDmode,
- FP_MODE_REG (FIRST_STACK_REG, SFmode),
+ init = gen_rtx_SET (FP_MODE_REG (FIRST_STACK_REG, SFmode),
not_a_num);
insert_insn_on_edge (init, e);
inserted = 1;
if (retvalue)
{
value_reg_low = REGNO (retvalue);
- value_reg_high = END_HARD_REGNO (retvalue) - 1;
+ value_reg_high = END_REGNO (retvalue) - 1;
}
- output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in;
+ output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR_FOR_FN (cfun))->stack_in;
if (value_reg_low == -1)
output_stack->top = -1;
else
}
else
{
- rtx seq, after;
+ rtx_insn *seq;
+ rtx_note *after;
current_block = NULL;
start_sequence ();
starting_stack_p = false;
- FOR_EACH_BB (bb)
- if (bb != ENTRY_BLOCK_PTR)
+ FOR_EACH_BB_FN (bb, cfun)
+ if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun))
{
edge e;
edge_iterator ei;
struct stack_def regstack;
block_info bi = BLOCK_INFO (block);
int reg;
- rtx insn, next;
+ rtx_insn *insn, *next;
bool control_flow_insn_deleted = false;
bool cfg_altered = false;
int debug_insns_with_starting_stack = 0;
if (dump_file)
fprintf (dump_file, "Emitting insn initializing reg %d\n", reg);
- set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), not_a_num);
+ set = gen_rtx_SET (FP_MODE_REG (reg, SFmode), not_a_num);
insn = emit_insn_after (set, insn);
control_flow_insn_deleted |= subst_stack_regs (insn, ®stack);
}
is only processed after all its predecessors. The number of predecessors
of every block has already been computed. */
- stack = XNEWVEC (basic_block, n_basic_blocks);
+ stack = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun));
sp = stack;
*sp++ = block;
/* Construct the desired stack for function exit. */
convert_regs_exit ();
- BLOCK_INFO (EXIT_BLOCK_PTR)->done = 1;
+ BLOCK_INFO (EXIT_BLOCK_PTR_FOR_FN (cfun))->done = 1;
/* ??? Future: process inner loops first, and give them arbitrary
initial stacks which emit_swap_insn can modify. This ought to
prevent double fxch that often appears at the head of a loop. */
/* Process all blocks reachable from all entry points. */
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
+ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs)
cfg_altered |= convert_regs_2 (e->dest);
/* ??? Process all unreachable blocks. Though there's no excuse
for keeping these even when not optimizing. */
- FOR_EACH_BB (b)
+ FOR_EACH_BB_FN (b, cfun)
{
block_info bi = BLOCK_INFO (b);
/* Set up block info for each basic block. */
alloc_aux_for_blocks (sizeof (struct block_info_def));
- FOR_EACH_BB (bb)
+ FOR_EACH_BB_FN (bb, cfun)
{
block_info bi = BLOCK_INFO (bb);
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
if (!(e->flags & EDGE_DFS_BACK)
- && e->src != ENTRY_BLOCK_PTR)
+ && e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
bi->predecessors++;
/* Set current register status at last instruction `uninitialized'. */
/* Create the replacement registers up front. */
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
{
- enum machine_mode mode;
+ machine_mode mode;
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
REAL_VALUE_TYPE r;
real_nan (&r, "", 1, SFmode);
- not_a_num = CONST_DOUBLE_FROM_REAL_VALUE (r, SFmode);
+ not_a_num = const_double_from_real_value (r, SFmode);
not_a_num = force_const_mem (SFmode, not_a_num);
}
}
#endif /* STACK_REGS */
\f
-static bool
-gate_handle_stack_regs (void)
+namespace {
+
+const pass_data pass_data_stack_regs =
+{
+ RTL_PASS, /* type */
+ "*stack_regs", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_REG_STACK, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_stack_regs : public rtl_opt_pass
{
+public:
+ pass_stack_regs (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_regs, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
#ifdef STACK_REGS
- return 1;
+ return true;
#else
- return 0;
+ return false;
#endif
-}
+ }
+
+}; // class pass_stack_regs
-struct rtl_opt_pass pass_stack_regs =
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_stack_regs (gcc::context *ctxt)
{
- {
- RTL_PASS,
- "*stack_regs", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- gate_handle_stack_regs, /* gate */
- NULL, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_REG_STACK, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
-};
+ return new pass_stack_regs (ctxt);
+}
/* Convert register usage from flat register file usage to a stack
register file. */
return 0;
}
-struct rtl_opt_pass pass_stack_regs_run =
+namespace {
+
+const pass_data pass_data_stack_regs_run =
{
- {
- RTL_PASS,
- "stack", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- NULL, /* gate */
- rest_of_handle_stack_regs, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_REG_STACK, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_df_finish | TODO_verify_rtl_sharing /* todo_flags_finish */
- }
+ RTL_PASS, /* type */
+ "stack", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_REG_STACK, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
};
+
+class pass_stack_regs_run : public rtl_opt_pass
+{
+public:
+ pass_stack_regs_run (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_stack_regs_run, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *)
+ {
+ return rest_of_handle_stack_regs ();
+ }
+
+}; // class pass_stack_regs_run
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_stack_regs_run (gcc::context *ctxt)
+{
+ return new pass_stack_regs_run (ctxt);
+}