public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: gcc-patches <gcc-patches@gcc.gnu.org>, Jeff Law <law@redhat.com>,
	       Richard Henderson <rth@redhat.com>
Subject: [cxx-mem-model] disallow load data races (1 of some)
Date: Thu, 24 Mar 2011 17:33:00 -0000	[thread overview]
Message-ID: <4D8B8051.2030307@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1152 bytes --]

This is my first stab at disallowing load data races that happen when we 
cache the value of a global.  I would appreciate input before 
committing, especially on the RTL bits, cause it's been quite a while 
since I typed d-e-b-u-g-_-r-t-x. :-)

In the example below we usually hoist "global" into a register or 
temporary to avoid reading from it at each step.  This would cause a 
race if another thread had modified "global" in between iterations.

	for (x=0; x< 5; x++)
		sum[x] =  global;

As expected, multiple passes can cause the same end result, so plugging 
the problem involves multiple places.  First, loop invariant movement 
moves the invariant.  Barring that, PRE moves the load, and even if we 
get past the SSA passes, rtl-CSE pulls the rug from under us.  If that 
weren't enough, the post-reload pass performs CSE over the hard 
registers, and we end up eliminating subsequent loads of "global".  I am 
sure there are many other places, but I'm starting with whatever it 
takes to fix gcc.dg/memmodel/global-hoist.c.

The patch below fixes the test in question with "--param 
allow-load-data-races=0".  What do y'all think?

Thanks.

[-- Attachment #2: curr --]
[-- Type: text/plain, Size: 5294 bytes --]

	* tree.h (DECL_THREAD_VISIBLE_P): New.
	* cselib.c (cselib_lookup_mem): Return 0 for globals for
	restrictive memory model.
	* cse.c (hash_rtx_cb): Same.
	* gimple.h (gimple_has_thread_visible_ops): Protoize.
	* gimple.c (gimple_has_thread_visible_ops): New.
	* tree-ssa-loop-im.c (movement_possibility): Disallow when
	avoiding load data races.
	* tree-ssa-pre.c (compute_avail): Same, for globals.

Index: tree-ssa-loop-im.c
===================================================================
--- tree-ssa-loop-im.c	(revision 170745)
+++ tree-ssa-loop-im.c	(working copy)
@@ -377,6 +377,11 @@ movement_possibility (gimple stmt)
       || stmt_could_throw_p (stmt))
     return MOVE_IMPOSSIBLE;
 
