This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, i386]: Fix PR 38254 [Was: PR 36793: x86-64 does not get __sync_synchronize right]


H.J. Lu wrote:

Attached patch implements the suggestion with locked no-operation insn. On
!TARGET_SSE2, we generate:

lock orb $0, -1(%esp)

where memory location gets assigned by assign_386_stack_local (). This way,
we avoid various store forwarding stalls, since this is an exclusive QImode
address. Also, it can point into redzone area, when redzone is available.



This patch caused


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38254

Apparently, UNSPEC_VOLATILEs are not enough for a full memory barrier. Attached patch implements the same solution as linux is using (well, using "or $0, mem" instead of "add $0, mem") for a memory barrier on 32bit x86.


2008-11-25 Uros Bizjak <ubizjak@gmail.com>

   PR target/38256
   * config/i386/sync.md (memory_barrier_nosse): New insn
   (memory_barrier): Generate memory_barrier_nosse insn for !TARGET_SSE2.

Patch was tested on x86_64-pc-linux-gnu {,-m32}, committed to mainline.

Uros.
Index: config/i386/sync.md
===================================================================
--- config/i386/sync.md	(revision 142160)
+++ config/i386/sync.md	(working copy)
@@ -36,19 +36,30 @@
 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
   ""
 {
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+
   if (!TARGET_SSE2)
     {
-      /* Emit a locked no-operation when SSE2 is not available.  */
-      int slot = virtuals_instantiated ? SLOT_TEMP : SLOT_VIRTUAL;
-      rtx temp = assign_386_stack_local (QImode, slot);
-      emit_insn (gen_sync_iorqi (temp, CONST0_RTX (QImode)));
+      emit_insn (gen_memory_barrier_nosse (operands[0]));
       DONE;
     }
-
-  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
-  MEM_VOLATILE_P (operands[0]) = 1;
 })
 
+(define_insn "memory_barrier_nosse"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
+   (clobber (reg:CC FLAGS_REG))]
+
+  "!TARGET_SSE2"
+{
+  if (TARGET_64BIT)
+    return "lock{%;| }or{q}\t{$0, (%%rsp)|QWORD PTR [rsp], 0}";
+  else
+    return "lock{%;| }or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}";
+}
+  [(set_attr "memory" "unknown")])
+
 ;; ??? It would be possible to use cmpxchg8b on pentium for DImode
 ;; changes.  It's complicated because the insn uses ecx:ebx as the
 ;; new value; note that the registers are reversed from the order

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]