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] optimize transaction local malloc/alloca memory


Howdy!

There is no need to instrument malloc/alloca memory being dereferenced
in a transaction if it can be proven that the memory was allocated
inside the transaction and cannot escape.  

There is no instrumenting to do because for alloca, a transaction
restart will reset the stack pointer and we'll just reallocate again.
For malloc, a transaction restart will free the memory, and we'll also
reallocate again.

OK for branch?

	* trans-mem.c (transaction_local_dynamic_memory_p): New.
	(requires_barrier): Call transaction_local_dynamic_memory_p.

Index: testsuite/gcc.dg/tm/memopt-10.c
===================================================================
--- testsuite/gcc.dg/tm/memopt-10.c	(revision 0)
+++ testsuite/gcc.dg/tm/memopt-10.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */
+
+extern int something(void) __attribute__((transaction_safe));
+extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe));
+
+int f()
+{
+  int *p;
+
+  p = malloc (sizeof (*p) * 100);
+
+  __transaction {
+    /* Instrument store, since memory pointed to by P is not
+       transaction local.  */
+    p[5] = 123;
+
+    if (something())
+      __transaction_cancel;
+  }
+  return p[5];
+}
+
+/* { dg-final { scan-tree-dump-times "ITM_WU" 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
Index: testsuite/gcc.dg/tm/memopt-8.c
===================================================================
--- testsuite/gcc.dg/tm/memopt-8.c	(revision 0)
+++ testsuite/gcc.dg/tm/memopt-8.c	(revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */
+
+extern int something(void) __attribute__((transaction_safe));
+extern int escape(int *) __attribute__((transaction_safe));
+extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe));
+
+int f()
+{
+  int *p;
+
+  __transaction {
+    p = malloc (sizeof (*p) * 100);
+    escape (p);
+
+    /* This should be instrumented because P escapes.  */
+    p[5] = 123;
+
+    if (something())
+      __transaction_cancel;
+  }
+  return p[5];
+}
+
+/* { dg-final { scan-tree-dump-times "ITM_WU" 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
Index: testsuite/gcc.dg/tm/memopt-9.c
===================================================================
--- testsuite/gcc.dg/tm/memopt-9.c	(revision 0)
+++ testsuite/gcc.dg/tm/memopt-9.c	(revision 0)
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */
+
+extern int something(void) __attribute__((transaction_safe));
+extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe));
+
+struct large { int foo[500]; };
+
+int f()
+{
+  int *p;
+  struct large *lp;
+
+  __transaction {
+    p = malloc (sizeof (*p) * 100);
+    lp = malloc (sizeof (*lp) * 100);
+
+    /* No instrumentation necessary; P and LP are transaction local.  */
+    p[5] = 123;
+    lp->foo[66] = 123;
+
+    if (something())
+      __transaction_cancel;
+  }
+  return p[5];
+}
+
+/* { dg-final { scan-tree-dump-times "ITM_WU" 0 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 154874)
+++ trans-mem.c	(working copy)
@@ -1130,6 +1130,76 @@ static tree lower_sequence_tm (gimple_st
 static tree lower_sequence_no_tm (gimple_stmt_iterator *, bool *,
 				  struct walk_stmt_info *);
 
+/* Given an address that is being dereferenced, return TRUE if we can
+   prove that the memory being dereferenced is a malloced type memory
+   local to the transaction, which therefore requires no
+   instrumentation.
+
+   ENTRY_BLOCK is the entry block to the transaction containing the
+   dereference of X.  */
+static bool
+transaction_local_dynamic_memory_p (basic_block entry_block, tree x)
+{
+  gimple stmt = NULL;
+  enum tree_code code;
+
+  if (!entry_block)
+    return false;
+
+  /* Search back through the DEF chain to find the original definition
+     of this address.  */
+  while (TREE_CODE (x) == SSA_NAME)
+    {
+      if (ptr_deref_may_alias_global_p (x))
+	{
+	  /* Pointed to address escapes.  This is not thread-private.  */
+	  return false;
+	}
+
+      stmt = SSA_NAME_DEF_STMT (x);
+
+      /* Bail if the malloc call is outside the transaction.  We only
+	 care about transaction local mallocs.  There are no edges
+	 into a transaction from without, so a simple dominance test
+	 will do.  */
+      if (!dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), entry_block))
+	return false;
+
+      if (is_gimple_assign (stmt))
+	{
+	  code = gimple_assign_rhs_code (stmt);
+	  /* x = foo ==> foo */
+	  if (code == SSA_NAME)
+	    x = gimple_assign_rhs1 (stmt);
+	  /* x = foo + n ==> foo */
+	  else if (code == POINTER_PLUS_EXPR)
+	    x = gimple_assign_rhs1 (stmt);
+	  /* x = (cast*) foo ==> foo */
+	  else if (code == VIEW_CONVERT_EXPR || code == NOP_EXPR)
+	    x = gimple_assign_rhs1 (stmt);
+	  else
+	    return false;
+	}
+      else
+	break;
+    }
+  if (stmt && is_gimple_call (stmt))
+    {
+      tree fn = gimple_call_fndecl (stmt);
+
+      if (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+	  && (DECL_FUNCTION_CODE (fn) == BUILT_IN_MALLOC
+	      || DECL_FUNCTION_CODE (fn) == BUILT_IN_ALLOCA))
+	{
+	  /* No logging to do.  For alloca stack pointer gets reset by
+	     the retry and we reallocate.  For malloc, a transaction
+	     restart frees the memory and we reallocate.  */
+	  return true;
+	}
+    }
+  return false;
+}
+
 /* Determine whether X has to be instrumented using a read
    or write barrier.
 
@@ -1149,6 +1219,8 @@ requires_barrier (basic_block entry_bloc
   switch (TREE_CODE (x))
     {
     case INDIRECT_REF:
+      if (transaction_local_dynamic_memory_p (entry_block, TREE_OPERAND (x, 0)))
+	return false;
       return true;
 
     case ALIGN_INDIRECT_REF:


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