compiler.cfg.copy-prop: optimistic copy propagation

db4
Slava Pestov 2010-04-30 19:50:30 -04:00
parent e90712b1ed
commit 5979fe7f41
2 changed files with 163 additions and 44 deletions

View File

@ -0,0 +1,107 @@
USING: compiler.cfg.copy-prop tools.test namespaces kernel
compiler.cfg.debugger compiler.cfg accessors
compiler.cfg.registers compiler.cfg.instructions
cpu.architecture ;
IN: compiler.cfg.copy-prop.tests
: test-copy-propagation ( -- )
cfg new 0 get >>entry copy-propagation drop ;
! Simple example
V{
T{ ##prologue }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f 0 D 0 }
T{ ##branch }
} 1 test-bb
V{
T{ ##peek f 1 D 1 }
T{ ##branch }
} 2 test-bb
V{
T{ ##copy f 2 0 any-rep }
T{ ##branch }
} 3 test-bb
V{
T{ ##phi f 3 H{ { 2 0 } { 3 2 } } }
T{ ##phi f 4 H{ { 2 1 } { 3 2 } } }
T{ ##phi f 5 H{ { 2 1 } { 3 0 } } }
T{ ##branch }
} 4 test-bb
V{
T{ ##copy f 6 4 any-rep }
T{ ##replace f 3 D 0 }
T{ ##replace f 5 D 1 }
T{ ##replace f 6 D 2 }
T{ ##branch }
} 5 test-bb
V{
T{ ##epilogue }
T{ ##return }
} 6 test-bb
0 1 edge
1 { 2 3 } edges
2 4 edge
3 4 edge
4 5 edge
[ ] [ test-copy-propagation ] unit-test
[
V{
T{ ##replace f 0 D 0 }
T{ ##replace f 4 D 1 }
T{ ##replace f 4 D 2 }
T{ ##branch }
}
] [ 5 get instructions>> ] unit-test
! Test optimistic assumption
V{
T{ ##prologue }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f 0 D 0 }
T{ ##branch }
} 1 test-bb
V{
T{ ##phi f 1 H{ { 1 0 } { 2 2 } } }
T{ ##copy f 2 1 any-rep }
T{ ##branch }
} 2 test-bb
V{
T{ ##replace f 2 D 1 }
T{ ##branch }
} 3 test-bb
V{
T{ ##epilogue }
T{ ##return }
} 4 test-bb
0 1 edge
1 2 edge
2 { 2 3 } edges
3 4 edge
[ ] [ test-copy-propagation ] unit-test
[
V{
T{ ##replace f 0 D 1 }
T{ ##branch }
}
] [ 3 get instructions>> ] unit-test

View File

@ -1,78 +1,90 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces assocs accessors sequences grouping USING: sets kernel namespaces assocs accessors sequences grouping
combinators compiler.cfg.rpo compiler.cfg.renaming combinators fry compiler.cfg.def-use compiler.cfg.rpo
compiler.cfg.instructions compiler.cfg.predecessors ; compiler.cfg.renaming compiler.cfg.instructions
compiler.cfg.predecessors ;
FROM: namespaces => set ;
IN: compiler.cfg.copy-prop IN: compiler.cfg.copy-prop
! The first three definitions are also used in compiler.cfg.alias-analysis.
SYMBOL: copies
! Initialized per-basic-block; a mapping from inputs to dst for eliminating
! redundant phi instructions
SYMBOL: phis
: resolve ( vreg -- vreg )
copies get ?at drop ;
: (record-copy) ( dst src -- )
swap copies get set-at ; inline
: record-copy ( ##copy -- )
[ dst>> ] [ src>> resolve ] bi (record-copy) ; inline
<PRIVATE <PRIVATE
SYMBOL: changed?
SYMBOL: copies
! Initialized per-basic-block; a mapping from inputs to dst for
! eliminating redundant ##phi instructions
SYMBOL: phis
: resolve ( vreg -- vreg )
copies get at ;
: record-copy ( dst src -- )
swap copies get maybe-set-at [ changed? on ] when ; inline
GENERIC: visit-insn ( insn -- ) GENERIC: visit-insn ( insn -- )
M: ##copy visit-insn record-copy ; M: ##copy visit-insn
[ dst>> ] [ src>> resolve ] bi
dup [ record-copy ] [ 2drop ] if ;
: useless-phi ( dst inputs -- ) first (record-copy) ; : useless-phi ( dst inputs -- ) first record-copy ;
: redundant-phi ( dst inputs -- ) phis get at (record-copy) ; : redundant-phi ( dst inputs -- ) phis get at record-copy ;
: record-phi ( dst inputs -- ) phis get set-at ; : record-phi ( dst inputs -- )
[ phis get set-at ] [ drop dup record-copy ] 2bi ;
M: ##phi visit-insn M: ##phi visit-insn
[ dst>> ] [ inputs>> values [ resolve ] map ] bi [ dst>> ] [ inputs>> values [ resolve ] map ] bi
{ dup phis get key? [ redundant-phi ] [
{ [ dup all-equal? ] [ useless-phi ] } dup sift
{ [ dup phis get key? ] [ redundant-phi ] } dup all-equal?
[ record-phi ] [ nip useless-phi ]
} cond ; [ drop record-phi ] if
] if ;
M: vreg-insn visit-insn
defs-vreg [ dup record-copy ] when* ;
M: insn visit-insn drop ; M: insn visit-insn drop ;
: collect-copies ( cfg -- ) : (collect-copies) ( cfg -- )
H{ } clone copies set
[ [
H{ } clone phis set phis get clear-assoc
instructions>> [ visit-insn ] each instructions>> [ visit-insn ] each
] each-basic-block ; ] each-basic-block ;
: collect-copies ( cfg -- )
H{ } clone copies set
H{ } clone phis set
'[
changed? off
_ (collect-copies)
changed? get
] loop ;
GENERIC: update-insn ( insn -- keep? ) GENERIC: update-insn ( insn -- keep? )
M: ##copy update-insn drop f ; M: ##copy update-insn drop f ;
M: ##phi update-insn M: ##phi update-insn
dup dst>> copies get key? [ drop f ] [ call-next-method ] if ; dup call-next-method drop
[ dst>> ] [ inputs>> values ] bi [ = not ] with any? ;
M: insn update-insn rename-insn-uses t ; M: vreg-insn update-insn rename-insn-uses t ;
M: insn update-insn drop t ;
: rename-copies ( cfg -- ) : rename-copies ( cfg -- )
copies get dup assoc-empty? [ 2drop ] [ copies get renamings set
renamings set [ [ update-insn ] filter! ] simple-optimization ;
[
instructions>> [ update-insn ] filter! drop
] each-basic-block
] if ;
PRIVATE> PRIVATE>
: copy-propagation ( cfg -- cfg' ) : copy-propagation ( cfg -- cfg' )
needs-predecessors needs-predecessors
[ collect-copies ] dup collect-copies
[ rename-copies ] dup rename-copies ;
[ ]
tri ;