#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"
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];
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 *))
;
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.
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;
{
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)
#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)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c -= '0';
- if (c < operand_number && likely_spilled[c])
+ if (c < operand_number && likely_spilled[(unsigned char) c])
break;
matchp->with[operand_number] = c;
any_matches = 1;
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;
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;
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')
}
}
-/* 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 ()
{