===================================================================
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+#include <list>
+class Game
+{
+public:
+ struct BuildProject
+ {
+ int posX;
+ };
+ std::list<BuildProject> buildProjects;
+};
+
+static Game game;
+static std::list<std::list<Game::BuildProject>::iterator> erasableBuildProjects;
+
+static void *buildProjectSyncStepConcurrently(int id, int localTeam)
+{
+ __transaction [[relaxed]] {
+ std::list<std::list<Game::BuildProject>::iterator>::iterator it
+ = erasableBuildProjects.begin();
+ game.buildProjects.erase( (std::list<Game::BuildProject>
+ ::iterator) *it);
+ }
+ return 0;
+}
===================================================================
@@ -1678,6 +1678,9 @@ struct tm_region
/* The set of all blocks that have an TM_IRREVOCABLE call. */
bitmap irr_blocks;
+
+ /* True if there are pending edge statements to be committed. */
+ bool pending_edge_inserts_p;
};
static struct tm_region *all_tm_regions;
@@ -1707,6 +1710,7 @@ tm_region_init_0 (struct tm_region *oute
}
region->inner = NULL;
region->outer = outer;
+ region->pending_edge_inserts_p = false;
region->transaction_stmt = stmt;
@@ -2173,13 +2177,44 @@ expand_call_tm (struct tm_region *region
{
tree tmp = make_rename_temp (TREE_TYPE (lhs), NULL);
location_t loc = gimple_location (stmt);
+ edge fallthru_edge = NULL;
+
+ /* Remember if the call was going to throw. */
+ if (stmt_can_throw_internal (stmt))
+ {
+ edge_iterator ei;
+ edge e;
+ basic_block bb = gimple_bb (stmt);
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ fallthru_edge = e;
+ break;
+ }
+ }
gimple_call_set_lhs (stmt, tmp);
update_stmt (stmt);
stmt = gimple_build_assign (lhs, tmp);
gimple_set_location (stmt, loc);
- gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
- expand_assign_tm (region, gsi);
+
+ /* We cannot throw in the middle of a BB. If the call was going
+ to throw, place the instrumentation on the fallthru edge, so
+ the call remains the last statement in the block. */
+ if (fallthru_edge)
+ {
+ gimple_seq fallthru_seq = gimple_seq_alloc_with_stmt (stmt);
+ gimple_stmt_iterator fallthru_gsi = gsi_start (fallthru_seq);
+ expand_assign_tm (region, &fallthru_gsi);
+ gsi_insert_seq_on_edge (fallthru_edge, fallthru_seq);
+ region->pending_edge_inserts_p = true;
+ }
+ else
+ {
+ gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
+ expand_assign_tm (region, gsi);
+ }
transaction_subcode_ior (region, GTMA_HAVE_STORE);
}
@@ -2304,28 +2339,18 @@ execute_tm_mark (void)
else
subcode &= GTMA_DECLARATION_MASK;
gimple_transaction_set_subcode (region->transaction_stmt, subcode);
-
- queue = get_tm_region_blocks (region->entry_block,
- region->exit_blocks,
- region->irr_blocks,
- /*stop_at_irr_p=*/true);
- for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i)
- expand_block_tm (region, bb);
- VEC_free (basic_block, heap, queue);
- }
- else
- /* ...otherwise, we're a clone and the entire function is the
- region. */
- {
- FOR_EACH_BB (bb)
- {
- /* Stop at irrevocable blocks. */
- if (region->irr_blocks
- && bitmap_bit_p (region->irr_blocks, bb->index))
- break;
- expand_block_tm (region, bb);
- }
}
+
+ queue = get_tm_region_blocks (region->entry_block,
+ region->exit_blocks,
+ region->irr_blocks,
+ /*stop_at_irr_p=*/true);
+ for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i)
+ expand_block_tm (region, bb);
+ VEC_free (basic_block, heap, queue);
+ if (region->pending_edge_inserts_p)
+ gsi_commit_edge_inserts ();
+
tm_log_emit ();
}