Commit 16923e7b by John David Anglin Committed by John David Anglin

re PR target/46915 (Wrong code is generated for conditional branch followed by zero length asm)

	PR target/46915
	* config/pa/pa.c (branch_to_delay_slot_p): Use next_active_insn instead
	of next_real_insn.  Search forward checking for both ASM_INPUT and
	ASM_OPERANDS asms until exit condition is found.
	(branch_needs_nop_p): Likewise.
	(use_skip_p): New function.
	(output_cbranch): Use use_skip_p.
	(output_bb, output_bvb): Likewise.

From-SVN: r168026
parent c50ebc73
2010-12-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/46915
* config/pa/pa.c (branch_to_delay_slot_p): Use next_active_insn instead
of next_real_insn. Search forward checking for both ASM_INPUT and
ASM_OPERANDS asms until exit condition is found.
(branch_needs_nop_p): Likewise.
(use_skip_p): New function.
(output_cbranch): Use use_skip_p.
(output_bb, output_bvb): Likewise.
2010-12-18 Kai Tietz <kai.tietz@onevision.com> 2010-12-18 Kai Tietz <kai.tietz@onevision.com>
PR target/36834 PR target/36834
...@@ -6188,35 +6188,92 @@ pa_scalar_mode_supported_p (enum machine_mode mode) ...@@ -6188,35 +6188,92 @@ pa_scalar_mode_supported_p (enum machine_mode mode)
} }
/* Return TRUE if INSN, a jump insn, has an unfilled delay slot and /* Return TRUE if INSN, a jump insn, has an unfilled delay slot and
it branches to the next real instruction. Otherwise, return FALSE. */ it branches into the delay slot. Otherwise, return FALSE. */
static bool static bool
branch_to_delay_slot_p (rtx insn) branch_to_delay_slot_p (rtx insn)
{ {
rtx jump_insn;
if (dbr_sequence_length ()) if (dbr_sequence_length ())
return FALSE; return FALSE;
return next_real_insn (JUMP_LABEL (insn)) == next_real_insn (insn); jump_insn = next_active_insn (JUMP_LABEL (insn));
while (insn)
{
insn = next_active_insn (insn);
if (jump_insn == insn)
return TRUE;
/* We can't rely on the length of asms. So, we return FALSE when
the branch is followed by an asm. */
if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX
|| get_attr_length (insn) > 0)
break;
}
return FALSE;
} }
/* Return TRUE if INSN, a jump insn, needs a nop in its delay slot. /* Return TRUE if INSN, a forward jump insn, needs a nop in its delay slot.
This occurs when INSN has an unfilled delay slot and is followed This occurs when INSN has an unfilled delay slot and is followed
by an ASM_INPUT. Disaster can occur if the ASM_INPUT is empty and by an asm. Disaster can occur if the asm is empty and the jump
the jump branches into the delay slot. So, we add a nop in the delay branches into the delay slot. So, we add a nop in the delay slot
slot just to be safe. This messes up our instruction count, but we when this occurs. */
don't know how big the ASM_INPUT insn is anyway. */
static bool static bool
branch_needs_nop_p (rtx insn) branch_needs_nop_p (rtx insn)
{ {
rtx next_insn; rtx jump_insn;
if (dbr_sequence_length ()) if (dbr_sequence_length ())
return FALSE; return FALSE;
next_insn = next_real_insn (insn); jump_insn = next_active_insn (JUMP_LABEL (insn));
return GET_CODE (PATTERN (next_insn)) == ASM_INPUT; while (insn)
{
insn = next_active_insn (insn);
if (!insn || jump_insn == insn)
return TRUE;
if (!(GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX)
&& get_attr_length (insn) > 0)
break;
}
return FALSE;
}
/* Return TRUE if INSN, a forward jump insn, can use nullification
to skip the following instruction. This avoids an extra cycle due
to a mis-predicted branch when we fall through. */
static bool
use_skip_p (rtx insn)
{
rtx jump_insn = next_active_insn (JUMP_LABEL (insn));
while (insn)
{
insn = next_active_insn (insn);
/* We can't rely on the length of asms, so we can't skip asms. */
if (!insn
|| GET_CODE (PATTERN (insn)) == ASM_INPUT
|| extract_asm_operands (PATTERN (insn)) != NULL_RTX)
break;
if (get_attr_length (insn) == 4
&& jump_insn == next_active_insn (insn))
return TRUE;
if (get_attr_length (insn) > 0)
break;
}
return FALSE;
} }
/* This routine handles all the normal conditional branch sequences we /* This routine handles all the normal conditional branch sequences we
...@@ -6230,7 +6287,7 @@ const char * ...@@ -6230,7 +6287,7 @@ const char *
output_cbranch (rtx *operands, int negated, rtx insn) output_cbranch (rtx *operands, int negated, rtx insn)
{ {
static char buf[100]; static char buf[100];
int useskip = 0; bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn); int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn); int length = get_attr_length (insn);
int xdelay; int xdelay;
...@@ -6268,12 +6325,7 @@ output_cbranch (rtx *operands, int negated, rtx insn) ...@@ -6268,12 +6325,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
/* A forward branch over a single nullified insn can be done with a /* A forward branch over a single nullified insn can be done with a
comclr instruction. This avoids a single cycle penalty due to comclr instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */ mis-predicted branch if we fall through (branch not taken). */
if (length == 4 useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
&& next_real_insn (insn) != 0
&& get_attr_length (next_real_insn (insn)) == 4
&& JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
&& nullify)
useskip = 1;
switch (length) switch (length)
{ {
...@@ -6561,7 +6613,7 @@ const char * ...@@ -6561,7 +6613,7 @@ const char *
output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which) output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{ {
static char buf[100]; static char buf[100];
int useskip = 0; bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn); int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn); int length = get_attr_length (insn);
int xdelay; int xdelay;
...@@ -6587,13 +6639,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which) ...@@ -6587,13 +6639,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
/* A forward branch over a single nullified insn can be done with a /* A forward branch over a single nullified insn can be done with a
extrs instruction. This avoids a single cycle penalty due to extrs instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */ mis-predicted branch if we fall through (branch not taken). */
useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
if (length == 4
&& next_real_insn (insn) != 0
&& get_attr_length (next_real_insn (insn)) == 4
&& JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
&& nullify)
useskip = 1;
switch (length) switch (length)
{ {
...@@ -6752,7 +6798,7 @@ const char * ...@@ -6752,7 +6798,7 @@ const char *
output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which) output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{ {
static char buf[100]; static char buf[100];
int useskip = 0; bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn); int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn); int length = get_attr_length (insn);
int xdelay; int xdelay;
...@@ -6778,13 +6824,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which) ...@@ -6778,13 +6824,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
/* A forward branch over a single nullified insn can be done with a /* A forward branch over a single nullified insn can be done with a
extrs instruction. This avoids a single cycle penalty due to extrs instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */ mis-predicted branch if we fall through (branch not taken). */
useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
if (length == 4
&& next_real_insn (insn) != 0
&& get_attr_length (next_real_insn (insn)) == 4
&& JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
&& nullify)
useskip = 1;
switch (length) switch (length)
{ {
......
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