This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[trans-mem] aggregate instrumentation
- From: Aldy Hernandez <aldyh at redhat dot com>
- To: rth at redhat dot com, gcc-patches at gcc dot gnu dot org
- Date: Thu, 7 Jan 2010 11:50:07 -0400
- Subject: [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;
}