I swear, these inline asms in transactions are going to be the death of me.
In the attached testcase diagnose_tm_blocks() and lower_tm() do not
recognize the GIMPLE_ASM because early inlining has not yet run, so
there is nothing to see. However, by the time we run the IPA TM pass,
the assembly statement has been inlined but we no longer detect
GIMPLE_ASMs correctly:
/* Now validate all tm_safe functions, and all atomic regions in
other functions. */
for (node = cgraph_nodes; node; node = node->next)
if (node->reachable && node->lowered
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{
d = get_cg_data (&node, true);
if (is_tm_safe (node->decl)) <-- !! FINDS NOTHING !!
ipa_tm_diagnose_tm_safe (node);
else if (d->all_tm_regions)
ipa_tm_diagnose_transaction (node, d->all_tm_regions);
}
The call to ipa_tm_diagnose_tm_safe() does nothing because there are no
longer any calls in the function, since the function call has been inlined:
f ()
{
<bb 2>:
__asm__ __volatile__("");
return;
}
Perhaps we could issue the error when we notice the GIMPLE_ASM while
scanning for irrevocable blocks earlier. The attached patch does so,
and fixes the PR.
What am I missing, cause I *know* there's a rat's nest somewhere.
Aldy
PR middle-end/52141
* trans-mem.c (ipa_tm_scan_irr_block): Error on GIMPLE_ASM.
Index: testsuite/gcc.dg/tm/pr52141.c
===================================================================
--- testsuite/gcc.dg/tm/pr52141.c (revision 0)
+++ testsuite/gcc.dg/tm/pr52141.c (revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O1" } */
+
+inline void asmfunc(void)
+{
+ __asm__ (""); /* { dg-error "asm not allowed in .transaction_safe" } */
+}
+
+__attribute__((transaction_safe))
+static void f(void)
+{
+ asmfunc();
+}
+
+int main()
+{
+ __transaction_atomic {
+ f();
+ }
+ return 0;
+}
Index: trans-mem.c
===================================================================
--- trans-mem.c (revision 184181)
+++ trans-mem.c (working copy)
@@ -3736,6 +3736,10 @@ ipa_tm_scan_irr_block (basic_block bb)
assembly statement is not relevant to the transaction
is to wrap it in a __tm_waiver block. This is not
yet implemented, so we can't check for it. */
+ if (is_tm_safe (current_function_decl))
+ error_at (gimple_location (stmt),
+ "asm not allowed in %<transaction_safe%> function %qE",
+ current_function_decl);
return true;
default: