This PR was reopened because Luke Dalessandro found a testcase that was
still causing the stack corruption.
The problem here is that we split the block and call gsi_start_bb() to
start scanning the new block, but immediately after we call gsi_next()
which essentially skips the first instruction.
OK for branch and mainline? (Pending tests currently currently running
for both 4.7 and trunk).
PR middle-end/47530
* trans-mem.c (expand_block_edges): Do not skip the first
statement when resetting the BB.
Index: testsuite/g++.dg/tm/pr47530-2.C
===================================================================
--- testsuite/g++.dg/tm/pr47530-2.C (revision 0)
+++ testsuite/g++.dg/tm/pr47530-2.C (revision 0)
@@ -0,0 +1,34 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O2 -fno-inline" }
+
+class RBTree
+{
+ struct RBNode
+ {
+ RBNode* next;
+ };
+
+ public:
+ RBNode* sentinel;
+ __attribute__((transaction_safe)) bool lookup();
+};
+
+bool RBTree::lookup()
+{
+ RBNode* x = sentinel;
+ while (x)
+ x = x->next;
+ return false;
+}
+
+
+RBTree* SET;
+
+void bench_test()
+{
+ __transaction_atomic {
+ SET->lookup();
+ }
+}
+
+// { dg-final { scan-assembler-not "jmp.*ITM_commitTransaction" } }
Index: trans-mem.c
===================================================================
--- trans-mem.c (revision 188081)
+++ trans-mem.c (working copy)
@@ -2591,6 +2591,7 @@ expand_block_edges (struct tm_region *re
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
{
+ bool do_next = true;
gimple stmt = gsi_stmt (gsi);
/* ??? TM_COMMIT (and any other tm builtin function) in a nested
@@ -2612,6 +2613,7 @@ expand_block_edges (struct tm_region *re
make_tm_edge (stmt, bb, region);
bb = e->dest;
gsi = gsi_start_bb (bb);
+ do_next = false;
}
/* Delete any tail-call annotation that may have been added.
@@ -2620,7 +2622,8 @@ expand_block_edges (struct tm_region *re
gimple_call_set_tail (stmt, false);
}
- gsi_next (&gsi);
+ if (do_next)
+ gsi_next (&gsi);
}
}