OSDN Git Service

* configure.in: Fix typo.
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index b79c874..965aad0 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 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 \f
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "basic-block.h"
 #include "varray.h"
 #include "reload.h"
+#include "ggc.h"
+
+/* We use this array to cache info about insns, because otherwise we
+   spend too much time in stack_regs_mentioned_p.
+
+   Indexed by insn UIDs.  A value of zero is uninitialized, one indicates
+   the insn uses stack registers, two indicates the insn does not use
+   stack registers.  */
+static GTY(()) varray_type stack_regs_mentioned_data;
 
 #ifdef STACK_REGS
 
@@ -188,7 +199,7 @@ typedef struct stack_def
   unsigned char reg[REG_STACK_SIZE];/* register - stack mapping */
 } *stack;
 
-/* This is used to carry information about basic blocks.  It is 
+/* This is used to carry information about basic blocks.  It is
    attached to the AUX field of the standard CFG block.  */
 
 typedef struct block_info_def
@@ -197,7 +208,7 @@ typedef struct block_info_def
   struct stack_def stack_out;  /* Output stack configuration.  */
   HARD_REG_SET out_reg_set;    /* Stack regs live on output.  */
   int done;                    /* True if block already converted.  */
-  int predecesors;             /* Number of predecesors that needs
+  int predecessors;            /* Number of predecessors that needs
                                   to be visited.  */
 } *block_info;
 
@@ -210,23 +221,15 @@ enum emit_where
   EMIT_BEFORE
 };
 
-/* We use this array to cache info about insns, because otherwise we
-   spend too much time in stack_regs_mentioned_p. 
-
-   Indexed by insn UIDs.  A value of zero is uninitialized, one indicates
-   the insn uses stack registers, two indicates the insn does not use
-   stack registers.  */
-static varray_type stack_regs_mentioned_data;
-
 /* The block we're currently working on.  */
 static basic_block current_block;
 
-/* This is the register file for all register after conversion */
+/* This is the register file for all register after conversion */
 static rtx
   FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
 
 #define FP_MODE_REG(regno,mode)        \
-  (FP_mode_reg[(regno)-FIRST_STACK_REG][(int)(mode)])
+  (FP_mode_reg[(regno)-FIRST_STACK_REG][(int) (mode)])
 
 /* Used to initialize uninitialized registers.  */
 static rtx nan;
@@ -267,7 +270,7 @@ static rtx next_flags_user          PARAMS ((rtx));
 static void record_label_references    PARAMS ((rtx, rtx));
 static bool compensate_edge            PARAMS ((edge, FILE *));
 \f
-/* Return non-zero if any stack register is mentioned somewhere within PAT.  */
+/* Return nonzero if any stack register is mentioned somewhere within PAT.  */
 
 static int
 stack_regs_mentioned_p (pat)
@@ -336,7 +339,7 @@ static rtx
 next_flags_user (insn)
      rtx insn;
 {
-  /* Search forward looking for the first use of this value. 
+  /* Search forward looking for the first use of this value.
      Stop at block boundaries.  */
 
   while (insn != current_block->end)
@@ -344,7 +347,7 @@ next_flags_user (insn)
       insn = NEXT_INSN (insn);
 
       if (INSN_P (insn) && reg_mentioned_p (ix86_flags_rtx, PATTERN (insn)))
-        return insn;
+       return insn;
 
       if (GET_CODE (insn) == CALL_INSN)
        return NULL_RTX;
@@ -352,7 +355,7 @@ next_flags_user (insn)
   return NULL_RTX;
 }
 \f
-/* Reorganise the stack into ascending numbers,
+/* Reorganize the stack into ascending numbers,
    after this insn.  */
 
 static void
@@ -374,11 +377,11 @@ straighten_stack (insn, regstack)
 
   for (top = temp_stack.top = regstack->top; top >= 0; top--)
     temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top;
-  
+
   change_stack (insn, regstack, &temp_stack, EMIT_AFTER);
 }
 
-/* Pop a register from the stack */
+/* Pop a register from the stack */
 
 static void
 pop_stack (regstack, regno)
@@ -389,7 +392,7 @@ pop_stack (regstack, regno)
 
   CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
   regstack->top--;
