OSDN Git Service

Fix bad regexp
[pf3gnuchains/gcc-fork.git] / gcc / regrename.c
index 0079dc1..6463879 100644 (file)
@@ -1,5 +1,5 @@
 /* Register renaming for the GNU compiler.
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -325,7 +325,12 @@ regrename_optimize ()
              /* See whether it accepts all modes that occur in
                 definition and uses.  */
              for (tmp = this; tmp; tmp = tmp->next_use)
-               if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc)))
+               if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
+                   || (tmp->need_caller_save_reg
+                       && ! (HARD_REGNO_CALL_PART_CLOBBERED
+                             (reg, GET_MODE (*tmp->loc)))
+                       && (HARD_REGNO_CALL_PART_CLOBBERED
+                           (new_reg, GET_MODE (*tmp->loc)))))
                  break;
              if (! tmp)
                {
@@ -673,6 +678,7 @@ scan_rtx (insn, loc, class, action, type, earlyclobber)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case CC0:
@@ -758,7 +764,7 @@ build_def_use (bb)
          rtx note;
          rtx old_operands[MAX_RECOG_OPERANDS];
          rtx old_dups[MAX_DUP_OPERANDS];
-         int i;
+         int i, icode;
          int alt;
          int predicated;
 
@@ -778,8 +784,10 @@ build_def_use (bb)
             (6) For any write we find in an operand, make a new chain.
             (7) For any REG_UNUSED, close any chains we just opened.  */
 
+         icode = recog_memoized (insn);
          extract_insn (insn);
-         constrain_operands (1);
+         if (! constrain_operands (1))
+           fatal_insn_not_found (insn);        
          preprocess_constraints ();
          alt = which_alternative;
          n_ops = recog_data.n_operands;
@@ -821,8 +829,16 @@ build_def_use (bb)
            }
          for (i = 0; i < recog_data.n_dups; i++)
            {
+             int dup_num = recog_data.dup_num[i];
+
              old_dups[i] = *recog_data.dup_loc[i];
              *recog_data.dup_loc[i] = cc0_rtx;
+
+             /* For match_dup of match_operator or match_parallel, share
+                them, so that we don't miss changes in the dup.  */
+             if (icode >= 0
+                 && insn_data[icode].operand[dup_num].eliminable == 0)
+               old_dups[i] = recog_data.operand[dup_num];
            }
 
          scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
@@ -1090,6 +1106,14 @@ kill_value (x, vd)
      rtx x;
      struct value_data *vd;
 {
+  /* SUBREGS are supposed to have been eliminated by now.  But some
+     ports, e.g. i386 sse, use them to smuggle vector type information
+     through to instruction selection.  Each such SUBREG should simplify,
+     so if we get a NULL  we've done something wrong elsewhere.  */
+
+  if (GET_CODE (x) == SUBREG)
+    x = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
+                        GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
   if (REG_P (x))
     {
       unsigned int regno = REGNO (x);
@@ -1109,7 +1133,7 @@ kill_value (x, vd)
        {
          if (vd->e[j].mode == VOIDmode)
            continue;
-         n = HARD_REGNO_NREGS (regno, vd->e[j].mode);
+         n = HARD_REGNO_NREGS (j, vd->e[j].mode);
          if (j + n > regno)
            for (i = 0; i < n; ++i)
              kill_value_regno (j + i, vd);
@@ -1173,10 +1197,11 @@ kill_set_value (x, set, data)
      void *data;
 {
   struct value_data *vd = data;
-  if (GET_CODE (set) != CLOBBER && REG_P (x))
+  if (GET_CODE (set) != CLOBBER)
     {
       kill_value (x, vd);
-      set_value_regno (REGNO (x), GET_MODE (x), vd);
+      if (REG_P (x))
+        set_value_regno (REGNO (x), GET_MODE (x), vd);
     }
 }
 
@@ -1244,6 +1269,12 @@ copy_value (dest, src, vd)
   if (vd->e[sr].mode == VOIDmode)
     set_value_regno (sr, vd->e[dr].mode, vd);
 
+  /* If SRC had been assigned a mode narrower than the copy, we can't
+     link DEST into the chain, because not all of the pieces of the
+     copy came from oldest_regno.  */
+  else if (sn > (unsigned int) HARD_REGNO_NREGS (sr, vd->e[sr].mode))
+    return;
+
   /* Link DR at the end of the value chain used by SR.  */
 
   vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
@@ -1307,9 +1338,9 @@ find_oldest_value_reg (class, reg, vd)
   for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
     if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
        && (vd->e[i].mode == mode
-           || mode_change_ok (vd->e[i].mode, mode, regno)))
+           || mode_change_ok (vd->e[i].mode, mode, i)))
       {
-       rtx new = gen_rtx_REG (mode, i);
+       rtx new = gen_rtx_raw_REG (mode, i);
        ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
        return new;
       }
@@ -1516,7 +1547,8 @@ copyprop_hardreg_forward_1 (bb, vd)
 
       set = single_set (insn);
       extract_insn (insn);
-      constrain_operands (1);
+      if (! constrain_operands (1))
+       fatal_insn_not_found (insn);    
       preprocess_constraints ();
       alt = which_alternative;
       n_ops = recog_data.n_operands;
@@ -1594,9 +1626,10 @@ copyprop_hardreg_forward_1 (bb, vd)
          /* Otherwise, try all valid registers and see if its valid.  */
          for (i = vd->e[regno].oldest_regno; i != regno;
               i = vd->e[i].next_regno)
-           if (mode == vd->e[regno].mode)
+           if (vd->e[i].mode == mode
+               || mode_change_ok (vd->e[i].mode, mode, i))
              {
-               new = gen_rtx_REG (mode, i);
+               new = gen_rtx_raw_REG (mode, i);
                if (validate_change (insn, &SET_SRC (set), new, 0))
                  {
                    ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);