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 vreg-counter set-global
0 basic-block 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 reset-counters
V{ V{
@ -38,12 +48,6 @@ V{
1 3 edge 1 3 edge
2 3 edge 2 3 edge
: test-ssa ( -- )
cfg new 0 get >>entry
dup cfg set
construct-ssa
drop ;
[ ] [ test-ssa ] unit-test [ ] [ test-ssa ] unit-test
[ [
@ -69,9 +73,6 @@ V{
} }
] [ 2 get instructions>> ] unit-test ] [ 2 get instructions>> ] unit-test
: clean-up-phis ( insns -- insns' )
[ dup ##phi? [ [ [ [ number>> ] dip ] assoc-map ] change-inputs ] when ] map ;
[ [
V{ V{
T{ ##phi f 6 H{ { 1 4 } { 2 5 } } } T{ ##phi f 6 H{ { 1 4 } { 2 5 } } }
@ -83,6 +84,7 @@ V{
clean-up-phis clean-up-phis
] unit-test ] unit-test
! Test 2
reset-counters reset-counters
V{ } 0 test-bb V{ } 0 test-bb
@ -111,3 +113,88 @@ V{ } 6 test-bb
4 get instructions>> 4 get instructions>>
clean-up-phis 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. ! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel accessors sequences fry assocs USING: namespaces kernel accessors sequences fry assocs
sets math combinators sets math combinators deques dlists
compiler.cfg compiler.cfg
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.def-use compiler.cfg.def-use
compiler.cfg.liveness
compiler.cfg.registers compiler.cfg.registers
compiler.cfg.dominance compiler.cfg.dominance
compiler.cfg.instructions compiler.cfg.instructions
@ -15,12 +14,18 @@ compiler.cfg.ssa.construction.tdmsc ;
FROM: namespaces => set ; FROM: namespaces => set ;
IN: compiler.cfg.ssa.construction IN: compiler.cfg.ssa.construction
! The phi placement algorithm is implemented in ! Iterated dominance frontiers are computed using the DJ Graph
! compiler.cfg.ssa.construction.tdmsc. ! method in compiler.cfg.ssa.construction.tdmsc.
! The renaming algorithm is based on "Practical Improvements to ! The renaming algorithm is based on "Practical Improvements to
! the Construction and Destruction of Static Single Assignment Form", ! the Construction and Destruction of Static Single Assignment
! however we construct pruned SSA, not semi-pruned SSA. ! 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 ! 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 [ compute-insn-defs ] with each
] simple-analysis ; ] simple-analysis ;
! Maps basic blocks to sequences of vregs ! Maps basic blocks to sequences of ##phi instructions
SYMBOL: inserting-phi-nodes SYMBOL: inserting-phis
: insert-phi-node-later ( vreg bb -- ) : insert-phi-later ( vreg bb -- )
2dup live-in key? [
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep [ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
inserting-phi-nodes get push-at inserting-phis get push-at ;
] [ 2drop ] if ;
: compute-phi-nodes-for ( vreg bbs -- ) : compute-phis-for ( vreg bbs -- )
keys merge-set [ insert-phi-node-later ] with each ; keys merge-set [ insert-phi-later ] with each ;
: compute-phi-nodes ( -- ) : compute-phis ( -- )
H{ } clone inserting-phi-nodes set H{ } clone inserting-phis set
defs-multi get defs get '[ _ at compute-phi-nodes-for ] assoc-each ; defs-multi get defs get '[ _ at compute-phis-for ] assoc-each ;
: insert-phi-nodes-in ( phis bb -- ) ! Maps vregs to ##phi instructions
[ append ] change-instructions drop ; SYMBOL: phis
: insert-phi-nodes ( -- ) ! Worklist of used vregs, to calculate used phis
inserting-phi-nodes get [ swap insert-phi-nodes-in ] assoc-each ; SYMBOL: used-vregs
! Maps vregs to renaming stacks
SYMBOLS: stacks pushed ; SYMBOLS: stacks pushed ;
: init-renaming ( -- ) : init-renaming ( -- )
H{ } clone phis set
<hashed-dlist> used-vregs set
H{ } clone stacks set ; H{ } clone stacks set ;
: gen-name ( vreg -- vreg' ) : gen-name ( vreg -- vreg' )
@ -84,8 +90,12 @@ SYMBOLS: stacks pushed ;
[ conjoin stacks get push-at ] [ conjoin stacks get push-at ]
if ; if ;
: (top-name) ( vreg -- vreg' )
stacks get at [ f ] [ last ] if-empty ;
: top-name ( vreg -- vreg' ) : 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 ] [ ] RENAMING: ssa-rename [ gen-name ] [ top-name ] [ ]
@ -98,17 +108,22 @@ M: vreg-insn rename-insn
[ ssa-rename-insn-defs ] [ ssa-rename-insn-defs ]
bi ; bi ;
M: ##phi rename-insn : rename-phis ( bb -- )
ssa-rename-insn-defs ; inserting-phis get at [
[
[ ssa-rename-insn-defs ]
[ dup dst>> phis get set-at ] bi
] each
] when* ;
: rename-insns ( bb -- ) : rename-insns ( bb -- )
instructions>> [ rename-insn ] each ; instructions>> [ rename-insn ] each ;
: rename-successor-phi ( phi bb -- ) : rename-successor-phi ( phi bb -- )
swap inputs>> [ top-name ] change-at ; swap inputs>> [ (top-name) ] change-at ;
: rename-successor-phis ( succ bb -- ) : rename-successor-phis ( succ bb -- )
[ inserting-phi-nodes get at ] dip [ inserting-phis get at ] dip
'[ _ rename-successor-phi ] each ; '[ _ rename-successor-phi ] each ;
: rename-successors-phis ( bb -- ) : rename-successors-phis ( bb -- )
@ -119,26 +134,56 @@ M: ##phi rename-insn
: rename-in-block ( bb -- ) : rename-in-block ( bb -- )
H{ } clone pushed set H{ } clone pushed set
{
[ rename-phis ]
[ rename-insns ] [ rename-insns ]
[ rename-successors-phis ] [ rename-successors-phis ]
[ [
pushed get pushed get
[ dom-children [ rename-in-block ] each ] dip [ dom-children [ rename-in-block ] each ] dip
pushed set pushed set
] tri ]
} cleave
pop-stacks ; pop-stacks ;
: rename ( cfg -- ) : rename ( cfg -- )
init-renaming init-renaming
entry>> rename-in-block ; 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> PRIVATE>
: construct-ssa ( cfg -- cfg' ) : construct-ssa ( cfg -- cfg' )
{ {
[ compute-live-sets ]
[ compute-merge-sets ] [ compute-merge-sets ]
[ compute-defs compute-phi-nodes insert-phi-nodes ] [ compute-defs compute-phis ]
[ rename ] [ rename compute-live-phis insert-phis ]
[ ] [ ]
} cleave ; } cleave ;