* doc/tm.texi (MD_CAN_REDIRECT_BRANCH): New macro.
* config/sh/sh.h (MD_CAN_REDIRECT_BRANCH): New macro.
* config/sh/sh.c (sh_can_redirect_branch): New function.
* config/sh/sh-protos.h (sh_can_redirect_branch): Declare.
* reorg.c (steal_delay_list_from_target): Use
MD_CAN_REDIRECT_BRANCH to see if redirection is possible.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44269
138bc75d-0d04-0410-961f-
82ee72b054a4
+2001-07-13 Andrew Haley <aph@redhat.com>
+
+ * doc/tm.texi (MD_CAN_REDIRECT_BRANCH): New macro.
+ * config/sh/sh.h (MD_CAN_REDIRECT_BRANCH): New macro.
+ * config/sh/sh.c (sh_can_redirect_branch): New function.
+ * config/sh/sh-protos.h (sh_can_redirect_branch): Declare.
+ * reorg.c (steal_delay_list_from_target): Use
+ MD_CAN_REDIRECT_BRANCH to see if redirection is possible.
+
Mon Jul 23 17:20:18 CEST 2001 Jan Hubicka <jh@suse.cz>
* flow.c (try_simplify_condjump): Unlink insn chain on
extern void expand_df_binop PARAMS ((rtx (*)(rtx, rtx, rtx, rtx), rtx *));
extern void expand_fp_branch PARAMS ((rtx (*)(void), rtx (*)(void)));
extern int sh_insn_length_adjustment PARAMS ((rtx));
+extern int sh_can_redirect_branch PARAMS ((rtx, rtx));
#ifdef TREE_CODE
extern void sh_va_start PARAMS ((int, tree, rtx));
extern rtx sh_va_arg PARAMS ((tree, tree));
return lab;
}
+\f
+/* Return true if it's possible to redirect BRANCH1 to the destination
+ of an unconditional jump BRANCH2. We only want to do this if the
+ resulting branch will have a short displacement. */
+int
+sh_can_redirect_branch (branch1, branch2)
+ rtx branch1;
+ rtx branch2;
+{
+ if (flag_expensive_optimizations && simplejump_p (branch2))
+ {
+ rtx dest = XEXP (SET_SRC (single_set (branch2)), 0);
+ rtx insn;
+ int distance;
+
+ for (distance = 0, insn = NEXT_INSN (branch1);
+ insn && distance < 256;
+ insn = PREV_INSN (insn))
+ {
+ if (insn == dest)
+ return 1;
+ else
+ distance += get_attr_length (insn);
+ }
+ for (distance = 0, insn = NEXT_INSN (branch1);
+ insn && distance < 256;
+ insn = NEXT_INSN (insn))
+ {
+ if (insn == dest)
+ return 1;
+ else
+ distance += get_attr_length (insn);
+ }
+ }
+ return 0;
+}
+
#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \
fpscr_set_from_mem ((MODE), (HARD_REGS_LIVE))
+#define MD_CAN_REDIRECT_BRANCH(INSN, SEQ) \
+ sh_can_redirect_branch ((INSN), (SEQ))
+
#define DWARF_LINE_MIN_INSTR_LENGTH 2
/* SH constant pool breaks the devices in crtstuff.c to control section
built-in function.
@end deftypefn
+@findex MD_CAN_REDIRECT_BRANCH
+@item MD_CAN_REDIRECT_BRANCH(@var{branch1}, @var{branch2})
+
+Take a branch insn in @var{branch1} and a another in @var{branch2}.
+Return true if redirecting @var{branch1} to the destination of
+@var{branch2} is possible.
+
+On some targets, branches may have a limited range. Optimizing the
+filling of delay slots can result in branches being redirected, and this
+may in turn cause a branch offset to overflow.
+
@end table
|| ! single_set (XVECEXP (seq, 0, 0)))
return delay_list;
+#ifdef MD_CAN_REDIRECT_BRANCH
+ /* On some targets, branches with delay slots can have a limited
+ displacement. Give the back end a chance to tell us we can't do
+ this. */
+ if (! MD_CAN_REDIRECT_BRANCH (insn, XVECEXP (seq, 0, 0)))
+ return delay_list;
+#endif
+
for (i = 1; i < XVECLEN (seq, 0); i++)
{
rtx trial = XVECEXP (seq, 0, i);