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

--- Comment #3 from Uroš Bizjak <ubizjak at gmail dot com> ---
For reference:

The assert in create_pre_exit at mode-switching.c expects return copy
pair with nothing in between. However, the compiler starts mode
switching pass with the following sequence:

(insn 19 18 16 2 (set (reg:V2SF 21 xmm0)
        (mem/c:V2SF (plus:DI (reg/f:DI 7 sp)
                (const_int -72 [0xffffffffffffffb8])) [0  S8 A64]))
"pr88070.c":8 1157 {*movv2sf_internal}
     (nil))
(insn 16 19 20 2 (set (reg:V2SF 0 ax [orig:91 <retval> ] [91])
        (reg:V2SF 0 ax [89])) "pr88070.c":8 1157 {*movv2sf_internal}
     (nil))
(insn 20 16 21 2 (unspec_volatile [
            (const_int 0 [0])
        ] UNSPECV_BLOCKAGE) "pr88070.c":8 710 {blockage}
     (nil))
(insn 21 20 23 2 (use (reg:V2SF 21 xmm0)) "pr88070.c":8 -1
     (nil))

Please note how (insn 16) interferes with (insn 19)-(insn 21) return copy pair.

The culprit for this is the blockage instruction (insn 20), which
causes sched1 pass (pre reload scheduler) to skip marking (insn 19) as
unmovable instruction (as a dependent insn on return use insn), so the
scheduler is free to schedule (insn 16) between return copy pair (insn
19)-(insn 21).

The extra instruction is generated as a kludge in expand_function_end
to prevent instructions that may trap to be scheduled into function
epilogue. However, the same blockage is generated under exactly the
same conditions earlier in the expand_function_end. The first blockage
should prevent unwanted scheduling into the epilogue, so there is
actually no need for the second one.

Reply via email to