Commit ab11fb42 by John David Anglin Committed by John David Anglin

re PR target/55195 (shorten_branches generates incorrect forward branch distances)

	PR target/55195
	* config/pa/pa.md (type): Add sibcall and sh_func_adrs insn types.
	(in_branch_delay): Don't allow sibcall or sh_func_adrs insns.
	(in_nullified_branch_delay): Likewise.
	(in_call_delay): Likewise.
	Define delay for sibcall insns.  Adjust Z3 and Z4 insn reservations for
	new types.  Add opaque cond to mark all calls, sibcalls, dyncalls and
	the $$sh_func_adrs call as variable.  Update type of sibcalls and
	$$sh_func_adrs call.
	* config/pa/pa.c (pa_adjust_insn_length): Revise to return updated
	length instead of adjustment.  Handle negative and undefined call
	adjustments for insn_default_length.  Remove adjustment for millicode
	insn with unfilled delay slot.
	(pa_output_millicode_call): Update for revised millicode length.
	* config/pa/pa.h (ADJUST_INSN_LENGTH): Revise to set LENGTH.

From-SVN: r193464
parent 769b084b
2012-11-12 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/55195
* config/pa/pa.md (attr type): Add sibcall and sh_func_adrs insn types.
(in_branch_delay): Don't allow sibcall or sh_func_adrs insns.
(in_nullified_branch_delay): Likewise.
(in_call_delay): Likewise.
Define delay for sibcall insns. Adjust Z3 and Z4 insn reservations for
new types. Add opaque cond to mark all calls, sibcalls, dyncalls and
the $$sh_func_adrs call as variable. Update type of sibcalls and
$$sh_func_adrs call.
* config/pa/pa.c (pa_adjust_insn_length): Revise to return updated
length instead of adjustment. Handle negative and undefined call
adjustments for insn_default_length. Remove adjustment for millicode
insn with unfilled delay slot.
(pa_output_millicode_call): Update for revised millicode length.
* config/pa/pa.h (ADJUST_INSN_LENGTH): Revise to set LENGTH.
2012-11-12 Eric Botcazou <ebotcazou@adacore.com> 2012-11-12 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-ccp.c (dump_lattice_value) <CONSTANT>: Fix duplication. * tree-ssa-ccp.c (dump_lattice_value) <CONSTANT>: Fix duplication.
...@@ -4880,12 +4880,9 @@ pa_issue_rate (void) ...@@ -4880,12 +4880,9 @@ pa_issue_rate (void)
/* Return any length adjustment needed by INSN which already has its length /* Return any length plus adjustment needed by INSN which already has
computed as LENGTH. Return zero if no adjustment is necessary. its length computed as LENGTH. Return LENGTH if no adjustment is
necessary.
For the PA: function calls, millicode calls, and backwards short
conditional branches with unfilled delay slots need an adjustment by +1
(to account for the NOP which will be inserted into the instruction stream).
Also compute the length of an inline block move here as it is too Also compute the length of an inline block move here as it is too
complicated to express as a length attribute in pa.md. */ complicated to express as a length attribute in pa.md. */
...@@ -4894,19 +4891,40 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4894,19 +4891,40 @@ pa_adjust_insn_length (rtx insn, int length)
{ {
rtx pat = PATTERN (insn); rtx pat = PATTERN (insn);
/* If length is negative or undefined, provide initial length. */
if ((unsigned int) length >= INT_MAX)
{
if (GET_CODE (pat) == SEQUENCE)
insn = XVECEXP (pat, 0, 0);
switch (get_attr_type (insn))
{
case TYPE_MILLI:
length = pa_attr_length_millicode_call (insn);
break;
case TYPE_CALL:
length = pa_attr_length_call (insn, 0);
break;
case TYPE_SIBCALL:
length = pa_attr_length_call (insn, 1);
break;
case TYPE_DYNCALL:
length = pa_attr_length_indirect_call (insn);
break;
case TYPE_SH_FUNC_ADRS:
length = pa_attr_length_millicode_call (insn) + 20;
break;
default:
gcc_unreachable ();
}
}
/* Jumps inside switch tables which have unfilled delay slots need /* Jumps inside switch tables which have unfilled delay slots need
adjustment. */ adjustment. */
if (GET_CODE (insn) == JUMP_INSN if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (pat) == PARALLEL && GET_CODE (pat) == PARALLEL
&& get_attr_type (insn) == TYPE_BTABLE_BRANCH) && get_attr_type (insn) == TYPE_BTABLE_BRANCH)
return 4; length += 4;
/* Millicode insn with an unfilled delay slot. */
else if (GET_CODE (insn) == INSN
&& GET_CODE (pat) != SEQUENCE
&& GET_CODE (pat) != USE
&& GET_CODE (pat) != CLOBBER
&& get_attr_type (insn) == TYPE_MILLI)
return 4;
/* Block move pattern. */ /* Block move pattern. */
else if (GET_CODE (insn) == INSN else if (GET_CODE (insn) == INSN
&& GET_CODE (pat) == PARALLEL && GET_CODE (pat) == PARALLEL
...@@ -4915,7 +4933,7 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4915,7 +4933,7 @@ pa_adjust_insn_length (rtx insn, int length)
&& GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode) && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
return compute_movmem_length (insn) - 4; length += compute_movmem_length (insn) - 4;
/* Block clear pattern. */ /* Block clear pattern. */
else if (GET_CODE (insn) == INSN else if (GET_CODE (insn) == INSN
&& GET_CODE (pat) == PARALLEL && GET_CODE (pat) == PARALLEL
...@@ -4923,7 +4941,7 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4923,7 +4941,7 @@ pa_adjust_insn_length (rtx insn, int length)
&& GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
&& XEXP (XVECEXP (pat, 0, 0), 1) == const0_rtx && XEXP (XVECEXP (pat, 0, 0), 1) == const0_rtx
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode) && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode)
return compute_clrmem_length (insn) - 4; length += compute_clrmem_length (insn) - 4;
/* Conditional branch with an unfilled delay slot. */ /* Conditional branch with an unfilled delay slot. */
else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn)) else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
{ {
...@@ -4932,11 +4950,11 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4932,11 +4950,11 @@ pa_adjust_insn_length (rtx insn, int length)
&& length == 4 && length == 4
&& JUMP_LABEL (insn) != NULL_RTX && JUMP_LABEL (insn) != NULL_RTX
&& ! forward_branch_p (insn)) && ! forward_branch_p (insn))
return 4; length += 4;
else if (GET_CODE (pat) == PARALLEL else if (GET_CODE (pat) == PARALLEL
&& get_attr_type (insn) == TYPE_PARALLEL_BRANCH && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
&& length == 4) && length == 4)
return 4; length += 4;
/* Adjust dbra insn with short backwards conditional branch with /* Adjust dbra insn with short backwards conditional branch with
unfilled delay slot -- only for case where counter is in a unfilled delay slot -- only for case where counter is in a
general register register. */ general register register. */
...@@ -4946,11 +4964,9 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4946,11 +4964,9 @@ pa_adjust_insn_length (rtx insn, int length)
&& ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0)) && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
&& length == 4 && length == 4
&& ! forward_branch_p (insn)) && ! forward_branch_p (insn))
return 4; length += 4;
else
return 0;
} }
return 0; return length;
} }
/* Implement the TARGET_PRINT_OPERAND_PUNCT_VALID_P hook. */ /* Implement the TARGET_PRINT_OPERAND_PUNCT_VALID_P hook. */
...@@ -7511,15 +7527,13 @@ pa_output_millicode_call (rtx insn, rtx call_dest) ...@@ -7511,15 +7527,13 @@ pa_output_millicode_call (rtx insn, rtx call_dest)
/* Handle the common case where we are sure that the branch will /* Handle the common case where we are sure that the branch will
reach the beginning of the $CODE$ subspace. The within reach reach the beginning of the $CODE$ subspace. The within reach
form of the $$sh_func_adrs call has a length of 28. Because form of the $$sh_func_adrs call has a length of 28. Because it
it has an attribute type of multi, it never has a nonzero has an attribute type of sh_func_adrs, it never has a nonzero
sequence length. The length of the $$sh_func_adrs is the same sequence length (i.e., the delay slot is never filled). */
as certain out of reach PIC calls to other routines. */
if (!TARGET_LONG_CALLS if (!TARGET_LONG_CALLS
&& ((seq_length == 0 && (attr_length == 8
&& (attr_length == 12 || (attr_length == 28
|| (attr_length == 28 && get_attr_type (insn) == TYPE_MULTI))) && get_attr_type (insn) == TYPE_SH_FUNC_ADRS)))
|| (seq_length != 0 && attr_length == 8)))
{ {
output_asm_insn ("{bl|b,l} %0,%2", xoperands); output_asm_insn ("{bl|b,l} %0,%2", xoperands);
} }
......
...@@ -1273,8 +1273,8 @@ do { \ ...@@ -1273,8 +1273,8 @@ do { \
/* Handling the special cases is going to get too complicated for a macro, /* Handling the special cases is going to get too complicated for a macro,
just call `pa_adjust_insn_length' to do the real work. */ just call `pa_adjust_insn_length' to do the real work. */
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ #define ADJUST_INSN_LENGTH(INSN, LENGTH) \
LENGTH += pa_adjust_insn_length (INSN, LENGTH); ((LENGTH) = pa_adjust_insn_length ((INSN), (LENGTH)))
/* Millicode insns are actually function calls with some special /* Millicode insns are actually function calls with some special
constraints on arguments and register usage. constraints on arguments and register usage.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment