aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bennett <andrew.bennett@imgtec.com>2014-11-21 14:34:55 +0000
committerAndrew Bennett <abennett@gcc.gnu.org>2014-11-21 14:34:55 +0000
commit3b6eaaa53debeab9eddd9ce8042f9fab50ad58ba (patch)
treede256a7c54a3038c424444883e5ad5a8da4461d0
parent4bec983122f95df5e58de30ea76cbbb67e737cd3 (diff)
downloadgcc-3b6eaaa53debeab9eddd9ce8042f9fab50ad58ba.zip
gcc-3b6eaaa53debeab9eddd9ce8042f9fab50ad58ba.tar.gz
gcc-3b6eaaa53debeab9eddd9ce8042f9fab50ad58ba.tar.bz2
[MIPS] If using branch likelies in MIPS sync code fill the delay slot
with a nop. gcc/ * config/mips/mips.c (mips_process_sync_loop): Place a nop in the delay slot of the branch likely instruction. (mips_output_sync_loop): Ensure mips_branch_likely is set before calling mips_output_sync_loop. (mips_sync_loop_insns): Likewise. From-SVN: r217926
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/mips/mips.c18
2 files changed, 22 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd42d0c..4b14d1d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-11-21 Andrew Bennett <andrew.bennett@imgtec.com>
+
+ * config/mips/mips.c (mips_process_sync_loop): Place a
+ nop in the delay slot of the branch likely instruction.
+ (mips_output_sync_loop): Ensure mips_branch_likely is
+ set before calling mips_output_sync_loop.
+ (mips_sync_loop_insns): Likewise.
+
2014-11-21 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR/target 63673
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index db58d07..dad63eb 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -12997,7 +12997,14 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
This will sometimes be a delayed branch; see the write code below
for details. */
mips_multi_add_insn (is_64bit_p ? "scd\t%0,%1" : "sc\t%0,%1", at, mem, NULL);
- mips_multi_add_insn ("beq%?\t%0,%.,1b", at, NULL);
+
+ /* When using branch likely (-mfix-r10000), the delay slot instruction
+ will be annulled on false. The normal delay slot instructions
+ calculate the overall result of the atomic operation and must not
+ be annulled. To ensure this behaviour unconditionally use a NOP
+ in the delay slot for the branch likely case. */
+
+ mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL);
/* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]. */
if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval)
@@ -13005,7 +13012,7 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
mips_multi_copy_insn (tmp3_insn);
mips_multi_set_operand (mips_multi_last_index (), 0, newval);
}
- else if (!(required_oldval && cmp))
+ else if (!(required_oldval && cmp) && !mips_branch_likely)
mips_multi_add_insn ("nop", NULL);
/* CMP = 1 -- either standalone or in a delay slot. */
@@ -13029,12 +13036,12 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
const char *
mips_output_sync_loop (rtx_insn *insn, rtx *operands)
{
- mips_process_sync_loop (insn, operands);
-
/* Use branch-likely instructions to work around the LL/SC R10000
errata. */
mips_branch_likely = TARGET_FIX_R10000;
+ mips_process_sync_loop (insn, operands);
+
mips_push_asm_switch (&mips_noreorder);
mips_push_asm_switch (&mips_nomacro);
mips_push_asm_switch (&mips_noat);
@@ -13056,6 +13063,9 @@ mips_output_sync_loop (rtx_insn *insn, rtx *operands)
unsigned int
mips_sync_loop_insns (rtx_insn *insn, rtx *operands)
{
+ /* Use branch-likely instructions to work around the LL/SC R10000
+ errata. */
+ mips_branch_likely = TARGET_FIX_R10000;
mips_process_sync_loop (insn, operands);
return mips_multi_num_insns;
}