Hi! ix86_md_asm_adjust right above this code uses: machine_mode dest_mode = GET_MODE (dest); if (!SCALAR_INT_MODE_P (dest_mode)) { error ("invalid type for %<asm%> flag output"); continue; } but then assumes that dest_mode can be only [QHSD]Imode and nothing else.
The following patch handles TImode and hypothetically even wider modes by handling it like DImode for 32-bit. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-12-03 Jakub Jelinek <ja...@redhat.com> PR target/98086 * config/i386/i386.c (ix86_md_asm_adjust): Use dest_mode DImode or SImode for modes wider than DImode. If dest_mode isn't SImode or GET_MODE (dest) isn't DImode, use convert_to_mode. * gcc.target/i386/pr98086.c: New test. --- gcc/config/i386/i386.c.jj 2020-11-18 09:40:09.498664422 +0100 +++ gcc/config/i386/i386.c 2020-12-02 15:33:26.224184113 +0100 @@ -21508,6 +21508,8 @@ ix86_md_asm_adjust (vec<rtx> &outputs, v continue; } + if (GET_MODE_BITSIZE (dest_mode) > GET_MODE_BITSIZE (DImode)) + dest_mode = DImode; if (dest_mode == DImode && !TARGET_64BIT) dest_mode = SImode; @@ -21534,10 +21536,16 @@ ix86_md_asm_adjust (vec<rtx> &outputs, v if (dest_mode != GET_MODE (dest)) { - rtx tmp = gen_reg_rtx (SImode); + rtx tmp = gen_reg_rtx (dest_mode); emit_insn (gen_rtx_SET (tmp, x)); - emit_insn (gen_zero_extendsidi2 (dest, tmp)); + if (dest_mode == SImode && GET_MODE (dest) == DImode) + emit_insn (gen_zero_extendsidi2 (dest, tmp)); + else + { + tmp = convert_to_mode (GET_MODE (dest), tmp, 1); + emit_insn (gen_rtx_SET (dest, tmp)); + } } else emit_insn (gen_rtx_SET (dest, x)); --- gcc/testsuite/gcc.target/i386/pr98086.c.jj 2020-12-02 15:36:40.858951118 +0100 +++ gcc/testsuite/gcc.target/i386/pr98086.c 2020-12-02 15:37:27.305406401 +0100 @@ -0,0 +1,10 @@ +/* PR target/98086 */ +/* { dg-do compile { target int128 } } */ + +__int128_t x; + +void +foo (void) +{ + __asm ("" : "=@ccc" (x)); +} Jakub