This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [trans-mem] make alias oracle understand TM read/writes
>> 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. */