OSDN Git Service

Undo June 11th change
[pf3gnuchains/gcc-fork.git] / gcc / regmove.c
index 3f85f7b..ee56db5 100644 (file)
@@ -30,8 +30,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <varargs.h>
 #endif
 
-/* Must precede rtl.h for FFS.  */
-#include <stdio.h>
+/* stdio.h must precede rtl.h for FFS.  */
+#include "system.h"
 
 #include "rtl.h"
 #include "insn-config.h"
@@ -47,6 +47,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 static int optimize_reg_copy_1 PROTO((rtx, rtx, rtx));
 static void optimize_reg_copy_2        PROTO((rtx, rtx, rtx));
 static void optimize_reg_copy_3        PROTO((rtx, rtx, rtx));
+static rtx gen_add3_insn       PROTO((rtx, rtx, rtx));
 
 struct match {
   int with[MAX_RECOG_OPERANDS];
@@ -55,6 +56,9 @@ struct match {
   int early_clobber[MAX_RECOG_OPERANDS];
 };
 
+#ifdef AUTO_INC_DEC
+static int try_auto_increment PROTO((rtx, rtx, rtx, rtx, HOST_WIDE_INT, int));
+#endif
 static int find_matches PROTO((rtx, struct match *));
 static int fixup_match_1 PROTO((rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *))
 ;
@@ -62,6 +66,23 @@ static int reg_is_remote_constant_p PROTO((rtx, rtx, rtx));
 static int stable_but_for_p PROTO((rtx, rtx, rtx));
 static int loop_depth;
 
+/* Generate and return an insn body to add r1 and c,
+   storing the result in r0.  */
+static rtx
+gen_add3_insn (r0, r1, c)
+     rtx r0, r1, c;
+{
+  int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
+
+    if (icode == CODE_FOR_nothing
+      || ! (*insn_operand_predicate[icode][0]) (r0, insn_operand_mode[icode][0])
+      || ! (*insn_operand_predicate[icode][1]) (r1, insn_operand_mode[icode][1])
+      || ! (*insn_operand_predicate[icode][2]) (c, insn_operand_mode[icode][2]))
+    return NULL_RTX;
+
+  return (GEN_FCN (icode) (r0, r1, c));
+}
+
 #ifdef AUTO_INC_DEC
 
 /* INC_INSN is an instruction that adds INCREMENT to REG.
@@ -567,8 +588,24 @@ reg_is_remote_constant_p (reg, insn, first)
   return 0;
 }
 
+/* INSN is adding a CONST_INT to a REG.  We search backwards looking for
+   another add immediate instruction with the same source and dest registers,
+   and if we find one, we change INSN to an increment, and return 1.  If
+   no changes are made, we return 0.
+
+   This changes
+     (set (reg100) (plus reg1 offset1))
+     ...
+     (set (reg100) (plus reg1 offset2))
+   to
+     (set (reg100) (plus reg1 offset1))
+     ...
+     (set (reg100) (plus reg100 offset2-offset1))  */
+
+/* ??? What does this comment mean?  */
 /* cse disrupts preincrement / postdecrement squences when it finds a
    hard register as ultimate source, like the frame pointer.  */
+
 int
 fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
      rtx insn, dst, src, offset;
@@ -620,8 +657,9 @@ fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
         {
          HOST_WIDE_INT newconst
            = INTVAL (offset) - INTVAL (XEXP (SET_SRC (pset), 1));
-         if (validate_change (insn, &PATTERN (insn),
-                              gen_addsi3 (dst, dst, GEN_INT (newconst)), 0))
+         rtx add = gen_add3_insn (dst, dst, GEN_INT (newconst));
+
+         if (add && validate_change (insn, &PATTERN (insn), add, 0))
            {
              /* Remove the death note for DST from DST_DEATH.  */
              if (dst_death)
@@ -1140,6 +1178,11 @@ regmove_optimize (f, nregs, regmove_dump_file)
 #endif /* REGISTER_CONSTRAINTS */
 }
 
+/* Returns the INSN_CODE for INSN if its pattern has matching constraints for
+   any operand.  Returns -1 if INSN can't be recognized, or if the alternative
+   can't be determined.
+
+   Initialize the info in MATCHP based on the constraints.  */
 
 static int
 find_matches (insn, matchp)
@@ -1344,7 +1387,7 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
                     it is inside an EH region.  There is no easy way to tell,
                     so we just always break when we see a CALL_INSN if
                     flag_exceptions is nonzero.  */
-                 if (flag_exceptions && GET_CODE (p) == CALL_INSN)
+                 if (flag_exceptions && GET_CODE (q) == CALL_INSN)
                    {
                      q = 0;
                      break;
@@ -1519,7 +1562,7 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
                 it is inside an EH region.  There is no easy way to tell,
                 so we just always break when we see a CALL_INSN if
                 flag_exceptions is nonzero.  */
-             if (flag_exceptions && GET_CODE (p) == CALL_INSN)
+             if (flag_exceptions && GET_CODE (q) == CALL_INSN)
                {
                  q = 0;
                  break;
@@ -1603,7 +1646,7 @@ fixup_match_1 (insn, set, src, src_subreg, dst, backward, operand_number,
             is inside an EH region.  There is no easy way to tell so we
             just always break when we see a CALL_INSN if flag_exceptions
             is nonzero.  */
-         if (flag_exceptions && GET_CODE (p) == CALL_INSN)
+         if (flag_exceptions && GET_CODE (q) == CALL_INSN)
            break;
 
          if (GET_RTX_CLASS (GET_CODE (q)) != 'i')
@@ -1708,7 +1751,10 @@ stable_but_for_p (x, src, dst)
     }
 }
 
-/* Test if regmove seems profitable for this target.  */
+/* Test if regmove seems profitable for this target.  Regmove is useful only
+   if some common patterns are two address, i.e. require matching constraints,
+   so we check that condition here.  */
+
 int
 regmove_profitable_p ()
 {