https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92151

Alexander Monakov <amonakov at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |amonakov at gcc dot gnu.org

--- Comment #3 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
>> (or write actual assembly rather than using inline-asm).
> In this case, yes -- I now declare the function "naked" and avoid the issue.

I think this solution (hand-writing asm for the entire function) is generally
undesirable because you become responsible for ABI/calling convention, the
compiler won't help you with things like properly restoring callee-saved
registers, and violations may stay unnoticed as long as callers don't try to
use a particular callee-saved reg.

Here's a manually reduced variant that exhibits a similar issue at -O1:

void foo(int num, int c) {
    asm("# %0" : "+r"(num));
    while (--c)
        asm goto("# %0" :: "r"(num) :: l2);
l2:
    asm("# %0" :: "r"(num));
}

The main issue seems to be our 'asmcons' pass transforming RTL in such a way
that REG_DEAD notes are "behind" the actual death, so if the RA takes them
literally it operates on wrong (too conservative) lifetime information; e.g.,
for the first asm, just before IRA we have:

(insn 29 4 8 2 (set (reg:SI 84 [ num ])
        (reg:SI 85)) "./example.c":3:5 -1
     (nil))
(insn 8 29 7 2 (parallel [
            (set (reg:SI 84 [ num ])
                (asm_operands:SI ("# %0") ("=r") 0 [
                        (reg:SI 84 [ num ])
                    ]
                     [
                        (asm_input:SI ("0") ./example.c:3)
                    ]
                     [] ./example.c:3))
            (clobber (reg:CC 17 flags))
        ]) "./example.c":3:5 -1
     (expr_list:REG_DEAD (reg:SI 85)
        (expr_list:REG_UNUSED (reg:CC 17 flags)
            (nil))))

but register 85 actually dies in insn 29, not in insn 8.

Reply via email to