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


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

[trans-mem] aggregate instrumentation


This patch implements transactional loads and stores for aggregates by
punting off to the memmove code.  (Later we can check for overlaps and
use memcpy instead as suggested by the existing comment.)

I have also found that assignments embedded in a GIMPLE_CALL were not
being instrumented.  We hadn't noticed because the gimplifier adds an
additional temporary when gimplifying a CALL_EXPR, so we never saw a
call writing directly to a global.  For example:

	foo = function();

gets gimplified into:

	tmp = function();
	foo = tmp;

Since tmp is a temporary, it requires no instrumentation, but 
"foo = tmp" was get instrumented correctly.  However, the gimplifier
does not create this additional temporary for aggregates, so now we
notice.  I have fixed this below by making expand_call_tm() handle the
embedded assignment.

OK for branch?

p.s. I have changed the test "memopt-6.c" that previously tested for the
unimplemented message to handle aggregates.  Would it be better to
remove the test altogether (leave a hole in the memopt-* numbering
sequence) and add a separate test?

	* trans-mem.c (build_tm_load): Do not error on unsupported
	builtins.
	(build_tm_store): Same.
	(expand_assign_tm): Call tm_memmove on unsupported load/store
	builtins.
	(expand_call_tm): Instrument stores embedded in a call if
	appropriate.
	* testsuite/gcc.dg/tm/memopt-6.c: Remove unimplemented message.
	Check for implementation of aggregate instrumentation.

Index: testsuite/gcc.dg/tm/memopt-13.c
===================================================================
--- testsuite/gcc.dg/tm/memopt-13.c	(revision 0)
+++ testsuite/gcc.dg/tm/memopt-13.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */
+
+struct large { int x[100]; };
+struct large large_global;
+extern struct large function (void) __attribute__((transaction_safe));
+
+void f()
+{
+  __transaction {
+      large_global = function();
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&large_global," 1 "tmmark" } } */
Index: testsuite/gcc.dg/tm/memopt-6.c
===================================================================
--- testsuite/gcc.dg/tm/memopt-6.c	(revision 154874)
+++ testsuite/gcc.dg/tm/memopt-6.c	(working copy)
@@ -6,13 +6,15 @@ struct large bark();
 extern int test (void) __attribute__((transaction_safe));
 struct large lacopy;
 
-int f() /* { dg-message "unimplemented: transactional load" } */
+int f()
 {
   int i = readint();
   struct large lala = bark();
   __transaction {
     lala.x[55] = 666;
-    lala = lacopy;
+    lala = lacopy;		/* Aggregate instrumentation.  */
   }
   return lala.x[i];
 }
+
+/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&lala, &lacopy" 1 "tmedge" } } */
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 155394)
+++ trans-mem.c	(working copy)
@@ -1762,7 +1762,9 @@ transaction_subcode_ior (struct tm_regio
     }
 }
 
-/* Construct a memory load in a transactional context.  */
+/* Construct a memory load in a transactional context.  Return the
+   gimple statement performing the load, or NULL if there is no
+   TM_LOAD builtin of the appropriate size to do the load.  */
 
 static gimple
 build_tm_load (tree lhs, tree rhs, gimple_stmt_iterator *gsi)
@@ -1798,10 +1800,7 @@ build_tm_load (tree lhs, tree rhs, gimpl
     }
 
   if (code == END_BUILTINS)
-    {
-      sorry ("transactional load for %T not supported", type);
-      code = BUILT_IN_TM_LOAD_4;
-    }
+    return NULL;
 
   t = gimplify_addr (gsi, rhs);
   gcall = gimple_build_call (built_in_decls[code], 1, t);
@@ -1866,10 +1865,7 @@ build_tm_store (tree lhs, tree rhs, gimp
     }
 
   if (code == END_BUILTINS)
-    {
-      sorry ("transactional store for %T not supported", type);
-      code = BUILT_IN_TM_STORE_4;
-    }
+    return NULL;
 
   fn = built_in_decls[code];
   simple_type = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))));
@@ -1905,7 +1901,7 @@ expand_assign_tm (struct tm_region *regi
   tree rhs = gimple_assign_rhs1 (stmt);
   bool store_p = requires_barrier (region->entry_block, lhs, NULL);
   bool load_p = requires_barrier (region->entry_block, rhs, NULL);
-  gimple gcall;
+  gimple gcall = NULL;
 
   if (!load_p && !store_p)
     {
@@ -1917,9 +1913,22 @@ expand_assign_tm (struct tm_region *regi
 
   gsi_remove (gsi, true);
 
-  if (load_p && store_p)
+  if (load_p && !store_p)
+    {
+      transaction_subcode_ior (region, GTMA_HAVE_LOAD);
+      gcall = build_tm_load (lhs, rhs, gsi);
+    }
+  else if (store_p && !load_p)
     {
-      transaction_subcode_ior (region, GTMA_HAVE_LOAD | GTMA_HAVE_STORE);
+      transaction_subcode_ior (region, GTMA_HAVE_STORE);
+      gcall = build_tm_store (lhs, rhs, gsi);
+    }
+  if (!gcall)
+    {
+      if (load_p)
+	transaction_subcode_ior (region, GTMA_HAVE_LOAD);
+      if (store_p)
+	transaction_subcode_ior (region, GTMA_HAVE_STORE);
 
       /* ??? Figure out if there's any possible overlap between the LHS
 	 and the RHS and if not, use MEMCPY.  */
@@ -1929,16 +1938,6 @@ expand_assign_tm (struct tm_region *regi
 				 TYPE_SIZE_UNIT (TREE_TYPE (lhs)));
       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
     }
-  else if (load_p)
-    {
-      transaction_subcode_ior (region, GTMA_HAVE_LOAD);
-      gcall = build_tm_load (lhs, rhs, gsi);
-    }
-  else
-    {
-      transaction_subcode_ior (region, GTMA_HAVE_STORE);
-      gcall = build_tm_store (lhs, rhs, gsi);
-    }
 
   /* Now that we have the load/store in its instrumented form, add
      thread private addresses to the log if applicable.  */
@@ -2003,8 +2002,19 @@ expand_call_tm (struct tm_region *region
       return true;
     }
 
-  if (lhs)
-    (void) requires_barrier (region->entry_block, lhs, stmt);
+  /* Instrument the LHS load if needed.  */
+  if (lhs && requires_barrier (region->entry_block, lhs, stmt))
+    {
+      tree tmp = make_rename_temp (TREE_TYPE (lhs), NULL);
+
+      gimple_call_set_lhs (stmt, tmp);
+      update_stmt (stmt);
+      stmt = gimple_build_assign (lhs, tmp);
+      gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
+      expand_assign_tm (region, gsi);
+
+      transaction_subcode_ior (region, GTMA_HAVE_STORE);
+    }
 
   return retval;
 }


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