OSDN Git Service

* expr.c (init_expr_once): Don't use start/end_sequence.
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index a72f622..3e1a756 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.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -188,7 +188,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 +197,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;
 
@@ -211,7 +211,7 @@ enum emit_where
 };
 
 /* We use this array to cache info about insns, because otherwise we
-   spend too much time in stack_regs_mentioned_p. 
+   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
@@ -226,7 +226,7 @@ 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;
@@ -245,7 +245,6 @@ static void replace_reg                     PARAMS ((rtx *, int));
 static void remove_regno_note          PARAMS ((rtx, enum reg_note,
                                                 unsigned int));
 static int get_hard_regnum             PARAMS ((stack, rtx));
-static void delete_insn_for_stacker    PARAMS ((rtx));
 static rtx emit_pop_insn               PARAMS ((rtx, stack, rtx,
                                               enum emit_where));
 static void emit_swap_insn             PARAMS ((rtx, stack, rtx));
@@ -274,8 +273,8 @@ static int
 stack_regs_mentioned_p (pat)
      rtx pat;
 {
-  register const char *fmt;
-  register int i;
+  const char *fmt;
+  int i;
 
   if (STACK_REG_P (pat))
     return 1;
@@ -285,7 +284,7 @@ stack_regs_mentioned_p (pat)
     {
       if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
 
          for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
            if (stack_regs_mentioned_p (XVECEXP (pat, i, j)))
@@ -337,7 +336,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)
@@ -345,7 +344,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;
@@ -375,7 +374,7 @@ 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);
 }
 
@@ -421,7 +420,6 @@ reg_to_stack (first, file)
 {
   int i;
   int max_uid;
-  block_info bi;
 
   /* Clean up previous run.  */
   if (stack_regs_mentioned_data)
@@ -441,27 +439,27 @@ 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);
+    {
+      find_basic_blocks (first, max_reg_num (), file);
+      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.  */
-  bi = (block_info) xcalloc ((n_basic_blocks + 1), sizeof (*bi));
+  alloc_aux_for_blocks (sizeof (struct block_info_def));
   for (i = n_basic_blocks - 1; i >= 0; --i)
     {
       edge e;
       basic_block bb = BASIC_BLOCK (i);
-      bb->aux = bi + 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++;
     }
-  EXIT_BLOCK_PTR->aux = bi + n_basic_blocks;
 
   /* Create the replacement registers up front.  */
   for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
@@ -479,7 +477,7 @@ 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
@@ -501,7 +499,7 @@ reg_to_stack (first, file)
 
   convert_regs (file);
 
-  free (bi);
+  free_aux_for_blocks ();
 }
 \f
 /* Check PAT, which is in INSN, for LABEL_REFs.  Add INSN to the
@@ -512,14 +510,14 @@ static void
 record_label_references (insn, pat)
      rtx insn, pat;
 {
-  register enum rtx_code code = GET_CODE (pat);
-  register int i;
-  register const char *fmt;
+  enum rtx_code code = GET_CODE (pat);
+  int i;
+  const char *fmt;
 
   if (code == LABEL_REF)
     {
-      register rtx label = XEXP (pat, 0);
-      register rtx ref;
+      rtx label = XEXP (pat, 0);
+      rtx ref;
 
       if (GET_CODE (label) != CODE_LABEL)
        abort ();
@@ -551,7 +549,7 @@ record_label_references (insn, pat)
        record_label_references (insn, XEXP (pat, i));
       if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (pat, i); j++)
            record_label_references (insn, XVECEXP (pat, i, j));
        }
@@ -676,17 +674,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;
@@ -709,7 +707,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;
     }
 
@@ -746,7 +744,7 @@ 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;
     }
 
@@ -765,7 +763,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;
            }
       }
@@ -825,7 +823,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
@@ -871,9 +869,9 @@ remove_regno_note (insn, note, regno)
      enum reg_note note;
      unsigned int regno;
 {
-  register rtx *note_link, this;
+  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)
@@ -907,19 +905,6 @@ get_hard_regnum (regstack, reg)
 
   return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;
 }
-
-/* Delete INSN from the RTL.  Mark the insn, but don't remove it from
-   the chain of insns.  Doing so could confuse block_begin and block_end
-   if this were the only insn in the block.  */
-
-static void
-delete_insn_for_stacker (insn)
-     rtx insn;
-{
-  PUT_CODE (insn, NOTE);
-  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-  NOTE_SOURCE_FILE (insn) = 0;
-}
 \f
 /* Emit an insn to pop virtual register REG before or after INSN.
    REGSTACK is the stack state after INSN and is updated to reflect this
@@ -947,9 +932,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;
@@ -964,9 +949,9 @@ emit_pop_insn (insn, regstack, reg, where)
                         FP_MODE_REG (FIRST_STACK_REG, DFmode));
 
   if (where == EMIT_AFTER)
-    pop_insn = emit_block_insn_after (pop_rtx, insn, current_block);
+    pop_insn = emit_insn_after (pop_rtx, insn);
   else
-    pop_insn = emit_block_insn_before (pop_rtx, insn, current_block);
+    pop_insn = emit_insn_before (pop_rtx, insn);
 
   REG_NOTES (pop_insn)
     = gen_rtx_EXPR_LIST (REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode),
@@ -1062,9 +1047,9 @@ emit_swap_insn (insn, regstack, reg)
                         FP_MODE_REG (FIRST_STACK_REG, XFmode));
 
   if (i1)
-    emit_block_insn_after (swap_rtx, i1, current_block);
+    emit_insn_after (swap_rtx, i1);
   else if (current_block)
-    emit_block_insn_before (swap_rtx, current_block->head, current_block);
+    emit_insn_before (swap_rtx, current_block->head);
   else
     emit_insn_before (swap_rtx, insn);
 }
@@ -1114,7 +1099,7 @@ move_for_stack_reg (insn, regstack, pat)
            {
              emit_pop_insn (insn, regstack, src, EMIT_AFTER);
 
-             delete_insn_for_stacker (insn);
+             delete_insn (insn);
              return;
            }
 
@@ -1123,7 +1108,7 @@ move_for_stack_reg (insn, regstack, pat)
          SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
          CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
 
-         delete_insn_for_stacker (insn);
+         delete_insn (insn);
 
          return;
        }
@@ -1140,7 +1125,7 @@ move_for_stack_reg (insn, regstack, pat)
          if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
            emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
 
-         delete_insn_for_stacker (insn);
+         delete_insn (insn);
          return;
        }
 
@@ -1223,8 +1208,8 @@ static int
 swap_rtx_condition_1 (pat)
      rtx pat;
 {
-  register const char *fmt;
-  register int i, r = 0;
+  const char *fmt;
+  int i, r = 0;
 
   if (GET_RTX_CLASS (GET_CODE (pat)) == '<')
     {
@@ -1238,7 +1223,7 @@ swap_rtx_condition_1 (pat)
        {
          if (fmt[i] == 'E')
            {
-             register int j;
+             int j;
 
              for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
                r |= swap_rtx_condition_1 (XVECEXP (pat, i, j));
@@ -1279,7 +1264,7 @@ swap_rtx_condition (insn)
     {
       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)
        {
@@ -1445,15 +1430,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:
@@ -1470,7 +1455,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.  */
 
