OSDN Git Service

In libobjc/:
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 9c5d8d0..bed5768 100644 (file)
@@ -1417,7 +1417,7 @@ init_reg_last (void)
   unsigned int i;
   reg_stat_type *p;
 
-  for (i = 0; VEC_iterate (reg_stat_type, reg_stat, i, p); ++i)
+  FOR_EACH_VEC_ELT (reg_stat_type, reg_stat, i, p)
     memset (p, 0, offsetof (reg_stat_type, sign_bit_copies));
 }
 \f
@@ -2137,12 +2137,12 @@ cant_combine_insn_p (rtx insn)
   if (GET_CODE (dest) == SUBREG)
     dest = SUBREG_REG (dest);
   if (REG_P (src) && REG_P (dest)
-      && ((REGNO (src) < FIRST_PSEUDO_REGISTER
-          && ! fixed_regs[REGNO (src)]
-          && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
-         || (REGNO (dest) < FIRST_PSEUDO_REGISTER
-             && ! fixed_regs[REGNO (dest)]
-             && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
+      && ((HARD_REGISTER_P (src)
+          && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (src))
+          && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (src))))
+         || (HARD_REGISTER_P (dest)
+             && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (dest))
+             && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (dest))))))
     return 1;
 
   return 0;
@@ -2223,7 +2223,7 @@ likely_spilled_retval_p (rtx insn)
   do
     {
       if ((mask & 1 << nregs)
-         && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno + nregs)))
+         && targetm.class_likely_spilled_p (REGNO_REG_CLASS (regno + nregs)))
        return 1;
     } while (nregs--);
   return 0;
@@ -2862,7 +2862,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
   i1_feeds_i2_n = i1 && insn_a_feeds_b (i1, i2);
   i0_feeds_i1_n = i0 && insn_a_feeds_b (i0, i1);
   i0_feeds_i2_n = (i0 && (!i0_feeds_i1_n ? insn_a_feeds_b (i0, i2)
-                         : (!dead_or_set_p (i1, i0dest)
+                         : (!reg_overlap_mentioned_p (i1dest, i0dest)
                             && reg_overlap_mentioned_p (i0dest, i2src))));
 
   /* Ensure that I3's pattern can be the destination of combines.  */
@@ -3138,7 +3138,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
        }
 
       n_occurrences = 0;
-      subst_low_luid = DF_INSN_LUID (i1);
+      subst_low_luid = DF_INSN_LUID (i0);
       newpat = subst (newpat, i0dest, i0src, 0,
                      i0_feeds_i1_n && i0dest_in_i0src);
       substed_i0 = 1;
@@ -3725,7 +3725,58 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p)
       i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
       if (i2_code_number >= 0)
-       insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+       {
+         /* recog_for_combine might have added CLOBBERs to newi2pat.
+            Make sure NEWPAT does not depend on the clobbered regs.  */
+         if (GET_CODE (newi2pat) == PARALLEL)
+           {
+             for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
+               if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
+                 {
+                   rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
+                   if (reg_overlap_mentioned_p (reg, newpat))
+                     break;
+                 }
+
+             if (i >= 0)
+               {
+                 /* CLOBBERs on newi2pat prevent it going first.
+                    Try the other order of the insns if possible.  */
+                 temp = newpat;
+                 newpat = XVECEXP (newi2pat, 0, 0);
+                 newi2pat = temp;
+#ifdef HAVE_cc0
+                 if (reg_referenced_p (cc0_rtx, newpat))
+                   {
+                     undo_all ();
+                     return 0;
+                   }
+#endif
+
+                 i2_code_number = recog_for_combine (&newi2pat, i2,
+                                                     &new_i2_notes);
+                 if (i2_code_number < 0)
+                   {
+                     undo_all ();
+                     return 0;
+                   }
+
+                 if (GET_CODE (newi2pat) == PARALLEL)
+                   for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--)
+                     if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER)
+                       {
+                         rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0);
+                         if (reg_overlap_mentioned_p (reg, newpat))
+                           {
+                             undo_all ();
+                             return 0;
+                           }
+                       }
+               }
+           }
+
+         insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+       }
     }
 
   /* If it still isn't recognized, fail and change things back the way they
@@ -4771,6 +4822,23 @@ find_split_point (rtx *loc, rtx insn, bool set_src)
 
     case PLUS:
     case MINUS:
+      /* Canonicalization can produce (minus A (mult B C)), where C is a
+        constant.  It may be better to try splitting (plus (mult B -C) A)
+        instead if this isn't a multiply by a power of two.  */
+      if (set_src && code == MINUS && GET_CODE (XEXP (x, 1)) == MULT
+         && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
+         && exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1))) < 0)
+       {
+         enum machine_mode mode = GET_MODE (x);
+         unsigned HOST_WIDE_INT this_int = INTVAL (XEXP (XEXP (x, 1), 1));
+         HOST_WIDE_INT other_int = trunc_int_for_mode (-this_int, mode);
+         SUBST (*loc, gen_rtx_PLUS (mode, gen_rtx_MULT (mode,
+                                                        XEXP (XEXP (x, 1), 0),
+                                                        GEN_INT (other_int)),
+                                    XEXP (x, 0)));
+         return find_split_point (loc, insn, set_src);
+       }
+
       /* Split at a multiply-accumulate instruction.  However if this is
          the SET_SRC, we likely do not have such an instruction and it's
          worthless to try this split.  */
@@ -9841,7 +9909,9 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
                  > GET_MODE_SIZE (GET_MODE (varop)))
              && (unsigned int) ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
                                  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
-                == mode_words)
+                == mode_words
+             && GET_MODE_CLASS (GET_MODE (varop)) == MODE_INT
+             && GET_MODE_CLASS (GET_MODE (SUBREG_REG (varop))) == MODE_INT)
            {
              varop = SUBREG_REG (varop);
              if (GET_MODE_SIZE (GET_MODE (varop)) > GET_MODE_SIZE (mode))