1 ! Copyright (C) 2008, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel accessors sequences combinators fry
4 classes.algebra namespaces assocs words math math.private
5 math.partial-dispatch math.intervals classes classes.tuple
6 classes.tuple.private layouts definitions stack-checker.dependencies
10 compiler.tree.combinators
11 compiler.tree.propagation.info
12 compiler.tree.propagation.branches ;
13 IN: compiler.tree.cleanup
15 ! A phase run after propagation to finish the job, so to speak.
16 ! Codifies speculative inlining decisions, deletes branches
17 ! marked as never taken, and flattens local recursive blocks
18 ! that do not call themselves.
20 GENERIC: delete-node ( node -- )
22 M: #call-recursive delete-node
23 dup label>> calls>> [ node>> eq? not ] with filter! drop ;
25 M: #return-recursive delete-node
26 label>> f >>return drop ;
28 M: node delete-node drop ;
30 : delete-nodes ( nodes -- ) [ delete-node ] each-node ;
32 GENERIC: cleanup* ( node -- node/nodes )
34 : cleanup ( nodes -- nodes' )
35 #! We don't recurse into children here, instead the methods
36 #! do it since the logic is a bit more involved
37 [ cleanup* ] map-flat ;
40 : cleanup-folding? ( #call -- ? )
42 [ f ] [ [ literal?>> ] all? ] if-empty ;
44 : (cleanup-folding) ( #call -- nodes )
45 #! Replace a #call having a known result with a #drop of its
46 #! inputs followed by #push nodes for the outputs.
48 [ node-output-infos ] [ out-d>> ] bi
49 [ [ literal>> ] dip #push ] 2map
54 : record-predicate-folding ( #call -- )
55 [ node-input-infos first class>> ]
56 [ word>> "predicating" word-prop ]
57 [ node-output-infos first literal>> ] tri
58 [ depends-on-class<= ] [ depends-on-classes-disjoint ] if ;
60 : record-folding ( #call -- )
62 [ record-predicate-folding ]
63 [ word>> depends-on-definition ]
66 : cleanup-folding ( #call -- nodes )
67 [ (cleanup-folding) ] [ record-folding ] bi ;
70 : add-method-dependency ( #call -- )
72 [ [ class>> ] [ word>> ] bi depends-on-generic ]
73 [ [ class>> ] [ word>> ] [ method>> ] tri depends-on-method ]
77 : record-inlining ( #call -- )
79 [ add-method-dependency ]
80 [ word>> depends-on-definition ] if ;
82 : cleanup-inlining ( #call -- nodes )
83 [ record-inlining ] [ body>> cleanup ] bi ;
85 ! Removing overflow checks
86 : (remove-overflow-check?) ( #call -- ? )
87 node-output-infos first class>> fixnum class<= ;
89 : small-shift? ( #call -- ? )
90 node-input-infos second interval>>
91 cell-bits tag-bits get - [ neg ] keep [a,b] interval-subset? ;
93 : remove-overflow-check? ( #call -- ? )
95 { [ dup word>> \ fixnum-shift eq? ] [ [ (remove-overflow-check?) ] [ small-shift? ] bi and ] }
96 { [ dup word>> no-overflow-variant ] [ (remove-overflow-check?) ] }
100 : remove-overflow-check ( #call -- #call )
101 [ no-overflow-variant ] change-word cleanup* ;
105 { [ dup body>> ] [ cleanup-inlining ] }
106 { [ dup cleanup-folding? ] [ cleanup-folding ] }
107 { [ dup remove-overflow-check? ] [ remove-overflow-check ] }
111 : delete-unreachable-branches ( #branch -- )
112 dup live-branches>> '[
114 [ [ [ drop ] [ delete-nodes ] if ] 2each ]
117 ] change-children drop ;
119 : fold-only-branch ( #branch -- node/nodes )
120 #! If only one branch is live we don't need to branch at
121 #! all; just drop the condition value.
122 dup live-children sift dup length {
123 { 0 [ drop in-d>> #drop ] }
124 { 1 [ first swap in-d>> #drop prefix ] }
128 SYMBOL: live-branches
130 : cleanup-children ( #branch -- )
131 [ [ cleanup ] map ] change-children drop ;
135 [ delete-unreachable-branches ]
138 [ live-branches>> live-branches set ]
141 : output-fs ( values -- nodes )
142 [ f swap #push ] map ;
144 : eliminate-single-phi ( #phi -- node )
145 [ phi-in-d>> first ] [ out-d>> ] bi over [ +bottom+ eq? ] all?
146 [ [ drop ] [ output-fs ] bi* ]
150 : eliminate-phi ( #phi -- node )
151 live-branches get sift length {
152 { 0 [ out-d>> output-fs ] }
153 { 1 [ eliminate-single-phi ] }
158 #! Remove #phi function inputs which no longer exist.
160 [ '[ _ sift-children ] change-phi-in-d ]
161 [ '[ _ sift-children ] change-phi-info-d ]
162 [ '[ _ sift-children ] change-terminated ] tri
166 : >copy ( node -- #copy ) [ in-d>> ] [ out-d>> ] bi #copy ;
168 : flatten-recursive ( #recursive -- nodes )
169 #! convert #enter-recursive and #return-recursive into
173 unclip-last >copy suffix ;
175 M: #recursive cleanup*
176 #! Inline bodies of #recursive blocks with no calls left.
177 [ cleanup ] change-child
178 dup label>> calls>> empty? [ flatten-recursive ] when ;