@@ -1489,7 +1474,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
@@ -1813,7 +1798,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);
              }
 
            {
@@ -1852,7 +1837,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;
@@ -1914,7 +1899,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 ();
 
@@ -2172,8 +2157,8 @@ subst_stack_regs (insn, regstack)
      rtx insn;
      stack regstack;
 {
-  register rtx *note_link, note;
-  register int i;
+  rtx *note_link, note;
+  int i;
 
   if (GET_CODE (insn) == CALL_INSN)
     {
@@ -2230,7 +2215,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,
@@ -2238,7 +2223,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)))
       {
@@ -2311,7 +2296,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
@@ -2387,7 +2372,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.
 
@@ -2405,10 +2390,10 @@ convert_regs_entry ()
       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++)
        {
@@ -2419,11 +2404,11 @@ 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
      never seen by the convert_regs pass.  */
@@ -2525,7 +2510,7 @@ compensate_edge (e, file)
          tmpstack = regstack;
 
          change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER);
-          return false;
+         return false;
        }
 
       if (file)
@@ -2608,8 +2593,8 @@ 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 
+      /* ??? 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.  */
       after = emit_note (NULL, NOTE_INSN_DELETED);
@@ -2643,7 +2628,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)
@@ -2660,9 +2645,10 @@ convert_regs_1 (file, block)
        beste = e;
       else if (beste->count > e->count)
        ;
-      else if ((e->flags & EDGE_CRITICAL) != (beste->flags & EDGE_CRITICAL))
+      else if ((EDGE_CRITICAL_P (e) != 0)
+              != (EDGE_CRITICAL_P (beste) != 0))
        {
-         if (e->flags & EDGE_CRITICAL)
+         if (EDGE_CRITICAL_P (e))
            beste = e;
        }
       else if (e->src->index < beste->src->index)
@@ -2674,7 +2660,7 @@ convert_regs_1 (file, block)
     inserted |= compensate_edge (beste, file);
   else
     beste = NULL;
-  
+
   current_block = block;
 
   if (file)
@@ -2747,7 +2733,7 @@ convert_regs_1 (file, block)
 
          set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode),
                             nan);
-         insn = emit_block_insn_after (set, insn, block);
+         insn = emit_insn_after (set, insn);
          subst_stack_regs (insn, &regstack);
        }
     }
@@ -2767,7 +2753,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)
@@ -2777,7 +2763,7 @@ convert_regs_1 (file, block)
        {
          if (!BLOCK_INFO (e->src)->done)
            abort ();
-          inserted |= compensate_edge (e, file);
+         inserted |= compensate_edge (e, file);
        }
     }
 
@@ -2811,8 +2797,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;
          }
     }
@@ -2846,8 +2832,8 @@ 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)
     {
@@ -2868,6 +2854,7 @@ convert_regs (file)
        }
     }
 
+  fixup_abnormal_edges ();
   if (inserted)
     commit_edge_insertions ();