diff mbox

[cxx-mem-model] merge simulate-thread changes to branch

Message ID 4E931144.6010702@redhat.com
State New
Headers show

Commit Message

Aldy Hernandez Oct. 10, 2011, 3:37 p.m. UTC
I have merged the simulate-thread changes from trunk into the branch.

And yes, I merged in your infinite loop changes to the testing harness. 
  I did, however, choose to keep the "simulate_thread_memmodel_fini" 
name as opposed to your "__gdb_*_fini" changes, so we can be consistent 
throughout.

I also updated all the tests in the branch to use the 
simulate_thread_main() stub.

Committing to branch.
Merge from mainline:
	2011-10-10  Aldy Hernandez  <aldyh@redhat.com>
	* lib/gcc-simulate-thread.exp: New.
	* gcc.dg/simulate-thread/guality.h: New.
	* gcc.dg/simulate-thread/simulate-thread.h: New.
	* gcc.dg/simulate-thread/simulate-thread.exp: New.
	* gcc.dg/simulate-thread/simulate-thread.gdb: New.
	* gcc.dg/simulate-thread/README: New.
	* g++.dg/simulate-thread/guality.h: New.
	* g++.dg/simulate-thread/simulate-thread.h: New.
	* g++.dg/simulate-thread/simulate-thread.exp: New.
	* g++.dg/simulate-thread/simulate-thread.gdb: New.
	* c-c++-common/cxxbitfields-2.c: Remove.
	* c-c++-common/cxxbitfields.c: Remove.
	* c-c++-common/cxxbitfields-4.c: Remove.
	* c-c++-common/cxxbitfields-5.c: Remove.
	* c-c++-common/simulate-thread/bitfields-1.c: New.
	* c-c++-common/simulate-thread/bitfields-2.c: New.
	* c-c++-common/simulate-thread/bitfields-3.c: New.
	* c-c++-common/simulate-thread/bitfields-4.c: New.
diff mbox

Patch

Index: lib/gcc-dg.exp
===================================================================
--- lib/gcc-dg.exp	(revision 179750)
+++ lib/gcc-dg.exp	(working copy)
@@ -747,4 +747,26 @@  proc dg-message { args } {
     process-message saved-dg-warning "" $args
 }
 
+# Check the existence of a gdb in the path, and return true if there
+# is one.
+#
+# Set env(GDB_FOR_GCC_TESTING) accordingly.
+
+proc gdb-exists { args } {
+    if ![info exists ::env(GDB_FOR_GCC_TESTING)] {
+	global GDB
+	if ![info exists ::env(GDB_FOR_GCC_TESTING)] {
+	    if [info exists GDB] {
+		setenv GDB_FOR_GCC_TESTING "$GDB"
+	    } else {
+		setenv GDB_FOR_GCC_TESTING "[transform gdb]"
+	    }
+	}
+    }
+    if { [which $::env(GDB_FOR_GCC_TESTING)] != 0 } {
+	return 1;
+    }
+    return 0;
+}
+
 set additional_prunes ""
