OSDN Git Service

2006-12-13 Jakub Jelinek <jakub@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index 73c132f..49c733e 100644 (file)
 #include "timevar.h"
 #include "tree-pass.h"
 #include "target.h"
+#include "vecprim.h"
+
+#ifdef STACK_REGS
 
 /* 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
+static VEC(char,heap) *stack_regs_mentioned_data;
 
 #define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1)
 
+int regstack_completed = 0;
+
 /* This is the basic stack record.  TOP is an index into REG[] such
    that REG[TOP] is the top of stack.  If TOP is -1 the stack is empty.
 
@@ -309,21 +312,27 @@ stack_regs_mentioned (rtx insn)
     return 0;
 
   uid = INSN_UID (insn);
-  max = VARRAY_SIZE (stack_regs_mentioned_data);
+  max = VEC_length (char, stack_regs_mentioned_data);
   if (uid >= max)
     {
+      char *p;
+      unsigned int old_max = max;
+
       /* Allocate some extra size to avoid too many reallocs, but
         do not grow too quickly.  */
-      max = uid + uid / 20;
-      VARRAY_GROW (stack_regs_mentioned_data, max);
+      max = uid + uid / 20 + 1;
+      VEC_safe_grow (char, heap, stack_regs_mentioned_data, max);
+      p = VEC_address (char, stack_regs_mentioned_data);
+      memset (&p[old_max], 0,
+             sizeof (char) * (max - old_max));
     }
 
-  test = VARRAY_CHAR (stack_regs_mentioned_data, uid);
+  test = VEC_index (char, stack_regs_mentioned_data, uid);
   if (test == 0)
     {
       /* This insn has yet to be examined.  Do so now.  */
       test = stack_regs_mentioned_p (PATTERN (insn)) ? 1 : 2;
-      VARRAY_CHAR (stack_regs_mentioned_data, uid) = test;
+      VEC_replace (char, stack_regs_mentioned_data, uid, test);
     }
 
   return test == 1;
@@ -430,6 +439,11 @@ get_true_reg (rtx *pat)
        pat = & XEXP (*pat, 0);
        break;
 
+      case UNSPEC:
+       if (XINT (*pat, 1) == UNSPEC_TRUNC_NOOP)
+         pat = & XVECEXP (*pat, 0, 0);
+       return pat;
+
       case FLOAT_TRUNCATE:
        if (!flag_unsafe_math_optimizations)
          return pat;
@@ -1362,16 +1376,20 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
                if (!note)
                  {
                    rtx t = *dest;
-                   if (get_hard_regnum (regstack, t) == -1)
-                     control_flow_insn_deleted
-                       |= move_nan_for_stack_reg (insn, regstack, t);
                    if (COMPLEX_MODE_P (GET_MODE (t)))
                      {
-                       t = FP_MODE_REG (REGNO (t) + 1, DFmode);
-                       if (get_hard_regnum (regstack, t) == -1)
-                         control_flow_insn_deleted
-                           |= move_nan_for_stack_reg (insn, regstack, t);
+                       rtx u = FP_MODE_REG (REGNO (t) + 1, SFmode);
+                       if (get_hard_regnum (regstack, u) == -1)
+                         {
+                           rtx pat2 = gen_rtx_CLOBBER (VOIDmode, u);
+                           rtx insn2 = emit_insn_before (pat2, insn);
+                           control_flow_insn_deleted
+                             |= move_nan_for_stack_reg (insn2, regstack, u);
+                         }
                      }
+                   if (get_hard_regnum (regstack, t) == -1)
+                     control_flow_insn_deleted
+                       |= move_nan_for_stack_reg (insn, regstack, t);
                  }
              }
          }
@@ -1689,11 +1707,12 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
                /* 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);
-               }
+               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);
@@ -1720,11 +1739,12 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
                /* 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);
-               }
+               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);
@@ -1747,11 +1767,12 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
                /* 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);
-               }
+               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;
@@ -1773,13 +1794,14 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
 
                /* 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);
+               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++;
-               }
+                   regstack->top++;
+                 }
 
                replace_reg (src1, FIRST_STACK_REG);
                break;
@@ -2269,6 +2291,16 @@ subst_stack_regs (rtx insn, stack regstack)
   if (NOTE_P (insn) || INSN_DELETED_P (insn))
     return control_flow_insn_deleted;
 
+  /* If this a noreturn call, we can't insert pop insns after it.
+     Instead, reset the stack state to empty.  */
+  if (CALL_P (insn)
+      && find_reg_note (insn, REG_NORETURN, NULL))
+    {
+      regstack->top = -1;
+      CLEAR_HARD_REG_SET (regstack->reg_set);
+      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,
      since the form of the newly emitted pop insn references the reg,
@@ -3031,7 +3063,8 @@ reg_to_stack (void)
   int max_uid;
 
   /* Clean up previous run.  */
-  stack_regs_mentioned_data = 0;
+  if (stack_regs_mentioned_data != NULL)
+    VEC_free (char, heap, stack_regs_mentioned_data);
 
   /* See if there is something to do.  Flow analysis is quite
      expensive so we might save some compilation time.  */
@@ -3114,8 +3147,9 @@ reg_to_stack (void)
 
   /* Allocate a cache for stack_regs_mentioned.  */
   max_uid = get_max_uid ();
-  VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
-                   "stack_regs_mentioned cache");
+  stack_regs_mentioned_data = VEC_alloc (char, heap, max_uid + 1);
+  memset (VEC_address (char, stack_regs_mentioned_data),
+         0, sizeof (char) * max_uid + 1);
 
   convert_regs ();
 
@@ -3142,6 +3176,7 @@ rest_of_handle_stack_regs (void)
 #ifdef STACK_REGS
   if (reg_to_stack () && optimize)
     {
+      regstack_completed = 1;
       if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
                        | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0))
           && (flag_reorder_blocks || flag_reorder_blocks_and_partition))
@@ -3150,6 +3185,8 @@ rest_of_handle_stack_regs (void)
           cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
         }
     }
+  else 
+    regstack_completed = 1;
 #endif
   return 0;
 }
@@ -3171,5 +3208,3 @@ struct tree_opt_pass pass_stack_regs =
   TODO_ggc_collect,                     /* todo_flags_finish */
   'k'                                   /* letter */
 };
-
-#include "gt-reg-stack.h"