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
This commit is contained in:
John David Anglin 2010-12-18 17:10:34 +00:00 committed by John David Anglin
parent c50ebc7332
commit 16923e7bf3
2 changed files with 84 additions and 33 deletions

View file

@ -1,3 +1,14 @@
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>
PR target/36834

View file

@ -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
it branches to the next real instruction. Otherwise, return FALSE. */
it branches into the delay slot. Otherwise, return FALSE. */
static bool
branch_to_delay_slot_p (rtx insn)
{
rtx jump_insn;
if (dbr_sequence_length ())
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
by an ASM_INPUT. Disaster can occur if the ASM_INPUT is empty and
the jump branches into the delay slot. So, we add a nop in the delay
slot just to be safe. This messes up our instruction count, but we
don't know how big the ASM_INPUT insn is anyway. */
by an asm. Disaster can occur if the asm is empty and the jump
branches into the delay slot. So, we add a nop in the delay slot
when this occurs. */
static bool
branch_needs_nop_p (rtx insn)
{
rtx next_insn;
rtx jump_insn;
if (dbr_sequence_length ())
return FALSE;
next_insn = next_real_insn (insn);
return GET_CODE (PATTERN (next_insn)) == ASM_INPUT;
jump_insn = next_active_insn (JUMP_LABEL (insn));
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
@ -6230,7 +6287,7 @@ const char *
output_cbranch (rtx *operands, int negated, rtx insn)
{
static char buf[100];
int useskip = 0;
bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn);
int xdelay;
@ -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
comclr instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */
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;
useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
switch (length)
{
@ -6561,7 +6613,7 @@ const char *
output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{
static char buf[100];
int useskip = 0;
bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn);
int xdelay;
@ -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
extrs instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */
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;
useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
switch (length)
{
@ -6752,7 +6798,7 @@ const char *
output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{
static char buf[100];
int useskip = 0;
bool useskip;
int nullify = INSN_ANNULLED_BRANCH_P (insn);
int length = get_attr_length (insn);
int xdelay;
@ -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
extrs instruction. This avoids a single cycle penalty due to
mis-predicted branch if we fall through (branch not taken). */
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;
useskip = (length == 4 && nullify) ? use_skip_p (insn) : FALSE;
switch (length)
{