pa.c (pa_adjust_insn_length): dbra and movb insns which have their output in a FP register do not need adjustment.
* pa.c (pa_adjust_insn_length): dbra and movb insns which have their output in a FP register do not need adjustment. (output_cbranch, output_bb): Handle conditional jump to the following instruction. (output_dbra): New function extracted from dbra pattern. (output_movb): New function. (eq_neq_comparison_operator): New function. (movb_comparison_operator): New function. From-SVN: r4888
This commit is contained in:
parent
98b2d88783
commit
b1a275e1e0
|
@ -2543,10 +2543,12 @@ pa_adjust_insn_length (insn, length)
|
|||
&& ! forward_branch_p (insn))
|
||||
return 1;
|
||||
/* Adjust dbra insn with short backwards conditional branch with
|
||||
unfilled delay slot -- only for case where counter is in a register. */
|
||||
unfilled delay slot -- only for case where counter is in a
|
||||
general register register. */
|
||||
else if (GET_CODE (pat) == PARALLEL
|
||||
&& GET_CODE (XVECEXP (pat, 0, 1)) == SET
|
||||
&& GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
|
||||
&& ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
|
||||
&& length == 1
|
||||
&& ! forward_branch_p (insn))
|
||||
return 1;
|
||||
|
@ -3250,10 +3252,18 @@ output_cbranch (operands, nullify, length, negated, insn)
|
|||
rtx *operands;
|
||||
int nullify, length, negated;
|
||||
rtx insn;
|
||||
{
|
||||
{
|
||||
static char buf[100];
|
||||
int useskip = 0;
|
||||
|
||||
/* A conditional branch to the following instruction (eg the delay slot) is
|
||||
asking for a disaster. This can happen when not optimizing.
|
||||
|
||||
In such cases it is safe to emit nothing. */
|
||||
|
||||
if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
|
||||
return "";
|
||||
|
||||
/* If this is a long branch with its delay slot unfilled, set `nullify'
|
||||
as it can nullify the delay slot and save a nop. */
|
||||
if (length == 2 && dbr_sequence_length () == 0)
|
||||
|
@ -3343,10 +3353,18 @@ output_bb (operands, nullify, length, negated, insn, which)
|
|||
int nullify, length, negated;
|
||||
rtx insn;
|
||||
int which;
|
||||
{
|
||||
{
|
||||
static char buf[100];
|
||||
int useskip = 0;
|
||||
|
||||
/* A conditional branch to the following instruction (eg the delay slot) is
|
||||
asking for a disaster. I do not think this can happen as this pattern
|
||||
is only used when optimizing; jump optimization should eliminate the
|
||||
jump. But be prepared just in case. */
|
||||
|
||||
if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
|
||||
return "";
|
||||
|
||||
/* If this is a long branch with its delay slot unfilled, set `nullify'
|
||||
as it can nullify the delay slot and save a nop. */
|
||||
if (length == 2 && dbr_sequence_length () == 0)
|
||||
|
@ -3441,6 +3459,197 @@ output_bb (operands, nullify, length, negated, insn, which)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/* Return the output template for emitting a dbra type insn.
|
||||
|
||||
Note it may perform some output operations on its own before
|
||||
returning the final output string. */
|
||||
char *
|
||||
output_dbra (operands, insn, which_alternative)
|
||||
rtx *operands;
|
||||
rtx insn;
|
||||
int which_alternative;
|
||||
{
|
||||
|
||||
/* A conditional branch to the following instruction (eg the delay slot) is
|
||||
asking for a disaster. Be prepared! */
|
||||
|
||||
if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
|
||||
{
|
||||
if (which_alternative == 0)
|
||||
return "ldo %1(%0),%0";
|
||||
else if (which_alternative == 1)
|
||||
{
|
||||
output_asm_insn ("fstws %0,-16(0,%%r30)",operands);
|
||||
output_asm_insn ("ldw -16(0,%%r30),%4",operands);
|
||||
output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
|
||||
return "fldws -16(0,%%r30),%0";
|
||||
}
|
||||
else
|
||||
{
|
||||
output_asm_insn ("ldw %0,%4", operands);
|
||||
return "ldo %1(%4),%4\n\tstw %4,%0";
|
||||
}
|
||||
}
|
||||
|
||||
if (which_alternative == 0)
|
||||
{
|
||||
int nullify = INSN_ANNULLED_BRANCH_P (insn);
|
||||
int length = get_attr_length (insn);
|
||||
|
||||
/* If this is a long branch with its delay slot unfilled, set `nullify'
|
||||
as it can nullify the delay slot and save a nop. */
|
||||
if (length == 2 && dbr_sequence_length () == 0)
|
||||
nullify = 1;
|
||||
|
||||
/* If this is a short forward conditional branch which did not get
|
||||
its delay slot filled, the delay slot can still be nullified. */
|
||||
if (! nullify && length == 1 && dbr_sequence_length () == 0)
|
||||
nullify = forward_branch_p (insn);
|
||||
|
||||
/* Handle short versions first. */
|
||||
if (length == 1 && nullify)
|
||||
return "addib,%C2,n %1,%0,%3";
|
||||
else if (length == 1 && ! nullify)
|
||||
return "addib,%C2 %1,%0,%3";
|
||||
else if (length == 2)
|
||||
{
|
||||
/* Handle weird backwards branch with a fulled delay slot
|
||||
which is nullified. */
|
||||
if (dbr_sequence_length () != 0
|
||||
&& ! forward_branch_p (insn)
|
||||
&& nullify)
|
||||
return "addib,%N2,n %1,%0,.+12\n\tbl %3,0";
|
||||
|
||||
/* Handle normal cases. */
|
||||
if (nullify)
|
||||
return "addi,%N2 %1,%0,%0\n\tbl,n %3,0";
|
||||
else
|
||||
return "addi,%N2 %1,%0,%0\n\tbl %3,0";
|
||||
}
|
||||
else
|
||||
abort();
|
||||
}
|
||||
/* Deal with gross reload from FP register case. */
|
||||
else if (which_alternative == 1)
|
||||
{
|
||||
/* Move loop counter from FP register to MEM then into a GR,
|
||||
increment the GR, store the GR into MEM, and finally reload
|
||||
the FP register from MEM from within the branch's delay slot. */
|
||||
output_asm_insn ("fstws %0,-16(0,%%r30)\n\tldw -16(0,%%r30),%4",operands);
|
||||
output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
|
||||
if (get_attr_length (insn) == 6)
|
||||
return "comb,%S2 0,%4,%3\n\tfldws -16(0,%%r30),%0";
|
||||
else
|
||||
return "comclr,%B2 0,%4,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
|
||||
}
|
||||
/* Deal with gross reload from memory case. */
|
||||
else
|
||||
{
|
||||
/* Reload loop counter from memory, the store back to memory
|
||||
happens in the branch's delay slot. */
|
||||
output_asm_insn ("ldw %0,%4", operands);
|
||||
if (get_attr_length (insn) == 3)
|
||||
return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
|
||||
else
|
||||
return "addi,%N2 %1,%4,%0\n\tbl %3,0\n\tstw %4,%0";
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the output template for emitting a dbra type insn.
|
||||
|
||||
Note it may perform some output operations on its own before
|
||||
returning the final output string. */
|
||||
char *
|
||||
output_movb (operands, insn, which_alternative, reverse_comparison)
|
||||
rtx *operands;
|
||||
rtx insn;
|
||||
int which_alternative;
|
||||
int reverse_comparison;
|
||||
{
|
||||
|
||||
/* A conditional branch to the following instruction (eg the delay slot) is
|
||||
asking for a disaster. Be prepared! */
|
||||
|
||||
if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
|
||||
{
|
||||
if (which_alternative == 0)
|
||||
return "copy %1,%0";
|
||||
else if (which_alternative == 1)
|
||||
{
|
||||
output_asm_insn ("fstws %1,-16(0,%%r30)",operands);
|
||||
return "fldws -16(0,%%r30),%0";
|
||||
}
|
||||
else
|
||||
return "stw %1,%0";
|
||||
}
|
||||
|
||||
/* Support the second variant. */
|
||||
if (reverse_comparison)
|
||||
PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
|
||||
|
||||
if (which_alternative == 0)
|
||||
{
|
||||
int nullify = INSN_ANNULLED_BRANCH_P (insn);
|
||||
int length = get_attr_length (insn);
|
||||
|
||||
/* If this is a long branch with its delay slot unfilled, set `nullify'
|
||||
as it can nullify the delay slot and save a nop. */
|
||||
if (length == 2 && dbr_sequence_length () == 0)
|
||||
nullify = 1;
|
||||
|
||||
/* If this is a short forward conditional branch which did not get
|
||||
its delay slot filled, the delay slot can still be nullified. */
|
||||
if (! nullify && length == 1 && dbr_sequence_length () == 0)
|
||||
nullify = forward_branch_p (insn);
|
||||
|
||||
/* Handle short versions first. */
|
||||
if (length == 1 && nullify)
|
||||
return "movb,%C2,n %1,%0,%3";
|
||||
else if (length == 1 && ! nullify)
|
||||
return "movb,%C2 %1,%0,%3";
|
||||
else if (length == 2)
|
||||
{
|
||||
/* Handle weird backwards branch with a fulled delay slot
|
||||
which is nullified. */
|
||||
if (dbr_sequence_length () != 0
|
||||
&& ! forward_branch_p (insn)
|
||||
&& nullify)
|
||||
return "movb,%N2,n %1,%0,.+12\n\ttbl %3,0";
|
||||
|
||||
/* Handle normal cases. */
|
||||
if (nullify)
|
||||
return "or,%N2 %1,%%r0,%0\n\tbl,n %3,0";
|
||||
else
|
||||
return "or,%N2 %1,%%r0,%0\n\tbl %3,0";
|
||||
}
|
||||
else
|
||||
abort();
|
||||
}
|
||||
/* Deal with gross reload from FP register case. */
|
||||
else if (which_alternative == 1)
|
||||
{
|
||||
/* Move loop counter from FP register to MEM then into a GR,
|
||||
increment the GR, store the GR into MEM, and finally reload
|
||||
the FP register from MEM from within the branch's delay slot. */
|
||||
output_asm_insn ("fstws %1,-16(0,%%r30)",operands);
|
||||
if (get_attr_length (insn) == 3)
|
||||
return "comb,%S2 0,%1,%3\n\tfldws -16(0,%%r30),%0";
|
||||
else
|
||||
return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
|
||||
}
|
||||
/* Deal with gross reload from memory case. */
|
||||
else
|
||||
{
|
||||
/* Reload loop counter from memory, the store back to memory
|
||||
happens in the branch's delay slot. */
|
||||
if (get_attr_length (insn) == 2)
|
||||
return "comb,%S2 0,%1,%3\n\tstw %1,%0";
|
||||
else
|
||||
return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern struct obstack *saveable_obstack;
|
||||
|
||||
/* In HPUX 8.0's shared library scheme, special relocations are needed
|
||||
|
@ -3603,3 +3812,22 @@ forward_branch_p (insn)
|
|||
return (insn == label);
|
||||
}
|
||||
|
||||
/* Return 1 if OP is an equality comparison, else return 0. */
|
||||
int
|
||||
eq_neq_comparison_operator (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
|
||||
}
|
||||
|
||||
/* Return 1 if OP is an operator suitable for use in a movb instruction. */
|
||||
int
|
||||
movb_comparison_operator (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
return (GET_CODE (op) == EQ || GET_CODE (op) == NE
|
||||
|| GET_CODE (op) == LT || GET_CODE (op) == GE);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue