1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs fry kernel locals math math.order arrays
4 namespaces sequences sorting sets combinators combinators.short-circuit make
6 compiler.cfg.instructions
9 compiler.cfg.ssa.destruction.state
10 compiler.cfg.ssa.destruction.forest
11 compiler.cfg.ssa.destruction.interference ;
12 IN: compiler.cfg.ssa.destruction.process-blocks
14 ! phi-union maps a vreg to the predecessor block
15 ! that carries it to the phi node's block
17 ! unioned-blocks is a set of bb's which defined
18 ! the source vregs above
19 SYMBOLS: phi-union unioned-blocks ;
21 :: operand-live-into-phi-node's-block? ( bb src dst -- ? )
24 :: phi-node-is-live-out-of-operand's-block? ( bb src dst -- ? )
25 dst src def-of live-out key? ;
27 :: operand-is-phi-node-and-live-into-operand's-block? ( bb src dst -- ? )
28 { [ src insn-of ##phi? ] [ src src def-of live-in key? ] } 0&& ;
30 :: operand-being-renamed? ( bb src dst -- ? )
31 src processed-names get key? ;
33 :: two-operands-in-same-block? ( bb src dst -- ? )
34 src def-of unioned-blocks get key? ;
36 : trivial-interference? ( bb src dst -- ? )
38 [ operand-live-into-phi-node's-block? ]
39 [ phi-node-is-live-out-of-operand's-block? ]
40 [ operand-is-phi-node-and-live-into-operand's-block? ]
41 [ operand-being-renamed? ]
42 [ two-operands-in-same-block? ]
45 : don't-coalesce ( bb src dst -- )
48 :: trivial-interference ( bb src dst -- )
49 dst src bb waiting-for push-at
50 src used-by-another get push ;
52 :: add-to-renaming-set ( bb src dst -- )
53 bb src phi-union get set-at
54 src def-of unioned-blocks get conjoin ;
56 : process-phi-operand ( bb src dst -- )
58 { [ 2dup eq? ] [ don't-coalesce ] }
59 { [ 3dup trivial-interference? ] [ trivial-interference ] }
60 [ add-to-renaming-set ]
63 : node-is-live-in-of-child? ( node child -- ? )
64 [ vreg>> ] [ bb>> live-in ] bi* key? ;
66 : node-is-live-out-of-child? ( node child -- ? )
67 [ vreg>> ] [ bb>> live-out ] bi* key? ;
69 :: insert-copy ( bb src dst -- )
70 bb src dst trivial-interference
71 src phi-union get delete-at ;
73 :: insert-copy-for-parent ( bb src node dst -- )
74 src node vreg>> eq? [ bb src dst insert-copy ] when ;
76 : insert-copies-for-parent ( ##phi node child -- )
78 [ [ inputs>> ] [ dst>> ] bi ] dip
79 '[ _ _ insert-copy-for-parent ] assoc-each ;
81 : defined-in-same-block? ( node child -- ? ) [ bb>> ] bi@ eq? ;
83 : add-interference ( ##phi node child -- )
84 [ vreg>> ] bi@ 2array , drop ;
86 : process-df-child ( ##phi node child -- )
88 { [ 2dup node-is-live-out-of-child? ] [ insert-copies-for-parent ] }
89 { [ 2dup node-is-live-in-of-child? ] [ add-interference ] }
90 { [ 2dup defined-in-same-block? ] [ add-interference ] }
94 : process-df-node ( ##phi node -- )
96 [ [ process-df-child ] with with each ]
97 [ nip [ process-df-node ] with each ]
100 : process-phi-union ( ##phi dom-forest -- )
101 [ process-df-node ] with each ;
103 : add-local-interferences ( ##phi -- )
104 [ phi-union get ] dip dst>> '[ drop _ 2array , ] assoc-each ;
106 : compute-local-interferences ( ##phi -- pairs )
108 [ phi-union get keys compute-dom-forest process-phi-union ]
109 [ add-local-interferences ]
113 :: insert-copies-for-interference ( ##phi src -- )
114 ##phi inputs>> [| bb src' |
115 src src' eq? [ bb src ##phi dst>> insert-copy ] when
118 : process-local-interferences ( ##phi pairs -- )
120 first2 2dup interferes?
121 [ drop insert-copies-for-interference ] [ 3drop ] if
124 : add-renaming-set ( ##phi -- )
125 [ phi-union get ] dip dst>> renaming-sets get set-at
126 phi-union get [ drop processed-name ] assoc-each ;
128 : process-phi ( ##phi -- )
129 H{ } clone phi-union set
130 H{ } clone unioned-blocks set
131 [ [ inputs>> ] [ dst>> ] bi '[ _ process-phi-operand ] assoc-each ]
132 [ dup compute-local-interferences process-local-interferences ]
136 : process-block ( bb -- )
138 [ dup ##phi? [ process-phi t ] [ drop f ] if ] all? drop ;