 : compute-liveness ( rpo -- )
     <hashed-dlist> work-list set
     H{ } clone live-ins set
+    H{ } clone phi-live-ins set
     H{ } clone live-outs set
     <reversed> add-to-work-list
     work-list get [ liveness-step ] slurp-deque ;
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces deques accessors sets sequences assocs fry
dlists compiler.cfg.def-use ;
IN: compiler.cfg.liveness

! This is a backward dataflow analysis. See http://en.wikipedia.org/wiki/Liveness_analysis

: map-unique ( seq quot -- assoc )
    map concat unique ; inline

: gen-set ( instructions -- seq )
    [ ##phi? not ] filter [ uses-vregs ] map-unique ;

: kill-set ( instructions -- seq )
    [ defs-vregs ] map-unique ;

: compute-live-in ( basic-block -- live-in )
    dup instructions>>
    [ [ live-out ] [ gen-set ] bi* assoc-union ]
    [ nip kill-set ]
    2bi assoc-diff ;

: compute-phi-live-in ( basic-block -- phi-live-in )
    instructions>> [ ##phi? ] filter
    [ f ] [ [ inputs>> ] map flip [ unique ] map ] if-empty ;

: update-live-in ( basic-block -- changed? )
    [ [ compute-live-in ] keep live-ins get maybe-set-at ]
    [ [ compute-phi-live-in ] keep phi-live-ins get maybe-set-at ]
    bi and ; 

: compute-live-out ( basic-block -- live-out )
    [ successors>> [ live-in ] map ]
    [ dup successors>> [ phi-live-in ] with map ] bi
    append assoc-combine ;

: update-live-out ( basic-block -- changed? )
    [ compute-live-out ] keep
    live-outs get maybe-set-at ;

: liveness-step ( basic-block -- )
