summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2001-07-23 16:00:06 +0000
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2001-07-23 16:00:06 +0000
commite95ebfe01248c88832e21726accb01321f20a61e (patch)
treeef220d1f1710bdd39aaddf1da18b1709fc794695
parent40be2320a3646ff02c2caa7459eaccdce2b5c2f4 (diff)
downloadgcc-e95ebfe01248c88832e21726accb01321f20a61e.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44269 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c37
-rw-r--r--gcc/config/sh/sh.h3
-rw-r--r--gcc/doc/tm.texi11
-rw-r--r--gcc/reorg.c8
6 files changed, 69 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 642408d7876..b49083981f8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+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
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 1200ba2f41a..f11f2e2f74b 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -98,6 +98,7 @@ extern void expand_df_unop PARAMS ((rtx (*)(rtx, rtx, rtx), rtx *));
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));
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 18e6379fd60..ec09d08b666 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -5515,3 +5515,40 @@ static rtx mark_constant_pool_use (x)
return lab;
}
+
+/* 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;
+}
+
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index f72c07c9fbe..cc17258353f 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2421,6 +2421,9 @@ do { \
#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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index b5d8ba92d4d..81a55828c2e 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8681,4 +8681,15 @@ ignored. This function should return the result of the call to the
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
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 1f26e7e3751..3177e7117dd 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -1272,6 +1272,14 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
|| ! 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);