1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs kernel namespaces math sequences fry grouping
4 sets make combinators dlists deques
8 compiler.cfg.instructions
12 compiler.cfg.stack-analysis.state
13 compiler.cfg.stack-analysis.merge
14 compiler.cfg.utilities ;
15 IN: compiler.cfg.stack-analysis
17 SYMBOL: global-optimization?
19 : redundant-replace? ( vreg loc -- ? )
20 dup state get untranslate-loc n>> 0 <
21 [ 2drop t ] [ state get actual-locs>vregs>> at = ] if ;
23 : save-changed-locs ( state -- )
24 [ changed-locs>> keys ] [ locs>vregs>> ] bi '[
25 dup _ at swap 2dup redundant-replace?
26 [ 2drop ] [ state get untranslate-loc ##replace ] if
29 ERROR: poisoned-state state ;
33 [ dup poisoned?>> [ poisoned-state ] [ drop ] if ]
34 [ ds-height>> save-ds-height ]
35 [ rs-height>> save-rs-height ]
40 : poison-state ( -- ) state get t >>poisoned? drop ;
42 ! Abstract interpretation
43 GENERIC: visit ( insn -- )
46 n>> state get [ + ] change-ds-height drop ;
49 n>> state get [ + ] change-rs-height drop ;
51 ! Instructions which don't have any effect on the stack
57 M: neutral-insn visit , ;
59 UNION: sync-if-back-edge
67 : sync-state? ( -- ? )
68 basic-block get successors>>
69 [ [ predecessors>> ] keep '[ _ back-edge? ] any? ] any? ;
71 M: sync-if-back-edge visit
72 global-optimization? get [ sync-state? [ sync-state ] when ] unless
75 : eliminate-peek ( dst src -- )
76 ! the requested stack location is already in 'src'
77 [ ##copy ] [ swap copies get set-at ] 2bi ;
80 [ dst>> ] [ loc>> state get translate-loc ] bi dup loc>vreg
81 [ eliminate-peek ] [ [ record-peek ] [ ##peek ] 2bi ] ?if ;
84 [ src>> resolve ] [ loc>> state get translate-loc ] bi
88 [ call-next-method ] [ record-copy ] bi ;
90 M: poison-insn visit call-next-method poison-state ;
92 M: kill-vreg-insn visit sync-state , ;
94 ! Maps basic-blocks to states
97 : block-in-state ( bb -- states )
98 dup predecessors>> state-out get '[ _ at ] map merge-states ;
100 : set-block-out-state ( state bb -- )
101 [ clone ] dip state-out get set-at ;
103 : visit-block ( bb -- )
104 ! block-in-state may add phi nodes at the start of the basic block
105 ! so we wrap the whole thing with a 'make'
110 [ instructions>> [ visit ] each ]
111 [ [ state get ] dip set-block-out-state ]
115 ] V{ } make >>instructions drop ;
117 : stack-analysis ( cfg -- cfg' )
119 <hashed-dlist> work-list set
120 H{ } clone copies set
121 H{ } clone state-out set
122 dup [ visit-block ] each-basic-block
123 global-optimization? get [ work-list get [ visit-block ] slurp-deque ] when