-  /* If regno was not at the top of stack then adjust stack */
+  /* If regno was not at the top of stack then adjust stack */
   if (regstack->reg [top] != regno)
     {
       int i;
@@ -418,15 +421,12 @@ reg_to_stack (first, file)
      rtx first;
      FILE *file;
 {
+  basic_block bb;
   int i;
   int max_uid;
 
   /* Clean up previous run.  */
-  if (stack_regs_mentioned_data)
-    {
-      VARRAY_FREE (stack_regs_mentioned_data);
-      stack_regs_mentioned_data = 0;
-    }
+  stack_regs_mentioned_data = 0;
 
   if (!optimize)
     split_all_insns (0);
@@ -439,24 +439,24 @@ reg_to_stack (first, file)
   if (i > LAST_STACK_REG)
     return;
 
-  /* Ok, floating point instructions exist.  If not optimizing, 
+  /* Ok, floating point instructions exist.  If not optimizing,
      build the CFG and run life analysis.  */
   if (!optimize)
-    find_basic_blocks (first, max_reg_num (), file);
-  count_or_remove_death_notes (NULL, 1);
-  life_analysis (first, file, PROP_DEATH_NOTES);
+    {
+      count_or_remove_death_notes (NULL, 1);
+      life_analysis (first, file, PROP_DEATH_NOTES);
+    }
   mark_dfs_back_edges ();
 
   /* Set up block info for each basic block.  */
   alloc_aux_for_blocks (sizeof (struct block_info_def));
-  for (i = n_basic_blocks - 1; i >= 0; --i)
+  FOR_EACH_BB_REVERSE (bb)
     {
       edge e;
-      basic_block bb = BASIC_BLOCK (i);
       for (e = bb->pred; e; e=e->pred_next)
        if (!(e->flags & EDGE_DFS_BACK)
            && e->src != ENTRY_BLOCK_PTR)
-         BLOCK_INFO (bb)->predecesors++;
+         BLOCK_INFO (bb)->predecessors++;
     }
 
   /* Create the replacement registers up front.  */
@@ -475,10 +475,10 @@ reg_to_stack (first, file)
 
   ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
 
-  /* A QNaN for initializing uninitialized variables.  
+  /* A QNaN for initializing uninitialized variables.
 
      ??? We can't load from constant memory in PIC mode, because
-     we're insertting these instructions before the prologue and
+     we're inserting these instructions before the prologue and
      the PIC register hasn't been set up.  In that case, fall back
      on zero, which we can get from `ldz'.  */
 
@@ -566,7 +566,7 @@ get_true_reg (pat)
     switch (GET_CODE (*pat))
       {
       case SUBREG:
-       /* Eliminate FP subregister accesses in favour of the
+       /* Eliminate FP subregister accesses in favor of the
           actual FP register in use.  */
        {
          rtx subreg;
@@ -672,17 +672,17 @@ check_asm_stack_operands (insn)
       {
        if (reg_class_size[(int) recog_op_alt[i][alt].class] != 1)
          {
-           error_for_asm (insn, "Output constraint %d must specify a single register", i);
+           error_for_asm (insn, "output constraint %d must specify a single register", i);
            malformed_asm = 1;
          }
-        else
+       else
          {
            int j;
 
            for (j = 0; j < n_clobbers; j++)
              if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
                {
-                 error_for_asm (insn, "Output constraint %d cannot be specified together with \"%s\" clobber",
+                 error_for_asm (insn, "output constraint %d cannot be specified together with \"%s\" clobber",
                                 i, reg_names [REGNO (clobber_reg[j])]);
                  malformed_asm = 1;
                  break;
@@ -705,7 +705,7 @@ check_asm_stack_operands (insn)
 
   if (i != LAST_STACK_REG + 1)
     {
-      error_for_asm (insn, "Output regs must be grouped at top of stack");
+      error_for_asm (insn, "output regs must be grouped at top of stack");
       malformed_asm = 1;
     }
 
@@ -742,11 +742,11 @@ check_asm_stack_operands (insn)
   if (i != LAST_STACK_REG + 1)
     {
       error_for_asm (insn,
-                    "Implicitly popped regs must be grouped at top of stack");
+                    "implicitly popped regs must be grouped at top of stack");
       malformed_asm = 1;
     }
 
-  /* Enfore rule #3: If any input operand uses the "f" constraint, all
+  /* Enforce rule #3: If any input operand uses the "f" constraint, all
      output constraints must use the "&" earlyclobber.
 
      ??? Detect this more deterministically by having constrain_asm_operands
@@ -761,7 +761,7 @@ check_asm_stack_operands (insn)
          if (operands_match_p (recog_data.operand[j], recog_data.operand[i]))
            {
              error_for_asm (insn,
-                            "Output operand %d must use `&' constraint", j);
+                            "output operand %d must use `&' constraint", j);
              malformed_asm = 1;
            }
       }
@@ -821,7 +821,7 @@ stack_result (decl)
     {
 #ifdef FUNCTION_OUTGOING_VALUE
       result
-        = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
+       = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
 #else
       result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
 #endif
@@ -869,7 +869,7 @@ remove_regno_note (insn, note, regno)
 {
   rtx *note_link, this;
 
-  note_link = &REG_NOTES(insn);
+  note_link = &REG_NOTES (insn);
   for (this = *note_link; this; this = XEXP (this, 1))
     if (REG_NOTE_KIND (this) == note
        && REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno)
@@ -930,9 +930,9 @@ emit_pop_insn (insn, regstack, reg, where)
 
       pop_insn = NULL_RTX;
       if (get_hard_regnum (regstack, reg1) >= 0)
-         pop_insn = emit_pop_insn (insn, regstack, reg1, where);
+       pop_insn = emit_pop_insn (insn, regstack, reg1, where);
       if (get_hard_regnum (regstack, reg2) >= 0)
-         pop_insn = emit_pop_insn (insn, regstack, reg2, where);
+       pop_insn = emit_pop_insn (insn, regstack, reg2, where);
       if (!pop_insn)
        abort ();
       return pop_insn;
@@ -1127,7 +1127,7 @@ move_for_stack_reg (insn, regstack, pat)
          return;
        }
 
-      /* The destination ought to be dead */
+      /* The destination ought to be dead */
       if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
        abort ();
 
@@ -1183,7 +1183,7 @@ move_for_stack_reg (insn, regstack, pat)
         stack. The stack mapping is changed to reflect that DEST is
         now at top of stack.  */
 
-      /* The destination ought to be dead */
+      /* The destination ought to be dead */
       if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
        abort ();
 
@@ -1258,11 +1258,11 @@ swap_rtx_condition (insn)
 
   if (GET_CODE (pat) == SET
       && GET_CODE (SET_SRC (pat)) == UNSPEC
-      && XINT (SET_SRC (pat), 1) == 9)
+      && XINT (SET_SRC (pat), 1) == UNSPEC_FNSTSW)
     {
       rtx dest = SET_DEST (pat);
 
-      /* Search forward looking for the first use of this value. 
+      /* Search forward looking for the first use of this value.
         Stop at block boundaries.  */
       while (insn != current_block->end)
        {
@@ -1279,7 +1279,7 @@ swap_rtx_condition (insn)
       pat = PATTERN (insn);
       if (GET_CODE (pat) != SET
          || GET_CODE (SET_SRC (pat)) != UNSPEC
-         || XINT (SET_SRC (pat), 1) != 10
+         || XINT (SET_SRC (pat), 1) != UNSPEC_SAHF
          || ! dead_or_set_p (insn, dest))
        return 0;
 
@@ -1428,15 +1428,15 @@ subst_stack_regs_pat (insn, regstack, pat)
       /* Deaths in USE insns can happen in non optimizing compilation.
         Handle them by popping the dying register.  */
       src = get_true_reg (&XEXP (pat, 0));
-      if (STACK_REG_P (*src) 
-          && find_regno_note (insn, REG_DEAD, REGNO (*src)))
-        {
-          emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
-          return;
-        }
+      if (STACK_REG_P (*src)
+         && find_regno_note (insn, REG_DEAD, REGNO (*src)))
+       {
+         emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
+         return;
+       }
       /* ??? Uninitialized USE should not happen.  */
       else if (get_hard_regnum (regstack, *src) == -1)
-       abort();
+       abort ();
       break;
 
     case CLOBBER:
@@ -1453,7 +1453,7 @@ subst_stack_regs_pat (insn, regstack, pat)
                /* The fix_truncdi_1 pattern wants to be able to allocate
                   it's own scratch register.  It does this by clobbering
                   an fp reg so that it is assured of an empty reg-stack
-                  register.  If the register is live, kill it now. 
+                  register.  If the register is live, kill it now.
                   Remove the DEAD/UNUSED note so we don't try to kill it
                   later too.  */
 
@@ -1472,7 +1472,7 @@ subst_stack_regs_pat (insn, regstack, pat)
              {
                /* A top-level clobber with no REG_DEAD, and no hard-regnum
                   indicates an uninitialized value.  Because reload removed
-                  all other clobbers, this must be due to a function 
+                  all other clobbers, this must be due to a function
                   returning without a value.  Load up a NaN.  */
 
                if (! note
@@ -1689,7 +1689,7 @@ subst_stack_regs_pat (insn, regstack, pat)
                replace_reg (dest, get_hard_regnum (regstack, *dest));
              }
 
-           /* Keep operand 1 maching with destination.  */
+           /* Keep operand 1 matching with destination.  */
            if (GET_RTX_CLASS (GET_CODE (pat_src)) == 'c'
                && REG_P (*src1) && REG_P (*src2)
                && REGNO (*src1) != REGNO (*dest))
@@ -1703,8 +1703,8 @@ subst_stack_regs_pat (insn, regstack, pat)
          case UNSPEC:
            switch (XINT (pat_src, 1))
              {
-             case 1: /* sin */
-             case 2: /* cos */
+             case UNSPEC_SIN:
+             case UNSPEC_COS:
                /* These insns only operate on the top of the stack.  */
 
                src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
@@ -1726,19 +1726,84 @@ subst_stack_regs_pat (insn, regstack, pat)
                replace_reg (src1, FIRST_STACK_REG);
                break;
 
-             case 10:
-               /* (unspec [(unspec [(compare ..)] 9)] 10)
-                  Unspec 9 is fnstsw; unspec 10 is sahf.  The combination
-                  matches the PPRO fcomi instruction.  */
+             case UNSPEC_FPATAN:
+               /* These insns operate on the top two stack slots.  */
+
+               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));
+
+               {
+                 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);
+               }
+
+               replace_reg (src1, FIRST_STACK_REG);
+               replace_reg (src2, FIRST_STACK_REG + 1);
+
+               if (src1_note)
+                 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+               if (src2_note)
+                 replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
+
+               /* Pop both input operands from the stack.  */
+               CLEAR_HARD_REG_BIT (regstack->reg_set,
+                                   regstack->reg[regstack->top]);
+               CLEAR_HARD_REG_BIT (regstack->reg_set,
+                                   regstack->reg[regstack->top - 1]);
+               regstack->top -= 2;
+
+               /* Push the result back onto the stack.  */
+               regstack->reg[++regstack->top] = REGNO (*dest);
+               SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+               replace_reg (dest, FIRST_STACK_REG);
+               break;
+
+             case UNSPEC_SAHF:
+               /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF)
+                  The combination matches the PPRO fcomi instruction.  */
 
                pat_src = XVECEXP (pat_src, 0, 0);
                if (GET_CODE (pat_src) != UNSPEC
-                   || XINT (pat_src, 1) != 9)
+                   || XINT (pat_src, 1) != UNSPEC_FNSTSW)
                  abort ();
                /* FALLTHRU */
 
-             case 9:
-               /* (unspec [(compare ..)] 9) */
+             case UNSPEC_FNSTSW:
                /* Combined fcomp+fnstsw generated for doing well with
                   CSE.  When optimizing this would have been broken
                   up before now.  */
@@ -1773,8 +1838,8 @@ subst_stack_regs_pat (insn, regstack, pat)
                && REGNO (*dest) != regstack->reg[regstack->top])
              {
                /* In case one of operands is the top of stack and the operands
-                  dies, it is safe to make it the destination operand by reversing
-                  the direction of cmove and avoid fxch.  */
+                  dies, it is safe to make it the destination operand by
+                  reversing the direction of cmove and avoid fxch.  */
                if ((REGNO (*src1) == regstack->reg[regstack->top]
                     && src1_note)
                    || (REGNO (*src2) == regstack->reg[regstack->top]
@@ -1796,7 +1861,7 @@ subst_stack_regs_pat (insn, regstack, pat)
                              reversed_comparison_code (XEXP (pat_src, 0), insn));
                  }
                else
-                 emit_swap_insn (insn, regstack, *dest);       
+                 emit_swap_insn (insn, regstack, *dest);
              }
 
            {
@@ -1835,7 +1900,7 @@ subst_stack_regs_pat (insn, regstack, pat)
            /* Make dest the top of stack.  Add dest to regstack if
               not present.  */
            if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
-             regstack->reg[++regstack->top] = REGNO (*dest);   
+             regstack->reg[++regstack->top] = REGNO (*dest);
            SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
            replace_reg (dest, FIRST_STACK_REG);
            break;
@@ -1897,7 +1962,7 @@ subst_asm_stack_regs (insn, regstack)
 
   n_inputs = get_asm_operand_n_inputs (body);
   n_outputs = recog_data.n_operands - n_inputs;
-  
+
   if (alt < 0)
     abort ();
 
@@ -2213,7 +2278,7 @@ subst_stack_regs (insn, 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 (GET_CODE (insn) == NOTE)
+  if (GET_CODE (insn) == NOTE || INSN_DELETED_P (insn))
     return;
 
   /* If there is a REG_UNUSED note on a stack register on this insn,
@@ -2221,7 +2286,7 @@ subst_stack_regs (insn, regstack)
      since the form of the newly emitted pop insn references the reg,
      making it no longer `unset'.  */
 
-  note_link = &REG_NOTES(insn);
+  note_link = &REG_NOTES (insn);
   for (note = *note_link; note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_UNUSED && STACK_REG_P (XEXP (note, 0)))
       {
@@ -2294,7 +2359,7 @@ change_stack (insn, old, new, where)
        abort ();
 
       /* If the stack is not empty (new->top != -1), loop here emitting
-        swaps until the stack is correct. 
+        swaps until the stack is correct.
 
         The worst case number of swaps emitted is N + 2, where N is the
         depth of the stack.  In some cases, the reg at the top of
@@ -2370,7 +2435,7 @@ print_stack (file, s)
 }
 \f
 /* This function was doing life analysis.  We now let the regular live
-   code do it's job, so we only need to check some extra invariants 
+   code do it's job, so we only need to check some extra invariants
    that reg-stack expects.  Primary among these being that all registers
    are initialized before use.
 
@@ -2380,18 +2445,18 @@ print_stack (file, s)
 static int
 convert_regs_entry ()
 {
-  int inserted = 0, i;
+  int inserted = 0;
   edge e;
+  basic_block block;
 
-  for (i = n_basic_blocks - 1; i >= 0; --i)
+  FOR_EACH_BB_REVERSE (block)
     {
-      basic_block block = BASIC_BLOCK (i);
       block_info bi = BLOCK_INFO (block);
       int reg;
-      
+
       /* Set current register status at last instruction `uninitialized'.  */
       bi->stack_in.top = -2;
-  
+
       /* Copy live_at_end and live_at_start into temporaries.  */
       for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
        {
@@ -2402,13 +2467,13 @@ convert_regs_entry ()
        }
     }
 
-  /* Load something into each stack register live at function entry. 
+  /* Load something into each stack register live at function entry.
      Such live registers can be caused by uninitialized variables or
-     functions not returning values on all paths.  In order to keep 
+     functions not returning values on all paths.  In order to keep
      the push/pop code happy, and to not scrog the register stack, we
-     must put something in these registers.  Use a QNaN.  
+     must put something in these registers.  Use a QNaN.
 
-     Note that we are insertting converted code here.  This code is
+     Note that we are inserting converted code here.  This code is
      never seen by the convert_regs pass.  */
 
   for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
@@ -2466,7 +2531,7 @@ convert_regs_exit ()
       output_stack->top = value_reg_high - value_reg_low;
       for (reg = value_reg_low; reg <= value_reg_high; ++reg)
        {
-         output_stack->reg[reg - value_reg_low] = reg;
+         output_stack->reg[value_reg_high - reg] = reg;
          SET_HARD_REG_BIT (output_stack->reg_set, reg);
        }
     }
@@ -2508,7 +2573,7 @@ compensate_edge (e, file)
          tmpstack = regstack;
 
          change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER);
-          return false;
+         return false;
        }
 
       if (file)
@@ -2557,7 +2622,11 @@ compensate_edge (e, file)
       abort ();
     eh1:
 
+      /* We are sure that there is st(0) live, otherwise we won't compensate.
+        For complex return values, we may have st(1) live as well.  */
       SET_HARD_REG_BIT (tmp, FIRST_STACK_REG);
+      if (TEST_HARD_REG_BIT (regstack.reg_set, FIRST_STACK_REG + 1))
+        SET_HARD_REG_BIT (tmp, FIRST_STACK_REG + 1);
       GO_IF_HARD_REG_EQUAL (regstack.reg_set, tmp, eh2);
       abort ();
     eh2:
@@ -2591,16 +2660,13 @@ compensate_edge (e, file)
       current_block = NULL;
       start_sequence ();
 
-      /* ??? change_stack needs some point to emit insns after. 
-         Also needed to keep gen_sequence from returning a 
-         pattern as opposed to a sequence, which would lose
-         REG_DEAD notes.  */
+      /* ??? change_stack needs some point to emit insns after.  */
       after = emit_note (NULL, NOTE_INSN_DELETED);
 
       tmpstack = regstack;
       change_stack (after, &tmpstack, target_stack, EMIT_BEFORE);
 
-      seq = gen_sequence ();
+      seq = get_insns ();
       end_sequence ();
 
       insert_insn_on_edge (seq, e);
@@ -2626,7 +2692,7 @@ convert_regs_1 (file, block)
 
   /* Find the edge we will copy stack from.  It should be the most frequent
      one as it will get cheapest after compensation code is generated,
-     if multiple such exists, take one with largest count, preffer critical
+     if multiple such exists, take one with largest count, prefer critical
      one (as splitting critical edges is more expensive), or one with lowest
      index, to avoid random changes with different orders of the edges.  */
   for (e = block->pred; e ; e = e->pred_next)
@@ -2658,7 +2724,7 @@ convert_regs_1 (file, block)
     inserted |= compensate_edge (beste, file);
   else
     beste = NULL;
-  
+
   current_block = block;
 
   if (file)
@@ -2751,7 +2817,7 @@ convert_regs_1 (file, block)
          if (!BLOCK_INFO (e->dest)->done
              && e->dest != block)
            abort ();
-          inserted |= compensate_edge (e, file);
+         inserted |= compensate_edge (e, file);
        }
     }
   for (e = block->pred; e ; e = e->pred_next)
@@ -2761,7 +2827,7 @@ convert_regs_1 (file, block)
        {
          if (!BLOCK_INFO (e->src)->done)
            abort ();
-          inserted |= compensate_edge (e, file);
+         inserted |= compensate_edge (e, file);
        }
     }
 
