1 ! Copyright (C) 2009, 2010 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs combinators combinators.short-circuit
4 compiler.cfg.def-use compiler.cfg.instructions
5 compiler.cfg.predecessors compiler.cfg.registers
6 compiler.cfg.rpo compiler.cfg.ssa.destruction.leaders
7 compiler.cfg.utilities compiler.utilities cpu.architecture
8 deques dlists kernel namespaces sequences sets ;
9 IN: compiler.cfg.liveness
13 : live-in ( bb -- set )
18 : live-out ( bb -- set )
23 : edge-live-in ( predecessor basic-block -- set )
24 edge-live-ins get at at ;
28 GENERIC: visit-insn ( live-set insn -- )
30 ! This would be much better if live-set was a real set
31 : kill-defs ( live-set insn -- )
32 defs-vregs [ ?leader ] map
33 '[ drop ?leader _ in? ] assoc-reject! drop ; inline
35 : gen-uses ( live-set insn -- )
36 uses-vregs [ swap conjoin ] with each ; inline
38 M: vreg-insn visit-insn
39 [ kill-defs ] [ gen-uses ] 2bi ;
41 DEFER: lookup-base-pointer
43 GENERIC: lookup-base-pointer* ( vreg insn -- vreg/f )
45 M: ##tagged>integer lookup-base-pointer* nip src>> ;
47 M: ##unbox-any-c-ptr lookup-base-pointer*
48 ! If the input to unbox-any-c-ptr was an alien and not a
49 ! byte array, then the derived pointer will be outside of
50 ! the data heap. The GC has to handle this case and ignore
54 M: ##copy lookup-base-pointer* nip src>> lookup-base-pointer ;
56 M: ##add-imm lookup-base-pointer* nip src1>> lookup-base-pointer ;
58 M: ##sub-imm lookup-base-pointer* nip src1>> lookup-base-pointer ;
60 M: ##parallel-copy lookup-base-pointer* values>> value-at ;
62 M: ##add lookup-base-pointer*
63 ! If both operands have a base pointer, then the user better
64 ! not be doing memory reads and writes on the object, since
65 ! we don't give it a base pointer in that case at all.
66 nip [ src1>> ] [ src2>> ] bi [ lookup-base-pointer ] bi@ xor ;
68 M: ##sub lookup-base-pointer*
69 nip src1>> lookup-base-pointer ;
71 M: vreg-insn lookup-base-pointer* 2drop f ;
73 : lookup-base-pointer ( vreg -- vreg/f )
74 base-pointers get ?at [
75 f over base-pointers get set-at
76 [ dup ?leader insn-of lookup-base-pointer* ] keep
77 dupd base-pointers get set-at
80 :: visit-derived-root ( vreg derived-roots gc-roots -- )
81 vreg lookup-base-pointer :> base
83 { vreg base } derived-roots push
87 : visit-gc-root ( vreg derived-roots gc-roots -- )
89 { tagged-rep [ nip adjoin ] }
90 { int-rep [ visit-derived-root ] }
94 : gc-roots ( live-set -- derived-roots gc-roots )
95 keys V{ } clone HS{ } clone
96 [ '[ _ _ visit-gc-root ] each ] 2keep members ;
98 : fill-gc-map ( live-set gc-map -- )
99 [ gc-roots ] dip [ gc-roots<< ] [ derived-roots<< ] bi ;
101 M: gc-map-insn visit-insn
102 [ kill-defs ] [ gc-map>> fill-gc-map ] [ gen-uses ] 2tri ;
104 M: ##phi visit-insn kill-defs ;
106 M: insn visit-insn 2drop ;
108 : transfer-liveness ( live-set insns -- )
109 <reversed> [ visit-insn ] with each ;
111 : compute-live-in ( basic-block -- live-in )
112 [ live-out clone dup ] keep instructions>> transfer-liveness ;
114 : compute-edge-live-in ( basic-block -- edge-live-in )
116 '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
119 : update-live-in ( basic-block -- changed? )
120 [ [ compute-live-in ] keep live-ins get maybe-set-at ]
121 [ [ compute-edge-live-in ] keep edge-live-ins get maybe-set-at ]
124 : compute-live-out ( basic-block -- live-out )
125 [ successors>> [ live-in ] map ]
126 [ dup successors>> [ edge-live-in ] with map ] bi
127 append assoc-union-all ;
129 : update-live-out ( basic-block -- changed? )
130 [ compute-live-out ] keep
131 live-outs get maybe-set-at ;
133 : update-live-out/in ( basic-block -- changed? )
134 { [ update-live-out ] [ update-live-in ] } 1&& ;
136 : liveness-step ( basic-block -- basic-blocks )
137 [ update-live-out/in ] keep predecessors>> { } ? ;
139 : init-liveness ( -- )
140 H{ } clone live-ins namespaces:set
141 H{ } clone edge-live-ins namespaces:set
142 H{ } clone live-outs namespaces:set
143 H{ } clone base-pointers namespaces:set ;
145 : compute-live-sets ( cfg -- )
147 dup needs-predecessors dup compute-insns
148 post-order <hashed-dlist> [ push-all-front ] keep
149 [ liveness-step ] slurp/replenish-deque ;
151 : live-in? ( vreg bb -- ? ) live-in key? ;
153 : live-out? ( vreg bb -- ? ) live-out key? ;