Backport from GCC mainline.
[platform/upstream/linaro-gcc.git] / gcc / reg-stack.c
index 2dd9289..89a7a11 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
 
@@ -246,25 +246,25 @@ static int stack_regs_mentioned_p (const_rtx pat);
 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.  */
 
@@ -329,8 +329,8 @@ stack_regs_mentioned (const_rtx insn)
 \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.  */
@@ -343,15 +343,15 @@ next_flags_user (rtx insn)
        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;
@@ -429,7 +429,7 @@ get_true_reg (rtx *pat)
 
       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;
 
@@ -452,7 +452,7 @@ static bool any_malformed_asm;
    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;
@@ -461,28 +461,26 @@ check_asm_stack_operands (rtx insn)
 
   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++)
@@ -526,7 +524,7 @@ check_asm_stack_operands (rtx insn)
   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;
@@ -581,7 +579,7 @@ check_asm_stack_operands (rtx insn)
          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;
       }
 
@@ -609,7 +607,7 @@ check_asm_stack_operands (rtx insn)
      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;
 
@@ -695,7 +693,7 @@ replace_reg (rtx *reg, int regno)
    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;
 
@@ -738,10 +736,11 @@ get_hard_regnum (stack_ptr regstack, rtx reg)
    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
@@ -751,7 +750,7 @@ emit_pop_insn (rtx insn, stack_ptr regstack, rtx reg, enum emit_where where)
       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)
@@ -764,7 +763,7 @@ emit_pop_insn (rtx insn, stack_ptr regstack, rtx reg, enum emit_where where)
 
   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)
@@ -790,12 +789,12 @@ emit_pop_insn (rtx insn, stack_ptr regstack, rtx reg, enum emit_where where)
    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);
@@ -815,18 +814,15 @@ emit_swap_insn (rtx insn, stack_ptr regstack, rtx 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)
@@ -897,10 +893,10 @@ emit_swap_insn (rtx insn, stack_ptr regstack, rtx reg)
    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;
 
@@ -912,9 +908,7 @@ swap_to_top (rtx insn, stack_ptr regstack, rtx src1, rtx src2)
       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.  */
@@ -925,9 +919,7 @@ swap_to_top (rtx insn, stack_ptr regstack, rtx src1, rtx src2)
       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);
@@ -938,7 +930,7 @@ swap_to_top (rtx insn, stack_ptr regstack, rtx src1, rtx src2)
    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));
@@ -1089,12 +1081,12 @@ move_for_stack_reg (rtx insn, stack_ptr regstack, rtx 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;
 
@@ -1137,7 +1129,7 @@ swap_rtx_condition_1 (rtx pat)
 }
 
 static int
-swap_rtx_condition (rtx insn)
+swap_rtx_condition (rtx_insn *insn)
 {
   rtx pat = PATTERN (insn);
 
@@ -1228,7 +1220,7 @@ swap_rtx_condition (rtx 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;
@@ -1243,10 +1235,7 @@ compare_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat_src)
           && 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));
@@ -1307,46 +1296,34 @@ compare_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat_src)
     }
 }
 \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
@@ -1354,7 +1331,7 @@ subst_all_stack_regs_in_debug_insn (rtx insn, struct stack_def *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;
@@ -1431,7 +1408,7 @@ subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
                        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);
                          }
@@ -1474,8 +1451,7 @@ subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
          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);
@@ -1567,14 +1543,14 @@ subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
                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);
                  }
@@ -1664,8 +1640,8 @@ subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
          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:
@@ -2002,10 +1978,9 @@ subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
    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 */
@@ -2027,16 +2002,13 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
   /* 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
@@ -2058,6 +2030,8 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
   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);
 
@@ -2115,9 +2089,8 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
 
   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
@@ -2136,15 +2109,13 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
               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]);
          }
       }
 
@@ -2205,7 +2176,7 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
          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
@@ -2285,7 +2256,7 @@ subst_asm_stack_regs (rtx insn, stack_ptr regstack)
    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;
@@ -2353,7 +2324,7 @@ subst_stack_regs (rtx insn, stack_ptr regstack)
   /* 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.
@@ -2397,7 +2368,8 @@ subst_stack_regs (rtx insn, stack_ptr regstack)
    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;
@@ -2433,15 +2405,15 @@ change_stack (rtx insn, stack_ptr old, stack_ptr new_stack, enum emit_where wher
       {
        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];
@@ -2646,7 +2618,7 @@ convert_regs_entry (void)
      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);
@@ -2659,8 +2631,7 @@ convert_regs_entry (void)
 
            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;
@@ -2687,10 +2658,10 @@ convert_regs_exit (void)
   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
@@ -2812,7 +2783,8 @@ compensate_edge (edge e)
     }
   else
     {
-      rtx seq, after;
+      rtx_insn *seq;
+      rtx_note *after;
 
       current_block = NULL;
       start_sequence ();
@@ -2843,8 +2815,8 @@ compensate_edges (void)
 
   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;
@@ -2895,7 +2867,7 @@ convert_regs_1 (basic_block block)
   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;
@@ -3027,7 +2999,7 @@ convert_regs_1 (basic_block block)
          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, &regstack);
        }
@@ -3078,7 +3050,7 @@ convert_regs_2 (basic_block block)
      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;
@@ -3138,19 +3110,19 @@ convert_regs (void)
 
   /* 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);
 
@@ -3209,7 +3181,7 @@ reg_to_stack (void)
 
   /* 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;
@@ -3218,7 +3190,7 @@ reg_to_stack (void)
 
       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'.  */
@@ -3237,7 +3209,7 @@ reg_to_stack (void)
   /* 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))
@@ -3265,7 +3237,7 @@ reg_to_stack (void)
       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);
     }
 
@@ -3282,35 +3254,47 @@ reg_to_stack (void)
 }
 #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.  */
@@ -3324,22 +3308,40 @@ rest_of_handle_stack_regs (void)
   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);
+}