compiler.cfg.liveness: merge in compiler.cfg.liveness.ssa and simplify the code, since we don't compute live sets before SSA construction anymore

db4
Slava Pestov 2010-09-25 14:36:58 -07:00
parent 2d3c9fd7c8
commit ec2f42fd40
8 changed files with 139 additions and 152 deletions

View File

@ -6,7 +6,6 @@ cpu.architecture layouts
compiler.cfg compiler.cfg
compiler.cfg.def-use compiler.cfg.def-use
compiler.cfg.liveness compiler.cfg.liveness
compiler.cfg.liveness.ssa
compiler.cfg.registers compiler.cfg.registers
compiler.cfg.instructions compiler.cfg.instructions
compiler.cfg.linearization compiler.cfg.linearization

View File

@ -1,19 +1,15 @@
USING: compiler.cfg.liveness compiler.cfg.liveness.ssa USING: compiler.cfg.liveness
compiler.cfg.debugger compiler.cfg.instructions compiler.cfg.debugger compiler.cfg.instructions
compiler.cfg.predecessors compiler.cfg.registers compiler.cfg compiler.cfg.predecessors compiler.cfg.registers compiler.cfg
cpu.architecture accessors namespaces sequences kernel cpu.architecture accessors namespaces sequences kernel
tools.test vectors alien math compiler.cfg.comparisons tools.test vectors alien math compiler.cfg.comparisons
cpu.x86.assembler.operands ; cpu.x86.assembler.operands assocs ;
IN: compiler.cfg.liveness.tests IN: compiler.cfg.liveness.tests
: test-liveness ( -- ) : test-liveness ( -- )
cfg new 1 get >>entry cfg new 1 get >>entry
compute-live-sets ; compute-live-sets ;
: test-ssa-liveness ( -- )
cfg new 1 get >>entry
compute-ssa-live-sets ;
! Sanity check... ! Sanity check...
V{ V{
@ -148,9 +144,65 @@ V{
7 8 edge 7 8 edge
8 9 edge 8 9 edge
[ ] [ test-ssa-liveness ] unit-test [ ] [ test-liveness ] unit-test
[ H{ { 28 28 } { 29 29 } { 30 30 } { 31 31 } } ] [ 5 get live-out ] unit-test [ H{ { 28 28 } { 29 29 } { 30 30 } { 31 31 } } ] [ 5 get live-out ] unit-test
[ H{ { 28 28 } { 29 29 } { 30 30 } } ] [ 6 get live-in ] unit-test [ H{ { 28 28 } { 29 29 } { 30 30 } } ] [ 6 get live-in ] unit-test
[ H{ { 28 28 } { 29 29 } { 31 31 } } ] [ 7 get live-in ] unit-test [ H{ { 28 28 } { 29 29 } { 31 31 } } ] [ 7 get live-in ] unit-test
[ H{ { 30 30 } } ] [ 6 get 8 get edge-live-in ] unit-test [ H{ { 30 30 } } ] [ 6 get 8 get edge-live-in ] unit-test
V{
T{ ##prologue }
T{ ##branch }
} 0 test-bb
V{
T{ ##branch }
} 1 test-bb
V{
T{ ##load-integer f 0 0 }
T{ ##branch }
} 2 test-bb
V{
T{ ##load-integer f 1 1 }
T{ ##branch }
} 3 test-bb
V{
T{ ##phi f 2 H{ { 2 0 } { 3 1 } } }
T{ ##branch }
} 4 test-bb
V{
T{ ##branch }
} 5 test-bb
V{
T{ ##replace f 2 D 0 }
T{ ##branch }
} 6 test-bb
V{
T{ ##epilogue }
T{ ##return }
} 7 test-bb
0 1 edge
1 { 2 3 } edges
2 4 edge
3 4 edge
4 { 5 6 } edges
5 6 edge
6 7 edge
[ ] [ cfg new 0 get >>entry dup cfg set compute-live-sets ] unit-test
[ t ] [ 0 get live-in assoc-empty? ] unit-test
[ H{ { 2 2 } } ] [ 4 get live-out ] unit-test
[ H{ { 0 0 } } ] [ 2 get 4 get edge-live-in ] unit-test
[ H{ { 1 1 } } ] [ 3 get 4 get edge-live-in ] unit-test

View File

@ -1,17 +1,31 @@
! 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: kernel accessors assocs namespaces sequences sets USING: kernel accessors assocs fry deques dlists namespaces
compiler.cfg.def-use compiler.cfg.dataflow-analysis sequences sets compiler.cfg compiler.cfg.def-use
compiler.cfg.instructions compiler.cfg.registers compiler.cfg.instructions compiler.cfg.registers
cpu.architecture ; compiler.cfg.utilities compiler.cfg.predecessors
compiler.cfg.rpo cpu.architecture ;
FROM: namespaces => set ;
IN: compiler.cfg.liveness IN: compiler.cfg.liveness
! See http://en.wikipedia.org/wiki/Liveness_analysis ! See http://en.wikipedia.org/wiki/Liveness_analysis
! Do not run after SSA construction; compiler.cfg.liveness.ssa
! should be used instead. The transfer-liveness word is used
! by SSA liveness too, so it handles ##phi instructions.
BACKWARD-ANALYSIS: live SYMBOL: live-ins
: live-in ( bb -- set )
live-ins get at ;
SYMBOL: live-outs
: live-out ( bb -- set )
live-outs get at ;
! Assoc mapping basic blocks to sequences of sets of vregs; each
! sequence is in correspondence with a predecessor
SYMBOL: edge-live-ins
: edge-live-in ( predecessor basic-block -- set )
edge-live-ins get at at ;
GENERIC: visit-insn ( live-set insn -- live-set ) GENERIC: visit-insn ( live-set insn -- live-set )
@ -23,6 +37,11 @@ GENERIC: visit-insn ( live-set insn -- live-set )
M: vreg-insn visit-insn [ kill-defs ] [ gen-uses ] bi ; M: vreg-insn visit-insn [ kill-defs ] [ gen-uses ] bi ;
! Our liveness analysis annotates call sites with GC maps
! indicating the spill slots in the stack frame that contain
! tagged pointers, and thus have to be visited if a GC occurs
! inside the call.
: fill-gc-map ( live-set insn -- live-set ) : fill-gc-map ( live-set insn -- live-set )
representations get [ representations get [
gc-map>> over keys gc-map>> over keys
@ -44,8 +63,49 @@ M: insn visit-insn drop ;
: local-live-in ( instructions -- live-set ) : local-live-in ( instructions -- live-set )
[ H{ } ] dip transfer-liveness keys ; [ H{ } ] dip transfer-liveness keys ;
M: live-analysis transfer-set SYMBOL: work-list
drop instructions>> transfer-liveness ;
M: live-analysis join-sets : add-to-work-list ( basic-blocks -- )
2drop assoc-combine ; work-list get '[ _ push-front ] each ;
: compute-live-in ( basic-block -- live-in )
[ live-out ] keep instructions>> transfer-liveness ;
: compute-edge-live-in ( basic-block -- edge-live-in )
H{ } clone [
'[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
] keep ;
: update-live-in ( basic-block -- changed? )
[ [ compute-live-in ] keep live-ins get maybe-set-at ]
[ [ compute-edge-live-in ] keep edge-live-ins get maybe-set-at ]
bi or ;
: compute-live-out ( basic-block -- live-out )
[ successors>> [ live-in ] map ]
[ dup successors>> [ edge-live-in ] with map ] bi
append assoc-combine ;
: update-live-out ( basic-block -- changed? )
[ compute-live-out ] keep
live-outs get maybe-set-at ;
: liveness-step ( basic-block -- )
dup update-live-out [
dup update-live-in
[ predecessors>> add-to-work-list ] [ drop ] if
] [ drop ] if ;
: compute-live-sets ( cfg -- )
needs-predecessors
<hashed-dlist> work-list set
H{ } clone live-ins set
H{ } clone edge-live-ins set
H{ } clone live-outs set
post-order add-to-work-list
work-list get [ liveness-step ] slurp-deque ;
: live-in? ( vreg bb -- ? ) live-in key? ;
: live-out? ( vreg bb -- ? ) live-out key? ;

View File

@ -1,61 +0,0 @@
USING: accessors compiler.cfg compiler.cfg.debugger
compiler.cfg.instructions compiler.cfg.liveness.ssa
compiler.cfg.liveness arrays sequences assocs
compiler.cfg.registers kernel namespaces tools.test ;
IN: compiler.cfg.liveness.ssa.tests
V{
T{ ##prologue }
T{ ##branch }
} 0 test-bb
V{
T{ ##branch }
} 1 test-bb
V{
T{ ##load-integer f 0 0 }
T{ ##branch }
} 2 test-bb
V{
T{ ##load-integer f 1 1 }
T{ ##branch }
} 3 test-bb
V{
T{ ##phi f 2 H{ { 2 0 } { 3 1 } } }
T{ ##branch }
} 4 test-bb
V{
T{ ##branch }
} 5 test-bb
V{
T{ ##replace f 2 D 0 }
T{ ##branch }
} 6 test-bb
V{
T{ ##epilogue }
T{ ##return }
} 7 test-bb
0 1 edge
1 { 2 3 } edges
2 4 edge
3 4 edge
4 { 5 6 } edges
5 6 edge
6 7 edge
[ ] [ cfg new 0 get >>entry dup cfg set compute-ssa-live-sets ] unit-test
[ t ] [ 0 get live-in assoc-empty? ] unit-test
[ H{ { 2 2 } } ] [ 4 get live-out ] unit-test
[ H{ { 0 0 } } ] [ 2 get 4 get edge-live-in ] unit-test
[ H{ { 1 1 } } ] [ 3 get 4 get edge-live-in ] unit-test

View File

@ -1,63 +0,0 @@
! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces deques accessors sets sequences assocs fry
hashtables dlists compiler.cfg.def-use compiler.cfg.instructions
compiler.cfg.rpo compiler.cfg.liveness compiler.cfg.utilities
compiler.cfg.predecessors ;
FROM: namespaces => set ;
IN: compiler.cfg.liveness.ssa
! TODO: merge with compiler.cfg.liveness
! Assoc mapping basic blocks to sequences of sets of vregs; each sequence
! is in correspondence with a predecessor
SYMBOL: edge-live-ins
: edge-live-in ( predecessor basic-block -- set ) edge-live-ins get at at ;
SYMBOL: work-list
: add-to-work-list ( basic-blocks -- )
work-list get '[ _ push-front ] each ;
: compute-live-in ( basic-block -- live-in )
[ live-out ] keep instructions>> transfer-liveness ;
: compute-edge-live-in ( basic-block -- edge-live-in )
H{ } clone [
'[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
] keep ;
: update-live-in ( basic-block -- changed? )
[ [ compute-live-in ] keep live-ins get maybe-set-at ]
[ [ compute-edge-live-in ] keep edge-live-ins get maybe-set-at ]
bi or ;
: compute-live-out ( basic-block -- live-out )
[ successors>> [ live-in ] map ]
[ dup successors>> [ edge-live-in ] with map ] bi
append assoc-combine ;
: update-live-out ( basic-block -- changed? )
[ compute-live-out ] keep
live-outs get maybe-set-at ;
: liveness-step ( basic-block -- )
dup update-live-out [
dup update-live-in
[ predecessors>> add-to-work-list ] [ drop ] if
] [ drop ] if ;
: compute-ssa-live-sets ( cfg -- )
needs-predecessors
<hashed-dlist> work-list set
H{ } clone live-ins set
H{ } clone edge-live-ins set
H{ } clone live-outs set
post-order add-to-work-list
work-list get [ liveness-step ] slurp-deque ;
: live-in? ( vreg bb -- ? ) live-in key? ;
: live-out? ( vreg bb -- ? ) live-out key? ;

View File

@ -9,7 +9,7 @@ compiler.cfg.def-use
compiler.cfg.registers compiler.cfg.registers
compiler.cfg.dominance compiler.cfg.dominance
compiler.cfg.instructions compiler.cfg.instructions
compiler.cfg.liveness.ssa compiler.cfg.liveness
compiler.cfg.ssa.cssa compiler.cfg.ssa.cssa
compiler.cfg.ssa.interference compiler.cfg.ssa.interference
compiler.cfg.ssa.interference.live-ranges compiler.cfg.ssa.interference.live-ranges
@ -28,9 +28,9 @@ IN: compiler.cfg.ssa.destruction
! 2) Useless ##copy instructions, and all ##phi instructions, ! 2) Useless ##copy instructions, and all ##phi instructions,
! are eliminated, so the register allocator does not have to ! are eliminated, so the register allocator does not have to
! remove any redundant operations. ! remove any redundant operations.
! 3) A side effect of running this pass is that SSA liveness ! 3) This pass computes live sets and fills out GC maps with
! information is computed, so the register allocator does not ! compiler.cfg.liveness, so the linear scan register allocator
! need to compute it again. ! does not need to compute liveness again.
SYMBOL: leader-map SYMBOL: leader-map
@ -134,7 +134,7 @@ PRIVATE>
dup construct-cssa dup construct-cssa
dup compute-defs dup compute-defs
dup compute-insns dup compute-insns
dup compute-ssa-live-sets dup compute-live-sets
dup compute-live-ranges dup compute-live-ranges
dup prepare-coalescing dup prepare-coalescing
process-copies process-copies

View File

@ -1,6 +1,6 @@
USING: accessors compiler.cfg compiler.cfg.debugger USING: accessors compiler.cfg compiler.cfg.debugger
compiler.cfg.def-use compiler.cfg.dominance compiler.cfg.def-use compiler.cfg.dominance
compiler.cfg.instructions compiler.cfg.liveness.ssa compiler.cfg.instructions compiler.cfg.liveness
compiler.cfg.registers compiler.cfg.predecessors compiler.cfg.registers compiler.cfg.predecessors
compiler.cfg.comparisons compiler.cfg.ssa.interference compiler.cfg.comparisons compiler.cfg.ssa.interference
compiler.cfg.ssa.interference.private compiler.cfg.ssa.interference.private
@ -11,7 +11,7 @@ IN: compiler.cfg.ssa.interference.tests
: test-interference ( -- ) : test-interference ( -- )
cfg new 0 get >>entry cfg new 0 get >>entry
dup compute-ssa-live-sets dup compute-live-sets
dup compute-defs dup compute-defs
dup compute-insns dup compute-insns
compute-live-ranges ; compute-live-ranges ;

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs fry kernel namespaces sequences math USING: accessors assocs fry kernel namespaces sequences math
arrays compiler.cfg.def-use compiler.cfg.instructions arrays compiler.cfg.def-use compiler.cfg.instructions
compiler.cfg.liveness.ssa compiler.cfg.rpo compiler.cfg.liveness compiler.cfg.rpo
compiler.cfg.dominance compiler.cfg ; compiler.cfg.dominance compiler.cfg ;
IN: compiler.cfg.ssa.interference.live-ranges IN: compiler.cfg.ssa.interference.live-ranges