[trans-mem] make alias oracle understand TM read/writes

Aldy Hernandez aldyh@redhat.com
Mon Sep 7 17:56:00 GMT 2009


>> I guess if what y'all want is alias info for builtins created by hand
>> then I'll just rewrite my testcase with manually created builtin calls.
>>
>> Is this what you want?
>
> Yes, please.

In coming up with suitables testcases, I noticed that direct calls to
the builtins were getting wrapped unecessarily.  This was causing an SSA
verification failure down the road.  I fixed this by making the TM loads
marked as `tm_pure' which is what ipa_tm_transform_calls() needs to
ignore the builtin without instrumenting it.

I also found a buglet in gimplify_tm_atomic() which couldn't handle an
empty BIND.  Fixed.

And finally, I not only added 32/64 bit variants for the test, but I
added a test to check that alias does its thing even if we're going
through a wrapper function.

I've regtested for C and C++.

OK for branch?

	* builtin-attrs.def: (ATTR_TM_PURE): New.
	(ATTR_TM_TMPURE_NOTHROW_LIST): New.
	(ATTR_TM_PURE_TMPURE_NOTHROW_LIST): New.
	(ATTR_TM_PURE_NOTHROW_LIST): Remove.
	* gtm-builtins.def (BUILT_IN_TM_LOAD_*): Use
	ATTR_TM_PURE_TMPURE_NOTHROW_LIST instead.
	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle TM builtins.
	(call_may_clobber_ref_p_1): Same.
	* tree-ssa-structalias.c (find_func_aliases): Same.
	Fix function comment to reflect reality.

Index: builtin-attrs.def
===================================================================
--- builtin-attrs.def	(revision 151124)
+++ builtin-attrs.def	(working copy)
@@ -95,6 +95,7 @@ DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
 DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
 DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")
 DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm")
+DEF_ATTR_IDENT (ATTR_TM_PURE, "tm_pure")
 
 DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
 
@@ -197,12 +198,14 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3
 
 DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST,
 		    ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_TMPURE_NOTHROW_LIST,
+		    ATTR_TM_PURE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_TMPURE_NOTHROW_LIST,
+		    ATTR_PURE, ATTR_NULL, ATTR_TM_TMPURE_NOTHROW_LIST)
 DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOTHROW_LIST,
 		    ATTR_TM_REGPARM, ATTR_NULL, ATTR_NORETURN_NOTHROW_LIST)
 DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST,
 		    ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_TM_PURE_NOTHROW_LIST,
-		    ATTR_TM_REGPARM, ATTR_NULL, ATTR_PURE_NOTHROW_LIST)
 
 /* Construct a tree for a format_arg attribute.  */
 #define DEF_FORMAT_ARG_ATTRIBUTE(FA)					\
Index: testsuite/gcc.dg/tm/alias-1.c
===================================================================
--- testsuite/gcc.dg/tm/alias-1.c	(revision 0)
+++ testsuite/gcc.dg/tm/alias-1.c	(revision 0)
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-ealias -O" } */
+
+#if (__SIZEOF_LONG_LONG__ == __SIZEOF_POINTER__)
+typedef unsigned long long ptrcast;
+#elif (__SIZEOF_LONG__ == __SIZEOF_POINTER__)
+typedef unsigned long ptrcast;
+#elif (__SIZEOF_INT__ == __SIZEOF_POINTER__)
+typedef unsigned int ptrcast;
+#else
+#error Add target support here
+#endif
+
+#if (__SIZEOF_POINTER__ == 4)
+#define TM_LOAD  __builtin__ITM_RU4
+#define TM_STORE __builtin__ITM_WU4
+#elif (__SIZEOF_POINTER__ == 8)
+#define TM_LOAD __builtin__ITM_RU8
+#define TM_STORE __builtin__ITM_WU8
+#else
+#error Add target support here
+#endif
+
+struct mystruct_type {
+  ptrcast *ptr;
+} *mystruct;
+
+ptrcast *someptr, **pp;
+ptrcast ui;
+
+void f(void)
+{
+  __tm_atomic {
+    ui = TM_LOAD  (&mystruct);
+    mystruct = (struct mystruct_type *) ui;
+    ui = TM_LOAD  (&someptr);
+    someptr = (ptrcast *) ui;
+    ui = (ptrcast) someptr;
+    pp = &mystruct->ptr;
+    TM_STORE (pp, ui);
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "mystruct = \{ .*ESCAPED" 1 "ealias" } } */
+/* { dg-final { scan-tree-dump-times "someptr = same as mystruct" 1 "ealias" } } */
+/* { dg-final { scan-tree-dump-times "ui\..* = same as mystruct" 1 "ealias" } } */
+/* { dg-final { scan-tree-dump-times "pp\..* = same as mystruct" 1 "ealias" } } */
+/* { dg-final { cleanup-tree-dump "ealias" } } */
Index: testsuite/gcc.dg/tm/alias-2.c
===================================================================
--- testsuite/gcc.dg/tm/alias-2.c	(revision 0)
+++ testsuite/gcc.dg/tm/alias-2.c	(revision 0)
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-ealias -O" } */
+
+#if (__SIZEOF_LONG_LONG__ == __SIZEOF_POINTER__)
+typedef unsigned long long ptrcast;
+#elif (__SIZEOF_LONG__ == __SIZEOF_POINTER__)
+typedef unsigned long ptrcast;
+#elif (__SIZEOF_INT__ == __SIZEOF_POINTER__)
+typedef unsigned int ptrcast;
+#else
+#error Add target support here
+#endif
+
+#if (__SIZEOF_POINTER__ == 4)
+#define TM_LOAD  __builtin__ITM_RU4
+#define TM_STORE __builtin__ITM_WU4
+#elif (__SIZEOF_POINTER__ == 8)
+#define TM_LOAD __builtin__ITM_RU8
+#define TM_STORE __builtin__ITM_WU8
+#else
+#error Add target support here
+#endif
+
+void candy ();
+
+struct mystruct_type {
+  ptrcast *ptr;
+} *mystruct, *mystruct2;
+
+ptrcast *someptr, **pp;
+ptrcast ui;
+
+void tootsie_roll () __attribute__((tm_wrap (candy)));
+void tootsie_roll ()
+{
+  ui = TM_LOAD  (&mystruct);
+  mystruct2 = (struct mystruct_type *) ui;
+
+  pp = &mystruct2->ptr;
+}
+
+void foo()
+{
+  candy();
+}
+
+/* { dg-final { scan-tree-dump-times "ui\..* = same as mystruct" 1 "ealias" } } */
+/* { dg-final { scan-tree-dump-times "mystruct.*ESCAPED" 1 "ealias" } } */
+/* { dg-final { scan-tree-dump-times "pp = same as mystruct" 1 "ealias" } } */
+/* { dg-final { cleanup-tree-dump "ealias" } } */
Index: tree-ssa-alias.c
===================================================================
--- tree-ssa-alias.c	(revision 151124)
+++ tree-ssa-alias.c	(working copy)
@@ -886,8 +886,8 @@ ref_maybe_used_by_call_p_1 (gimple call,
       && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (callee))
       {
-	/* All the following functions clobber memory pointed to by
-	   their first argument.  */
+	/* All the following functions read memory pointed to by
+	   their second argument.  */
 	case BUILT_IN_STRCPY:
 	case BUILT_IN_STRNCPY:
 	case BUILT_IN_BCOPY:
@@ -898,10 +898,22 @@ ref_maybe_used_by_call_p_1 (gimple call,
 	case BUILT_IN_STPNCPY:
 	case BUILT_IN_STRCAT:
 	case BUILT_IN_STRNCAT:
+        case BUILT_IN_TM_MEMCPY:
+        case BUILT_IN_TM_MEMMOVE:
 	  {
 	    tree src = gimple_call_arg (call, 1);
 	    return ptr_deref_may_alias_ref_p (src, ref);
 	  }
+        /* The following functions read memory pointed to by their
+	   first argument.  */
+        case BUILT_IN_TM_LOAD_1:
+        case BUILT_IN_TM_LOAD_2:
+        case BUILT_IN_TM_LOAD_4:
+        case BUILT_IN_TM_LOAD_8:
+        case BUILT_IN_TM_LOAD_FLOAT:
+        case BUILT_IN_TM_LOAD_DOUBLE:
+        case BUILT_IN_TM_LOAD_LDOUBLE:
+	  return ptr_deref_may_alias_ref_p (gimple_call_arg (call, 0), ref);
 	/* The following builtins do not read from memory.  */
 	case BUILT_IN_FREE:
 	case BUILT_IN_MEMSET:
@@ -1106,6 +1118,15 @@ call_may_clobber_ref_p_1 (gimple call, a
 	case BUILT_IN_STPNCPY:
 	case BUILT_IN_STRCAT:
 	case BUILT_IN_STRNCAT:
+        case BUILT_IN_TM_STORE_1:
+        case BUILT_IN_TM_STORE_2:
+        case BUILT_IN_TM_STORE_4:
+        case BUILT_IN_TM_STORE_8:
+        case BUILT_IN_TM_STORE_FLOAT:
+        case BUILT_IN_TM_STORE_DOUBLE:
+        case BUILT_IN_TM_STORE_LDOUBLE:
+        case BUILT_IN_TM_MEMCPY:
+        case BUILT_IN_TM_MEMMOVE:
 	  {
 	    tree dest = gimple_call_arg (call, 0);
 	    return ptr_deref_may_alias_ref_p_1 (dest, ref);
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 151124)
+++ gimplify.c	(working copy)
@@ -6284,7 +6284,7 @@ gimplify_tm_atomic (tree *expr_p, gimple
   push_gimplify_context (&gctx);
 
   g = gimplify_and_return_first (TM_ATOMIC_BODY (expr), &body);
-  if (gimple_code (g) == GIMPLE_BIND)
+  if (g && gimple_code (g) == GIMPLE_BIND)
     pop_gimplify_context (g);
   else
     pop_gimplify_context (NULL);
Index: gtm-builtins.def
===================================================================
--- gtm-builtins.def	(revision 151125)
+++ gtm-builtins.def	(working copy)
@@ -36,16 +36,16 @@ DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBL
 		BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
 
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1",
-		BT_FN_I1_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2",
-		BT_FN_I2_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4",
-		BT_FN_I4_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8",
-		BT_FN_I8_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF",
-		BT_FN_FLOAT_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD",
-		BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
 DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE",
-		BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_NOTHROW_LIST)
+		BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
Index: tree-ssa-structalias.c
===================================================================
--- tree-ssa-structalias.c	(revision 151124)
+++ tree-ssa-structalias.c	(working copy)
@@ -3589,13 +3589,11 @@ handle_pure_call (gimple stmt, VEC(ce_s,
 
 /* Walk statement T setting up aliasing constraints according to the
    references found in T.  This function is the main part of the
-   constraint builder.  AI points to auxiliary alias information used
-   when building alias sets and computing alias grouping heuristics.  */
+   constraint builder.  */
 
 static void
-find_func_aliases (gimple origt)
+find_func_aliases (gimple t)
 {
-  gimple t = origt;
   VEC(ce_s, heap) *lhsc = NULL;
   VEC(ce_s, heap) *rhsc = NULL;
   struct constraint_expr *c;
@@ -3668,6 +3666,8 @@ find_func_aliases (gimple origt)
 	  case BUILT_IN_STPNCPY:
 	  case BUILT_IN_STRCAT:
 	  case BUILT_IN_STRNCAT:
+	  case BUILT_IN_TM_MEMCPY:
+	  case BUILT_IN_TM_MEMMOVE:
 	    {
 	      tree res = gimple_call_lhs (t);
 	      tree dest = gimple_call_arg (t, 0);
@@ -3728,6 +3728,44 @@ find_func_aliases (gimple origt)
 	      VEC_free (ce_s, heap, lhsc);
 	      return;
 	    }
+	  case BUILT_IN_TM_STORE_1:
+	  case BUILT_IN_TM_STORE_2:
+	  case BUILT_IN_TM_STORE_4:
+	  case BUILT_IN_TM_STORE_8:
+	  case BUILT_IN_TM_STORE_FLOAT:
+	  case BUILT_IN_TM_STORE_DOUBLE:
+	  case BUILT_IN_TM_STORE_LDOUBLE:
+	    {
+	      tree addr = gimple_call_arg (t, 0);
+	      tree src = gimple_call_arg (t, 1);
+
+	      get_constraint_for (addr, &lhsc);
+	      do_deref (&lhsc);
+	      get_constraint_for (src, &rhsc);
+	      process_all_all_constraints (lhsc, rhsc);
+	      VEC_free (ce_s, heap, lhsc);
+	      VEC_free (ce_s, heap, rhsc);
+	      return;
+	    }
+	  case BUILT_IN_TM_LOAD_1:
+	  case BUILT_IN_TM_LOAD_2:
+	  case BUILT_IN_TM_LOAD_4:
+	  case BUILT_IN_TM_LOAD_8:
+	  case BUILT_IN_TM_LOAD_FLOAT:
+	  case BUILT_IN_TM_LOAD_DOUBLE:
+	  case BUILT_IN_TM_LOAD_LDOUBLE:
+	    {
+	      tree dest = gimple_call_lhs (t);
+	      tree addr = gimple_call_arg (t, 0);
+
+	      get_constraint_for (dest, &lhsc);
+	      get_constraint_for (addr, &rhsc);
+	      do_deref (&rhsc);
+	      process_all_all_constraints (lhsc, rhsc);
+	      VEC_free (ce_s, heap, lhsc);
+	      VEC_free (ce_s, heap, rhsc);
+	      return;
+	    }
 	  /* All the following functions do not return pointers, do not
 	     modify the points-to sets of memory reachable from their
 	     arguments and do not add to the ESCAPED solution.  */



More information about the Gcc-patches mailing list