On Fri, 9 Feb 2024, Jakub Jelinek wrote:

> Hi!
> 
> The asm goto expansion ICEs on the following testcase (which normally
> is rejected later), because expand_asm_stmt emits the code to copy
> the large var out of the out operand to its memory location into
> after_rtl_seq ... after_rtl_end sequence and because it is asm goto,
> it duplicates the sequence on each successor edge of the asm goto.
> The problem is that with -mstringop-strategy=byte_loop that sequence
> contains loops, so CODE_LABELs, JUMP_INSNs, with other strategies
> could contain CALL_INSNs etc.
> But the copying is done using a loop doing
> emit_insn (copy_insn (PATTERN (curr)));
> which does the right thing solely for INSNs, it will do the wrong thing
> for JUMP_INSNs, CALL_INSNs, CODE_LABELs (with RTL checking even ICE on
> them), BARRIERs and the like.
> 
> The following patch partially fixes it (with the hope that such stuff only
> occurs in asms that really can't be accepted; if one uses say "=rm" or
> "=g" constraint then the operand uses the memory directly and nothing is
> copied) by using the
> duplicate_insn_chain function which is used e.g. in RTL loop unrolling and
> which can handle JUMP_INSNs, CALL_INSNs, BARRIERs etc.
> As it is meant to operate on sequences inside of basic blocks, it doesn't
> handle CODE_LABELs (well, it skips them), so if we need a solution that
> will be correct at runtime here for those cases, we'd need to do further
> work (e.g. still use duplicate_insn_chain, but if we notice any CODE_LABELs,
> walk the sequence again, add copies of the CODE_LABELs and then remap
> references to the old CODE_LABELs in the copied sequence to the new ones).
> Because as is now, if the code in one of the sequence copies (where the
> CODE_LABELs have been left out) decides to jump to such a CODE_LABEL, it
> will jump to the CODE_LABEL which has been in the original sequence (which
> the code emits on the last edge, after all, duplicating the sequence
> EDGE_COUNT times and throwing away the original was wasteful, compared to
> doing that just EDGE_COUNT - 1 times and using the original.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

> Or do need to handle even CODE_LABELs?

I guess we'll do when we run into it?  I'm not sure we can constrain
asm gotos in a way such complicated "after" sequences never happen,
right?  A sorry () might be a possibility for cases we don't handle.

Richard.

> 2024-02-09  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR middle-end/113415
>       * cfgexpand.cc (expand_asm_stmt): For asm goto, use
>       duplicate_insn_chain to duplicate after_rtl_seq sequence instead
>       of hand written loop with emit_insn of copy_insn and emit original
>       after_rtl_seq on the last edge.
> 
>       * gcc.target/i386/pr113415.c: New test.
> 
> --- gcc/cfgexpand.cc.jj       2024-01-24 13:11:21.011469855 +0100
> +++ gcc/cfgexpand.cc  2024-02-08 18:22:04.699621085 +0100
> @@ -3671,16 +3671,21 @@ expand_asm_stmt (gasm *stmt)
>       {
>         edge e;
>         edge_iterator ei;
> -       
> +       unsigned int cnt = EDGE_COUNT (gimple_bb (stmt)->succs);
> +
>         FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)
>           {
> -           start_sequence ();
> -           for (rtx_insn *curr = after_rtl_seq;
> -                curr != NULL_RTX;
> -                curr = NEXT_INSN (curr))
> -             emit_insn (copy_insn (PATTERN (curr)));
> -           rtx_insn *copy = get_insns ();
> -           end_sequence ();
> +           rtx_insn *copy;
> +           if (--cnt == 0)
> +             copy = after_rtl_seq;
> +           else
> +             {
> +               start_sequence ();
> +               duplicate_insn_chain (after_rtl_seq, after_rtl_end,
> +                                     NULL, NULL);
> +               copy = get_insns ();
> +               end_sequence ();
> +             }
>             insert_insn_on_edge (copy, e);
>           }
>       }
> --- gcc/testsuite/gcc.target/i386/pr113415.c.jj       2024-02-08 
> 18:26:27.622966847 +0100
> +++ gcc/testsuite/gcc.target/i386/pr113415.c  2024-02-08 18:26:11.336193222 
> +0100
> @@ -0,0 +1,11 @@
> +/* PR middle-end/113415 */
> +/* { dg-do compile } */
> +/* { dg-options "-mstringop-strategy=byte_loop" } */
> +
> +void
> +foo (void)
> +{
> +  unsigned long arr[64];
> +lab:
> +  __asm__ goto ("" : "=r" (arr) : : : lab);  /* { dg-error "impossible 
> constraint in 'asm'" } */
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to