aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2004-07-13 15:14:06 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2004-07-13 13:14:06 +0000
commit1b3c2c2d72f89d67c2a085bbf5cda557d755a2dc (patch)
tree9a7f67d12d03fd432de176c0261de308dc0a1cee /gcc
parent883d9e0c3f8da4b06c0fdef2c4e0db8d1c7c7a19 (diff)
downloadgcc-1b3c2c2d72f89d67c2a085bbf5cda557d755a2dc.zip
gcc-1b3c2c2d72f89d67c2a085bbf5cda557d755a2dc.tar.gz
gcc-1b3c2c2d72f89d67c2a085bbf5cda557d755a2dc.tar.bz2
re PR target/13926 (GCC generates jumps that are too large to fit in word displacement field)
PR target/13926 * config/sparc/sparc-protos.h (output_ubranch): New prototype. * config/sparc/sparc.c (output_ubranch): New function. * config/sparc/sparc.md (jump pattern): Use it. From-SVN: r84621
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c67
-rw-r--r--gcc/config/sparc/sparc.md19
4 files changed, 73 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4191d04..0eb6fac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2004-07-13 Eric Botcazou <ebotcazou@libertysurf.fr>
+ PR target/13926
+ * config/sparc/sparc-protos.h (output_ubranch): New prototype.
+ * config/sparc/sparc.c (output_ubranch): New function.
+ * config/sparc/sparc.md (jump pattern): Use it.
+
+2004-07-13 Eric Botcazou <ebotcazou@libertysurf.fr>
+
PR target/16494
* config/sparc/sparc.c (output_cbranch): Properly guard
the code handling far branches with TARGET_V9.
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 8a541b3..c28c318 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -82,6 +82,7 @@ extern void sparc_emit_set_const64 (rtx, rtx);
extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
extern int sparc_splitdi_legitimate (rtx, rtx);
extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
+extern const char *output_ubranch (rtx, int, rtx);
extern const char *output_cbranch (rtx, rtx, int, int, int, int, rtx);
extern const char *output_return (rtx);
extern const char *output_sibcall (rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 199ae0a..5c2188a 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -6085,18 +6085,77 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
return build_fold_indirect_ref (addr);
}
+/* Return the string to output an unconditional branch to LABEL, which is
+ the operand number of the label.
+
+ DEST is the destination insn (i.e. the label), INSN is the source. */
+
+const char *
+output_ubranch (rtx dest, int label, rtx insn)
+{
+ static char string[64];
+ bool noop = false;
+ char *p;
+
+ /* TurboSPARC is reported to have problems with
+ with
+ foo: b,a foo
+ i.e. an empty loop with the annul bit set. The workaround is to use
+ foo: b foo; nop
+ instead. */
+
+ if (! TARGET_V9 && flag_delayed_branch
+ && (INSN_ADDRESSES (INSN_UID (dest))
+ == INSN_ADDRESSES (INSN_UID (insn))))
+ {
+ strcpy (string, "b\t");
+ noop = true;
+ }
+ else
+ {
+ bool v9_form = false;
+
+ if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
+ {
+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta >= -260000 && delta < 260000)
+ v9_form = true;
+ }
+
+ if (v9_form)
+ strcpy (string, "ba%*,pt\t%%xcc, ");
+ else
+ strcpy (string, "b%*\t");
+ }
+
+ p = strchr (string, '\0');
+ *p++ = '%';
+ *p++ = 'l';
+ *p++ = '0' + label;
+ *p++ = '%';
+ if (noop)
+ *p++ = '#';
+ else
+ *p++ = '(';
+ *p = '\0';
+
+ return string;
+}
+
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label. OP is the conditional expression.
XEXP (OP, 0) is assumed to be a condition code register (integer or
floating point) and its mode specifies what kind of comparison we made.
+ DEST is the destination insn (i.e. the label), INSN is the source.
+
REVERSED is nonzero if we should reverse the sense of the comparison.
ANNUL is nonzero if we should generate an annulling branch.
- NOOP is nonzero if we have to follow this branch by a noop.
-
- INSN, if set, is the insn. */
+ NOOP is nonzero if we have to follow this branch by a noop. */
const char *
output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
@@ -6557,6 +6616,8 @@ sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
operand number of the reg. OP is the conditional expression. The mode
of REG says what kind of comparison we made.
+ DEST is the destination insn (i.e. the label), INSN is the source.
+
REVERSED is nonzero if we should reverse the sense of the comparison.
ANNUL is nonzero if we should generate an annulling branch.
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index fecce78..9446cbe 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7278,27 +7278,10 @@
[(set_attr "type" "shift")])
;; Unconditional and other jump instructions
-;; On the SPARC, by setting the annul bit on an unconditional branch, the
-;; following insn is never executed. This saves us a nop. Dbx does not
-;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
-{
- /* TurboSPARC is reported to have problems with
- with
- foo: b,a foo
- i.e. an empty loop with the annul bit set. The workaround is to use
- foo: b foo; nop
- instead. */
-
- if (! TARGET_V9 && flag_delayed_branch
- && (INSN_ADDRESSES (INSN_UID (operands[0]))
- == INSN_ADDRESSES (INSN_UID (insn))))
- return "b\t%l0%#";
- else
- return TARGET_V9 ? "ba%*,pt\t%%xcc, %l0%(" : "b%*\t%l0%(";
-}
+ "* return output_ubranch (operands[0], 0, insn);"
[(set_attr "type" "uncond_branch")])
(define_expand "tablejump"