Merge branch 'master' into dcn
commit
091d2d07f2
|
@ -3,7 +3,7 @@
|
||||||
USING: kernel math namespaces assocs hashtables sequences arrays
|
USING: kernel math namespaces assocs hashtables sequences arrays
|
||||||
accessors vectors combinators sets classes compiler.cfg
|
accessors vectors combinators sets classes compiler.cfg
|
||||||
compiler.cfg.registers compiler.cfg.instructions
|
compiler.cfg.registers compiler.cfg.instructions
|
||||||
compiler.cfg.copy-prop compiler.cfg.rpo compiler.cfg.def-use ;
|
compiler.cfg.copy-prop compiler.cfg.rpo compiler.cfg.liveness ;
|
||||||
IN: compiler.cfg.alias-analysis
|
IN: compiler.cfg.alias-analysis
|
||||||
|
|
||||||
! We try to eliminate redundant slot operations using some simple heuristics.
|
! We try to eliminate redundant slot operations using some simple heuristics.
|
||||||
|
@ -196,9 +196,6 @@ M: ##set-slot insn-object obj>> resolve ;
|
||||||
M: ##set-slot-imm insn-object obj>> resolve ;
|
M: ##set-slot-imm insn-object obj>> resolve ;
|
||||||
M: ##alien-global insn-object drop \ ##alien-global ;
|
M: ##alien-global insn-object drop \ ##alien-global ;
|
||||||
|
|
||||||
: inputs ( insns -- seq )
|
|
||||||
[ [ ##phi? not ] filter gen-set ] [ kill-set ] bi assoc-diff keys ;
|
|
||||||
|
|
||||||
: init-alias-analysis ( insns -- insns' )
|
: init-alias-analysis ( insns -- insns' )
|
||||||
H{ } clone histories set
|
H{ } clone histories set
|
||||||
H{ } clone vregs>acs set
|
H{ } clone vregs>acs set
|
||||||
|
@ -210,7 +207,7 @@ M: ##alien-global insn-object drop \ ##alien-global ;
|
||||||
0 ac-counter set
|
0 ac-counter set
|
||||||
next-ac heap-ac set
|
next-ac heap-ac set
|
||||||
|
|
||||||
dup inputs [ set-heap-ac ] each ;
|
dup local-live-in [ set-heap-ac ] each ;
|
||||||
|
|
||||||
GENERIC: analyze-aliases* ( insn -- insn' )
|
GENERIC: analyze-aliases* ( insn -- insn' )
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ compiler.cfg.predecessors ;
|
||||||
: test-dominance ( -- )
|
: test-dominance ( -- )
|
||||||
cfg new 0 get >>entry
|
cfg new 0 get >>entry
|
||||||
compute-predecessors
|
compute-predecessors
|
||||||
compute-dominance
|
compute-dominance ;
|
||||||
drop ;
|
|
||||||
|
|
||||||
! Example with no back edges
|
! Example with no back edges
|
||||||
V{ } 0 test-bb
|
V{ } 0 test-bb
|
||||||
|
@ -74,3 +73,25 @@ V{ } 5 test-bb
|
||||||
[ ] [ test-dominance ] unit-test
|
[ ] [ test-dominance ] unit-test
|
||||||
|
|
||||||
[ t ] [ 0 5 [a,b] [ get dom-parent 0 get eq? ] all? ] unit-test
|
[ t ] [ 0 5 [a,b] [ get dom-parent 0 get eq? ] all? ] unit-test
|
||||||
|
|
||||||
|
V{ } 0 test-bb
|
||||||
|
V{ } 1 test-bb
|
||||||
|
V{ } 2 test-bb
|
||||||
|
V{ } 3 test-bb
|
||||||
|
V{ } 4 test-bb
|
||||||
|
V{ } 5 test-bb
|
||||||
|
V{ } 6 test-bb
|
||||||
|
|
||||||
|
0 get 1 get 5 get V{ } 2sequence >>successors drop
|
||||||
|
1 get 2 get 3 get V{ } 2sequence >>successors drop
|
||||||
|
2 get 4 get 1vector >>successors drop
|
||||||
|
3 get 4 get 1vector >>successors drop
|
||||||
|
4 get 6 get 1vector >>successors drop
|
||||||
|
5 get 6 get 1vector >>successors drop
|
||||||
|
|
||||||
|
[ ] [ test-dominance ] unit-test
|
||||||
|
|
||||||
|
[ t ] [
|
||||||
|
2 get 3 get 2array iterated-dom-frontier
|
||||||
|
4 get 6 get 2array set=
|
||||||
|
] unit-test
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2009 Slava Pestov.
|
! Copyright (C) 2009 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors assocs combinators sets math fry kernel math.order
|
USING: accessors assocs combinators sets math fry kernel math.order
|
||||||
namespaces sequences sorting compiler.cfg.rpo ;
|
dlists deques namespaces sequences sorting compiler.cfg.rpo ;
|
||||||
IN: compiler.cfg.dominance
|
IN: compiler.cfg.dominance
|
||||||
|
|
||||||
! Reference:
|
! Reference:
|
||||||
|
@ -85,8 +85,31 @@ PRIVATE>
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: compute-dominance ( cfg -- cfg' )
|
: compute-dominance ( cfg -- )
|
||||||
[ compute-dom-parents compute-dom-children ]
|
[ compute-dom-parents compute-dom-children ]
|
||||||
[ compute-dom-frontiers ]
|
[ compute-dom-frontiers ]
|
||||||
[ ]
|
bi ;
|
||||||
tri ;
|
|
||||||
|
<PRIVATE
|
||||||
|
|
||||||
|
SYMBOLS: work-list visited ;
|
||||||
|
|
||||||
|
: add-to-work-list ( bb -- )
|
||||||
|
dom-frontier work-list get push-all-front ;
|
||||||
|
|
||||||
|
: iterated-dom-frontier-step ( bb -- )
|
||||||
|
dup visited get key? [ drop ] [
|
||||||
|
[ visited get conjoin ]
|
||||||
|
[ add-to-work-list ] bi
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: iterated-dom-frontier ( bbs -- bbs' )
|
||||||
|
[
|
||||||
|
<dlist> work-list set
|
||||||
|
H{ } clone visited set
|
||||||
|
[ add-to-work-list ] each
|
||||||
|
work-list get [ iterated-dom-frontier-step ] slurp-deque
|
||||||
|
visited get keys
|
||||||
|
] with-scope ;
|
|
@ -6,13 +6,13 @@ cpu.architecture
|
||||||
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.instructions
|
compiler.cfg.instructions
|
||||||
compiler.cfg.linear-scan.mapping
|
compiler.cfg.linear-scan.mapping
|
||||||
compiler.cfg.linear-scan.allocation
|
compiler.cfg.linear-scan.allocation
|
||||||
compiler.cfg.linear-scan.allocation.state
|
compiler.cfg.linear-scan.allocation.state
|
||||||
compiler.cfg.linear-scan.live-intervals
|
compiler.cfg.linear-scan.live-intervals ;
|
||||||
compiler.cfg.linear-scan.liveness ;
|
|
||||||
IN: compiler.cfg.linear-scan.assignment
|
IN: compiler.cfg.linear-scan.assignment
|
||||||
|
|
||||||
! This contains both active and inactive intervals; any interval
|
! This contains both active and inactive intervals; any interval
|
||||||
|
|
|
@ -4,9 +4,9 @@ USING: kernel accessors namespaces make locals
|
||||||
cpu.architecture
|
cpu.architecture
|
||||||
compiler.cfg
|
compiler.cfg
|
||||||
compiler.cfg.rpo
|
compiler.cfg.rpo
|
||||||
|
compiler.cfg.liveness
|
||||||
compiler.cfg.instructions
|
compiler.cfg.instructions
|
||||||
compiler.cfg.linear-scan.numbering
|
compiler.cfg.linear-scan.numbering
|
||||||
compiler.cfg.linear-scan.liveness
|
|
||||||
compiler.cfg.linear-scan.live-intervals
|
compiler.cfg.linear-scan.live-intervals
|
||||||
compiler.cfg.linear-scan.allocation
|
compiler.cfg.linear-scan.allocation
|
||||||
compiler.cfg.linear-scan.allocation.state
|
compiler.cfg.linear-scan.allocation.state
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: namespaces kernel assocs accessors sequences math math.order fry
|
USING: namespaces kernel assocs accessors sequences math math.order fry
|
||||||
combinators binary-search compiler.cfg.instructions compiler.cfg.registers
|
combinators binary-search compiler.cfg.instructions compiler.cfg.registers
|
||||||
compiler.cfg.def-use compiler.cfg.linear-scan.liveness compiler.cfg.rpo
|
compiler.cfg.def-use compiler.cfg.liveness compiler.cfg.rpo
|
||||||
compiler.cfg ;
|
compiler.cfg ;
|
||||||
IN: compiler.cfg.linear-scan.live-intervals
|
IN: compiler.cfg.linear-scan.live-intervals
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
! Copyright (C) 2009 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: kernel accessors assocs compiler.cfg.def-use
|
|
||||||
compiler.cfg.dataflow-analysis ;
|
|
||||||
IN: compiler.cfg.linear-scan.liveness
|
|
||||||
|
|
||||||
! See http://en.wikipedia.org/wiki/Liveness_analysis
|
|
||||||
|
|
||||||
BACKWARD-ANALYSIS: live
|
|
||||||
|
|
||||||
M: live-analysis transfer-set
|
|
||||||
drop instructions>>
|
|
||||||
[ gen-set assoc-union ] keep
|
|
||||||
kill-set assoc-diff ;
|
|
||||||
|
|
||||||
M: live-analysis join-sets
|
|
||||||
drop assoc-combine ;
|
|
|
@ -4,11 +4,11 @@ USING: accessors arrays assocs combinators
|
||||||
combinators.short-circuit fry kernel locals
|
combinators.short-circuit fry kernel locals
|
||||||
make math sequences
|
make math sequences
|
||||||
compiler.cfg.rpo
|
compiler.cfg.rpo
|
||||||
|
compiler.cfg.liveness
|
||||||
compiler.cfg.utilities
|
compiler.cfg.utilities
|
||||||
compiler.cfg.instructions
|
compiler.cfg.instructions
|
||||||
compiler.cfg.linear-scan.assignment
|
compiler.cfg.linear-scan.assignment
|
||||||
compiler.cfg.linear-scan.mapping
|
compiler.cfg.linear-scan.mapping ;
|
||||||
compiler.cfg.linear-scan.liveness ;
|
|
||||||
IN: compiler.cfg.linear-scan.resolve
|
IN: compiler.cfg.linear-scan.resolve
|
||||||
|
|
||||||
: add-mapping ( from to reg-class -- )
|
: add-mapping ( from to reg-class -- )
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
USING: compiler.cfg.liveness compiler.cfg.debugger
|
||||||
|
compiler.cfg.instructions compiler.cfg.predecessors
|
||||||
|
compiler.cfg.registers compiler.cfg cpu.architecture
|
||||||
|
accessors namespaces sequences kernel tools.test ;
|
||||||
|
IN: compiler.cfg.liveness.tests
|
||||||
|
|
||||||
|
! Sanity check...
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##peek f V int-regs 0 D 0 }
|
||||||
|
T{ ##replace f V int-regs 0 D 0 }
|
||||||
|
T{ ##replace f V int-regs 1 D 1 }
|
||||||
|
T{ ##peek f V int-regs 1 D 1 }
|
||||||
|
} 1 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##replace f V int-regs 2 D 0 }
|
||||||
|
} 2 test-bb
|
||||||
|
|
||||||
|
V{
|
||||||
|
T{ ##replace f V int-regs 3 D 0 }
|
||||||
|
} 3 test-bb
|
||||||
|
|
||||||
|
1 get 2 get 3 get V{ } 2sequence >>successors drop
|
||||||
|
|
||||||
|
cfg new 1 get >>entry
|
||||||
|
compute-predecessors
|
||||||
|
compute-live-sets
|
||||||
|
|
||||||
|
[
|
||||||
|
H{
|
||||||
|
{ V int-regs 1 V int-regs 1 }
|
||||||
|
{ V int-regs 2 V int-regs 2 }
|
||||||
|
{ V int-regs 3 V int-regs 3 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
[ 1 get live-in ]
|
||||||
|
unit-test
|
|
@ -0,0 +1,26 @@
|
||||||
|
! Copyright (C) 2009 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: kernel accessors assocs sequences sets
|
||||||
|
compiler.cfg.def-use compiler.cfg.dataflow-analysis
|
||||||
|
compiler.cfg.instructions ;
|
||||||
|
IN: compiler.cfg.liveness
|
||||||
|
|
||||||
|
! See http://en.wikipedia.org/wiki/Liveness_analysis
|
||||||
|
! Do not run after SSA construction
|
||||||
|
|
||||||
|
BACKWARD-ANALYSIS: live
|
||||||
|
|
||||||
|
: transfer-liveness ( live-set instructions -- live-set' )
|
||||||
|
[ clone ] [ <reversed> ] bi* [
|
||||||
|
[ uses-vregs [ over conjoin ] each ]
|
||||||
|
[ defs-vregs [ over delete-at ] each ] bi
|
||||||
|
] each ;
|
||||||
|
|
||||||
|
: local-live-in ( instructions -- live-set )
|
||||||
|
[ ##phi? not ] filter [ H{ } ] dip transfer-liveness keys ;
|
||||||
|
|
||||||
|
M: live-analysis transfer-set
|
||||||
|
drop instructions>> transfer-liveness ;
|
||||||
|
|
||||||
|
M: live-analysis join-sets
|
||||||
|
drop assoc-combine ;
|
|
@ -5,9 +5,12 @@ compiler.cfg.registers cpu.architecture kernel namespaces sequences
|
||||||
tools.test vectors ;
|
tools.test vectors ;
|
||||||
IN: compiler.cfg.ssa.tests
|
IN: compiler.cfg.ssa.tests
|
||||||
|
|
||||||
! Reset counters so that results are deterministic w.r.t. hash order
|
: reset-counters ( -- )
|
||||||
0 vreg-counter set-global
|
! Reset counters so that results are deterministic w.r.t. hash order
|
||||||
0 basic-block set-global
|
0 vreg-counter set-global
|
||||||
|
0 basic-block set-global ;
|
||||||
|
|
||||||
|
reset-counters
|
||||||
|
|
||||||
V{
|
V{
|
||||||
T{ ##load-immediate f V int-regs 1 100 }
|
T{ ##load-immediate f V int-regs 1 100 }
|
||||||
|
@ -38,7 +41,6 @@ V{
|
||||||
: test-ssa ( -- )
|
: test-ssa ( -- )
|
||||||
cfg new 0 get >>entry
|
cfg new 0 get >>entry
|
||||||
compute-predecessors
|
compute-predecessors
|
||||||
compute-dominance
|
|
||||||
construct-ssa
|
construct-ssa
|
||||||
drop ;
|
drop ;
|
||||||
|
|
||||||
|
@ -67,6 +69,9 @@ 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 V int-regs 6 H{ { 1 V int-regs 4 } { 2 V int-regs 5 } } }
|
T{ ##phi f V int-regs 6 H{ { 1 V int-regs 4 } { 2 V int-regs 5 } } }
|
||||||
|
@ -75,5 +80,34 @@ V{
|
||||||
}
|
}
|
||||||
] [
|
] [
|
||||||
3 get instructions>>
|
3 get instructions>>
|
||||||
[ dup ##phi? [ [ [ [ number>> ] dip ] assoc-map ] change-inputs ] when ] map
|
clean-up-phis
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
reset-counters
|
||||||
|
|
||||||
|
V{ } 0 test-bb
|
||||||
|
V{ } 1 test-bb
|
||||||
|
V{ T{ ##peek f V int-regs 0 D 0 } } 2 test-bb
|
||||||
|
V{ T{ ##peek f V int-regs 0 D 0 } } 3 test-bb
|
||||||
|
V{ T{ ##replace f V int-regs 0 D 0 } } 4 test-bb
|
||||||
|
V{ } 5 test-bb
|
||||||
|
V{ } 6 test-bb
|
||||||
|
|
||||||
|
0 get 1 get 5 get V{ } 2sequence >>successors drop
|
||||||
|
1 get 2 get 3 get V{ } 2sequence >>successors drop
|
||||||
|
2 get 4 get 1vector >>successors drop
|
||||||
|
3 get 4 get 1vector >>successors drop
|
||||||
|
4 get 6 get 1vector >>successors drop
|
||||||
|
5 get 6 get 1vector >>successors drop
|
||||||
|
|
||||||
|
[ ] [ test-ssa ] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
V{
|
||||||
|
T{ ##phi f V int-regs 3 H{ { 2 V int-regs 1 } { 3 V int-regs 2 } } }
|
||||||
|
T{ ##replace f V int-regs 3 D 0 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
4 get instructions>>
|
||||||
|
clean-up-phis
|
||||||
] unit-test
|
] unit-test
|
|
@ -1,19 +1,21 @@
|
||||||
! Copyright (C) 2009 Slava Pestov.
|
! Copyright (C) 2009 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 dlists
|
USING: namespaces kernel accessors sequences fry assocs
|
||||||
deques assocs sets math combinators sorting
|
sets math combinators
|
||||||
compiler.cfg
|
compiler.cfg
|
||||||
compiler.cfg.rpo
|
compiler.cfg.rpo
|
||||||
compiler.cfg.def-use
|
compiler.cfg.def-use
|
||||||
compiler.cfg.renaming
|
compiler.cfg.renaming
|
||||||
|
compiler.cfg.liveness
|
||||||
compiler.cfg.registers
|
compiler.cfg.registers
|
||||||
compiler.cfg.dominance
|
compiler.cfg.dominance
|
||||||
compiler.cfg.instructions ;
|
compiler.cfg.instructions ;
|
||||||
IN: compiler.cfg.ssa
|
IN: compiler.cfg.ssa
|
||||||
|
|
||||||
! SSA construction. Predecessors and dominance must be computed first.
|
! SSA construction. Predecessors must be computed first.
|
||||||
|
|
||||||
! This is the classical algorithm based on dominance frontiers:
|
! This is the classical algorithm based on dominance frontiers, except
|
||||||
|
! we consult liveness information to build pruned SSA:
|
||||||
! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.8240
|
! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.8240
|
||||||
|
|
||||||
! Eventually might be worth trying something fancier:
|
! Eventually might be worth trying something fancier:
|
||||||
|
@ -32,45 +34,22 @@ SYMBOL: inserting-phi-nodes
|
||||||
'[
|
'[
|
||||||
dup instructions>> [
|
dup instructions>> [
|
||||||
defs-vregs [
|
defs-vregs [
|
||||||
_ push-at
|
_ conjoin-at
|
||||||
] with each
|
] with each
|
||||||
] with each
|
] with each
|
||||||
] each-basic-block ;
|
] each-basic-block ;
|
||||||
|
|
||||||
SYMBOLS: has-already ever-on-work-list work-list ;
|
|
||||||
|
|
||||||
: init-insert-phi-nodes ( bbs -- )
|
|
||||||
H{ } clone has-already set
|
|
||||||
[ unique ever-on-work-list set ]
|
|
||||||
[ <hashed-dlist> [ push-all-front ] keep work-list set ] bi ;
|
|
||||||
|
|
||||||
: add-to-work-list ( bb -- )
|
|
||||||
dup ever-on-work-list get key? [ drop ] [
|
|
||||||
[ ever-on-work-list get conjoin ]
|
|
||||||
[ work-list get push-front ]
|
|
||||||
bi
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: insert-phi-node-later ( vreg bb -- )
|
: insert-phi-node-later ( vreg bb -- )
|
||||||
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
|
2dup live-in key? [
|
||||||
inserting-phi-nodes get push-at ;
|
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
|
||||||
|
inserting-phi-nodes get push-at
|
||||||
: compute-phi-node-in ( vreg bb -- )
|
] [ 2drop ] if ;
|
||||||
dup has-already get key? [ 2drop ] [
|
|
||||||
[ insert-phi-node-later ]
|
|
||||||
[ has-already get conjoin ]
|
|
||||||
[ add-to-work-list ]
|
|
||||||
tri
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: compute-phi-nodes-for ( vreg bbs -- )
|
: compute-phi-nodes-for ( vreg bbs -- )
|
||||||
dup length 2 >= [
|
keys dup length 2 >= [
|
||||||
init-insert-phi-nodes
|
iterated-dom-frontier [
|
||||||
work-list get [
|
insert-phi-node-later
|
||||||
dom-frontier [
|
] with each
|
||||||
compute-phi-node-in
|
|
||||||
] with each
|
|
||||||
] with slurp-deque
|
|
||||||
] [ 2drop ] if ;
|
] [ 2drop ] if ;
|
||||||
|
|
||||||
: compute-phi-nodes ( -- )
|
: compute-phi-nodes ( -- )
|
||||||
|
@ -143,4 +122,10 @@ M: ##phi rename-insn
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: construct-ssa ( cfg -- cfg' )
|
: construct-ssa ( cfg -- cfg' )
|
||||||
dup [ compute-defs compute-phi-nodes insert-phi-nodes ] [ rename ] bi ;
|
{
|
||||||
|
[ ]
|
||||||
|
[ compute-live-sets ]
|
||||||
|
[ compute-dominance ]
|
||||||
|
[ compute-defs compute-phi-nodes insert-phi-nodes ]
|
||||||
|
[ rename ]
|
||||||
|
} cleave ;
|
Loading…
Reference in New Issue