/* Optimize by combining instructions for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
assignments later. */
if (regno >= FIRST_PSEUDO_REGISTER
|| asm_noperands (PATTERN (use_insn)) < 0)
- LOG_LINKS (use_insn) =
- alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
+ {
+ /* Don't add duplicate links between instructions. */
+ rtx links;
+ for (links = LOG_LINKS (use_insn); links;
+ links = XEXP (links, 1))
+ if (insn == XEXP (links, 0))
+ break;
+
+ if (!links)
+ LOG_LINKS (use_insn) =
+ alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
+ }
}
next_use[regno] = NULL_RTX;
}
if (i1 && GET_CODE (newpat) != CLOBBER)
{
- /* Before we can do this substitution, we must redo the test done
- above (see detailed comments there) that ensures that I1DEST
- isn't mentioned in any SETs in NEWPAT that are field assignments. */
-
- if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX,
- 0, (rtx*) 0))
+ /* Check that an autoincrement side-effect on I1 has not been lost.
+ This happens if I1DEST is mentioned in I2 and dies there, and
+ has disappeared from the new pattern. */
+ if ((FIND_REG_INC_NOTE (i1, NULL_RTX) != 0
+ && !i1_feeds_i3
+ && dead_or_set_p (i2, i1dest)
+ && !reg_overlap_mentioned_p (i1dest, newpat))
+ /* Before we can do this substitution, we must redo the test done
+ above (see detailed comments there) that ensures that I1DEST
+ isn't mentioned in any SETs in NEWPAT that are field assignments. */
+ || !combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX, 0, 0))
{
undo_all ();
return 0;
&& OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
return &XEXP (XEXP (x, 0), 0);
}
+
+ /* If we have a PLUS whose first operand is complex, try computing it
+ separately by making a split there. */
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && ! memory_address_p (GET_MODE (x), XEXP (x, 0))
+ && ! OBJECT_P (XEXP (XEXP (x, 0), 0))
+ && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
+ && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
+ return &XEXP (XEXP (x, 0), 0);
break;
case SET:
/* Look for cases where we have (abs x) or (neg (abs X)). */
if (GET_MODE_CLASS (mode) == MODE_INT
+ && comparison_p
+ && XEXP (cond, 1) == const0_rtx
&& GET_CODE (false_rtx) == NEG
&& rtx_equal_p (true_rtx, XEXP (false_rtx, 0))
- && comparison_p
&& rtx_equal_p (true_rtx, XEXP (cond, 0))
&& ! side_effects_p (true_rtx))
switch (true_code)
return 0;
}
-struct tree_opt_pass pass_combine =
+struct rtl_opt_pass pass_combine =
{
+ {
+ RTL_PASS,
"combine", /* name */
gate_handle_combine, /* gate */
rest_of_handle_combine, /* execute */
TODO_dump_func |
TODO_df_finish | TODO_verify_rtl_sharing |
TODO_ggc_collect, /* todo_flags_finish */
- 'c' /* letter */
+ }
};