1 ! Copyright (C) 2009 Daniel Ehrenberg
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences assocs accessors
4 namespaces fry math sets combinators locals
8 compiler.cfg.instructions ;
9 FROM: namespaces => set ;
10 IN: compiler.cfg.ssa.liveness
12 ! Liveness checking on SSA IR, as described in
13 ! "Fast Liveness Checking for SSA-Form Programs", Sebastian Hack et al.
14 ! http://hal.archives-ouvertes.fr/docs/00/19/22/19/PDF/fast_liveness.pdf
18 ! The sets T_q and R_q are described there
22 ! Targets of back edges
23 SYMBOL: back-edge-targets
31 : back-edge-target? ( block -- ? )
32 back-edge-targets get key? ;
34 : next-R_q ( q -- R_q )
35 [ ] [ successors>> ] [ number>> ] tri
36 '[ number>> _ >= ] filter
37 [ R_q ] map assoc-combine
41 [ next-R_q ] keep R_q-sets get set-at ;
43 : set-back-edges ( q -- )
44 [ successors>> ] [ number>> ] bi '[
46 [ back-edge-targets get conjoin ] [ drop ] if
50 H{ } clone R_q-sets set
51 H{ } clone back-edge-targets set ;
53 : compute-R_q ( cfg -- )
56 [ set-R_q ] [ set-back-edges ] bi
59 ! This algorithm for computing T_q uses equation (1)
60 ! but not the faster algorithm described in the paper
62 : back-edges-from ( q -- edges )
64 [ successors>> ] [ number>> ] bi
65 '[ number>> _ < ] filter
69 [ back-edges-from ] [ R_q ] bi
70 '[ _ key? not ] filter ;
72 : next-T_q ( q -- T_q )
73 dup dup T^_q [ next-T_q keys ] map
74 concat unique [ conjoin ] keep
75 [ swap T_q-sets get set-at ] keep ;
77 : compute-T_q ( cfg -- )
79 [ next-T_q drop ] each-basic-block ;
83 : precompute-liveness ( cfg -- )
84 [ compute-R_q ] [ compute-T_q ] bi ;
88 ! This doesn't take advantage of ordering T_q,a so you
89 ! only have to check one if the CFG is reducible.
90 ! It should be changed to be more efficient.
92 : only? ( seq obj -- ? )
95 : strictly-dominates? ( bb1 bb2 -- ? )
96 [ dominates? ] [ eq? not ] 2bi and ;
98 : T_q,a ( a q -- T_q,a )
99 ! This could take advantage of the structure of dominance,
100 ! but probably I'll replace it with the algorithm that works
101 ! on reducible CFGs anyway
103 [ '[ _ swap strictly-dominates? ] filter ] when* ;
105 : live? ( vreg node quot -- ? )
106 [ [ T_q,a ] [ drop uses-of ] 2bi ] dip
107 '[ [ R_q keys _ ] keep @ intersects? ] any? ; inline
111 : live-in? ( vreg node -- ? )
116 : (live-out?) ( vreg node -- ? )
118 _ = _ back-edge-target? not and
119 [ _ swap remove ] when
124 :: live-out? ( vreg node -- ? )
127 { [ node def eq? ] [ vreg uses-of def only? not ] }
128 { [ def node strictly-dominates? ] [ vreg node (live-out?) ] }