===================================================================
@@ -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;
+}
===================================================================
@@ -2173,12 +2173,52 @@ 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 (!gimple_call_nothrow_p (stmt)
+ && gsi_one_before_end_p (*gsi))
+ {
+ 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);
+
+ /* We cannot throw in the middle of a BB. If the call was going
+ to throw, split the block so the call remains the last
+ statement in the block after we add instrumentation. */
+ if (fallthru_edge)
+ {
+ basic_block bb;
+
+ gsi_insert_on_edge_immediate (fallthru_edge, stmt);
+
+ /* Split the block so the instrumentation code resides in
+ it's own separate BB. Then we can mark this BB as handled
+ and avoid rescanning it again. */
+ bb = gimple_bb (stmt);
+ split_block (bb, stmt);
+ *gsi = gsi_start_bb (bb);
+
+ /* Mark BB as completely handled to avoid expanding it
+ again, thus creating useless tm_save logs. */
+ bb->aux = (void *) true;
+ }
+ else
+ gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
+
expand_assign_tm (region, gsi);
transaction_subcode_ior (region, GTMA_HAVE_STORE);
@@ -2304,28 +2344,25 @@ 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. */
+
+ 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)
{
- 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);
- }
+ /* In expand_block_tm, we set the BB->AUX field for any
+ block which we have already handled, to avoid rescanning
+ it. This happens in expand_call_tm() on any new BB
+ inserted which only contains instrumentation code. */
+ if (bb->aux == NULL)
+ expand_block_tm (region, bb);
+ else
+ bb->aux = NULL;
}
+ VEC_free (basic_block, heap, queue);
+
tm_log_emit ();
}