Rainer Orth <r...@cebitec.uni-bielefeld.de> wrote:

>> Rainer Orth <r...@cebitec.uni-bielefeld.de> wrote:
>>>> On Sat, Apr 11, 2020 at 03:46:18PM +0100, Iain Sandoe wrote:
>>>>> Unfortunately, several targets have ABI constraints that prevent
>>>>> an indirect tail-call, which results in the PRs compile error.
>> 
>> So .. after scanning the current published testsuite results I have:
>> 
>> // See PR94359 - some targets are unable to make general indirect tailcalls
>> // for example, between different DSOs.
>> // { dg-xfail-run-if "" { hppa*-*-hpux11* } }
>> // { dg-xfail-run-if "" { ia64-*-linux-gnu } }
>> // { dg-xfail-run-if "" { { lp64 && { powerpc*-linux-gnu } } || { *-*-aix*
>> } } }
>> // { dg-xfail-run-if "" { sparc-*-solaris2* } }
> 
> this is wrong: for one, it needs to allow for 64-bit-default SPARC
> configurations (i.e. sparcv9-*-* and sparc64-*-*), and AFAICS there's
> nothing Solaris-specific here.  So this should be sparc*-*-* instead.
> 
>> I’d say it would be a reasonable idea to get this in sooner rather than
>> later, we
>> can always increase the list (or a target maintainer can trivially add
>> their target)
> 
> Fine with me.  If the list gets much longer or the conditions more
> complex, it might still be worthwhile to use an effective-target keyword
> instead.

This is what I’ve pushed after re-checking on
x86_64-linux/darwin
sparc-solaris11
powerpc64-linux-gnu

I won’t be entirely surprised if the list needs amendment or additions
but that’s realistically what I can test.

thanks for the reviews,

Iain

coroutines: Fix compile error with symmetric transfers [PR94359]

For symmetric transfers to work with C++20 coroutines, it is
currently necessary to tail call the callee coroutine from resume
method of the caller coroutine. The current codegen marks these
resume calls as "MUST_TAIL_CALL" to indicate that the tail call is
required for correctness.

Unfortunately, several targets have ABI constraints that prevent
an indirect tail-call, which results in the PRs compile error.

The change here tests the target sibcall hook for the resume
expression and only marks it as requiring a tail call if that's
supported.

This doesn't fix the underlying problem; that really a solution is
needed to allow the tail-calls (or equivalent) to take place - but
that will be deferred until next stage 1.

gcc/cp/ChangeLog:

2020-04-14  Iain Sandoe  <i...@sandoe.co.uk>

        PR c++/94359
        * coroutines.cc (build_actor_fn): Check that the target can
        support the resume tailcall before mandating it.

gcc/testsuite/ChangeLog:

2020-04-14  Iain Sandoe  <i...@sandoe.co.uk>

        PR c++/94359
        * g++.dg/coroutines/torture/symmetric-transfer-00-basic.C:
        Expect a run fail for targets without arbitrary indirect
        tail-calls.


diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 57172853639..e4ba642d527 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2376,14 +2376,22 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   tree resume = build_call_expr_loc
     (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
 
+  /* In order to support an arbitrary number of coroutine continuations,
+     we must tail call them.  However, some targets might not support this
+     for indirect calls, or calls between DSOs.
+     FIXME: see if there's an alternate strategy for such targets.  */
   /* Now we have the actual call, and we can mark it as a tail.  */
   CALL_EXPR_TAILCALL (resume) = true;
-  /* ... and for optimisation levels 0..1, mark it as requiring a tail-call
-     for correctness.  It seems that doing this for optimisation levels that
-     normally perform tail-calling, confuses the ME (or it would be logical
-     to put this on unilaterally).  */
-  if (optimize < 2)
-    CALL_EXPR_MUST_TAIL_CALL (resume) = true;
+  /* Temporarily, switch cfun so that we can use the target hook.  */
+  push_struct_function (actor);
+  if (targetm.function_ok_for_sibcall (NULL_TREE, resume))
+    {
+      /* ... and for optimisation levels 0..1, which do not normally tail-
+       -call, mark it as requiring a tail-call for correctness.  */
+      if (optimize < 2)
+       CALL_EXPR_MUST_TAIL_CALL (resume) = true;
+    }
+  pop_cfun ();
   resume = coro_build_cvt_void_expr_stmt (resume, loc);
   add_stmt (resume);
 
@@ -3951,7 +3959,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree 
*destroyer)
 
   push_deferring_access_checks (dk_no_check);
 
-  /* Actor ...  */
+  /* Build the actor...  */
   build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
                  &local_var_uses, param_dtor_list, initial_await, final_await,
                  body_aw_points.await_number, frame_size);

diff --git 
a/gcc/testsuite/g++.dg/coroutines/torture/symmetric-transfer-00-basic.C 
b/gcc/testsuite/g++.dg/coroutines/torture/symmetric-transfer-00-basic.C
index 864846e365c..6f379c8e77a 100644
--- a/gcc/testsuite/g++.dg/coroutines/torture/symmetric-transfer-00-basic.C
+++ b/gcc/testsuite/g++.dg/coroutines/torture/symmetric-transfer-00-basic.C
@@ -1,4 +1,10 @@
-//  { dg-do run }
+// { dg-do run }
+// See PR94359 - some targets are unable to make general indirect tailcalls
+// for example, between different DSOs.
+// { dg-xfail-run-if "" { hppa*-*-hpux11* } }
+// { dg-xfail-run-if "" { ia64-*-linux-gnu } }
+// { dg-xfail-run-if "" { { lp64 && { powerpc*-linux-gnu } } || { *-*-aix* } } 
}
+// { dg-xfail-run-if "" { sparc*-*-* } }
 
 #if __has_include(<coroutine>)
 

Reply via email to