OSDN Git Service

* intl.h (open_quote, close_quote): New.
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index 08d26f6..5b28f0e 100644 (file)
@@ -1,6 +1,6 @@
 /* Register to Stack convert for GNU compiler.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -232,7 +232,7 @@ static rtx
   (FP_mode_reg[(regno)-FIRST_STACK_REG][(int) (mode)])
 
 /* Used to initialize uninitialized registers.  */
-static rtx nan;
+static rtx not_a_num;
 
 /* Forward declarations */
 
@@ -249,13 +249,14 @@ static void remove_regno_note (rtx, enum reg_note, unsigned int);
 static int get_hard_regnum (stack, rtx);
 static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
 static void emit_swap_insn (rtx, stack, rtx);
-static void move_for_stack_reg (rtx, stack, rtx);
+static void swap_to_top(rtx, stack, rtx, rtx);
+static bool move_for_stack_reg (rtx, stack, rtx);
 static int swap_rtx_condition_1 (rtx);
 static int swap_rtx_condition (rtx);
 static void compare_for_stack_reg (rtx, stack, rtx);
-static void subst_stack_regs_pat (rtx, stack, rtx);
+static bool subst_stack_regs_pat (rtx, stack, rtx);
 static void subst_asm_stack_regs (rtx, stack);
-static void subst_stack_regs (rtx, stack);
+static bool subst_stack_regs (rtx, stack);
 static void change_stack (rtx, stack, stack, enum emit_where);
 static int convert_regs_entry (void);
 static void convert_regs_exit (void);
@@ -336,7 +337,7 @@ next_flags_user (rtx insn)
   /* Search forward looking for the first use of this value.
      Stop at block boundaries.  */
 
-  while (insn != current_block->end)
+  while (insn != BB_END (current_block))
     {
       insn = NEXT_INSN (insn);
 
@@ -398,8 +399,7 @@ pop_stack (stack regstack, int regno)
 }
 \f
 /* Convert register usage from "flat" register file usage to a "stack
-   register file.  FIRST is the first insn in the function, FILE is the
-   dump file, if used.
+   register file.  FILE is the dump file, if used.
 
    Construct a CFG and run life analysis.  Then convert each insn one
    by one.  Run a last cleanup_cfg pass, if optimizing, to eliminate
@@ -407,7 +407,7 @@ pop_stack (stack regstack, int regno)
    the edges.  */
 
 bool
-reg_to_stack (rtx first, FILE *file)
+reg_to_stack (FILE *file)
 {
   basic_block bb;
   int i;
@@ -433,7 +433,7 @@ reg_to_stack (rtx first, FILE *file)
          && flag_schedule_insns_after_reload))
     {
       count_or_remove_death_notes (NULL, 1);
-      life_analysis (first, file, PROP_DEATH_NOTES);
+      life_analysis (file, PROP_DEATH_NOTES);
     }
   mark_dfs_back_edges ();
 
@@ -472,11 +472,11 @@ reg_to_stack (rtx first, FILE *file)
      on zero, which we can get from `ldz'.  */
 
   if (flag_pic)
-    nan = CONST0_RTX (SFmode);
+    not_a_num = CONST0_RTX (SFmode);
   else
     {
-      nan = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
-      nan = force_const_mem (SFmode, nan);
+      not_a_num = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
+      not_a_num = force_const_mem (SFmode, not_a_num);
     }
 
   /* Allocate a cache for stack_regs_mentioned.  */
@@ -574,6 +574,13 @@ get_true_reg (rtx *pat)
       case FIX:
       case FLOAT_EXTEND:
        pat = & XEXP (*pat, 0);
+       break;
+
+      case FLOAT_TRUNCATE:
+       if (!flag_unsafe_math_optimizations)
+         return pat;
+       pat = & XEXP (*pat, 0);
+       break;
       }
 }
 \f
@@ -973,10 +980,10 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
   /* Find the previous insn involving stack regs, but don't pass a
      block boundary.  */
   i1 = NULL;
-  if (current_block && insn != current_block->head)
+  if (current_block && insn != BB_HEAD (current_block))
     {
       rtx tmp = PREV_INSN (insn);
-      rtx limit = PREV_INSN (current_block->head);
+      rtx limit = PREV_INSN (BB_HEAD (current_block));
       while (tmp != limit)
        {
          if (GET_CODE (tmp) == CODE_LABEL
@@ -1022,21 +1029,71 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
   if (i1)
     emit_insn_after (swap_rtx, i1);
   else if (current_block)
-    emit_insn_before (swap_rtx, current_block->head);
+    emit_insn_before (swap_rtx, BB_HEAD (current_block));
   else
     emit_insn_before (swap_rtx, insn);
 }
 \f
-/* Handle a move to or from a stack register in PAT, which is in INSN.
-   REGSTACK is the current stack.  */
+/* Emit an insns before INSN to swap virtual register SRC1 with
+   the top of stack and virtual register SRC2 with second stack
+   slot. REGSTACK is the stack state before the swaps, and
+   is updated to reflect the swaps.  A swap insn is represented as a
+   PARALLEL of two patterns: each pattern moves one reg to the other.
+
+   If SRC1 and/or SRC2 are already at the right place, no swap insn
+   is emitted.  */
 
 static void
+swap_to_top (rtx insn, stack regstack, rtx src1, rtx src2)
+{
+  struct stack_def temp_stack;
+  int regno, j, k, temp;
+
+  temp_stack = *regstack;
+
+  /* Place operand 1 at the top of stack.  */
+  regno = get_hard_regnum (&temp_stack, src1);
+  if (regno < 0)
+    abort ();
+  if (regno != FIRST_STACK_REG)
+    {
+      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;
+    }
+
+  /* Place operand 2 next on the stack.  */
+  regno = get_hard_regnum (&temp_stack, src2);
+  if (regno < 0)
+    abort ();
+  if (regno != FIRST_STACK_REG + 1)
+    {
+      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;
+    }
+
+  change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
+}
+\f
+/* Handle a move to or from a stack register in PAT, which is in INSN.
+   REGSTACK is the current stack.  Return whether a control flow insn
+   was deleted in the process.  */
+
+static bool
 move_for_stack_reg (rtx insn, stack regstack, rtx pat)
 {
   rtx *psrc =  get_true_reg (&SET_SRC (pat));
   rtx *pdest = get_true_reg (&SET_DEST (pat));
   rtx src, dest;
   rtx note;
+  bool control_flow_insn_deleted = false;
 
   src = *psrc; dest = *pdest;
 
@@ -1066,21 +1123,17 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
             If so, just pop the src.  */
 
          if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
+           emit_pop_insn (insn, regstack, src, EMIT_AFTER);
+         else
            {
-             emit_pop_insn (insn, regstack, src, EMIT_AFTER);
-
-             delete_insn (insn);
-             return;
+             regstack->reg[i] = REGNO (dest);
+             SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
+             CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
            }
 
-         regstack->reg[i] = REGNO (dest);
-
-         SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
-         CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
-
+         control_flow_insn_deleted |= control_flow_insn_p (insn);
          delete_insn (insn);
-
-         return;
+         return control_flow_insn_deleted;
        }
 
       /* The source reg does not die.  */
@@ -1095,8 +1148,9 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
          if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
            emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
 
+         control_flow_insn_deleted |= control_flow_insn_p (insn);
          delete_insn (insn);
-         return;
+         return control_flow_insn_deleted;
        }
 
       /* The destination ought to be dead.  */
@@ -1165,6 +1219,8 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
     }
   else
     abort ();
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Swap the condition on a branch, if there is one.  Return true if we
@@ -1177,7 +1233,7 @@ swap_rtx_condition_1 (rtx pat)
   const char *fmt;
   int i, r = 0;
 
-  if (GET_RTX_CLASS (GET_CODE (pat)) == '<')
+  if (COMPARISON_P (pat))
     {
       PUT_CODE (pat, swap_condition (GET_CODE (pat)));
       r = 1;
@@ -1231,7 +1287,7 @@ swap_rtx_condition (rtx insn)
 
       /* Search forward looking for the first use of this value.
         Stop at block boundaries.  */
-      while (insn != current_block->end)
+      while (insn != BB_END (current_block))
        {
          insn = NEXT_INSN (insn);
          if (INSN_P (insn) && reg_mentioned_p (dest, insn))
@@ -1376,12 +1432,14 @@ compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src)
 }
 \f
 /* Substitute new registers in PAT, which is part of INSN.  REGSTACK
-   is the current register layout.  */
+   is the current register layout.  Return whether a control flow insn
+   was deleted in the process.  */
 
-static void
+static bool
 subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 {
   rtx *dest, *src;
+  bool control_flow_insn_deleted = false;
 
   switch (GET_CODE (pat))
     {
@@ -1393,7 +1451,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
          && find_regno_note (insn, REG_DEAD, REGNO (*src)))
        {
          emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
-         return;
+         return control_flow_insn_deleted;
        }
       /* ??? Uninitialized USE should not happen.  */
       else if (get_hard_regnum (regstack, *src) == -1)
@@ -1441,18 +1499,18 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                  {
                    pat = gen_rtx_SET (VOIDmode,
                                       FP_MODE_REG (REGNO (*dest), SFmode),
-                                      nan);
+                                      not_a_num);
                    PATTERN (insn) = pat;
-                   move_for_stack_reg (insn, regstack, pat);
+                   control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
                  }
                if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
                    && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1)
                  {
                    pat = gen_rtx_SET (VOIDmode,
                                       FP_MODE_REG (REGNO (*dest) + 1, SFmode),
-                                      nan);
+                                      not_a_num);
                    PATTERN (insn) = pat;
-                   move_for_stack_reg (insn, regstack, pat);
+                   control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
                  }
              }
          }
@@ -1475,7 +1533,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                && (GET_CODE (*src) == REG || GET_CODE (*src) == MEM
                    || GET_CODE (*src) == CONST_DOUBLE)))
          {
-           move_for_stack_reg (insn, regstack, pat);
+           control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
            break;
          }
 
@@ -1488,7 +1546,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
          case CALL:
            {
              int count;
-             for (count = HARD_REGNO_NREGS (REGNO (*dest), GET_MODE (*dest));
+             for (count = hard_regno_nregs[REGNO (*dest)][GET_MODE (*dest)];
                   --count >= 0;)
                {
                  regstack->reg[++regstack->top] = REGNO (*dest) + count;
@@ -1651,7 +1709,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
              }
 
            /* Keep operand 1 matching with destination.  */
-           if (GET_RTX_CLASS (GET_CODE (pat_src)) == 'c'
+           if (COMMUTATIVE_ARITH_P (pat_src)
                && REG_P (*src1) && REG_P (*src2)
                && REGNO (*src1) != REGNO (*dest))
             {
@@ -1674,24 +1732,21 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
                emit_swap_insn (insn, regstack, *src1);
 
+               /* Input should never die, it is
+                  replaced with output.  */
                src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+               if (src1_note)
+                 abort();
 
                if (STACK_REG_P (*dest))
                  replace_reg (dest, FIRST_STACK_REG);
 
-               if (src1_note)
-                 {
-                   replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
-                   regstack->top--;
-                   CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
-                 }
-
                replace_reg (src1, FIRST_STACK_REG);
                break;
 
              case UNSPEC_FPATAN:
              case UNSPEC_FYL2X:
-             case UNSPEC_FSCALE:
+             case UNSPEC_FYL2XP1:
                /* These insns operate on the top two stack slots.  */
 
                src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
@@ -1700,42 +1755,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
                src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
 
-               {
-                 struct stack_def temp_stack;
-                 int regno, j, k, temp;
-
-                 temp_stack = *regstack;
-
-                 /* Place operand 1 at the top of stack.  */
-                 regno = get_hard_regnum (&temp_stack, *src1);
-                 if (regno < 0)
-                   abort ();
-                 if (regno != FIRST_STACK_REG)
-                   {
-                     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;
-                   }
-
-                 /* Place operand 2 next on the stack.  */
-                 regno = get_hard_regnum (&temp_stack, *src2);
-                 if (regno < 0)
-                   abort ();
-                 if (regno != FIRST_STACK_REG + 1)
-                   {
-                     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;
-                   }
-
-                 change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
-               }
+               swap_to_top (insn, regstack, *src1, *src2);
 
                replace_reg (src1, FIRST_STACK_REG);
                replace_reg (src2, FIRST_STACK_REG + 1);
@@ -1758,6 +1778,124 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                replace_reg (dest, FIRST_STACK_REG);
                break;
 
+             case UNSPEC_FSCALE_FRACT:
+             case UNSPEC_FPREM_F:
+             case UNSPEC_FPREM1_F:
+               /* These insns operate on the top two stack slots.
+                  first part of double input, double output insn.  */
+
+               src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+               src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
+
+               src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+               src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
+               /* Inputs should never die, they are
+                  replaced with outputs.  */
+               if ((src1_note) || (src2_note))
+                 abort();
+
+               swap_to_top (insn, regstack, *src1, *src2);
+
+               /* Push the result back onto stack. Empty stack slot
+                  will be filled in second part of insn. */
+               if (STACK_REG_P (*dest)) {
+                 regstack->reg[regstack->top] = REGNO (*dest);
+                 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+                 replace_reg (dest, FIRST_STACK_REG);
+               }
+
+               replace_reg (src1, FIRST_STACK_REG);
+               replace_reg (src2, FIRST_STACK_REG + 1);
+               break;
+
+             case UNSPEC_FSCALE_EXP:
+             case UNSPEC_FPREM_U:
+             case UNSPEC_FPREM1_U:
+               /* These insns operate on the top two stack slots./
+                  second part of double input, double output insn.  */
+
+               src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+               src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
+
+               src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+               src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
+               /* Inputs should never die, they are
+                  replaced with outputs.  */
+               if ((src1_note) || (src2_note))
+                 abort();
+
+               swap_to_top (insn, regstack, *src1, *src2);
+
+               /* Push the result back onto stack. Fill empty slot from
+                  first part of insn and fix top of stack pointer.  */
+               if (STACK_REG_P (*dest)) {
+                 regstack->reg[regstack->top - 1] = REGNO (*dest);
+                 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+                 replace_reg (dest, FIRST_STACK_REG + 1);
+               }
+
+               replace_reg (src1, FIRST_STACK_REG);
+               replace_reg (src2, FIRST_STACK_REG + 1);
+               break;
+
+             case UNSPEC_SINCOS_COS:
+             case UNSPEC_TAN_ONE:
+             case UNSPEC_XTRACT_FRACT:
+               /* These insns operate on the top two stack slots,
+                  first part of one input, double output insn.  */
+
+               src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+
+               emit_swap_insn (insn, regstack, *src1);
+
+               /* Input should never die, it is
+                  replaced with output.  */
+               src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+               if (src1_note)
+                 abort();
+
+               /* Push the result back onto stack. Empty stack slot
+                  will be filled in second part of insn. */
+               if (STACK_REG_P (*dest)) {
+                 regstack->reg[regstack->top + 1] = REGNO (*dest);
+                 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+                 replace_reg (dest, FIRST_STACK_REG);
+               }
+
+               replace_reg (src1, FIRST_STACK_REG);
+               break;
+
+             case UNSPEC_SINCOS_SIN:
+             case UNSPEC_TAN_TAN:
+             case UNSPEC_XTRACT_EXP:
+               /* These insns operate on the top two stack slots,
+                  second part of one input, double output insn.  */
+
+               src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+
+               emit_swap_insn (insn, regstack, *src1);
+
+               /* Input should never die, it is
+                  replaced with output.  */
+               src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+               if (src1_note)
+                 abort();
+
+               /* Push the result back onto stack. Fill empty slot from
+                  first part of insn and fix top of stack pointer.  */
+               if (STACK_REG_P (*dest)) {
+                 regstack->reg[regstack->top] = REGNO (*dest);
+                 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+                 replace_reg (dest, FIRST_STACK_REG + 1);
+
+                 regstack->top++;
+               }
+
+               replace_reg (src1, FIRST_STACK_REG);
+               break;
+
              case UNSPEC_SAHF:
                /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF)
                   The combination matches the PPRO fcomi instruction.  */
@@ -1766,7 +1904,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                if (GET_CODE (pat_src) != UNSPEC
                    || XINT (pat_src, 1) != UNSPEC_FNSTSW)
                  abort ();
-               /* FALLTHRU */
+               /* Fall through.  */
 
              case UNSPEC_FNSTSW:
                /* Combined fcomp+fnstsw generated for doing well with
@@ -1879,6 +2017,8 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
     default:
       break;
     }
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Substitute hard regnums for any stack regs in INSN, which has
@@ -2176,12 +2316,14 @@ subst_asm_stack_regs (rtx insn, stack regstack)
 /* Substitute stack hard reg numbers for stack virtual registers in
    INSN.  Non-stack register numbers are not changed.  REGSTACK is the
    current stack content.  Insns may be emitted as needed to arrange the
-   stack for the 387 based on the contents of the insn.  */
+   stack for the 387 based on the contents of the insn.  Return whether
+   a control flow insn was deleted in the process.  */
 
-static void
+static bool
 subst_stack_regs (rtx insn, stack regstack)
 {
   rtx *note_link, note;
+  bool control_flow_insn_deleted = false;
   int i;
 
   if (GET_CODE (insn) == CALL_INSN)
@@ -2222,25 +2364,32 @@ subst_stack_regs (rtx insn, stack regstack)
             Any REG_UNUSED notes will be handled by subst_asm_stack_regs.  */
 
          subst_asm_stack_regs (insn, regstack);
-         return;
+         return control_flow_insn_deleted;
        }
 
       if (GET_CODE (PATTERN (insn)) == PARALLEL)
        for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
          {
            if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
-             subst_stack_regs_pat (insn, regstack,
-                                   XVECEXP (PATTERN (insn), 0, i));
+             {
+               if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == CLOBBER)
+                  XVECEXP (PATTERN (insn), 0, i)
+                    = shallow_copy_rtx (XVECEXP (PATTERN (insn), 0, i));
+               control_flow_insn_deleted
+                 |= subst_stack_regs_pat (insn, regstack,
+                                          XVECEXP (PATTERN (insn), 0, i));
+             }
          }
       else
-       subst_stack_regs_pat (insn, regstack, PATTERN (insn));
+       control_flow_insn_deleted
+         |= subst_stack_regs_pat (insn, regstack, PATTERN (insn));
     }
 
   /* 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 (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn))
-    return;
+    return control_flow_insn_deleted;
 
   /* If there is a REG_UNUSED note on a stack register on this insn,
      the indicated reg must be popped.  The REG_UNUSED note is removed,
@@ -2256,6 +2405,8 @@ subst_stack_regs (rtx insn, stack regstack)
       }
     else
       note_link = &XEXP (note, 1);
+
+  return control_flow_insn_deleted;
 }
 \f
 /* Change the organization of the stack so that it fits a new basic
@@ -2281,7 +2432,7 @@ change_stack (rtx insn, stack old, stack new, enum emit_where where)
 
   if (where == EMIT_AFTER)
     {
-      if (current_block && current_block->end == insn)
+      if (current_block && BB_END (current_block) == insn)
        update_end = 1;
       insn = NEXT_INSN (insn);
     }
@@ -2364,7 +2515,7 @@ change_stack (rtx insn, stack old, stack new, enum emit_where where)
     }
 
   if (update_end)
-    current_block->end = PREV_INSN (insn);
+    BB_END (current_block) = PREV_INSN (insn);
 }
 \f
 /* Print stack configuration.  */
@@ -2446,7 +2597,7 @@ convert_regs_entry (void)
 
            init = gen_rtx_SET (VOIDmode,
                                FP_MODE_REG (FIRST_STACK_REG, SFmode),
-                               nan);
+                               not_a_num);
            insert_insn_on_edge (init, e);
            inserted = 1;
          }
@@ -2473,7 +2624,7 @@ convert_regs_exit (void)
     {
       value_reg_low = REGNO (retvalue);
       value_reg_high = value_reg_low
-       + HARD_REGNO_NREGS (value_reg_low, GET_MODE (retvalue)) - 1;
+       + hard_regno_nregs[value_reg_low][GET_MODE (retvalue)] - 1;
     }
 
   output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in;
@@ -2525,7 +2676,7 @@ compensate_edge (edge e, FILE *file)
          /* change_stack kills values in regstack.  */
          tmpstack = regstack;
 
-         change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER);
+         change_stack (BB_END (block), &tmpstack, target_stack, EMIT_AFTER);
          return false;
        }
 
@@ -2596,8 +2747,8 @@ compensate_edge (edge e, FILE *file)
       /* change_stack kills values in regstack.  */
       tmpstack = regstack;
 
-      change_stack (block->end, &tmpstack, target_stack,
-                   (GET_CODE (block->end) == JUMP_INSN
+      change_stack (BB_END (block), &tmpstack, target_stack,
+                   (GET_CODE (BB_END (block)) == JUMP_INSN
                     ? EMIT_BEFORE : EMIT_AFTER));
     }
   else
@@ -2638,6 +2789,7 @@ convert_regs_1 (FILE *file, basic_block block)
   int deleted, inserted, reg;
   rtx insn, next;
   edge e, beste = NULL;
+  bool control_flow_insn_deleted = false;
 
   inserted = 0;
   deleted = 0;
@@ -2702,7 +2854,7 @@ convert_regs_1 (FILE *file, basic_block block)
 
   /* Process all insns in this block.  Keep track of NEXT so that we
      don't process insns emitted while substituting in INSN.  */
-  next = block->head;
+  next = BB_HEAD (block);
   regstack = bi->stack_in;
   do
     {
@@ -2712,7 +2864,7 @@ convert_regs_1 (FILE *file, basic_block block)
       /* Ensure we have not missed a block boundary.  */
       if (next == NULL)
        abort ();
-      if (insn == block->end)
+      if (insn == BB_END (block))
        next = NULL;
 
       /* Don't bother processing unless there is a stack reg
@@ -2726,8 +2878,7 @@ convert_regs_1 (FILE *file, basic_block block)
                       INSN_UID (insn));
              print_stack (file, &regstack);
            }
-         subst_stack_regs (insn, &regstack);
-         deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
+         control_flow_insn_deleted |= subst_stack_regs (insn, &regstack);
        }
     }
   while (next);
@@ -2742,7 +2893,7 @@ convert_regs_1 (FILE *file, basic_block block)
       print_stack (file, &regstack);
     }
 
-  insn = block->end;
+  insn = BB_END (block);
   if (GET_CODE (insn) == JUMP_INSN)
     insn = PREV_INSN (insn);
 
@@ -2764,10 +2915,9 @@ convert_regs_1 (FILE *file, basic_block block)
            }
 
          set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode),
-                            nan);
+                            not_a_num);
          insn = emit_insn_after (set, insn);
-         subst_stack_regs (insn, &regstack);
-         deleted |= (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn));
+         control_flow_insn_deleted |= subst_stack_regs (insn, &regstack);
        }
     }
   
@@ -2777,12 +2927,18 @@ convert_regs_1 (FILE *file, basic_block block)
      called at the end of convert_regs.  The order in which we process the
      blocks ensures that we never delete an already processed edge.
 
+     Note that, at this point, the CFG may have been damaged by the emission
+     of instructions after an abnormal call, which moves the basic block end
+     (and is the reason why we call fixup_abnormal_edges later).  So we must
+     be sure that the trapping insn has been deleted before trying to purge
+     dead edges, otherwise we risk purging valid edges.
+
      ??? We are normally supposed not to delete trapping insns, so we pretend
      that the insns deleted above don't actually trap.  It would have been
      better to detect this earlier and avoid creating the EH edge in the first
      place, still, but we don't have enough information at that time.  */
 
-  if (deleted)
+  if (control_flow_insn_deleted)
     purge_dead_edges (block);
 
   /* Something failed if the stack lives don't match.  If we had malformed
@@ -2893,7 +3049,7 @@ convert_regs (FILE *file)
 
   /* ??? Future: process inner loops first, and give them arbitrary
      initial stacks which emit_swap_insn can modify.  This ought to
-     prevent double fxch that aften appears at the head of a loop.  */
+     prevent double fxch that often appears at the head of a loop.  */
 
   /* Process all blocks reachable from all entry points.  */
   for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)