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
This commit is contained in:
parent
883d9e0c3f
commit
1b3c2c2d72
@ -1,3 +1,10 @@
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user