OSDN Git Service

* lib/gcc-defs.exp (${tool}_check_compile): xfail test cases that
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index eb7a3c1..57924ce 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,
@@ -2526,11 +2558,28 @@ print_stack (FILE *file, stack s)
 static int
 convert_regs_entry (void)
 {
+  tree params = DECL_ARGUMENTS (current_function_decl);
+  tree p;
+  HARD_REG_SET incoming_regs;
+  rtx inc_rtx;
+
   int inserted = 0;
   edge e;
   edge_iterator ei;
 
-  /* Load something into each stack register live at function entry.
+  /* Find out which registers were used as argument passing registers.  */
+
+  CLEAR_HARD_REG_SET (incoming_regs);
+  for (p = params; p; p = TREE_CHAIN (p))
+    {
+      inc_rtx = DECL_INCOMING_RTL (p);
+
+      if (REG_P (inc_rtx)
+          && IN_RANGE (REGNO (inc_rtx), FIRST_STACK_REG, LAST_STACK_REG))
+       SET_HARD_REG_BIT (incoming_regs, REGNO (inc_rtx));
+    }
+
+  /* Load something into remaining 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
      the push/pop code happy, and to not scrog the register stack, we
@@ -2552,6 +2601,10 @@ convert_regs_entry (void)
 
            bi->stack_in.reg[++top] = reg;
 
+           /* Skip argument passing registers.  */
+           if (TEST_HARD_REG_BIT (incoming_regs, reg))
+             continue;
+
            init = gen_rtx_SET (VOIDmode,
                                FP_MODE_REG (FIRST_STACK_REG, SFmode),
                                not_a_num);
@@ -3031,7 +3084,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 +3168,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 ();
 
@@ -3136,12 +3191,13 @@ gate_handle_stack_regs (void)
 
 /* Convert register usage from flat register file usage to a stack
    register file.  */
-static void
+static unsigned int
 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,7 +3206,10 @@ rest_of_handle_stack_regs (void)
           cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
         }
     }
+  else 
+    regstack_completed = 1;
 #endif
+  return 0;
 }
 
 struct tree_opt_pass pass_stack_regs =
@@ -3170,5 +3229,3 @@ struct tree_opt_pass pass_stack_regs =
   TODO_ggc_collect,                     /* todo_flags_finish */
   'k'                                   /* letter */
 };
-
-#include "gt-reg-stack.h"