 
 GENERIC: prepare-insn ( insn -- )
 
-: maybe-eliminate-copy-later ( dst src -- )
-    2array copies get push ;
-
 M: insn prepare-insn drop ;
 
 M: alien-call-insn prepare-insn drop ;

        2dup [ empty? not ] both? [
            [ first ] bi@
            2dup [ rep-of reg-class-of ] bi@ eq?
            [ maybe-eliminate-copy-later ] [ 2drop ] if
        ] [ 2drop ] if
    ] bi ;

M: ##copy prepare-insn
    [ dst>> ] [ src>> ] bi maybe-eliminate-copy-later ;

M: ##parallel-copy prepare-insn
    values>> [ first2 maybe-eliminate-copy-later ] each ;

: leaders ( vreg1 vreg2 -- vreg1' vreg2' )
    [ leader ] bi@ ;

: vregs-interfere? ( vreg1 vreg2 -- merged/f ? )
    [ class-elements ] bi@ sets-interfere? ;

ERROR: vregs-shouldn't-interfere vreg1 vreg2 ;

:: must-eliminate-copy ( vreg1 vreg2 -- )
    ! Eliminate a copy.
    vreg1 vreg2 = [
        vreg1 vreg2 vregs-interfere?
        [ vreg1 vreg2 vregs-shouldn't-interfere ]

    [ leaders must-eliminate-copy ] with each ;

: prepare-coalescing ( cfg -- )
    init-coalescing [ [ prepare-insn ] each ] simple-analysis ;

:: maybe-eliminate-copy ( vreg1 vreg2 -- )
    vreg1 vreg2 = [
        vreg1 vreg2 vregs-interfere?
        [ drop ] [ vreg1 vreg2 coalesce-vregs ] if
