Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This module looks for cases where matching constraints would force
static int optimize_reg_copy_1 PARAMS ((rtx, rtx, rtx));
static void optimize_reg_copy_2 PARAMS ((rtx, rtx, rtx));
static void optimize_reg_copy_3 PARAMS ((rtx, rtx, rtx));
-static rtx gen_add3_insn PARAMS ((rtx, rtx, rtx));
static void copy_src_to_dest PARAMS ((rtx, rtx, rtx, int));
static int *regmove_bb_head;
static int try_auto_increment PARAMS ((rtx, rtx, rtx, rtx, HOST_WIDE_INT, int));
static int find_matches PARAMS ((rtx, struct match *));
-static void replace_in_call_usage PARAMS ((rtx *, int, rtx, rtx));
+static void replace_in_call_usage PARAMS ((rtx *, unsigned int, rtx, rtx));
static int fixup_match_1 PARAMS ((rtx, rtx, rtx, rtx, rtx, int, int, int, FILE *))
;
static int reg_is_remote_constant_p PARAMS ((rtx, rtx, rtx));
&& ! CLASS_LIKELY_SPILLED_P (class1)));
}
-/* 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_data[icode].operand[0].predicate)
- (r0, insn_data[icode].operand[0].mode))
- || ! ((*insn_data[icode].operand[1].predicate)
- (r1, insn_data[icode].operand[1].mode))
- || ! ((*insn_data[icode].operand[2].predicate)
- (c, insn_data[icode].operand[2].mode)))
- return NULL_RTX;
-
- return (GEN_FCN (icode) (r0, r1, c));
-}
-
-
/* INC_INSN is an instruction that adds INCREMENT to REG.
Try to fold INC_INSN as a post/pre in/decrement into INSN.
Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src.
int sregno = REGNO (src);
int dregno = REGNO (dest);
- /* We don't want to mess with hard regs if register classes are small. */
+ /* We don't want to mess with hard regs if register classes are small. */
if (sregno == dregno
|| (SMALL_REGISTER_CLASSES
&& (sregno < FIRST_PSEUDO_REGISTER
if (recog_data.operand[match_no] != SET_DEST (set))
continue;
- /* If the operands already match, then there is nothing to do. */
+ /* If the operands already match, then there is nothing to do. */
if (operands_match_p (src, dst))
continue;
if (! regclass_compatible_p (src_class, dst_class))
continue;
+ if (GET_MODE (src) != GET_MODE (dst))
+ continue;
+
if (fixup_match_1 (insn, set, src, src_subreg, dst, pass,
op_no, match_no,
regmove_dump_file))
|| RTX_UNCHANGING_P (dst))
continue;
- /* If the operands already match, then there is nothing to do. */
+ /* If the operands already match, then there is nothing to do. */
if (operands_match_p (src, dst))
continue;
if (! set)
continue;
+ /* Note that single_set ignores parts of a parallel set for
+ which one of the destinations is REG_UNUSED. We can't
+ handle that here, since we can wind up rewriting things
+ such that a single register is set twice within a single
+ parallel. */
+ if (reg_set_p (src, insn))
+ continue;
+
/* match_no/dst must be a write-only operand, and
operand_operand/src must be a read-only operand. */
if (match.use[op_no] != READ
static void
replace_in_call_usage (loc, dst_reg, src, insn)
rtx *loc;
- int dst_reg;
+ unsigned int dst_reg;
rtx src;
rtx insn;
{
{
/* ??? We can't scan past the end of a basic block without updating
the register lifetime info
- (REG_DEAD/basic_block_live_at_start). */
+ (REG_DEAD/basic_block_live_at_start). */
if (perhaps_ends_bb_p (q))
break;
else if (! INSN_P (q))