diff options
author | John David Anglin <dave.anglin@nrc-cnrc.gc.ca> | 2010-12-18 17:10:34 +0000 |
---|---|---|
committer | John David Anglin <danglin@gcc.gnu.org> | 2010-12-18 17:10:34 +0000 |
commit | 16923e7bf333db732aed3686972b40ac2e458109 (patch) | |
tree | 1e81f7c53d72184586caf1560f886f5fa2696c0d /gcc | |
parent | c50ebc7332db306b3b7e122fb5251605db3bcd96 (diff) | |
download | gcc-16923e7bf333db732aed3686972b40ac2e458109.zip gcc-16923e7bf333db732aed3686972b40ac2e458109.tar.gz gcc-16923e7bf333db732aed3686972b40ac2e458109.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/pa/pa.c | 106 |
2 files changed, 84 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5b7241e..9536e0a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index ab54e4b..89f7e50 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -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) { |