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] automatically wrap malloc type functions


Hi.

Calls to malloc/calloc/free inside a transaction should be automatically
converted to their TM counterparts.  This patch accomplishes this.

A few notes.

- I am setting the _ITM_malloc type builtins to transaction_pure.

- I did not put realloc in the mix because in a separate IRC chat we
  agreed that the libitm implementation of _ITM_realloc is not thread
  safe, and should be deleted.  I will do so next.

- In diagnose_tm_1(), I have equated is_tm_pure() implies is_tm_safe().
  Let me know if you disagree.

- Lastly, I set TREE_NOTHROW for the replacement functions for the C++
  FE (see tm_malloc_replacement), as I've seen you do in cp/except.c for
  some replacements.  Otherwise verify_stmt() dies in the C++ testcase
  with:

	"statement marked for throw, but doesn't"

I noticed Linux's <stdlib.h> sets "throw()" on the malloc prototype for
C++, so I assume this is the expected declaration.  This code in
tm_malloc_replacement automates it, like I believe is happening in the
TM code in cp/except.c.

OK for branch?

	* tree.h (tm_malloc_replacement): Protoize.
	* builtin-attrs.def (ATTR_TM_PURE_MALLOC_NOTHROW_LIST): New.
	(ATTR_TM_PURE_NOTHROW_LIST): New.
	* builtins.def: Add comments regarding TM synchronization.
	* gtm-builtins.def (BUILT_IN_TM_MALLOC): New.
	(BUILT_IN_TM_CALLOC): New.
	(BUILT_IN_TM_FREE): New.
	* trans-mem.c (tm_malloc_replacement): New.
	(diagnose_tm_1): TM pure functions are safe.
	Handle replacements.
	* c-typeck.c (build_function_call_vec): Call
	tm_malloc_replacement.
	* cp/call.c (build_new_function_call): Call tm_malloc_replacement.

Index: tree.h
===================================================================
--- tree.h	(revision 158824)
+++ tree.h	(working copy)
@@ -5388,6 +5388,7 @@ extern bool is_tm_callable (tree);
 extern bool is_tm_irrevocable (tree);
 extern bool is_tm_may_cancel_outer (tree);
 extern void record_tm_replacement (tree, tree);
+extern void tm_malloc_replacement (tree, bool);
 
 /* In tree-inline.c.  */
 
Index: builtin-attrs.def
===================================================================
--- builtin-attrs.def	(revision 158824)
+++ builtin-attrs.def	(working copy)
@@ -207,6 +207,13 @@ DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOT
 DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST,
 		    ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
 
+/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown in.  */
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_MALLOC_NOTHROW_LIST,
+		    ATTR_TM_PURE, ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+/* Same attributes used for BUILT_IN_FREE except with TM_PURE thrown in.  */
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_NOTHROW_LIST,
+		    ATTR_TM_PURE, ATTR_NULL, ATTR_NOTHROW_LIST)
+
 /* Construct a tree for a format_arg attribute.  */
 #define DEF_FORMAT_ARG_ATTRIBUTE(FA)					\
   DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG,		\
