compiler.cfg.ssa.construction: use the baller method for pruned SSA

db4
Slava Pestov 2010-09-18 20:26:03 -07:00 committed by Slava Pestov
parent f9c9814e57
commit 8bc2ea7a5c
2 changed files with 179 additions and 47 deletions

View File

@ -10,6 +10,16 @@ IN: compiler.cfg.ssa.construction.tests
0 vreg-counter set-global
0 basic-block set-global ;
: test-ssa ( -- )
cfg new 0 get >>entry
dup cfg set
construct-ssa
drop ;
: clean-up-phis ( insns -- insns' )
[ dup ##phi? [ [ [ [ number>> ] dip ] assoc-map ] change-inputs ] when ] map ;
! Test 1
reset-counters
V{
@ -38,12 +48,6 @@ V{
1 3 edge
2 3 edge
: test-ssa ( -- )
cfg new 0 get >>entry
dup cfg set
construct-ssa
drop ;
[ ] [ test-ssa ] unit-test
[
@ -69,9 +73,6 @@ V{
}
] [ 2 get instructions>> ] unit-test
: clean-up-phis ( insns -- insns' )
[ dup ##phi? [ [ [ [ number>> ] dip ] assoc-map ] change-inputs ] when ] map ;
[
V{
T{ ##phi f 6 H{ { 1 4 } { 2 5 } } }
@ -83,6 +84,7 @@ V{
clean-up-phis
] unit-test
! Test 2
reset-counters
V{ } 0 test-bb
@ -110,4 +112,89 @@ V{ } 6 test-bb
] [
4 get instructions>>
clean-up-phis
] unit-test
] unit-test
! Test 3
reset-counters
V{
T{ ##branch }
} 0 test-bb
V{
T{ ##load-integer f 3 3 }
T{ ##branch }
} 1 test-bb
V{
T{ ##load-integer f 3 4 }
T{ ##branch }
} 2 test-bb
V{
T{ ##branch }
} 3 test-bb
V{
T{ ##return }
} 4 test-bb
0 { 1 2 3 } edges
1 4 edge
2 4 edge
3 4 edge
[ ] [ test-ssa ] unit-test
[ V{ } ] [ 4 get instructions>> [ ##phi? ] filter ] unit-test
! Test 4
reset-counters
V{
T{ ##branch }
} 0 test-bb
V{
T{ ##branch }
} 1 test-bb
V{
T{ ##load-integer f 0 4 }
T{ ##branch }
} 2 test-bb
V{
T{ ##load-integer f 0 4 }
T{ ##branch }
} 3 test-bb
V{
T{ ##branch }
} 4 test-bb
V{
T{ ##branch }
} 5 test-bb
V{
T{ ##branch }
} 6 test-bb
V{
T{ ##return }
} 7 test-bb
0 { 1 6 } edges
1 { 2 3 4 } edges
2 5 edge
3 5 edge
4 5 edge
5 7 edge
6 7 edge
[ ] [ test-ssa ] unit-test
[ V{ } ] [ 5 get instructions>> [ ##phi? ] filter ] unit-test
[ V{ } ] [ 7 get instructions>> [ ##phi? ] filter ] unit-test

View File

@ -1,11 +1,10 @@
! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel accessors sequences fry assocs
sets math combinators
sets math combinators deques dlists
compiler.cfg
compiler.cfg.rpo
compiler.cfg.def-use
compiler.cfg.liveness
compiler.cfg.registers
compiler.cfg.dominance
compiler.cfg.instructions
@ -15,12 +14,18 @@ compiler.cfg.ssa.construction.tdmsc ;
FROM: namespaces => set ;
IN: compiler.cfg.ssa.construction
! The phi placement algorithm is implemented in
! compiler.cfg.ssa.construction.tdmsc.
! Iterated dominance frontiers are computed using the DJ Graph
! method in compiler.cfg.ssa.construction.tdmsc.
! The renaming algorithm is based on "Practical Improvements to
! the Construction and Destruction of Static Single Assignment Form",
! however we construct pruned SSA, not semi-pruned SSA.
! the Construction and Destruction of Static Single Assignment
! Form".
! We construct pruned SSA without computing live sets, by
! building a dependency graph for phi instructions, marking the
! transitive closure of a vertex as live if it is referenced by
! some non-phi instruction. Thanks to Cameron Zwarich for the
! trick.
! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.49.9683
@ -50,31 +55,32 @@ M: vreg-insn compute-insn-defs
[ compute-insn-defs ] with each
] simple-analysis ;
! Maps basic blocks to sequences of vregs
SYMBOL: inserting-phi-nodes
! Maps basic blocks to sequences of ##phi instructions
SYMBOL: inserting-phis
: insert-phi-node-later ( vreg bb -- )
2dup live-in key? [
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
inserting-phi-nodes get push-at
] [ 2drop ] if ;
: insert-phi-later ( vreg bb -- )
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
inserting-phis get push-at ;
: compute-phi-nodes-for ( vreg bbs -- )
keys merge-set [ insert-phi-node-later ] with each ;
: compute-phis-for ( vreg bbs -- )
keys merge-set [ insert-phi-later ] with each ;
: compute-phi-nodes ( -- )
H{ } clone inserting-phi-nodes set
defs-multi get defs get '[ _ at compute-phi-nodes-for ] assoc-each ;
: compute-phis ( -- )
H{ } clone inserting-phis set
defs-multi get defs get '[ _ at compute-phis-for ] assoc-each ;
: insert-phi-nodes-in ( phis bb -- )
[ append ] change-instructions drop ;
! Maps vregs to ##phi instructions
SYMBOL: phis
: insert-phi-nodes ( -- )
inserting-phi-nodes get [ swap insert-phi-nodes-in ] assoc-each ;
! Worklist of used vregs, to calculate used phis
SYMBOL: used-vregs
! Maps vregs to renaming stacks
SYMBOLS: stacks pushed ;
: init-renaming ( -- )
H{ } clone phis set
<hashed-dlist> used-vregs set
H{ } clone stacks set ;
: gen-name ( vreg -- vreg' )
@ -84,8 +90,12 @@ SYMBOLS: stacks pushed ;
[ conjoin stacks get push-at ]
if ;
: (top-name) ( vreg -- vreg' )
stacks get at [ f ] [ last ] if-empty ;
: top-name ( vreg -- vreg' )
stacks get at last ;
(top-name)
dup [ dup used-vregs get push-front ] when ;
RENAMING: ssa-rename [ gen-name ] [ top-name ] [ ]
@ -98,17 +108,22 @@ M: vreg-insn rename-insn
[ ssa-rename-insn-defs ]
bi ;
M: ##phi rename-insn
ssa-rename-insn-defs ;
: rename-phis ( bb -- )
inserting-phis get at [
[
[ ssa-rename-insn-defs ]
[ dup dst>> phis get set-at ] bi
] each
] when* ;
: rename-insns ( bb -- )
instructions>> [ rename-insn ] each ;
: rename-successor-phi ( phi bb -- )
swap inputs>> [ top-name ] change-at ;
swap inputs>> [ (top-name) ] change-at ;
: rename-successor-phis ( succ bb -- )
[ inserting-phi-nodes get at ] dip
[ inserting-phis get at ] dip
'[ _ rename-successor-phi ] each ;
: rename-successors-phis ( bb -- )
@ -119,26 +134,56 @@ M: ##phi rename-insn
: rename-in-block ( bb -- )
H{ } clone pushed set
[ rename-insns ]
[ rename-successors-phis ]
[
pushed get
[ dom-children [ rename-in-block ] each ] dip
pushed set
] tri
{
[ rename-phis ]
[ rename-insns ]
[ rename-successors-phis ]
[
pushed get
[ dom-children [ rename-in-block ] each ] dip
pushed set
]
} cleave
pop-stacks ;
: rename ( cfg -- )
init-renaming
entry>> rename-in-block ;
! Live phis
SYMBOL: live-phis
: live-phi? ( ##phi -- ? )
dst>> live-phis get key? ;
: compute-live-phis ( -- )
H{ } clone live-phis set
used-vregs get [
phis get at [
[
dst>>
[ live-phis get conjoin ]
[ phis get delete-at ]
bi
]
[ inputs>> [ nip used-vregs get push-front ] assoc-each ] bi
] when*
] slurp-deque ;
: insert-phis-in ( phis bb -- )
[ [ live-phi? ] filter! ] dip
[ append ] change-instructions drop ;
: insert-phis ( -- )
inserting-phis get
[ swap insert-phis-in ] assoc-each ;
PRIVATE>
: construct-ssa ( cfg -- cfg' )
{
[ compute-live-sets ]
[ compute-merge-sets ]
[ compute-defs compute-phi-nodes insert-phi-nodes ]
[ rename ]
[ compute-defs compute-phis ]
[ rename compute-live-phis insert-phis ]
[ ]
} cleave ;