1 ! Copyright (C) 2009, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: namespaces kernel accessors sequences fry assocs
4 sets math combinators deques dlists
10 compiler.cfg.instructions
12 compiler.cfg.renaming.functor
13 compiler.cfg.ssa.construction.tdmsc ;
14 FROM: assocs => change-at ;
15 FROM: namespaces => set ;
16 IN: compiler.cfg.ssa.construction
18 ! Iterated dominance frontiers are computed using the DJ Graph
19 ! method in compiler.cfg.ssa.construction.tdmsc.
21 ! The renaming algorithm is based on "Practical Improvements to
22 ! the Construction and Destruction of Static Single Assignment
25 ! We construct pruned SSA without computing live sets, by
26 ! building a dependency graph for phi instructions, marking the
27 ! transitive closure of a vertex as live if it is referenced by
28 ! some non-phi instruction. Thanks to Cameron Zwarich for the
31 ! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.9683
35 ! Maps vregs to sets of basic blocks
38 ! Set of vregs defined in more than one basic block
41 GENERIC: compute-insn-defs ( bb insn -- )
43 M: insn compute-insn-defs 2drop ;
45 M: vreg-insn compute-insn-defs
47 defs get [ conjoin-at ] [ drop ] [ at assoc-size 1 > ] 2tri
48 [ defs-multi get conjoin ] [ drop ] if
51 : compute-defs ( cfg -- )
53 H{ } clone defs-multi set
55 [ basic-block get ] dip
56 [ compute-insn-defs ] with each
59 ! Maps basic blocks to sequences of ##phi instructions
60 SYMBOL: inserting-phis
62 : insert-phi-later ( vreg bb -- )
63 [ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
64 inserting-phis get push-at ;
66 : compute-phis-for ( vreg bbs -- )
67 keys merge-set [ insert-phi-later ] with each ;
70 H{ } clone inserting-phis set
71 defs-multi get defs get '[ _ at compute-phis-for ] assoc-each ;
73 ! Maps vregs to ##phi instructions
76 ! Worklist of used vregs, to calculate used phis
79 ! Maps vregs to renaming stacks
80 SYMBOLS: stacks pushed ;
82 : init-renaming ( -- )
84 <hashed-dlist> used-vregs set
85 H{ } clone stacks set ;
87 : gen-name ( vreg -- vreg' )
89 dup pushed get 2dup key?
90 [ 2drop stacks get at set-last ]
91 [ conjoin stacks get push-at ]
94 : (top-name) ( vreg -- vreg' )
95 stacks get at [ f ] [ last ] if-empty ;
97 : top-name ( vreg -- vreg' )
99 dup [ dup used-vregs get push-front ] when ;
101 RENAMING: ssa-rename [ gen-name ] [ top-name ] [ ]
103 GENERIC: rename-insn ( insn -- )
105 M: insn rename-insn drop ;
107 M: vreg-insn rename-insn
108 [ ssa-rename-insn-uses ]
109 [ ssa-rename-insn-defs ]
112 : rename-phis ( bb -- )
113 inserting-phis get at [
115 [ ssa-rename-insn-defs ]
116 [ dup dst>> phis get set-at ] bi
120 : rename-insns ( bb -- )
121 instructions>> [ rename-insn ] each ;
123 : rename-successor-phi ( phi bb -- )
124 swap inputs>> [ (top-name) ] change-at ;
126 : rename-successor-phis ( succ bb -- )
127 [ inserting-phis get at ] dip
128 '[ _ rename-successor-phi ] each ;
130 : rename-successors-phis ( bb -- )
131 [ successors>> ] keep '[ _ rename-successor-phis ] each ;
134 pushed get stacks get '[ drop _ at pop* ] assoc-each ;
136 : rename-in-block ( bb -- )
137 H{ } clone pushed set
141 [ rename-successors-phis ]
144 [ dom-children [ rename-in-block ] each ] dip
152 entry>> rename-in-block ;
157 : live-phi? ( ##phi -- ? )
158 dst>> live-phis get key? ;
160 : compute-live-phis ( -- )
161 H{ } clone live-phis set
166 [ live-phis get conjoin ]
167 [ phis get delete-at ]
170 [ inputs>> [ nip used-vregs get push-front ] assoc-each ] bi
174 : insert-phis-in ( phis bb -- )
175 [ [ live-phi? ] filter! ] dip
176 [ append ] change-instructions drop ;
180 [ swap insert-phis-in ] assoc-each ;
184 : construct-ssa ( cfg -- cfg' )
186 [ compute-merge-sets ]
187 [ compute-defs compute-phis ]
188 [ rename compute-live-phis insert-phis ]