Index: lib/gcc-memmodel-gdb-test.exp
===================================================================
--- lib/gcc-memmodel-gdb-test.exp	(revision 179750)
+++ lib/gcc-memmodel-gdb-test.exp	(working copy)
@@ -1,77 +0,0 @@ 
-#   Copyright (C) 2011 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <http://www.gnu.org/licenses/>.
-
-# Utility for running a given test through the memmodel harness using gdb.
-# This is invoked via dg-final.
-#
-# Adapted from the guality harness.
-#
-# Call 'fail' if a given test printed "FAIL:", otherwise call 'pass'.
-
-proc memmodel-gdb-test { args } {
-    if { ![isnative] || [is_remote target] } { return }
-
-    if { [llength $args] == 1 } {
-	switch [dg-process-target [lindex $args 0]] {
-		"F" { setup_xfail "*-*-*" }
-	}
-    }
-
-    # This assumes that we are three frames down from dg-test, and that
-    # it still stores the filename of the testcase in a local variable "name".
-    # A cleaner solution would require a new DejaGnu release.
-    upvar 2 name testcase
-    upvar 2 prog prog
-    upvar 2 srcdir testsuite_dir
-
-    set gdb_name $::env(GUALITY_GDB_NAME)
-    set exec_file "[file rootname [file tail $prog]].exe"
-    set cmd_file "$testsuite_dir/gcc.dg/memmodel/memmodel.gdb"
-
-    if ![file exists $exec_file] {
-	return
-    }
-
-    send_log "Spawning: $gdb_name -nx -nw -quiet -x $cmd_file ./$exec_file\n"
-    set res [remote_spawn target "$gdb_name -nx -nw  -x $cmd_file ./$exec_file"]
-    if { $res < 0 || $res == "" } {
-	unsupported "$testcase"
-	return
-    }
-
-    remote_expect target [timeout_value] {
-	-re "FAIL:" {
-	    fail "$testcase"
-	    remote_close target
-	    return
-	}
-	# Too old GDB
-	-re "Unhandled dwarf expression|Error in sourced command file" {
-	    unsupported "$testcase"
-	    remote_close target
-	    return
-	}
-	timeout {
-	    unsupported "$testcase"
-	    remote_close target
-	    return
-	}
-    }
-
-    remote_close target
-    pass "$testcase"
-    return
-}
Index: lib/gcc-simulate-thread.exp
===================================================================
--- lib/gcc-simulate-thread.exp	(revision 0)
+++ lib/gcc-simulate-thread.exp	(revision 0)
@@ -0,0 +1,90 @@ 
+#   Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Utility for running a given test through the simulate-thread harness
+# using gdb.  This is invoked via dg-final.
+#
+# Adapted from the guality harness.
+#
+# Call 'fail' if a given test printed "FAIL:", otherwise call 'pass'.
+
+proc simulate-thread { args } {
+    if { ![isnative] || [is_remote target] } { return }
+
+    if { [llength $args] == 1 } {
+	switch [dg-process-target [lindex $args 0]] {
+		"F" { setup_xfail "*-*-*" }
+	}
+    }
+
+    # This assumes that we are three frames down from dg-test, and that
+    # it still stores the filename of the testcase in a local variable "name".
+    # A cleaner solution would require a new DejaGnu release.
+    upvar 2 name testcase
+    upvar 2 prog prog
+    upvar 2 srcdir testsuite_dir
+
+    set gdb_name $::env(GDB_FOR_GCC_TESTING)
+    set exec_file "[file rootname [file tail $prog]].exe"
+    set cmd_file "$testsuite_dir/gcc.dg/simulate-thread/simulate-thread.gdb"
+
+    if ![file exists $exec_file] {
+	return
+    }
+
+    send_log "Spawning: $gdb_name -nx -nw -quiet -x $cmd_file ./$exec_file\n"
+    set res [remote_spawn target "$gdb_name -nx -nw  -x $cmd_file ./$exec_file"]
+    if { $res < 0 || $res == "" } {
+	unsupported "$testcase"
+	return
+    }
+
+    set gdb_worked 0
+    remote_expect target [timeout_value] {
+	# Too old GDB
+	-re "Unhandled dwarf expression|Error in sourced command file" {
+	    unsupported "$testcase"
+	    remote_close target
+	    return
+	}
+	-re "FAIL:" {
+	    fail "$testcase"
+	    remote_close target
+	    return
+	}
+	# If the gdb output contained simulate_thread_main, assume
+	# that at the very least, we had a working gdb that was able
+	# to break in simulate_thread_main.
+	-re "simulate_thread_main" {
+	    set gdb_worked 1
+	    exp_continue
+	}
+	timeout {
+	    unsupported "$testcase"
+	    remote_close target
+	    return
+	}
+    }
+
+    remote_close target
+    if {$gdb_worked} {
+	pass "$testcase"
+    } else {
+	# Fail in the absence of a sane GDB.
+	fail "$testcase"
+    }
+    return
+}
Index: gcc.dg/simulate-thread/strict-align-global.c
===================================================================
--- gcc.dg/simulate-thread/strict-align-global.c	(revision 0)
+++ gcc.dg/simulate-thread/strict-align-global.c	(revision 0)
@@ -0,0 +1,52 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-packed-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* This test verifies writes to globals do not write to adjacent
+   globals.  This mostly happens on strict-align targets that are not
+   byte addressable (old Alphas, etc).  */
+
+char a = 0;
+char b = 77;
+
+void simulate_thread_other_threads() 
+{
+}
+
+int simulate_thread_step_verify()
+{
+  if (b != 77)
+    {
+      printf("FAIL: Unexpected value.  <b> is %d, should be 77\n", b);
+      return 1;
+    }
+  return 0;
+}
+
+/* Verify that every variable has the correct value.  */
+int simulate_thread_final_verify()
+{
+  int ret = simulate_thread_step_verify ();
+  if (a != 66)
+    {
+      printf("FAIL: Unexpected value.  <a> is %d, should be 66\n", a);
+      return 1;
+    }
+  return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  a = 66;
+}
+
+int main ()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: gcc.dg/simulate-thread/simulate-thread.exp
===================================================================
--- gcc.dg/simulate-thread/simulate-thread.exp	(revision 0)
+++ gcc.dg/simulate-thread/simulate-thread.exp	(revision 0)
@@ -0,0 +1,38 @@ 
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Your run of the mill dg test, but verify that we have a working GDB first.
+
+load_lib gcc-dg.exp
+load_lib gcc-simulate-thread.exp
+load_lib torture-options.exp
+
+dg-init
+torture-init
+set-torture-options [list \
+	{ -O0 -g } \
+	{ -O1 -g } \
+	{ -O2 -g } \
+	{ -O3 -g } \
+	{ -Os -g } ]
+
+if [gdb-exists] {
+  gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] ""
+  gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/simulate-thread/*.c]] ""
+}
+
+torture-finish
+dg-finish
Index: gcc.dg/simulate-thread/simulate-thread.gdb
===================================================================
--- gcc.dg/simulate-thread/simulate-thread.gdb	(revision 0)
+++ gcc.dg/simulate-thread/simulate-thread.gdb	(revision 0)
@@ -0,0 +1,17 @@ 
+set height 0
+break simulate_thread_main
+disp/i $pc
+run
+
+set $ret = 0
+while (simulate_thread_fini != 1) && (! $ret)
+  call simulate_thread_wrapper_other_threads()
+  stepi
+  set $ret |= simulate_thread_step_verify()
+end
+
+if (! $ret)
+  set $ret |= simulate_thread_wrapper_final_verify()
+end
+continue
+quit $ret
Index: gcc.dg/simulate-thread/sync-load-longlong.c
===================================================================
--- gcc.dg/simulate-thread/sync-load-longlong.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-load-longlong.c	(revision 0)
@@ -0,0 +1,117 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_long_long } */
+/* { dg-options "" } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+
+/* Testing load for atomicity is a little trickier.  
+
+   Set up the atomic value so that it changes value after every instruction 
+   is executed.
+
+   Simply alternating between 2 values wouldn't be sufficient since a load of
+   one part, followed by the load of the second part 2 instructions later would
+   appear to be valid.
+
+   set up a table of 16 values which change a bit in every byte of the value 
+   each time, this will give us a 16 instruction cycle before repetition
+   kicks in, which should be sufficient to detect any issues.  Just to be sure,
+   we also change the table cycle size during execution. 
+   
+   The end result is that all loads should always get one of the values from
+   the table. Any other pattern means the load failed.  */
+
+unsigned long long ret;
+unsigned long long value = 0;
+unsigned long long result = 0;
+unsigned long long table[16] = {
+0x0000000000000000, 
+0x1111111111111111, 
+0x2222222222222222, 
+0x3333333333333333,
+0x4444444444444444,
+0x5555555555555555,
+0x6666666666666666,
+0x7777777777777777,
+0x8888888888888888,
+0x9999999999999999,
+0xAAAAAAAAAAAAAAAA,
+0xBBBBBBBBBBBBBBBB,
+0xCCCCCCCCCCCCCCCC,
+0xDDDDDDDDDDDDDDDD,
+0xEEEEEEEEEEEEEEEE,
+0xFFFFFFFFFFFFFFFF
+};
+
+int table_cycle_size = 16;
+
+/* Return 0 if 'result' is a valid value to have loaded.  */
+int verify_result ()
+{
+  int x;
+  int found = 0;
+
+  /* Check entire table for valid values.  */
+  for (x = 0; x < 16 ; x++)
+    if (result == table[x])
+      {
+	found = 1;
+	break;
+      }
+
+  if (!found)
+    printf("FAIL: Invalid result returned from fetch\n");
+
+  return !found;
+}
+
+/* Iterate VALUE through the different valid values. */
+void simulate_thread_other_threads ()
+{
+  static int current = 0;
+
+  if (++current >= table_cycle_size)
+    current = 0;
+  value = table[current];
+}
+
+int simulate_thread_step_verify ()
+{
+  return verify_result ();
+}
+
+int simulate_thread_final_verify ()
+{
+  return verify_result ();
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  int x;
+
+  /* Execute loads with value changing at various cyclic values.  */
+  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
+    {
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      /* In order to verify the returned value (which is not atomic), it needs
+	 to be atomically stored into another variable and check that.  */
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+
+      /* Execute the fetch/store a couple of times just to ensure the cycles
+         have a chance to be interesting.  */
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+    }
+}
+
+main()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-other-longlong.c
===================================================================
--- gcc.dg/simulate-thread/sync-other-longlong.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-other-longlong.c	(revision 0)
@@ -0,0 +1,117 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_long_long } */
+/* { dg-options "" } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* Test all the __sync routines for proper atomicity on 8 byte values.  */
+
+unsigned long long zero = 0;
+unsigned long long max = ~0;
+
+unsigned long long changing_value = 0;
+unsigned long long value = 0;
+unsigned long long ret;
+
+void test_abort()
+{
+  static int reported = 0;
+  if (!reported)
+    {
+      printf ("FAIL: improper execution of __sync builtin.\n");
+      reported = 1;
+    }
+}
+
+void simulate_thread_other_threads ()
+{
+}
+
+int simulate_thread_step_verify ()
+{
+  if (value != zero && value != max)
+    {
+      printf ("FAIL: invalid intermediate result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify ()
+{
+  if (value != 0)
+    {
+      printf ("FAIL: invalid final result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* All values written to 'value' alternate between 'zero' and 'max'. Any other
+   value detected by simulate_thread_step_verify() between instructions would indicate
+   that the value was only partially written, and would thus fail this 
+   atomicity test.  
+
+   This function tests each different __sync_mem routine once, with the
+   exception of the load instruction which requires special testing.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
+  if (ret != zero || value != max)
+    test_abort();
+
+  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
+  if (value != zero)
+    test_abort();
+
+  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+}
+
+int main ()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/README
===================================================================
--- gcc.dg/simulate-thread/README	(revision 0)
+++ gcc.dg/simulate-thread/README	(revision 0)
@@ -0,0 +1,118 @@ 
+OVERVIEW
+--------
+
+This is a harness to test the atomicity of certain operations, and to
+make sure the compiler does not introduce data races in a
+multi-threaded environment.
+
+The basic premise is that we set up testcases such that the thing we
+want test, say an atomic instruction which stores a double word is in
+a function of its own.  We then run this testcase within GDB,
+controlled by a gdb script (simulate-thread.gdb).  The gdb script will
+break on the function to be tested, and then single step through every
+machine instruction in the function.  We set this up so GDB can make a
+couple of inferior function calls before and after each of these
+single step instructions for a couple of purposes:
+
+       1.  One of the calls simulates another thread running in the
+           process which changes or access memory.
+
+       2.  The other calls are used to verify that we always get the
+           expected behavior.
+
+For example, in the case of an atomic store, anyone looking at the
+memory associated with an atomic variable should never see any in
+between states. If you have an atomic long long int, and it starts
+with the value 0, and you write the value MAX_LONG_LONG, any other
+thread looking at that variable should never see anything other than 0
+or MAX_LONG_LONG.  If you implement the atomic write as a sequence of
+2 stores, it is possible for another thread to read the location after
+the first store, but before the second one is complete. That thread
+would then see an in-between state (one word would still be 0).
+
+We simulate this in the testcase by having GDB step through the
+program, instruction by instruction, and after each step, making an
+inferior function call which looks at the value of the atomic variable
+and verifies that it sees either 0 or MAX_LONG_LONG.  If it sees any
+other value, it fails the testcase.
+
+This way, we are *sure* there is no in between state because we
+effectively acted like an OS and switched to another thread after
+every single instruction of the routine is executed and looked at the
+results each time.
+
+We use the same idea to test for data races to see if an illegal load
+has been hoisted, or that two parallel bitfield writes don't overlap
+in a data race.
+
+Below is a skeleton of how a test should look like.  For more details,
+look at the tests themselves.
+
+ANATOMY OF A TEST
+-----------------
+
+/* { dg-do link } */
+/* { dg-options "-some-flags" } */
+/* { dg-final { simulate-thread } } */
+
+/* NOTE: Any failure must be indicated by displaying "FAIL:".  */
+
+#include "simulate-thread.h"
+
+/* Called before each instruction, simulating another thread executing.  */
+void simulate_thread_other_threads()
+{
+}
+
+/* Called after each instruction.  Returns 1 if any inconsistency is
+   found, 0 otherwise.  */
+int simulate_thread_step_verify()
+{
+  if (some_problem)
+    {
+      printf("FAIL: reason\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* Called at the end of the program (simulate_thread_fini == 1).  Verifies
+   the state of the program and returns 1 if any inconsistency is
+   found, 0 otherwise.  */
+int simulate_thread_final_verify()
+{
+  if (some_problem)
+    {
+      printf("FAIL: reason\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* The gdb script will break on simulate_thread_main(), so make sure
+   GCC does not inline it, thus making the break point fail.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  /* Do stuff.  */
+}
+
+int main()
+{
+
+  /* Perform any setup code that will run outside of the testing
+     harness.  Put code here that you do NOT want to be interrupted on
+     an instruction basis.  E.g., setup code, and system library
+     calls.  */
+
+     /* Do un-instrumented stuff. */
+     /* ... */
+
+  /* Start the instrumented show.  */
+  simulate_thread_main();
+
+  /* Must be called at the end of the test.  */
+  simulate_thread_done();
+
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-load-int128.c
===================================================================
--- gcc.dg/simulate-thread/sync-load-int128.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-load-int128.c	(revision 0)
@@ -0,0 +1,132 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_int_128 } */
+/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+
+/* Testing load for atomicity is a little trickier.  
+
+   Set up the atomic value so that it changes value after every instruction 
+   is executed.
+
+   Simply alternating between 2 values wouldn't be sufficient since a load of
+   one part, followed by the load of the second part 2 instructions later would
+   appear to be valid.
+
+   set up a table of 16 values which change a bit in every byte of the value 
+   each time, this will give us a 16 instruction cycle before repetition
+   kicks in, which should be sufficient to detect any issues.  Just to be sure,
+   we also change the table cycle size during execution. 
+   
+   The end result is that all loads should always get one of the values from
+   the table. Any other pattern means the load failed.  */
+
+__int128_t ret;
+__int128_t value = 0;
+__int128_t result = 0;
+__int128_t table[16] = {
+0x0000000000000000, 
+0x1111111111111111, 
+0x2222222222222222, 
+0x3333333333333333,
+0x4444444444444444,
+0x5555555555555555,
+0x6666666666666666,
+0x7777777777777777,
+0x8888888888888888,
+0x9999999999999999,
+0xAAAAAAAAAAAAAAAA,
+0xBBBBBBBBBBBBBBBB,
+0xCCCCCCCCCCCCCCCC,
+0xDDDDDDDDDDDDDDDD,
+0xEEEEEEEEEEEEEEEE,
+0xFFFFFFFFFFFFFFFF
+};
+
+int table_cycle_size = 16;
+
+/* Since we don't have 128 bit constants, we have to properly pad the table.  */
+void fill_table()
+{
+  int x;
+  for (x = 0; x < 16; x++)
+    {
+      ret = table[x];
+      ret = (ret << 64) | ret;
+      table[x] = ret;
+    }
+}
+
+/* Return 0 if 'result' is a valid value to have loaded.  */
+int verify_result ()
+{
+  int x;
+  int found = 0;
+
+  /* Check entire table for valid values.  */
+  for (x = 0; x < 16; x++)
+    if (result == table[x])
+      {
+	found = 1;
+	break;
+      }
+
+  if (!found)
+    printf("FAIL: Invalid result returned from fetch\n");
+
+  return !found;
+}
+
+/* Iterate VALUE through the different valid values. */
+void simulate_thread_other_threads ()
+{
+  static int current = 0;
+
+  if (++current >= table_cycle_size)
+    current = 0;
+  value = table[current];
+}
+
+int simulate_thread_step_verify ()
+{
+  return verify_result ();
+}
+
+int simulate_thread_final_verify ()
+{
+  return verify_result ();
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  int x;
+
+  fill_table ();
+  /* Make sure value starts with an atomic value now.  */
+  __sync_mem_store (&value, ret, __SYNC_MEM_SEQ_CST);
+
+  /* Execute loads with value changing at various cyclic values.  */
+  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
+    {
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      /* In order to verify the returned value (which is not atomic), it needs
+	 to be atomically stored into another variable and check that.  */
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+
+      /* Execute the fetch/store a couple of times just to ensure the cycles
+         have a chance to be interesting.  */
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+    }
+}
+
+main()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/speculative-store.c
===================================================================
--- gcc.dg/simulate-thread/speculative-store.c	(revision 0)
+++ gcc.dg/simulate-thread/speculative-store.c	(revision 0)
@@ -0,0 +1,57 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* This file tests that speculative store movement out of a loop doesn't 
+   happen.  This is disallowed when --param allow-store-data-races is 0.  */
+
+int global = 100;
+
+/* Other thread makes sure global is 100 before the next instruction is
+ * exceuted.  */
+void simulate_thread_other_threads() 
+{
+  global = 100;
+}
+
+int simulate_thread_step_verify()
+{
+  if (global != 100)
+    {
+      printf("FAIL: global variable was assigned to.  \n");
+      return 1;
+    }
+}
+
+int simulate_thread_final_verify()
+{
+  return 0;
+}
+
+/* The variable global should never be assigned if func(0) is called.
+   This tests store movement out of loop thats never executed. */
+void test (int y)
+{
+  int x;
+  for (x=0; x< y; x++)
+    {
+       global = y;   /* This should never speculatively execute.  */
+    }
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  test(0);
+  simulate_thread_done();
+}
+
+__attribute__((noinline))
+int main()
+{
+  simulate_thread_main();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-other-int128.c
===================================================================
--- gcc.dg/simulate-thread/sync-other-int128.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-other-int128.c	(revision 0)
@@ -0,0 +1,116 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_int_128 } */
+/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* Test all the __sync routines for proper atomicity on 16 byte values.  */
+
+__int128_t zero = 0;
+__int128_t max = ~0;
+__int128_t changing_value = 0;
+__int128_t value = 0;
+__int128_t ret;
+
+void test_abort()
+{
+  static int reported = 0;
+  if (!reported)
+    {
+      printf ("FAIL: improper execution of __sync builtin.\n");
+      reported = 1;
+    }
+}
+
+void simulate_thread_other_threads ()
+{
+}
+
+int simulate_thread_step_verify ()
+{
+  if (value != zero && value != max)
+    {
+      printf ("FAIL: invalid intermediate result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify ()
+{
+  if (value != 0)
+    {
+      printf ("FAIL: invalid final result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* All values written to 'value' alternate between 'zero' and 'max'. Any other
+   value detected by simulate_thread_step_verify() between instructions would indicate
+   that the value was only partially written, and would thus fail this 
+   atomicity test.  
+
+   This function tests each different __sync_mem routine once, with the
+   exception of the load instruction which requires special testing.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  
+  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
+  if (ret != zero || value != max)
+    test_abort();
+
+  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
+  if (value != zero)
+    test_abort();
+
+  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+}
+
+int main()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/subfields.c
===================================================================
--- gcc.dg/simulate-thread/subfields.c	(revision 0)
+++ gcc.dg/simulate-thread/subfields.c	(revision 0)
@@ -0,0 +1,93 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-packed-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* This test verifies that data races aren't introduced by structure subfield 
+   stores. */
+
+struct test_struct {
+  char a;
+  char b;
+  char c;
+  char d;
+} var = {0,0,0,0};
+
+
+/* This routine sets field a to 'x'.  If executed properly, it will
+   not affect any of the other fields in the structure.  An improper
+   implementation may load an entire word, change the 8 bits for field
+   'a' and write the entire word back out. */
+__attribute__((noinline))
+void set_a(char x)
+{
+  var.a = x;
+}
+
+static int global = 0;
+
+/* The other thread increments the value of each of the other fields
+   in the structure every cycle.  If the store to the 'a' field does
+   an incorrect full or partial word load, mask and store, it will
+   write back an incorrect value to one or more of the other
+   fields.  */
+void simulate_thread_other_threads() 
+{
+  global++;
+  var.b = global;
+  var.c = global;
+  var.d = global;
+}
+
+
+/* Make sure that none of the other fields have been changed.  */
+int simulate_thread_step_verify()
+{
+  int ret = 0;
+  if (var.b != global)
+    {
+      printf("FAIL: Unexpected value. var.b is %d, should be %d\n",
+	     var.b, global);
+      ret = 1;
+    }
+  if (var.c != global)
+    {
+      printf("FAIL: Unexpected value. var.c is %d, should be %d\n",
+	     var.c, global);
+      ret = 1;
+    }
+  if (var.d != global)
+    {
+      printf("FAIL: Unexpected value. var.d is %d, should be %d\n",
+	     var.d, global);
+      ret = 1;
+    }
+  return ret;
+}
+
+/* Verify that every variable has the correct value.  */
+int simulate_thread_final_verify()
+{
+  int ret = simulate_thread_step_verify();
+  if (var.a != 1)
+    {
+      printf("FAIL: Unexpected value. var.a is %d, should be %d\n", var.a, 1);
+      ret = 1;
+    }
+  return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  set_a(1);
+}
+
+int main ()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-load-int.c
===================================================================
--- gcc.dg/simulate-thread/sync-load-int.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-load-int.c	(revision 0)
@@ -0,0 +1,116 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_int_long } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+
+/* Testing load for atomicity is a little trickier.  
+
+   Set up the atomic value so that it changes value after every instruction 
+   is executed.
+
+   Simply alternating between 2 values wouldn't be sufficient since a load of
+   one part, followed by the load of the second part 2 instructions later would
+   appear to be valid.
+
+   set up a table of 16 values which change a bit in every byte of the value 
+   each time, this will give us a 16 instruction cycle before repetition
+   kicks in, which should be sufficient to detect any issues.  Just to be sure,
+   we also change the table cycle size during execution. 
+   
+   The end result is that all loads should always get one of the values from
+   the table. Any other pattern means the load failed.  */
+
+unsigned int ret;
+unsigned int value = 0;
+unsigned int result = 0;
+unsigned int table[16] = {
+0x00000000, 
+0x11111111, 
+0x22222222, 
+0x33333333,
+0x44444444,
+0x55555555,
+0x66666666,
+0x77777777,
+0x88888888,
+0x99999999,
+0xAAAAAAAA,
+0xBBBBBBBB,
+0xCCCCCCCC,
+0xDDDDDDDD,
+0xEEEEEEEE,
+0xFFFFFFFF
+};
+
+int table_cycle_size = 16;
+
+/* Return 0 if 'result' is a valid value to have loaded.  */
+int verify_result ()
+{
+  int x;
+  int found = 0;
+
+  /* Check entire table for valid values.  */
+  for (x = 0; x < 16 ; x++)
+    if (result == table[x])
+      {
+	found = 1;
+	break;
+      }
+
+  if (!found)
+    printf("FAIL: Invalid result returned from fetch\n");
+
+  return !found;
+}
+
+/* Iterate VALUE through the different valid values. */
+void simulate_thread_other_threads ()
+{
+  static int current = 0;
+
+  if (++current >= table_cycle_size)
+    current = 0;
+  value = table[current];
+}
+
+int simulate_thread_step_verify ()
+{
+  return verify_result ();
+}
+
+int simulate_thread_final_verify ()
+{
+  return verify_result ();
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  int x;
+
+  /* Execute loads with value changing at various cyclic values.  */
+  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
+    {
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      /* In order to verify the returned value (which is not atomic), it needs
+	 to be atomically stored into another variable and check that.  */
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+
+      /* Execute the fetch/store a couple of times just to ensure the cycles
+         have a chance to be interesting.  */
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+    }
+}
+
+main()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-other-int.c
===================================================================
--- gcc.dg/simulate-thread/sync-other-int.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-other-int.c	(revision 0)
@@ -0,0 +1,118 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_int_long } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* Test all the __sync routines for proper atomicity on 4 byte values.  */
+
+unsigned int zero = 0;
+unsigned int max = ~0;
+
+unsigned int changing_value = 0;
+unsigned int value = 0;
+unsigned int ret;
+
+void test_abort()
+{
+  static int reported = 0;
+  if (!reported)
+    {
+      printf ("FAIL: improper execution of __sync builtin.\n");
+      reported = 1;
+    }
+}
+
+void simulate_thread_other_threads ()
+{
+}
+
+int simulate_thread_step_verify ()
+{
+  if (value != zero && value != max)
+    {
+      printf ("FAIL: invalid intermediate result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify ()
+{
+  if (value != 0)
+    {
+      printf ("FAIL: invalid final result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* All values written to 'value' alternate between 'zero' and
+   'max'. Any other value detected by simulate_thread_step_verify()
+   between instructions would indicate that the value was only
+   partially written, and would thus fail this atomicity test.
+
+   This function tests each different __sync_mem routine once, with
+   the exception of the load instruction which requires special
+   testing.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  
+  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
+  if (ret != zero || value != max)
+    test_abort();
+
+  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
+  if (value != zero)
+    test_abort();
+
+  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+}
+
+main ()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-load-short.c
===================================================================
--- gcc.dg/simulate-thread/sync-load-short.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-load-short.c	(revision 0)
@@ -0,0 +1,116 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_char_short } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+
+/* Testing load for atomicity is a little trickier.  
+
+   Set up the atomic value so that it changes value after every instruction 
+   is executed.
+
+   Simply alternating between 2 values wouldn't be sufficient since a load of
+   one part, followed by the load of the second part 2 instructions later would
+   appear to be valid.
+
+   set up a table of 16 values which change a bit in every byte of the value 
+   each time, this will give us a 16 instruction cycle before repetition
+   kicks in, which should be sufficient to detect any issues.  Just to be sure,
+   we also change the table cycle size during execution. 
+   
+   The end result is that all loads should always get one of the values from
+   the table. Any other pattern means the load failed.  */
+
+unsigned short ret;
+unsigned short value = 0;
+unsigned short result = 0;
+unsigned short table[16] = {
+0x0000, 
+0x1111, 
+0x2222, 
+0x3333,
+0x4444,
+0x5555,
+0x6666,
+0x7777,
+0x8888,
+0x9999,
+0xAAAA,
+0xBBBB,
+0xCCCC,
+0xDDDD,
+0xEEEE,
+0xFFFF
+};
+
+int table_cycle_size = 16;
+
+/* Return 0 if 'result' is a valid value to have loaded.  */
+int verify_result ()
+{
+  int x;
+  int found = 0;
+
+  /* Check entire table for valid values.  */
+  for (x = 0; x < 16 ; x++)
+    if (result == table[x])
+      {
+	found = 1;
+	break;
+      }
+
+  if (!found)
+    printf("FAIL: Invalid result returned from fetch\n");
+
+  return !found;
+}
+
+/* Iterate VALUE through the different valid values. */
+void simulate_thread_other_threads ()
+{
+  static int current = 0;
+
+  if (++current >= table_cycle_size)
+    current = 0;
+  value = table[current];
+}
+
+int simulate_thread_step_verify ()
+{
+  return verify_result ();
+}
+
+int simulate_thread_final_verify ()
+{
+  return verify_result ();
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  int x;
+
+  /* Execute loads with value changing at various cyclic values.  */
+  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
+    {
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      /* In order to verify the returned value (which is not atomic), it needs
+	 to be atomically stored into another variable and check that.  */
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+
+      /* Execute the fetch/store a couple of times just to ensure the cycles
+         have a chance to be interesting.  */
+      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
+      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
+    }
+}
+
+main()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/sync-other-short.c
===================================================================
--- gcc.dg/simulate-thread/sync-other-short.c	(revision 0)
+++ gcc.dg/simulate-thread/sync-other-short.c	(revision 0)
@@ -0,0 +1,117 @@ 
+/* { dg-do link } */
+/* { dg-require-effective-target sync_char_short } */
+/* { dg-final { simulate-thread } } */
+
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+/* Test all the __sync routines for proper atomicity on 2 byte values.  */
+
+unsigned short zero = 0;
+unsigned short max = ~0;
+
+unsigned short changing_value = 0;
+unsigned short value = 0;
+unsigned short ret;
+
+void test_abort()
+{
+  static int reported = 0;
+  if (!reported)
+    {
+      printf ("FAIL: improper execution of __sync builtin.\n");
+      reported = 1;
+    }
+}
+
+void simulate_thread_other_threads ()
+{
+}
+
+int simulate_thread_step_verify ()
+{
+  if (value != zero && value != max)
+    {
+      printf ("FAIL: invalid intermediate result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify ()
+{
+  if (value != 0)
+    {
+      printf ("FAIL: invalid final result for value.\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* All values written to 'value' alternate between 'zero' and
+   'max'. Any other value detected by simulate_thread_step_verify()
+   between instructions would indicate that the value was only
+   partially written, and would thus fail this atomicity test.
+
+   This function tests each different __sync_mem routine once, with
+   the exception of the load instruction which requires special
+   testing.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
+  if (ret != zero || value != max)
+    test_abort();
+
+  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
+  if (value != zero)
+    test_abort();
+
+  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+
+  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != max || ret != max)
+    test_abort ();
+
+  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
+  if (value != zero || ret != zero)
+    test_abort ();
+}
+
+int main ()
+{
+  simulate_thread_main ();
+  simulate_thread_done ();
+  return 0;
+}
Index: gcc.dg/simulate-thread/simulate-thread.h
===================================================================
--- gcc.dg/simulate-thread/simulate-thread.h	(revision 0)
+++ gcc.dg/simulate-thread/simulate-thread.h	(revision 0)
@@ -0,0 +1,111 @@ 
+int simulate_thread_fini = 0;
+
+void __attribute__((noinline))
+simulate_thread_done ()
+{
+  simulate_thread_fini = 1;
+}
+
+/* A hostile thread is one which changes a memory location so quickly
+   that another thread may never see the same value again.  This is
+   simulated when simulate_thread_other_thread() is defined to modify
+   a memory location every cycle.
+
+   A process implementing a dependency on this value can run into
+   difficulties with such a hostile thread.  For instance,
+   implementing an add with a compare_and_swap loop goes something
+   like:
+
+     expected = *mem;
+   loop:
+     new = expected += value;
+     if (!succeed (expected = compare_and_swap (mem, expected, new)))
+       goto loop;
+
+   If the content of 'mem' are changed every cycle by
+   simulate_thread_other_thread () this will become an infinite loop
+   since the value *mem will never be 'expected' by the time the
+   compare_and_swap is executed.
+
+   HOSTILE_THREAD_THRESHOLD defines the number of intructions which a
+   program will execute before triggering the hostile thread
+   pause. The pause will last for HOSTILE_THREAD_PAUSE instructions,
+   and then the counter will reset and begin again.  During the pause
+   period, simulate_thread_other_thread will not be called.
+
+   This provides a chance for forward progress to be made and the
+   infinite loop to be avoided.
+
+   If the testcase defines HOSTILE_PAUSE_ERROR, then it will be
+   considered an RUNTIME FAILURE if the hostile pause is triggered.
+   This will allow to test for guaranteed forward progress routines.
+
+   If the default values for HOSTILE_THREAD_THRESHOLD or
+   HOSTILE_THREAD_PAUSE are insufficient, then the testcase may
+   override these by defining the values before including this file.
+
+   Most testcase are intended to run for very short periods of time,
+   so these defaults are considered to be high enough to not trigger
+   on a typical case, but not drag the test time out too much if a
+   hostile condition is interferring.  */
+
+  
+/* Define the threshold to start pausing the hostile thread.  */
+#if !defined (HOSTILE_THREAD_THRESHOLD)
+#define HOSTILE_THREAD_THRESHOLD 	500
+#endif
+
+/* Define the length of pause in cycles for the hostile thread to pause to
+   allow forward progress to be made.  */
+#if !defined (HOSTILE_THREAD_PAUSE)
+#define HOSTILE_THREAD_PAUSE	20
+#endif
+
+void simulate_thread_other_threads (void);
+int simulate_thread_final_verify (void);
+
+static int simulate_thread_hostile_pause = 0;
+
+/* This function wraps simulate_thread_other_threads an monitors for
+   an infinite loop.  If the threshold value HOSTILE_THREAD_THRESHOLD
+   is reached, the other_thread process is paused for
+   HOSTILE_THREAD_PAUSE cycles before resuming, and the counters start
+   again.  */
+void
+simulate_thread_wrapper_other_threads()
+{
+  static int count = 0;
+  static int pause = 0;
+
+  if (++count >= HOSTILE_THREAD_THRESHOLD)
+    {
+      if (!simulate_thread_hostile_pause)
+        simulate_thread_hostile_pause = 1;
+
+      /* Count cycles before calling the hostile thread again.  */
+      if (pause++ < HOSTILE_THREAD_PAUSE)
+	return;
+
+      /* Reset the pause counter, as well as the thread counter.  */
+      pause = 0;
+      count = 0;
+    }
+  simulate_thread_other_threads ();
+}
+
+
+/* If the test case defines HOSTILE_PAUSE_ERROR, then the test case
+   will fail execution if it had a hostile pause.  */
+int
+simulate_thread_wrapper_final_verify ()
+{
+  int ret = simulate_thread_final_verify ();
+#if defined (HOSTILE_PAUSE_ERROR)
+  if (simulate_thread_hostile_pause)
+    {
+      printf ("FAIL: Forward progress made only by pausing hostile thread\n");
+      ret = ret | 1;    /* 0 indicates proper comnpletion.  */
+    }
+#endif
+  return ret;
+}
Index: gcc.dg/memmodel/strict-align-global.c
===================================================================
--- gcc.dg/memmodel/strict-align-global.c	(revision 179750)
+++ gcc.dg/memmodel/strict-align-global.c	(working copy)
@@ -1,46 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "--param allow-packed-store-data-races=0" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* This test verifies writes to globals do not write to adjacent
-   globals.  This mostly happens on strict-align targets that are not
-   byte addressable (old Alphas, etc).  */
-
-char a = 0;
-char b = 77;
-
-void memmodel_other_threads() 
-{
-}
-
-int memmodel_step_verify()
-{
-  if (b != 77)
-    {
-      printf("FAIL: Unexpected value.  <b> is %d, should be 77\n", b);
-      return 1;
-    }
-  return 0;
-}
-
-/* Verify that every variable has the correct value.  */
-int memmodel_final_verify()
-{
-  int ret = memmodel_step_verify ();
-  if (a != 66)
-    {
-      printf("FAIL: Unexpected value.  <a> is %d, should be 66\n", a);
-      return 1;
-    }
-  return ret;
-}
-
-int main ()
-{
-  a = 66;
-  memmodel_done();
-  return 0;
-}
Index: gcc.dg/memmodel/memmodel.h
===================================================================
--- gcc.dg/memmodel/memmodel.h	(revision 179750)
+++ gcc.dg/memmodel/memmodel.h	(working copy)
@@ -1,107 +0,0 @@ 
-int __gdb_memmodel_fini = 0;
-
-void __attribute__((noinline))
-memmodel_done ()
-{
-  __gdb_memmodel_fini = 1;
-}
-
-
-/* A hostile thread is one which changes a memory location so quickly that 
-   another thread may never see the same value again.  This is simulated when
-   memmodel_other_thread() is defined to modify a memory location every cycle.
-
-   A process implementing a dependency on this value can run into difficulties
-   with such a hostile thread.  for instance, implementing an add with a 
-   compare_and_swap loop goes something like:
-     expected = *mem;
-   loop:
-     new = expected += value;
-     if (!succeed (expected = compare_and_swap (mem, expected, new)))
-       goto loop;
-
-   if the content of 'mem' are changed every cycle by memodel_other_thread ()
-   this will become an infinite loop since the value *mem will never be 
-   'expected' by the time the compare_and_swap is executed.
-
-   HOSTILE_THREAD_THRESHOLD defines the number of intructions which a program 
-   will execute before triggering the hostile threead pause. The pause will 
-   last for HOSTILE_THREAD_PAUSE instructions, and then the counter will reset
-   and begin again.  During the pause period, memodel_other_thread will not
-   be called. 
-
-   This provides a chance for forward progress to be made and the infinite loop
-   to be avoided.
-
-   if the testcase defines HOSTILE_PAUSE_ERROR, then it will be considered an
-   RUNTIME FAILURE if the hostile pause is triggered.  This will allow to test
-   for guaranteed forward progress routines.
-
-   If the default values for HOSTILE_THREAD_THRESHOLD or HOSTILE_THREAD_PAUSE
-   are insufficient, then the testcase may override these by defining the
-   values before including this file.   
-
-   Most testcase are intended to run for very short periods of time, so these
-   defaults are considered to be high enough to not trigger on a typical case,
-   but not drag the test time out too much if a hostile condition is 
-   interferring.  */
-
-  
-/* Define the threshold to start pausing the hostile thread.  */
-#if !defined (HOSTILE_THREAD_THRESHOLD)
-#define HOSTILE_THREAD_THRESHOLD 	500
-#endif
-
-/* Define the length of pause in cycles for the hostile thread to pause to
-   allow forward progress to be made.  */
-#if !defined (HOSTILE_THREAD_PAUSE)
-#define HOSTILE_THREAD_PAUSE	20
-#endif
-
-void memmodel_other_threads (void);
-int memmodel_final_verify (void);
-
-static int __gdb_hostile_pause = 0;
-
-/* This function wraps memodel_other_threads an monitors for an infinite loop.
-   If the threshold value HOSTILE_THREAD_THRESHOLD is reached, the other_thread
-   process is paused for HOSTILE_THREAD_PAUSE cycles before resuming, and the
-   counters start again.  */
-void
-__gdb_wrapper_other_threads()
-{
-  static int count = 0;
-  static int pause = 0;
-
-  if (++count >= HOSTILE_THREAD_THRESHOLD)
-    {
-      if (!__gdb_hostile_pause)
-        __gdb_hostile_pause = 1;
-
-      /* Count cycles before calling the hostile thread again.  */
-      if (pause++ < HOSTILE_THREAD_PAUSE)
-	return;
-
-      /* Reset the pause counter, as well as the thread counter.  */
-      pause = 0;
-      count = 0;
-    }
-  memmodel_other_threads ();
-}
-
-
-/* If the test case defines HOSTILE_PAUSE_ERROR, then the test case will 
-   fail execution if it had a hostile pause.  */
-int
-__gdb_wrapper_final_verify ()
-{
-  int ret = memmodel_final_verify ();
-#if defined (HOSTILE_PAUSE_ERROR)
-  if (__gdb_hostile_pause)
-    {
-      printf ("FAIL: Forward progress made only by pausing hostile thread\n");
-      ret = ret | 1;    /* 0 indicates proper comnpletion.  */
-    }
-#endif
-  return ret;
-}
Index: gcc.dg/memmodel/sync-load-longlong.c
===================================================================
--- gcc.dg/memmodel/sync-load-longlong.c	(revision 179750)
+++ gcc.dg/memmodel/sync-load-longlong.c	(working copy)
@@ -1,112 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_long_long } */
-/* { dg-options "" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-
-/* Testing load for atomicity is a little trickier.  
-
-   Set up the atomic value so that it changes value after every instruction 
-   is executed.
-
-   Simply alternating between 2 values wouldn't be sufficient since a load of
-   one part, followed by the load of the second part 2 instructions later would
-   appear to be valid.
-
-   set up a table of 16 values which change a bit in every byte of the value 
-   each time, this will give us a 16 instruction cycle before repetition
-   kicks in, which should be sufficient to detect any issues.  Just to be sure,
-   we also change the table cycle size during execution. 
-   
-   The end result is that all loads should always get one of the values from
-   the table. Any other pattern means the load failed.  */
-
-unsigned long long ret;
-unsigned long long value = 0;
-unsigned long long result = 0;
-unsigned long long table[16] = {
-0x0000000000000000, 
-0x1111111111111111, 
-0x2222222222222222, 
-0x3333333333333333,
-0x4444444444444444,
-0x5555555555555555,
-0x6666666666666666,
-0x7777777777777777,
-0x8888888888888888,
-0x9999999999999999,
-0xAAAAAAAAAAAAAAAA,
-0xBBBBBBBBBBBBBBBB,
-0xCCCCCCCCCCCCCCCC,
-0xDDDDDDDDDDDDDDDD,
-0xEEEEEEEEEEEEEEEE,
-0xFFFFFFFFFFFFFFFF
-};
-
-int table_cycle_size = 16;
-
-/* Return 0 if 'result' is a valid value to have loaded.  */
-int verify_result ()
-{
-  int x;
-  int found = 0;
-
-  /* Check entire table for valid values.  */
-  for (x = 0; x < 16 ; x++)
-    if (result == table[x])
-      {
-	found = 1;
-	break;
-      }
-
-  if (!found)
-    printf("FAIL: Invalid result returned from fetch\n");
-
-  return !found;
-}
-
-/* Iterate VALUE through the different valid values. */
-void memmodel_other_threads ()
-{
-  static int current = 0;
-
-  if (++current >= table_cycle_size)
-    current = 0;
-  value = table[current];
-}
-
-int memmodel_step_verify ()
-{
-  return verify_result ();
-}
-
-int memmodel_final_verify ()
-{
-  return verify_result ();
-}
-
-main()
-{
-  int x;
-
-  /* Execute loads with value changing at various cyclic values.  */
-  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
-    {
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      /* In order to verify the returned value (which is not atomic), it needs
-	 to be atomically stored into another variable and check that.  */
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-
-      /* Execute the fetch/store a couple of times just to ensure the cycles
-         have a chance to be interesting.  */
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-    }
-  
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/sync-other-longlong.c
===================================================================
--- gcc.dg/memmodel/sync-other-longlong.c	(revision 179750)
+++ gcc.dg/memmodel/sync-other-longlong.c	(working copy)
@@ -1,113 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_long_long } */
-/* { dg-options "" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* Test all the __sync routines for proper atomicity on 8 byte values.  */
-
-unsigned long long zero = 0;
-unsigned long long max = ~0;
-
-unsigned long long changing_value = 0;
-unsigned long long value = 0;
-unsigned long long ret;
-
-void test_abort()
-{
-  static int reported = 0;
-  if (!reported)
-    {
-      printf ("FAIL: improper execution of __sync builtin.\n");
-      reported = 1;
-    }
-}
-
-void memmodel_other_threads ()
-{
-}
-
-int memmodel_step_verify ()
-{
-  if (value != zero && value != max)
-    {
-      printf ("FAIL: invalid intermediate result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-int memmodel_final_verify ()
-{
-  if (value != 0)
-    {
-      printf ("FAIL: invalid final result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-/* All values written to 'value' alternate between 'zero' and 'max'. Any other
-   value detected by memmodel_step_verify() between instructions would indicate
-   that the value was only partially written, and would thus fail this 
-   atomicity test.  
-
-   This function tests each different __sync_mem routine once, with the
-   exception of the load instruction which requires special testing.  */
-main()
-{
-  
-  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
-  if (ret != zero || value != max)
-    test_abort();
-
-  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
-  if (value != zero)
-    test_abort();
-
-  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/memmodel.gdb
===================================================================
--- gcc.dg/memmodel/memmodel.gdb	(revision 179750)
+++ gcc.dg/memmodel/memmodel.gdb	(working copy)
@@ -1,17 +0,0 @@ 
-set height 0
-break main
-disp/i $pc
-run
-
-set $ret = 0
-while (__gdb_memmodel_fini != 1) && (! $ret)
-  call __gdb_wrapper_other_threads()
-  stepi
-  set $ret |= memmodel_step_verify()
-end
-
-if (! $ret)
-  set $ret |= __gdb_wrapper_final_verify()
-end
-continue
-quit $ret
Index: gcc.dg/memmodel/memmodel.exp
===================================================================
--- gcc.dg/memmodel/memmodel.exp	(revision 179750)
+++ gcc.dg/memmodel/memmodel.exp	(working copy)
@@ -1,58 +0,0 @@ 
-# Your run of the mill dg test, but verify that we have a working GDB first.
-
-load_lib gcc-dg.exp
-load_lib gcc-memmodel-gdb-test.exp
-load_lib torture-options.exp
-
-proc check_guality {args} {
-    set result [eval check_compile guality_check executable $args "-g -O0"]
-    set lines [lindex $result 0]
-    set output [lindex $result 1]
-    set ret 0
-    if {[string match "" $lines]} {
-      set execout [gcc_load "./$output"]
-      set ret [string match "*1 PASS, 0 FAIL, 0 UNRESOLVED*" $execout]
-    }
-    remote_file build delete $output
-    return $ret
-}
-
-dg-init
-torture-init
-set-torture-options [list \
-	{ -O0 -g } \
-	{ -O1 -g } \
-	{ -O2 -g } \
-	{ -O3 -g } \
-	{ -Os -g } ]
-
-# Test the presence of gdb with the guality infrastructure.
-global GDB
-if ![info exists ::env(GUALITY_GDB_NAME)] {
-    if [info exists GDB] {
-	set guality_gdb_name "$GDB"
-    } else {
-	set guality_gdb_name "[transform gdb]"
-    }
-    setenv GUALITY_GDB_NAME "$guality_gdb_name"
-}
-if {[check_guality "
-  #include \"$srcdir/$subdir/guality.h\"
-  volatile long int varl = 6;
-  int main (int argc, char *argv\[\])
-  {
-    GUALCHKVAL (varl);
-    return 0;
-  }
-"]} {
-  gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.c]] ""
-# Uncomment line below when we have common C/C++ tests.
-#  gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/memmodel/*.c]] ""
-}
-
-if [info exists guality_gdb_name] {
-    unsetenv GUALITY_GDB_NAME
-}
-
-torture-finish
-dg-finish
Index: gcc.dg/memmodel/sync-load-int128.c
===================================================================
--- gcc.dg/memmodel/sync-load-int128.c	(revision 179750)
+++ gcc.dg/memmodel/sync-load-int128.c	(working copy)
@@ -1,127 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
-/* { dg-final { memmodel-gdb-test } } */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-
-/* Testing load for atomicity is a little trickier.  
-
-   Set up the atomic value so that it changes value after every instruction 
-   is executed.
-
-   Simply alternating between 2 values wouldn't be sufficient since a load of
-   one part, followed by the load of the second part 2 instructions later would
-   appear to be valid.
-
-   set up a table of 16 values which change a bit in every byte of the value 
-   each time, this will give us a 16 instruction cycle before repetition
-   kicks in, which should be sufficient to detect any issues.  Just to be sure,
-   we also change the table cycle size during execution. 
-   
-   The end result is that all loads should always get one of the values from
-   the table. Any other pattern means the load failed.  */
-
-__int128_t ret;
-__int128_t value = 0;
-__int128_t result = 0;
-__int128_t table[16] = {
-0x0000000000000000, 
-0x1111111111111111, 
-0x2222222222222222, 
-0x3333333333333333,
-0x4444444444444444,
-0x5555555555555555,
-0x6666666666666666,
-0x7777777777777777,
-0x8888888888888888,
-0x9999999999999999,
-0xAAAAAAAAAAAAAAAA,
-0xBBBBBBBBBBBBBBBB,
-0xCCCCCCCCCCCCCCCC,
-0xDDDDDDDDDDDDDDDD,
-0xEEEEEEEEEEEEEEEE,
-0xFFFFFFFFFFFFFFFF
-};
-
-int table_cycle_size = 16;
-
-/* Since we don't have 128 bit constants, we have to properly pad the table.  */
-void fill_table()
-{
-  int x;
-  for (x = 0; x < 16; x++)
-    {
-      ret = table[x];
-      ret = (ret << 64) | ret;
-      table[x] = ret;
-    }
-}
-
-/* Return 0 if 'result' is a valid value to have loaded.  */
-int verify_result ()
-{
-  int x;
-  int found = 0;
-
-  /* Check entire table for valid values.  */
-  for (x = 0; x < 16; x++)
-    if (result == table[x])
-      {
-	found = 1;
-	break;
-      }
-
-  if (!found)
-    printf("FAIL: Invalid result returned from fetch\n");
-
-  return !found;
-}
-
-/* Iterate VALUE through the different valid values. */
-void memmodel_other_threads ()
-{
-  static int current = 0;
-
-  if (++current >= table_cycle_size)
-    current = 0;
-  value = table[current];
-}
-
-int memmodel_step_verify ()
-{
-  return verify_result ();
-}
-
-int memmodel_final_verify ()
-{
-  return verify_result ();
-}
-
-main()
-{
-  int x;
-
-  fill_table ();
-  /* Make sure value starts with an atomic value now.  */
-  __sync_mem_store (&value, ret, __SYNC_MEM_SEQ_CST);
-
-  /* Execute loads with value changing at various cyclic values.  */
-  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
-    {
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      /* In order to verify the returned value (which is not atomic), it needs
-	 to be atomically stored into another variable and check that.  */
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-
-      /* Execute the fetch/store a couple of times just to ensure the cycles
-         have a chance to be interesting.  */
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-    }
-  
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/README
===================================================================
--- gcc.dg/memmodel/README	(revision 179750)
+++ gcc.dg/memmodel/README	(working copy)
@@ -1,102 +0,0 @@ 
-OVERVIEW
---------
-
-This is a harness to test the atomicity of certain operations, and to
-make sure the compiler does not introduce data races in a
-multi-threaded environment.
-
-The basic premise is that we set up testcases such that the thing we
-want test, say an atomic instruction which stores a double word is in
-a function of its own.  We then run this testcase within GDB,
-controlled by a gdb script (memmodel.gdb).  The gdb script will break
-on the function to be tested, and then single step through every
-machine instruction in the function.  We set this up so GDB can make a
-couple of inferior function calls before and after each of these
-single step instructions for a couple of purposes:
-
-       1.  One of the calls simulates another thread running in the
-           process which changes or access memory.
-
-       2.  The other calls are used to verify that we always get the
-           expected behavior.
-
-For example, in the case of an atomic store, anyone looking at the
-memory associated with an atomic variable should never see any in
-between states. If you have an atomic long long int, and it starts
-with the value 0, and you write the value MAX_LONG_LONG, any other
-thread looking at that variable should never see anything other than 0
-or MAX_LONG_LONG.  If you implement the atomic write as a sequence of
-2 stores, it is possible for another thread to read the location after
-the first store, but before the second one is complete. That thread
-would then see an in-between state (one word would still be 0).
-
-We simulate this in the testcase by having GDB step through the
-program, instruction by instruction, and after each step, making an
-inferior function call which looks at the value of the atomic variable
-and verifies that it sees either 0 or MAX_LONG_LONG.  If it sees any
-other value, it fails the testcase.
-
-This way, we are *sure* there is no in between state because we
-effectively acted like an OS and switched to another thread after
-every single instruction of the routine is executed and looked at the
-results each time.
-
-We use the same idea to test for data races to see if an illegal load
-has been hoisted, or that two parallel bitfield writes don't overlap
-in a data race.
-
-Below is a skeleton of how a test should look like.  For more details,
-look at the tests themselves.
-
-ANATOMY OF A TEST
------------------
-
-/* { dg-do link } */
-/* { dg-options "-some-flags" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-/* NOTE: Any failure must be indicated by displaying "FAIL:".  */
-
-#include "memmodel.h"
-
-/* Called before each instruction, simulating another thread
-   executing.  */
-void memmodel_other_threads()
-{
-}
-
-/* Called after each instruction.  Returns 1 if any inconsistency is
-   found, 0 otherwise.  */
-int memmodel_step_verify()
-{
-  if (some_problem)
-    {
-      printf("FAIL: reason\n");
-      return 1;
-    }
-  return 0;
-}
-
-/* Called at the end of the program (memmodel_fini == 1).  Verifies
-   the state of the program and returns 1 if any inconsistency is
-   found, 0 otherwise.  */
-int memmodel_final_verify()
-{
-  if (some_problem)
-    {
-      printf("FAIL: reason\n");
-      return 1;
-    }
-  return 0;
-}
-
-int main()
-{
-  /* Do stuff.  */
-  /* ... */
-
-  /* Must be called at the end of the test.  */
-  memmodel_done();
-
-  return 0;
-}
Index: gcc.dg/memmodel/sync-other-int128.c
===================================================================
--- gcc.dg/memmodel/sync-other-int128.c	(revision 179750)
+++ gcc.dg/memmodel/sync-other-int128.c	(working copy)
@@ -1,111 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_int_128 } */
-/* { dg-options "-mcx16" { target { x86_64-*-* } } } */
-/* { dg-final { memmodel-gdb-test } } */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* Test all the __sync routines for proper atomicity on 16 byte values.  */
-
-__int128_t zero = 0;
-__int128_t max = ~0;
-__int128_t changing_value = 0;
-__int128_t value = 0;
-__int128_t ret;
-
-void test_abort()
-{
-  static int reported = 0;
-  if (!reported)
-    {
-      printf ("FAIL: improper execution of __sync builtin.\n");
-      reported = 1;
-    }
-}
-
-void memmodel_other_threads ()
-{
-}
-
-int memmodel_step_verify ()
-{
-  if (value != zero && value != max)
-    {
-      printf ("FAIL: invalid intermediate result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-int memmodel_final_verify ()
-{
-  if (value != 0)
-    {
-      printf ("FAIL: invalid final result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-/* All values written to 'value' alternate between 'zero' and 'max'. Any other
-   value detected by memmodel_step_verify() between instructions would indicate
-   that the value was only partially written, and would thus fail this 
-   atomicity test.  
-
-   This function tests each different __sync_mem routine once, with the
-   exception of the load instruction which requires special testing.  */
-main()
-{
-  
-  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
-  if (ret != zero || value != max)
-    test_abort();
-
-  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
-  if (value != zero)
-    test_abort();
-
-  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/speculative-store.c
===================================================================
--- gcc.dg/memmodel/speculative-store.c	(revision 179750)
+++ gcc.dg/memmodel/speculative-store.c	(working copy)
@@ -1,49 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "--param allow-store-data-races=0" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* This file tests that speculative store movement out of a loop doesn't 
-   happen.  This is disallowed when --param allow-store-data-races is 0.  */
-
-int global = 100;
-
-/* Other thread makes sure global is 100 before the next instruction is
- * exceuted.  */
-void memmodel_other_threads() 
-{
-  global = 100;
-}
-
-int memmodel_step_verify()
-{
-  if (global != 100)
-    {
-      printf("FAIL: global variable was assigned to.  \n");
-      return 1;
-    }
-}
-
-int memmodel_final_verify()
-{
-  return 0;
-}
-
-/* The variable global should never be assigned if func(0) is called.
-   This tests store movement out of loop thats never executed. */
-void test (int y)
-{
-  int x;
-  for (x=0; x< y; x++)
-    {
-       global = y;   /* This should never speculatively execute.  */
-    }
-}
-
-int main()
-{
-  test(0);
-  memmodel_done();
-}
Index: gcc.dg/memmodel/subfields.c
===================================================================
--- gcc.dg/memmodel/subfields.c	(revision 179750)
+++ gcc.dg/memmodel/subfields.c	(working copy)
@@ -1,87 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "--param allow-packed-store-data-races=0" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* This test verifies that data races aren't introduced by structure subfield 
-   stores. */
-
-struct test_struct {
-  char a;
-  char b;
-  char c;
-  char d;
-} var = {0,0,0,0};
-
-
-/* This routine sets field a to 'x'.  If executed properly, it will
-   not affect any of the other fields in the structure.  An improper
-   implementation may load an entire word, change the 8 bits for field
-   'a' and write the entire word back out. */
-__attribute__((noinline))
-void set_a(char x)
-{
-  var.a = x;
-}
-
-static int global = 0;
-
-/* The other thread increments the value of each of the other fields
-   in the structure every cycle.  If the store to the 'a' field does
-   an incorrect full or partial word load, mask and store, it will
-   write back an incorrect value to one or more of the other
-   fields.  */
-void memmodel_other_threads() 
-{
-  global++;
-  var.b = global;
-  var.c = global;
-  var.d = global;
-}
-
-
-/* Make sure that none of the other fields have been changed.  */
-int memmodel_step_verify()
-{
-  int ret = 0;
-  if (var.b != global)
-    {
-      printf("FAIL: Unexpected value. var.b is %d, should be %d\n",
-	     var.b, global);
-      ret = 1;
-    }
-  if (var.c != global)
-    {
-      printf("FAIL: Unexpected value. var.c is %d, should be %d\n",
-	     var.c, global);
-      ret = 1;
-    }
-  if (var.d != global)
-    {
-      printf("FAIL: Unexpected value. var.d is %d, should be %d\n",
-	     var.d, global);
-      ret = 1;
-    }
-  return ret;
-}
-
-/* Verify that every variable has the correct value.  */
-int memmodel_final_verify()
-{
-  int ret = memmodel_step_verify();
-  if (var.a != 1)
-    {
-      printf("FAIL: Unexpected value. var.a is %d, should be %d\n", var.a, 1);
-      ret = 1;
-    }
-  return ret;
-}
-
-int main ()
-{
-  set_a(1);
-  memmodel_done();
-  return 0;
-}
Index: gcc.dg/memmodel/sync-load-int.c
===================================================================
--- gcc.dg/memmodel/sync-load-int.c	(revision 179750)
+++ gcc.dg/memmodel/sync-load-int.c	(working copy)
@@ -1,111 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_int_long } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-
-/* Testing load for atomicity is a little trickier.  
-
-   Set up the atomic value so that it changes value after every instruction 
-   is executed.
-
-   Simply alternating between 2 values wouldn't be sufficient since a load of
-   one part, followed by the load of the second part 2 instructions later would
-   appear to be valid.
-
-   set up a table of 16 values which change a bit in every byte of the value 
-   each time, this will give us a 16 instruction cycle before repetition
-   kicks in, which should be sufficient to detect any issues.  Just to be sure,
-   we also change the table cycle size during execution. 
-   
-   The end result is that all loads should always get one of the values from
-   the table. Any other pattern means the load failed.  */
-
-unsigned int ret;
-unsigned int value = 0;
-unsigned int result = 0;
-unsigned int table[16] = {
-0x00000000, 
-0x11111111, 
-0x22222222, 
-0x33333333,
-0x44444444,
-0x55555555,
-0x66666666,
-0x77777777,
-0x88888888,
-0x99999999,
-0xAAAAAAAA,
-0xBBBBBBBB,
-0xCCCCCCCC,
-0xDDDDDDDD,
-0xEEEEEEEE,
-0xFFFFFFFF
-};
-
-int table_cycle_size = 16;
-
-/* Return 0 if 'result' is a valid value to have loaded.  */
-int verify_result ()
-{
-  int x;
-  int found = 0;
-
-  /* Check entire table for valid values.  */
-  for (x = 0; x < 16 ; x++)
-    if (result == table[x])
-      {
-	found = 1;
-	break;
-      }
-
-  if (!found)
-    printf("FAIL: Invalid result returned from fetch\n");
-
-  return !found;
-}
-
-/* Iterate VALUE through the different valid values. */
-void memmodel_other_threads ()
-{
-  static int current = 0;
-
-  if (++current >= table_cycle_size)
-    current = 0;
-  value = table[current];
-}
-
-int memmodel_step_verify ()
-{
-  return verify_result ();
-}
-
-int memmodel_final_verify ()
-{
-  return verify_result ();
-}
-
-main()
-{
-  int x;
-
-  /* Execute loads with value changing at various cyclic values.  */
-  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
-    {
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      /* In order to verify the returned value (which is not atomic), it needs
-	 to be atomically stored into another variable and check that.  */
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-
-      /* Execute the fetch/store a couple of times just to ensure the cycles
-         have a chance to be interesting.  */
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-    }
-  
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/sync-other-int.c
===================================================================
--- gcc.dg/memmodel/sync-other-int.c	(revision 179750)
+++ gcc.dg/memmodel/sync-other-int.c	(working copy)
@@ -1,112 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_int_long } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* Test all the __sync routines for proper atomicity on 4 byte values.  */
-
-unsigned int zero = 0;
-unsigned int max = ~0;
-
-unsigned int changing_value = 0;
-unsigned int value = 0;
-unsigned int ret;
-
-void test_abort()
-{
-  static int reported = 0;
-  if (!reported)
-    {
-      printf ("FAIL: improper execution of __sync builtin.\n");
-      reported = 1;
-    }
-}
-
-void memmodel_other_threads ()
-{
-}
-
-int memmodel_step_verify ()
-{
-  if (value != zero && value != max)
-    {
-      printf ("FAIL: invalid intermediate result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-int memmodel_final_verify ()
-{
-  if (value != 0)
-    {
-      printf ("FAIL: invalid final result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-/* All values written to 'value' alternate between 'zero' and 'max'. Any other
-   value detected by memmodel_step_verify() between instructions would indicate
-   that the value was only partially written, and would thus fail this 
-   atomicity test.  
-
-   This function tests each different __sync_mem routine once, with the
-   exception of the load instruction which requires special testing.  */
-main()
-{
-  
-  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
-  if (ret != zero || value != max)
-    test_abort();
-
-  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
-  if (value != zero)
-    test_abort();
-
-  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/guality.h
===================================================================
--- gcc.dg/memmodel/guality.h	(revision 179750)
+++ gcc.dg/memmodel/guality.h	(working copy)
@@ -1 +0,0 @@ 
-#include "../../gcc.dg/guality/guality.h"
Index: gcc.dg/memmodel/sync-load-short.c
===================================================================
--- gcc.dg/memmodel/sync-load-short.c	(revision 179750)
+++ gcc.dg/memmodel/sync-load-short.c	(working copy)
@@ -1,111 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_char_short } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-
-/* Testing load for atomicity is a little trickier.  
-
-   Set up the atomic value so that it changes value after every instruction 
-   is executed.
-
-   Simply alternating between 2 values wouldn't be sufficient since a load of
-   one part, followed by the load of the second part 2 instructions later would
-   appear to be valid.
-
-   set up a table of 16 values which change a bit in every byte of the value 
-   each time, this will give us a 16 instruction cycle before repetition
-   kicks in, which should be sufficient to detect any issues.  Just to be sure,
-   we also change the table cycle size during execution. 
-   
-   The end result is that all loads should always get one of the values from
-   the table. Any other pattern means the load failed.  */
-
-unsigned short ret;
-unsigned short value = 0;
-unsigned short result = 0;
-unsigned short table[16] = {
-0x0000, 
-0x1111, 
-0x2222, 
-0x3333,
-0x4444,
-0x5555,
-0x6666,
-0x7777,
-0x8888,
-0x9999,
-0xAAAA,
-0xBBBB,
-0xCCCC,
-0xDDDD,
-0xEEEE,
-0xFFFF
-};
-
-int table_cycle_size = 16;
-
-/* Return 0 if 'result' is a valid value to have loaded.  */
-int verify_result ()
-{
-  int x;
-  int found = 0;
-
-  /* Check entire table for valid values.  */
-  for (x = 0; x < 16 ; x++)
-    if (result == table[x])
-      {
-	found = 1;
-	break;
-      }
-
-  if (!found)
-    printf("FAIL: Invalid result returned from fetch\n");
-
-  return !found;
-}
-
-/* Iterate VALUE through the different valid values. */
-void memmodel_other_threads ()
-{
-  static int current = 0;
-
-  if (++current >= table_cycle_size)
-    current = 0;
-  value = table[current];
-}
-
-int memmodel_step_verify ()
-{
-  return verify_result ();
-}
-
-int memmodel_final_verify ()
-{
-  return verify_result ();
-}
-
-main()
-{
-  int x;
-
-  /* Execute loads with value changing at various cyclic values.  */
-  for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--)
-    {
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      /* In order to verify the returned value (which is not atomic), it needs
-	 to be atomically stored into another variable and check that.  */
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-
-      /* Execute the fetch/store a couple of times just to ensure the cycles
-         have a chance to be interesting.  */
-      ret = __sync_mem_load (&value, __SYNC_MEM_SEQ_CST);
-      __sync_mem_store (&result, ret, __SYNC_MEM_SEQ_CST);
-    }
-  
-  memmodel_done ();
-  return 0;
-}
Index: gcc.dg/memmodel/sync-other-short.c
===================================================================
--- gcc.dg/memmodel/sync-other-short.c	(revision 179750)
+++ gcc.dg/memmodel/sync-other-short.c	(working copy)
@@ -1,112 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-require-effective-target sync_char_short } */
-/* { dg-final { memmodel-gdb-test } } */
-
-
-#include <stdio.h>
-#include "memmodel.h"
-
-/* Test all the __sync routines for proper atomicity on 2 byte values.  */
-
-unsigned short zero = 0;
-unsigned short max = ~0;
-
-unsigned short changing_value = 0;
-unsigned short value = 0;
-unsigned short ret;
-
-void test_abort()
-{
-  static int reported = 0;
-  if (!reported)
-    {
-      printf ("FAIL: improper execution of __sync builtin.\n");
-      reported = 1;
-    }
-}
-
-void memmodel_other_threads ()
-{
-}
-
-int memmodel_step_verify ()
-{
-  if (value != zero && value != max)
-    {
-      printf ("FAIL: invalid intermediate result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-int memmodel_final_verify ()
-{
-  if (value != 0)
-    {
-      printf ("FAIL: invalid final result for value.\n");
-      return 1;
-    }
-  return 0;
-}
-
-/* All values written to 'value' alternate between 'zero' and 'max'. Any other
-   value detected by memmodel_step_verify() between instructions would indicate
-   that the value was only partially written, and would thus fail this 
-   atomicity test.  
-
-   This function tests each different __sync_mem routine once, with the
-   exception of the load instruction which requires special testing.  */
-main()
-{
-  
-  ret = __sync_mem_exchange (&value, max, __SYNC_MEM_SEQ_CST);
-  if (ret != zero || value != max)
-    test_abort();
-
-  __sync_mem_store (&value, zero, __SYNC_MEM_SEQ_CST);
-  if (value != zero)
-    test_abort();
-
-  ret = __sync_mem_fetch_add (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_sub (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_or (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_fetch_and (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_fetch_xor (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_add_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_sub_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  ret = __sync_mem_or_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_and_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != max || ret != max)
-    test_abort ();
-
-  ret = __sync_mem_xor_fetch (&value, max, __SYNC_MEM_SEQ_CST);
-  if (value != zero || ret != zero)
-    test_abort ();
-
-  memmodel_done ();
-  return 0;
-}
Index: g++.dg/simulate-thread/atomics-2.C
===================================================================
--- g++.dg/simulate-thread/atomics-2.C	(revision 0)
+++ g++.dg/simulate-thread/atomics-2.C	(revision 0)
@@ -0,0 +1,58 @@ 
+/* { dg-do link } */
+/* { dg-options "-std=c++0x" } */
+/* { dg-final { simulate-thread } } */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "simulate-thread.h"
+
+atomic_int atomi;
+
+/* Non-atomic.  Use a type wide enough to possibly coerce GCC into
+   moving things around.  */
+long double j;
+
+
+/* Test that an atomic store synchronizes with an atomic load.
+
+   In this case, test that the store to <j> happens-before the atomic
+   store to <atomi>.  Make sure the compiler does not reorder the
+   stores.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  j = 13.0;
+  atomi.store(1);
+}
+
+int main ()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
+
+void simulate_thread_other_threads()
+{
+}
+
+/* Verify that side-effects before an atomic store are correctly
+   synchronized with the an atomic load to the same location.  */
+int simulate_thread_step_verify()
+{
+  if (atomi.load() == 1 && j != 13.0)
+    {
+      printf ("FAIL: invalid synchronization for atomic load/store.\n");
+      return 1;
+    }
+  return 0;
+}
+
+
+int simulate_thread_final_verify()
+{
+  return simulate_thread_step_verify();
+}
Index: g++.dg/simulate-thread/simulate-thread.exp
===================================================================
--- g++.dg/simulate-thread/simulate-thread.exp	(revision 0)
+++ g++.dg/simulate-thread/simulate-thread.exp	(revision 0)
@@ -0,0 +1,39 @@ 
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+
+# Your run of the mill dg test, but verify that we have a working GDB first.
+
+load_lib g++-dg.exp
+load_lib gcc-simulate-thread.exp
+load_lib torture-options.exp
+
+dg-init
+torture-init
+set-torture-options [list \
+	{ -O0 -g } \
+	{ -O1 -g } \
+	{ -O2 -g } \
+	{ -O3 -g } \
+	{ -Os -g } ]
+
+if [gdb-exists] {
+  gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] ""
+  gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/simulate-thread/*.c]] ""
+}
+
+torture-finish
+dg-finish
Index: g++.dg/simulate-thread/simulate-thread.gdb
===================================================================
--- g++.dg/simulate-thread/simulate-thread.gdb	(revision 0)
+++ g++.dg/simulate-thread/simulate-thread.gdb	(revision 0)
@@ -0,0 +1 @@ 
+source ../../gcc.dg/simulate-thread/simulate-thread.gdb
Index: g++.dg/simulate-thread/bitfields-2.C
===================================================================
--- g++.dg/simulate-thread/bitfields-2.C	(revision 0)
+++ g++.dg/simulate-thread/bitfields-2.C	(revision 0)
@@ -0,0 +1,77 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
+   In the C++ memory model, non contiguous bitfields ("a" and "c"
+   here) should be considered as distinct memory locations, so we
+   can't use bit twiddling to set either one.  */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+#define CONSTA 12
+
+static int global;
+struct S
+{
+  unsigned int a : 4;
+  unsigned char b;
+  unsigned int c : 6;
+} var;
+
+__attribute__((noinline))
+void set_a()
+{
+  var.a = CONSTA;
+}
+
+void simulate_thread_other_threads()
+{
+  ++global;
+  var.b = global;
+  var.c = global;
+}
+
+int simulate_thread_step_verify()
+{
+  int ret = 0;
+  if (var.b != global)
+    {
+      printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
+	      var.b, global);
+      ret = 1;
+    }
+  if (var.c != global)
+    {
+      printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
+	      var.c, global);
+      ret = 1;
+    }
+  return ret;
+}
+
+int simulate_thread_final_verify()
+{
+  int ret = simulate_thread_step_verify();
+  if (var.a != CONSTA)
+    {
+      printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
+	      var.a, CONSTA);
+      ret = 1;
+    }
+  return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  set_a();
+}
+
+int main()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: g++.dg/simulate-thread/bitfields.C
===================================================================
--- g++.dg/simulate-thread/bitfields.C	(revision 0)
+++ g++.dg/simulate-thread/bitfields.C	(revision 0)
@@ -0,0 +1,80 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
+   In the C++ memory model, non contiguous bitfields ("a" and "c"
+   here) should be considered as distinct memory locations, so we
+   can't use bit twiddling to set either one.  */
+
+#include <stdio.h>
+#include "simulate-thread.h"
+
+#define CONSTA 12
+
+static int global;
+struct S
+{
+  /* On x86-64, the volatile causes us to access <a> with a 32-bit
+     access, and thus trigger this test.  */
+  volatile unsigned int a : 4;
+
+  unsigned char b;
+  unsigned int c : 6;
+} var;
+
+__attribute__((noinline))
+void set_a()
+{
+  var.a = CONSTA;
+}
+
+void simulate_thread_other_threads()
+{
+  ++global;
+  var.b = global;
+  var.c = global;
+}
+
+int simulate_thread_step_verify()
+{
+  int ret = 0;
+  if (var.b != global)
+    {
+      printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
+	      var.b, global);
+      ret = 1;
+    }
+  if (var.c != global)
+    {
+      printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
+	      var.c, global);
+      ret = 1;
+    }
+  return ret;
+}
+
+int simulate_thread_final_verify()
+{
+  int ret = simulate_thread_step_verify();
+  if (var.a != CONSTA)
+    {
+      printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
+	      var.a, CONSTA);
+      ret = 1;
+    }
+  return ret;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  set_a();
+}
+
+int main ()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: g++.dg/simulate-thread/atomics-1.C
===================================================================
--- g++.dg/simulate-thread/atomics-1.C	(revision 0)
+++ g++.dg/simulate-thread/atomics-1.C	(revision 0)
@@ -0,0 +1,73 @@ 
+/* { dg-do link } */
+/* { dg-options "-std=c++0x" } */
+/* { dg-final { simulate-thread } } */
+
+/* Test that atomic int and atomic char work properly.  */
+
+using namespace std;
+
+#include <atomic>
+#include <limits.h>
+#include <stdio.h>
+#include "simulate-thread.h"
+
+atomic<int> atomi;
+atomic<char> atomc;
+
+/* No need for parallel threads to do anything */
+void simulate_thread_other_threads()
+{
+}
+
+/* Verify after every instruction is executed, that the atmoic int and
+   char have one of the 2 legitimate values. */
+int simulate_thread_step_verify()
+{
+  if (atomi != 0 && atomi != INT_MAX)
+    {
+      printf ("FAIL: invalid intermediate result for atomi (%d).\n",
+	      (int)atomi);
+      return 1;
+    }
+  if (atomc != 0 && atomc != CHAR_MAX)
+    {
+      printf ("FAIL: invalid intermediate result for atomc (%d).\n",
+	      (int)atomc);
+      return 1;
+    }
+  return 0;
+}
+
+
+/* Verify that both atmoics have the corerct value.  */
+int simulate_thread_final_verify()
+{
+  if (atomi != INT_MAX)
+    {
+      printf ("FAIL: invalid final result for atomi (%d).\n",
+	      (int)atomi);
+      return 1;
+    }
+  if (atomc != CHAR_MAX)
+    {
+      printf ("FAIL: invalid final result for atomc (%d).\n",
+	      (int)atomc);
+      return 1;
+    }
+  return 0;
+}
+
+/* Test a store to an atomic int and an atomic char. */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  atomi = INT_MAX;
+  atomc = CHAR_MAX;
+}
+
+int main ()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: g++.dg/simulate-thread/simulate-thread.h
===================================================================
--- g++.dg/simulate-thread/simulate-thread.h	(revision 0)
+++ g++.dg/simulate-thread/simulate-thread.h	(revision 0)
@@ -0,0 +1 @@ 
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
Index: g++.dg/memmodel/atomics-2.C
===================================================================
--- g++.dg/memmodel/atomics-2.C	(revision 179750)
+++ g++.dg/memmodel/atomics-2.C	(working copy)
@@ -1,51 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "-std=c++0x" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-using namespace std;
-
-#include <atomic>
-#include <limits.h>
-#include <stdio.h>
-#include "memmodel.h"
-
-atomic_int atomi;
-
-/* Non-atomic.  Use a type wide enough to possibly coerce GCC into
-   moving things around.  */
-long double j;
-
-
-/* Test that an atomic store synchronizes with an atomic load.
-
-   In this case, test that the store to <j> happens-before the atomic
-   store to <atomi>.  Make sure the compiler does not reorder the
-   stores.  */
-main()
-{
-  j = 13.0;
-  atomi.store(1);
-  memmodel_done();
-}
-
-void memmodel_other_threads()
-{
-}
-
-/* Verify that side-effects before an atomic store are correctly
-   synchronized with the an atomic load to the same location.  */
-int memmodel_step_verify()
-{
-  if (atomi.load() == 1 && j != 13.0)
-    {
-      printf ("FAIL: invalid synchronization for atomic load/store.\n");
-      return 1;
-    }
-  return 0;
-}
-
-
-int memmodel_final_verify()
-{
-  return memmodel_step_verify();
-}
Index: g++.dg/memmodel/guality.h
===================================================================
--- g++.dg/memmodel/guality.h	(revision 179750)
+++ g++.dg/memmodel/guality.h	(working copy)
@@ -1 +0,0 @@ 
-#include "../../gcc.dg/guality/guality.h"
Index: g++.dg/memmodel/memmodel.h
===================================================================
--- g++.dg/memmodel/memmodel.h	(revision 179750)
+++ g++.dg/memmodel/memmodel.h	(working copy)
@@ -1 +0,0 @@ 
-#include "../../gcc.dg/memmodel/memmodel.h"
Index: g++.dg/memmodel/bitfields-2.C
===================================================================
--- g++.dg/memmodel/bitfields-2.C	(revision 179750)
+++ g++.dg/memmodel/bitfields-2.C	(working copy)
@@ -1,71 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
-   In the C++ memory model, non contiguous bitfields ("a" and "c"
-   here) should be considered as distinct memory locations, so we
-   can't use bit twiddling to set either one.  */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-#define CONSTA 12
-
-static int global;
-struct S
-{
-  unsigned int a : 4;
-  unsigned char b;
-  unsigned int c : 6;
-} var;
-
-__attribute__((noinline))
-void set_a()
-{
-  var.a = CONSTA;
-}
-
-void memmodel_other_threads()
-{
-  ++global;
-  var.b = global;
-  var.c = global;
-}
-
-int memmodel_step_verify()
-{
-  int ret = 0;
-  if (var.b != global)
-    {
-      printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
-	      var.b, global);
-      ret = 1;
-    }
-  if (var.c != global)
-    {
-      printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
-	      var.c, global);
-      ret = 1;
-    }
-  return ret;
-}
-
-int memmodel_final_verify()
-{
-  int ret = memmodel_step_verify();
-  if (var.a != CONSTA)
-    {
-      printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
-	      var.a, CONSTA);
-      ret = 1;
-    }
-  return ret;
-}
-
-int main()
-{
-  set_a();
-  memmodel_done();
-  return 0;
-}
Index: g++.dg/memmodel/bitfields.C
===================================================================
--- g++.dg/memmodel/bitfields.C	(revision 179750)
+++ g++.dg/memmodel/bitfields.C	(working copy)
@@ -1,74 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "--param allow-load-data-races=0 --param allow-store-data-races=0" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-/* Test that setting <var.a> does not touch either <var.b> or <var.c>.
-   In the C++ memory model, non contiguous bitfields ("a" and "c"
-   here) should be considered as distinct memory locations, so we
-   can't use bit twiddling to set either one.  */
-
-#include <stdio.h>
-#include "memmodel.h"
-
-#define CONSTA 12
-
-static int global;
-struct S
-{
-  /* On x86-64, the volatile causes us to access <a> with a 32-bit
-     access, and thus trigger this test.  */
-  volatile unsigned int a : 4;
-
-  unsigned char b;
-  unsigned int c : 6;
-} var;
-
-__attribute__((noinline))
-void set_a()
-{
-  var.a = CONSTA;
-}
-
-void memmodel_other_threads()
-{
-  ++global;
-  var.b = global;
-  var.c = global;
-}
-
-int memmodel_step_verify()
-{
-  int ret = 0;
-  if (var.b != global)
-    {
-      printf ("FAIL: Unexpected value: var.b is %d, should be %d\n",
-	      var.b, global);
-      ret = 1;
-    }
-  if (var.c != global)
-    {
-      printf ("FAIL: Unexpected value: var.c is %d, should be %d\n",
-	      var.c, global);
-      ret = 1;
-    }
-  return ret;
-}
-
-int memmodel_final_verify()
-{
-  int ret = memmodel_step_verify();
-  if (var.a != CONSTA)
-    {
-      printf ("FAIL: Unexpected value: var.a is %d, should be %d\n",
-	      var.a, CONSTA);
-      ret = 1;
-    }
-  return ret;
-}
-
-int main()
-{
-  set_a();
-  memmodel_done();
-  return 0;
-}
Index: g++.dg/memmodel/memmodel.gdb
===================================================================
--- g++.dg/memmodel/memmodel.gdb	(revision 179750)
+++ g++.dg/memmodel/memmodel.gdb	(working copy)
@@ -1 +0,0 @@ 
-source ../../gcc.dg/memmodel/memmodel.gdb
Index: g++.dg/memmodel/memmodel.exp
===================================================================
--- g++.dg/memmodel/memmodel.exp	(revision 179750)
+++ g++.dg/memmodel/memmodel.exp	(working copy)
@@ -1,58 +0,0 @@ 
-# Your run of the mill dg test, but verify that we have a working GDB first.
-
-load_lib g++-dg.exp
-load_lib gcc-memmodel-gdb-test.exp
-load_lib torture-options.exp
-
-proc check_guality {args} {
-    set result [eval check_compile guality_check executable $args "-g -O0"]
-    set lines [lindex $result 0]
-    set output [lindex $result 1]
-    set ret 0
-    if {[string match "" $lines]} {
-      set execout [g++_load "./$output"]
-      set ret [string match "*1 PASS, 0 FAIL, 0 UNRESOLVED*" $execout]
-    }
-    remote_file build delete $output
-    return $ret
-}
-
-dg-init
-torture-init
-set-torture-options [list \
-	{ -O0 -g } \
-	{ -O1 -g } \
-	{ -O2 -g } \
-	{ -O3 -g } \
-	{ -Os -g } ]
-
-# Test the presence of gdb with the guality infrastructure.
-global GDB
-if ![info exists ::env(GUALITY_GDB_NAME)] {
-    if [info exists GDB] {
-	set guality_gdb_name "$GDB"
-    } else {
-	set guality_gdb_name "[transform gdb]"
-    }
-    setenv GUALITY_GDB_NAME "$guality_gdb_name"
-}
-if {[check_guality "
-  #include \"$srcdir/$subdir/guality.h\"
-  volatile long int varl = 6;
-  int main (int argc, char *argv\[\])
-  {
-    GUALCHKVAL (varl);
-    return 0;
-  }
-"]} {
-  gcc-dg-runtest [lsort [glob $srcdir/$subdir/*.C]] ""
-# Uncomment line below when we have common C/C++ tests.
-#  gcc-dg-runtest [lsort [glob $srcdir/c-c++-common/memmodel/*.c]] ""
-}
-
-if [info exists guality_gdb_name] {
-    unsetenv GUALITY_GDB_NAME
-}
-
-torture-finish
-dg-finish
Index: g++.dg/memmodel/atomics-1.C
===================================================================
--- g++.dg/memmodel/atomics-1.C	(revision 179750)
+++ g++.dg/memmodel/atomics-1.C	(working copy)
@@ -1,66 +0,0 @@ 
-/* { dg-do link } */
-/* { dg-options "-std=c++0x" } */
-/* { dg-final { memmodel-gdb-test } } */
-
-/* Test that atomic int and atomic char work properly.  */
-
-using namespace std;
-
-#include <atomic>
-#include <limits.h>
-#include <stdio.h>
-#include "memmodel.h"
-
-atomic<int> atomi;
-atomic<char> atomc;
-
-/* No need for parallel threads to do anything */
-void memmodel_other_threads()
-{
-}
-
-/* Verify after every instruction is executed, that the atmoic int and
-   char have one of the 2 legitimate values. */
-int memmodel_step_verify()
-{
-  if (atomi != 0 && atomi != INT_MAX)
-    {
-      printf ("FAIL: invalid intermediate result for atomi (%d).\n",
-	      (int)atomi);
-      return 1;
-    }
-  if (atomc != 0 && atomc != CHAR_MAX)
-    {
-      printf ("FAIL: invalid intermediate result for atomc (%d).\n",
-	      (int)atomc);
-      return 1;
-    }
-  return 0;
-}
-
-
-/* Verify that both atmoics have the corerct value.  */
-int memmodel_final_verify()
-{
-  if (atomi != INT_MAX)
-    {
-      printf ("FAIL: invalid final result for atomi (%d).\n",
-	      (int)atomi);
-      return 1;
-    }
-  if (atomc != CHAR_MAX)
-    {
-      printf ("FAIL: invalid final result for atomc (%d).\n",
-	      (int)atomc);
-      return 1;
-    }
-  return 0;
-}
-
-/* Test a store to an atomic int and an atomic char. */
-main()
-{
-  atomi = INT_MAX;
-  atomc = CHAR_MAX;
-  memmodel_done();
-}
Index: c-c++-common/simulate-thread/bitfields-1.c
===================================================================
--- c-c++-common/simulate-thread/bitfields-1.c	(revision 0)
+++ c-c++-common/simulate-thread/bitfields-1.c	(revision 0)
@@ -0,0 +1,71 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Test that we don't store past VAR.A.  */
+
+struct S
+{
+  volatile unsigned int a : 4;
+  unsigned char b;
+  unsigned int c : 6;
+} var = { 1, 2, 3 };
+
+static int global = 0;
+
+/* Called before each instruction, simulating another thread
+   executing.  */
+void simulate_thread_other_threads()
+{
+  global++;
+  var.b = global;
+  /* Don't go past the 6 bits var.c can hold.  */
+  var.c = global % 64;
+}
+
+/* Called after each instruction.  Returns 1 if any inconsistency is
+   found, 0 otherwise.  */
+int simulate_thread_step_verify()
+{
+  int ret = 0;
+  if (var.b != global)
+    {
+      printf("FAIL: invalid intermediate value for <b>.\n");
+      ret = 1;
+    }
+  if (var.c != global % 64)
+    {
+      printf("FAIL: invalid intermediate value for <c>.\n");
+      ret = 1;
+    }
+  return ret;
+}
+
+/* Called at the end of the program (simulate_thread_fini == 1).  Verifies
+   the state of the program and returns 1 if any inconsistency is
+   found, 0 otherwise.  */
+int simulate_thread_final_verify()
+{
+  if (var.a != 12)
+    {
+      printf("FAIL: invalid final result for <a>.\n");
+      return 1;
+    }
+  return 0;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  var.a = 12;
+}
+
+int main()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: c-c++-common/simulate-thread/bitfields-2.c
===================================================================
--- c-c++-common/simulate-thread/bitfields-2.c	(revision 0)
+++ c-c++-common/simulate-thread/bitfields-2.c	(revision 0)
@@ -0,0 +1,59 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Test that we don't store past VAR.K.  */
+
+struct S
+{
+  volatile int i;
+  volatile int j: 32;
+  volatile int k: 15;
+  volatile unsigned char c[2];
+} var;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+  global++;
+  var.c[0] = global % 256;
+  var.c[1] = global % 256;
+}
+
+int simulate_thread_step_verify()
+{
+  if (var.c[0] != global % 256
+      || var.c[1] != global % 256)
+    {
+      printf("FAIL: invalid intermediate result for <var.c[]>.\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify()
+{
+  if (var.k != 13)
+    {
+      printf("FAIL: invalid final result\n");
+      return 1;
+    }
+  return 0;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  var.k = 13;
+}
+
+int main()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: c-c++-common/simulate-thread/bitfields-3.c
===================================================================
--- c-c++-common/simulate-thread/bitfields-3.c	(revision 0)
+++ c-c++-common/simulate-thread/bitfields-3.c	(revision 0)
@@ -0,0 +1,63 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+/* Store into <c> should not clobber <d>.  */
+
+struct bits
+{
+  char a;
+  int b:7;
+  int c:9;
+  unsigned char d;
+} var;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+  global++;
+  var.d = global;
+}
+
+int simulate_thread_step_verify()
+{
+  if (var.d != global)
+    {
+      printf("FAIL: invalid intermediate result\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify()
+{
+  if (var.c != 5)
+    {
+      printf("FAIL: invalid final result\n");
+      return 1;
+    }
+  return 0;
+}
+
+__attribute__((noinline))
+void update_c(struct bits *p, int val) 
+{
+    p -> c = val;
+}
+
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  update_c(&var, 5);
+}
+
+int main()
+{
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: c-c++-common/simulate-thread/bitfields-4.c
===================================================================
--- c-c++-common/simulate-thread/bitfields-4.c	(revision 0)
+++ c-c++-common/simulate-thread/bitfields-4.c	(revision 0)
@@ -0,0 +1,60 @@ 
+/* { dg-do link } */
+/* { dg-options "--param allow-store-data-races=0" } */
+/* { dg-final { simulate-thread } } */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../../gcc.dg/simulate-thread/simulate-thread.h"
+
+struct bits
+{
+  char a;
+  int b:7;
+  int c:9;
+  unsigned char d;
+} *p;
+
+static int global = 0;
+
+void simulate_thread_other_threads()
+{
+  global++;
+  p->d = global % 256;
+}
+
+int simulate_thread_step_verify()
+{
+  if (p->d != global % 256)
+    {
+      printf("FAIL: invalid intermediate result\n");
+      return 1;
+    }
+  return 0;
+}
+
+int simulate_thread_final_verify()
+{
+  if (p->c != 55)
+    {
+      printf("FAIL: invalid final result\n");
+      return 1;
+    }
+  return 0;
+}
+
+/* Store into <c> should not clobber <d>.  */
+/* We should not use a 32-bit move to store into p->, but a smaller move.  */
+__attribute__((noinline))
+void simulate_thread_main()
+{
+  p -> c = 55;
+}
+  
+
+int main()
+{
+  p = (struct bits *) calloc (1, sizeof (struct bits));
+  simulate_thread_main();
+  simulate_thread_done();
+  return 0;
+}
Index: c-c++-common/cxxbitfields-2.c
===================================================================
--- c-c++-common/cxxbitfields-2.c	(revision 179750)
+++ c-c++-common/cxxbitfields-2.c	(working copy)
@@ -1,19 +0,0 @@ 
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-/* Test that we don't store past VAR.K.  */
-
-struct S
-{
-  volatile int i;
-  volatile int j: 32;
-  volatile int k: 15;
-  volatile char c[2];
-} var;
-
-void setit()
-{
-  var.k = 13;
-}
-
-/* { dg-final { scan-assembler-not "movl.*, var" } } */
Index: c-c++-common/cxxbitfields.c
===================================================================
--- c-c++-common/cxxbitfields.c	(revision 179750)
+++ c-c++-common/cxxbitfields.c	(working copy)
@@ -1,18 +0,0 @@ 
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-/* Test that we don't store past VAR.A.  */
-
-struct S
-{
-  volatile unsigned int a : 4;
-  unsigned char b;
-  unsigned int c : 6;
-} var;
-
-void set_a()
-{
-  var.a = 12;
-}
-
-/* { dg-final { scan-assembler-not "movl.*, var" } } */
Index: c-c++-common/cxxbitfields-4.c
===================================================================
--- c-c++-common/cxxbitfields-4.c	(revision 179750)
+++ c-c++-common/cxxbitfields-4.c	(working copy)
@@ -1,18 +0,0 @@ 
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-struct bits
-{
-  char a;
-  int b:7;
-  int c:9;
-  unsigned char d;
-} x;
-
-/* Store into <c> should not clobber <d>.  */
-void update_c(struct bits *p, int val) 
-{
-    p -> c = val;
-}
-
-/* { dg-final { scan-assembler "mov\[bw\]" } } */
Index: c-c++-common/cxxbitfields-5.c
===================================================================
--- c-c++-common/cxxbitfields-5.c	(revision 179750)
+++ c-c++-common/cxxbitfields-5.c	(working copy)
@@ -1,29 +0,0 @@ 
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2 --param allow-store-data-races=0" } */
-
-#include <stdlib.h>
-
-struct bits
-{
-  char a;
-  int b:7;
-  int c:9;
-  unsigned char d;
-} x;
-
-struct bits *p;
-
-static void allocit()
-{
-  p = (struct bits *) malloc (sizeof (struct bits));
-}
-
-/* Store into <c> should not clobber <d>.  */
-/* We should not use a 32-bit move to store into p->, but a smaller move.  */
-void foo()
-{
-  allocit();
-  p -> c = 55;
-}
-
-/* { dg-final { scan-assembler "mov\[bw\]" } } */