[PATCH] If using branch likelies in MIPS sync code fill the delay slot with a nop

Andrew Bennett Andrew.Bennett@imgtec.com
Tue Nov 18 13:48:00 GMT 2014


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)



More information about the Gcc-patches mailing list