This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] If using branch likelies in MIPS sync code fill the delay slot with a nop
- From: Andrew Bennett <Andrew dot Bennett at imgtec dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 18 Nov 2014 13:37:13 +0000
- Subject: [PATCH] If using branch likelies in MIPS sync code fill the delay slot with a nop
- Authentication-results: sourceware.org; auth=none
Hi,
The atomic-compare-exchange-3.c and atomic-op-3.c tests are failing when
using the -mfix-r10000 option. This is due to the fact that the delay
slot of the branch instruction that checks if the atomic operation was
not successful can be filled with an operation that returns the output
result. For the branch likely case this operation can not go in the
delay slot because it wont execute when the atomic operation was
successful and therefore the wrong result will be returned. This patch
forces a nop to be placed in the delay slot if a branch likely is used.
The fix is as simple as possible; it does cause a second nop to be introduced
after the branch instruction in the branch likely case. As this option is
rarely used, it makes more sense to keep the code readable than trying to
optimise it.
The atomic tests now pass successfully. The ChangeLog and patch are below.
Ok to commit?
Many thanks,
Andrew
gcc/
* config/mips/mips.c (mips_process_sync_loop): Place a nop in the
delay slot of the branch likely instruction.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 02268f3..6dd3728 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -12997,7 +12997,12 @@ 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);
+
+ /* We can not put the NEWVAL = $TMP3 or CMP = 1 operations in the delay slot
+ of the branch if it is a branch likely because they will not execute when
+ the atomic operation is successful, so place a NOP in there instead. */
+
+ 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)