@@ -2795,8 +2861,8 @@ convert_regs_2 (file, block)
       for (e = block->succ; e ; e = e->succ_next)
        if (! (e->flags & EDGE_DFS_BACK))
          {
-           BLOCK_INFO (e->dest)->predecesors--;
-           if (!BLOCK_INFO (e->dest)->predecesors)
+           BLOCK_INFO (e->dest)->predecessors--;
+           if (!BLOCK_INFO (e->dest)->predecessors)
               *sp++ = e->dest;
          }
     }
@@ -2813,7 +2879,8 @@ static int
 convert_regs (file)
      FILE *file;
 {
-  int inserted, i;
+  int inserted;
+  basic_block b;
   edge e;
 
   /* Initialize uninitialized registers on function entry.  */
@@ -2830,12 +2897,11 @@ convert_regs (file)
   /* Process all blocks reachable from all entry points.  */
   for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
     inserted |= convert_regs_2 (file, e->dest);
-  
-  /* ??? Process all unreachable blocks.  Though there's no excuse 
+
+  /* ??? Process all unreachable blocks.  Though there's no excuse
      for keeping these even when not optimizing.  */
-  for (i = 0; i < n_basic_blocks; ++i)
+  FOR_EACH_BB (b)
     {
-      basic_block b = BASIC_BLOCK (i);
       block_info bi = BLOCK_INFO (b);
 
       if (! bi->done)
@@ -2852,6 +2918,7 @@ convert_regs (file)
        }
     }
 
+  fixup_abnormal_edges ();
   if (inserted)
     commit_edge_insertions ();
 
@@ -2861,3 +2928,5 @@ convert_regs (file)
   return inserted;
 }
 #endif /* STACK_REGS */
+
+#include "gt-reg-stack.h"