+  /* Do not move loads of globals if under a restrictive memory model.  */
+  if (PARAM_VALUE (PARAM_ALLOW_LOAD_DATA_RACES) == 0
+      && gimple_has_thread_visible_ops (stmt))
+    return MOVE_IMPOSSIBLE;
+
   if (is_gimple_call (stmt))
     {
       /* While pure or const call is guaranteed to have no side effects, we
Index: tree.h
===================================================================
--- tree.h	(revision 170745)
+++ tree.h	(working copy)
@@ -3102,6 +3102,10 @@ struct GTY(()) tree_parm_decl {
 #define DECL_THREAD_LOCAL_P(NODE) \
   (VAR_DECL_CHECK (NODE)->decl_with_vis.tls_model >= TLS_MODEL_REAL)
 
+/* Return true if a VAR_DECL is visible from another thread.  */
+#define DECL_THREAD_VISIBLE_P(NODE) \
+  (TREE_STATIC (NODE) && !DECL_THREAD_LOCAL_P (NODE))
+
 /* In a non-local VAR_DECL with static storage duration, true if the
    variable has an initialization priority.  If false, the variable
    will be initialized at the DEFAULT_INIT_PRIORITY.  */
Index: cse.c
===================================================================
--- cse.c	(revision 170745)
+++ cse.c	(working copy)
@@ -2402,6 +2402,19 @@ hash_rtx_cb (const_rtx x, enum machine_m
       }
 
     case MEM:
+      /* Avoid hoisting loads of globals if under a restrictive memory
+	 model.  */
+      if (PARAM_VALUE (PARAM_ALLOW_LOAD_DATA_RACES) == 0)
+	{
+	  tree decl = MEM_EXPR (x);
+	  if (do_not_record_p
+	      && decl && TREE_CODE (decl) == VAR_DECL
+	      && DECL_THREAD_VISIBLE_P (decl))
+	    {
+	      *do_not_record_p = 1;
+	      return 0;
+	    }
+	}
       /* We don't record if marked volatile or if BLKmode since we don't
 	 know the size of the move.  */
       if (do_not_record_p && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
Index: cselib.c
===================================================================
--- cselib.c	(revision 170745)
+++ cselib.c	(working copy)
@@ -1190,6 +1190,16 @@ cselib_lookup_mem (rtx x, int create)
   cselib_val *mem_elt;
   struct elt_list *l;
 
+  /* Forget any reads from globals if under a restrictive memory
+     model.  */
+  if (PARAM_VALUE (PARAM_ALLOW_LOAD_DATA_RACES) == 0)
+    {
+      tree decl = MEM_EXPR (x);
+      if (decl && TREE_CODE (decl) == VAR_DECL
+	  && DECL_THREAD_VISIBLE_P (decl))
+	return 0;
+    }
+
   if (MEM_VOLATILE_P (x) || mode == BLKmode
       || !cselib_record_memory
       || (FLOAT_MODE_P (mode) && flag_float_store))
Index: tree-ssa-pre.c
===================================================================
--- tree-ssa-pre.c	(revision 170745)
+++ tree-ssa-pre.c	(working copy)
@@ -4000,6 +4000,12 @@ compute_avail (void)
 	      || stmt_could_throw_p (stmt))
 	    continue;
 
+	  /* Do not move loads of globals if under a restrictive
+	     memory model.  */
+	  if (PARAM_VALUE (PARAM_ALLOW_LOAD_DATA_RACES) == 0
+	      && gimple_has_thread_visible_ops (stmt))
+	    continue;
+
 	  switch (gimple_code (stmt))
 	    {
 	    case GIMPLE_RETURN:
Index: gimple.c
===================================================================
--- gimple.c	(revision 170745)
+++ gimple.c	(working copy)
@@ -2388,6 +2388,36 @@ gimple_rhs_has_side_effects (const_gimpl
   return false;
 }
 
+/* Return true if any of the operands in S are visible from another
+   thread (globals that are not TLS.  */
+/* ?? If this becomes a performance penalty, we should cache this
+   value as we do with volatiles.  */
+
+bool
+gimple_has_thread_visible_ops (const_gimple s)
+{
+  unsigned int i;
+
+  if (is_gimple_debug (s))
+    return false;
+
+  if (is_gimple_assign (s))
+    {
+      /* Skip the LHS.  */
+      i = 1;
+    }
+  else
+    i = 0;
+  for (; i < gimple_num_ops (s); i++)
+    {
+      tree op = gimple_op (s, i);
+      if (op && TREE_CODE (op) == VAR_DECL
+	  && DECL_THREAD_VISIBLE_P (op))
+	return true;
+    }
+  return false;
+}
+
 /* Helper for gimple_could_trap_p and gimple_assign_rhs_could_trap_p.
    Return true if S can trap.  When INCLUDE_MEM is true, check whether
    the memory operations could trap.  When INCLUDE_STORES is true and
Index: gimple.h
===================================================================
--- gimple.h	(revision 170745)
+++ gimple.h	(working copy)
@@ -882,6 +882,7 @@ gimple gimple_build_cond_from_tree (tree
 void gimple_cond_set_condition_from_tree (gimple, tree);
 bool gimple_has_side_effects (const_gimple);
 bool gimple_rhs_has_side_effects (const_gimple);
+bool gimple_has_thread_visible_ops (const_gimple);
 bool gimple_could_trap_p (gimple);
 bool gimple_could_trap_p_1 (gimple, bool, bool);
 bool gimple_assign_rhs_could_trap_p (gimple);

             reply	other threads:[~2011-03-24 17:33 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-24 17:33 Aldy Hernandez [this message]
2011-03-24 19:58 ` Richard Henderson
2011-03-24 21:31   ` Aldy Hernandez
2011-03-24 21:51     ` Joseph S. Myers
2011-03-24 23:57       ` Andrew MacLeod
2011-03-25 10:03         ` Richard Guenther
2011-03-25 12:58           ` Aldy Hernandez
2011-03-25 15:27             ` Michael Matz
2011-03-25 15:33               ` Jeff Law
2011-03-25 15:35                 ` Jakub Jelinek
2011-03-25 15:46                   ` Richard Guenther
2011-03-29 16:52                     ` Aldy Hernandez
2011-03-31 13:12         ` Jeff Law
2011-03-31 13:32           ` Richard Guenther
2011-03-31 13:32             ` Jeff Law
2011-03-31 21:07               ` Michael Matz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D8B8051.2030307@redhat.com \
    --to=aldyh@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=law@redhat.com \
    --cc=rth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).