Index: testsuite/c-c++-common/tm/malloc.c
===================================================================
--- testsuite/c-c++-common/tm/malloc.c	(revision 0)
+++ testsuite/c-c++-common/tm/malloc.c	(revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */
+
+#include <stdlib.h>
+
+char *z;
+
+void foobar(void)
+{
+    char *p, *q;
+    __transaction {
+        p = (char *)malloc(123);
+        q = (char *)calloc(555,1);
+        free(q);
+	free(p);
+    }
+    z = (char *)malloc (666);
+}
+
+/* { dg-final { scan-tree-dump-times " malloc .666" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_malloc" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_calloc" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_free" 2 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 158824)
+++ cp/call.c	(working copy)
@@ -3169,6 +3169,9 @@ build_new_function_call (tree fn, VEC(tr
 	return error_mark_node;
     }
 
+  if (flag_tm)
+    tm_malloc_replacement (fn, true);
+
   /* If this function was found without using argument dependent
      lookup, then we want to ignore any undeclared friend
      functions.  */
Index: builtins.def
===================================================================
--- builtins.def	(revision 158824)
+++ builtins.def	(working copy)
@@ -617,6 +617,7 @@ DEF_GCC_BUILTIN        (BUILT_IN_ARGS_IN
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LIST)
+/* Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed.  */
 DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
@@ -650,6 +651,7 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_FFSL, "
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN        (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
+/* Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed.  */
 DEF_LIB_BUILTIN        (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
@@ -686,6 +688,8 @@ DEF_GCC_BUILTIN        (BUILT_IN_ISUNORD
 DEF_LIB_BUILTIN        (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST)
+/* If the attribute used for malloc below is changed, also change the memory
+   allocation builtins in gtm-builtins.def (See BUILT_IN_TM_MALLOC).  */
 DEF_LIB_BUILTIN        (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 158930)
+++ trans-mem.c	(working copy)
@@ -485,6 +485,44 @@ find_tm_replacement_function (tree fndec
 
   return NULL;
 }
+
+/* When appropriate, record TM replacement for memory allocation functions.
+
+   FROM is the FNDECL to wrap.
+
+   NOTHROW is true if TREE_NOTHROW must be set for the replacement.
+   This is usually set for C++.  */
+void
+tm_malloc_replacement (tree from, bool nothrow)
+{
+  const char *str;
+  tree to;
+
+  if (TREE_CODE (from) != FUNCTION_DECL)
+    return;
+
+  /* If we have a previous replacement, the user must be explicitly
+     wrapping malloc/calloc/free.  They better know what they're
+     doing... */
+  if (find_tm_replacement_function (from))
+    return;
+
+  str = IDENTIFIER_POINTER (DECL_NAME (from));
+
+  if (!strcmp (str, "malloc"))
+    to = built_in_decls[BUILT_IN_TM_MALLOC];
+  else if (!strcmp (str, "calloc"))
+    to = built_in_decls[BUILT_IN_TM_CALLOC];
+  else if (!strcmp (str, "free"))
+    to = built_in_decls[BUILT_IN_TM_FREE];
+  else
+    return;
+
+  if (nothrow)
+    TREE_NOTHROW (to) = 0;
+
+  record_tm_replacement (from, to);
+}
 
 /* Diagnostics for tm_safe functions/regions.  Called by the front end
    once we've lowered the function to high-gimple.  */
@@ -529,9 +567,25 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi
 
 	if (d->summary_flags & DIAG_TM_SAFE)
 	  {
-	    bool is_safe;
+	    bool is_safe, direct_call_p;
+	    tree replacement;
+
+	    if (TREE_CODE (fn) == ADDR_EXPR
+		&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+	      {
+		direct_call_p = true;
+		replacement = TREE_OPERAND (fn, 0);
+		replacement = find_tm_replacement_function (replacement);
+		if (replacement)
+		  fn = replacement;
+	      }
+	    else
+	      {
+		direct_call_p = false;
+		replacement = NULL_TREE;
+	      }
 
-	    if (is_tm_safe (fn))
+	    if (is_tm_safe (fn) || is_tm_pure (fn))
 	      is_safe = true;
 	    else if (is_tm_callable (fn) || is_tm_irrevocable (fn))
 	      {
@@ -540,10 +594,9 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi
 		   unsafe as part of its ABI, regardless of its contents.  */
 		is_safe = false;
 	      }
-	    else if (TREE_CODE (fn) == ADDR_EXPR
-		     && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+	    else if (direct_call_p)
 	      {
-		if (find_tm_replacement_function (TREE_OPERAND (fn, 0)))
+		if (replacement)
 		  {
 		    /* ??? At present we've been considering replacements
 		       merely transaction_callable, and therefore might
Index: c-typeck.c
===================================================================
--- c-typeck.c	(revision 158824)
+++ c-typeck.c	(working copy)
@@ -2638,6 +2638,9 @@ build_function_call_vec (location_t loc,
 	return tem;
 
       name = DECL_NAME (function);
+
+      if (flag_tm)
+	tm_malloc_replacement (function, false);
       fundecl = function;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
Index: gtm-builtins.def
===================================================================
--- gtm-builtins.def	(revision 158824)
+++ gtm-builtins.def	(working copy)
@@ -20,6 +20,14 @@ DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_I
 DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe",
 		BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
 
+/* Memory allocation builtins.  */
+DEF_TM_BUILTIN (BUILT_IN_TM_MALLOC, "_ITM_malloc",
+	        BT_FN_PTR_SIZE, ATTR_TM_PURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_CALLOC, "_ITM_calloc",
+	        BT_FN_PTR_SIZE_SIZE, ATTR_TM_PURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_FREE, "_ITM_free",
+	        BT_FN_VOID_PTR, ATTR_TM_PURE_NOTHROW_LIST)
+
 /* Logging builtins.  */
 DEF_TM_BUILTIN (BUILT_IN_TM_LOG_1, "_ITM_LU1",
                 BT_FN_VOID_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)


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