Hi! For input arguments, we do: /* If we can't make copies, we can only accept memory. */ if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (link)))) { if (allows_mem) allows_reg = 0; else { error ("impossible constraint in %<asm%>"); error ("non-memory input %d must stay in memory", i); return GS_ERROR; } } The following patch does the same thing for output operands as well. For the cases where !allows_mem, that will just result in one extra error explaining what's going on (previously one would get the impossible constraint in %<asm%> error during vregs pass, now it gets during gimplification + the extra error too), and if allows_mem, it will for the + case make sure we get "=rm" (x) ... : "rm" (x) instead of "=rm" (x) ... : "0" (x) that LRA ICEs on.
While the LRA ICE needs to be fixed in any case (one can still reproduce it with __asm volatile ("" : "=rm" (a0), "=rm" (a1) : "0" (a0), "1" (a1)); ), this patch opens the possibility to accept "+rm" (a0) and reject "=rm" (a0) ... "0" (a0) if reload can't prove it is the same address. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-03-18 Jakub Jelinek <ja...@redhat.com> PR target/89752 * gimplify.c (gimplify_asm_expr): For output argument with TREE_ADDRESSABLE type, clear allows_reg if it allows memory, otherwise diagnose error. * g++.dg/ext/asm15.C: Check for particular diagnostic wording. * g++.dg/ext/asm16.C: Likewise. * g++.dg/ext/asm17.C: New test. --- gcc/gimplify.c.jj 2019-03-07 20:45:39.168938360 +0100 +++ gcc/gimplify.c 2019-03-18 16:18:16.515466234 +0100 @@ -6155,6 +6155,19 @@ gimplify_asm_expr (tree *expr_p, gimple_ is_inout = false; } + /* If we can't make copies, we can only accept memory. */ + if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (link)))) + { + if (allows_mem) + allows_reg = 0; + else + { + error ("impossible constraint in %<asm%>"); + error ("non-memory output %d must stay in memory", i); + return GS_ERROR; + } + } + if (!allows_reg && allows_mem) mark_addressable (TREE_VALUE (link)); --- gcc/testsuite/g++.dg/ext/asm15.C.jj 2018-05-06 23:13:33.252652046 +0200 +++ gcc/testsuite/g++.dg/ext/asm15.C 2019-03-18 18:00:48.907456236 +0100 @@ -6,5 +6,6 @@ struct S { S (); ~S (); int s; }; void foo (S &s) { - __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "" } + __asm volatile ("" : "+r" (s) : : "memory"); // { dg-error "impossible constraint" } + // { dg-error "must stay in memory" "" { target *-*-* } .-1 } } --- gcc/testsuite/g++.dg/ext/asm16.C.jj 2018-05-06 23:13:33.252652046 +0200 +++ gcc/testsuite/g++.dg/ext/asm16.C 2019-03-18 18:00:35.978664187 +0100 @@ -6,5 +6,6 @@ struct S { S (); ~S (); int s[64]; } s; void foo () { - __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "" } + __asm volatile ("" : "=r" (s) : : "memory"); // { dg-error "impossible constraint" } + // { dg-error "must stay in memory" "" { target *-*-* } .-1 } } --- gcc/testsuite/g++.dg/ext/asm17.C.jj 2019-03-18 17:57:44.409424473 +0100 +++ gcc/testsuite/g++.dg/ext/asm17.C 2019-03-18 17:58:32.414651932 +0100 @@ -0,0 +1,11 @@ +// PR target/89752 +// { dg-do compile } + +struct A { A (); ~A (); short c; }; + +void +foo () +{ + A a0, a1; + __asm volatile ("" : "+rm" (a0), "+rm" (a1)); +} Jakub