===================================================================
@@ -0,0 +1,18 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O -fdump-tree-optimized" }
+
+// Test that we don't instrument the result from
+// _ITM_cxa_allocate_exception().
+
+static void throwit() {
+ throw 1;
+}
+
+void tranfunc() {
+ __transaction {
+ throwit();
+ }
+}
+
+// { dg-final { scan-tree-dump-times "_ITM_WU" 0 "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
===================================================================
@@ -1258,6 +1258,7 @@ thread_private_new_memory (basic_block e
tm_new_mem_map_t elt, *elt_p;
tree val = x;
enum thread_memory_type retval = mem_transaction_local;
+ bool escapes_function_p = false;
if (!entry_block
|| TREE_CODE (x) != SSA_NAME
@@ -1283,17 +1284,14 @@ thread_private_new_memory (basic_block e
do
{
if (ptr_deref_may_alias_global_p (x))
- {
- /* Address escapes. This is not thread-private. */
- retval = mem_non_local;
- goto new_memory_ret;
- }
+ escapes_function_p = true;
stmt = SSA_NAME_DEF_STMT (x);
/* If the malloc call is outside the transaction, this is
thread-local. */
if (retval != mem_thread_local
+ && gimple_code (stmt) != GIMPLE_NOP
&& !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), entry_block))
retval = mem_thread_local;
@@ -1357,6 +1355,33 @@ thread_private_new_memory (basic_block e
retval = mem_non_local;
new_memory_ret:
+ if (escapes_function_p)
+ {
+ tree fndecl;
+
+ /* If the address escapes the function, it also escapes the thread. */
+ retval = mem_non_local;
+
+ /* Unlesss... it's one of our special thread private calls. */
+ if (stmt && is_gimple_call (stmt)
+ && (fndecl = gimple_call_fndecl (stmt)))
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+ if (!strcmp (name, "_ITM_cxa_allocate_exception")
+ || !strcmp (name, "_ITM_cxa_begin_catch"))
+ {
+ retval = mem_transaction_local;
+ /* Set MEM_TRANSACTION_LOCAL which will get no
+ instrumentation for this address.
+
+ Even though we're technically thread private, treat
+ as transaction local, because a transaction restart
+ will call __cxa_tm_cleanup() which will cleanup any
+ (exception) memory allocated. */
+ }
+ }
+ }
+
elt_p->local_new_memory = retval;
return retval;
}