Merge branch 'master' of git://factorcode.org/git/factor

db4
Doug Coleman 2009-08-02 10:39:59 -05:00
commit 5f6eb8f068
40 changed files with 520 additions and 621 deletions

View File

@ -94,6 +94,7 @@ nl
{ {
memq? split harvest sift cut cut-slice start index clone memq? split harvest sift cut cut-slice start index clone
set-at reverse push-all class number>string string>number set-at reverse push-all class number>string string>number
like clone-like
} compile-unoptimized } compile-unoptimized
"." write flush "." write flush

View File

@ -46,11 +46,11 @@ V{ T{ ##branch } } 4 test-bb
V{ T{ ##branch } } 5 test-bb V{ T{ ##branch } } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 4 get V{ } 2sequence >>successors drop 1 { 3 4 } edges
2 get 3 get 4 get V{ } 2sequence >>successors drop 2 { 3 4 } edges
[ ] [ test-branch-splitting ] unit-test [ ] [ test-branch-splitting ] unit-test
@ -64,11 +64,11 @@ V{ T{ ##branch } } 3 test-bb
V{ T{ ##branch } } 4 test-bb V{ T{ ##branch } } 4 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 4 get V{ } 2sequence >>successors drop 1 { 3 4 } edges
2 get 4 get 1vector >>successors drop 2 4 edge
[ ] [ test-branch-splitting ] unit-test [ ] [ test-branch-splitting ] unit-test
@ -78,8 +78,8 @@ V{ T{ ##branch } } 1 test-bb
V{ T{ ##branch } } 2 test-bb V{ T{ ##branch } } 2 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 2 get 1vector >>successors drop 1 2 edge
[ ] [ test-branch-splitting ] unit-test [ ] [ test-branch-splitting ] unit-test

View File

@ -0,0 +1,37 @@
USING: accessors assocs compiler.cfg
compiler.cfg.critical-edges compiler.cfg.debugger
compiler.cfg.instructions compiler.cfg.predecessors
compiler.cfg.registers cpu.architecture kernel namespaces
sequences tools.test compiler.cfg.utilities ;
IN: compiler.cfg.critical-edges.tests
! Make sure we update phi nodes when splitting critical edges
: test-critical-edges ( -- )
cfg new 0 get >>entry
compute-predecessors
split-critical-edges ;
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f V int-regs 1 D 1 }
T{ ##branch }
} 1 test-bb
V{
T{ ##phi f V int-regs 2 H{ { 0 V int-regs 0 } { 1 V int-regs 1 } } }
T{ ##return }
} 2 test-bb
0 { 1 2 } edges
1 2 edge
[ ] [ test-critical-edges ] unit-test
[ t ] [ 0 get successors>> second successors>> first 2 get eq? ] unit-test
[ V int-regs 0 ] [ 2 get instructions>> first inputs>> 0 get successors>> second swap at ] unit-test

View File

@ -1,14 +1,22 @@
! 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: kernel math accessors sequences USING: kernel math accessors sequences locals assocs fry
compiler.cfg compiler.cfg.rpo compiler.cfg.utilities ; compiler.cfg compiler.cfg.rpo compiler.cfg.utilities ;
IN: compiler.cfg.critical-edges IN: compiler.cfg.critical-edges
: critical-edge? ( from to -- ? ) : critical-edge? ( from to -- ? )
[ successors>> length 1 > ] [ predecessors>> length 1 > ] bi* and ; [ successors>> length 1 > ] [ predecessors>> length 1 > ] bi* and ;
: new-key ( new-key old-key assoc -- )
[ delete-at* ] keep '[ swap _ set-at ] [ 2drop ] if ;
:: update-phis ( from to bb -- )
! Any phi nodes in 'to' which reference 'from'
! should now reference 'bb'.
to [ [ bb from ] dip inputs>> new-key ] each-phi ;
: split-critical-edge ( from to -- ) : split-critical-edge ( from to -- )
f <simple-block> insert-basic-block ; f <simple-block> [ insert-basic-block ] [ update-phis ] 3bi ;
: split-critical-edges ( cfg -- ) : split-critical-edges ( cfg -- )
dup [ dup [

View File

@ -1,14 +1,14 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel words sequences quotations namespaces io vectors USING: kernel words sequences quotations namespaces io vectors
classes.tuple accessors prettyprint prettyprint.config classes.tuple accessors prettyprint prettyprint.config assocs
prettyprint.backend prettyprint.custom prettyprint.sections prettyprint.backend prettyprint.custom prettyprint.sections
parser compiler.tree.builder compiler.tree.optimizer parser compiler.tree.builder compiler.tree.optimizer
compiler.cfg.builder compiler.cfg.linearization compiler.cfg.builder compiler.cfg.linearization
compiler.cfg.registers compiler.cfg.stack-frame compiler.cfg.registers compiler.cfg.stack-frame
compiler.cfg.linear-scan compiler.cfg.two-operand compiler.cfg.linear-scan compiler.cfg.two-operand
compiler.cfg.optimizer compiler.cfg.optimizer compiler.cfg.instructions
compiler.cfg.mr compiler.cfg ; compiler.cfg.utilities compiler.cfg.mr compiler.cfg ;
IN: compiler.cfg.debugger IN: compiler.cfg.debugger
GENERIC: test-cfg ( quot -- cfgs ) GENERIC: test-cfg ( quot -- cfgs )
@ -52,11 +52,23 @@ M: ds-loc pprint* \ D pprint-loc ;
M: rs-loc pprint* \ R pprint-loc ; M: rs-loc pprint* \ R pprint-loc ;
: resolve-phis ( bb -- )
[
[ [ [ get ] dip ] assoc-map ] change-inputs drop
] each-phi ;
: test-bb ( insns n -- ) : test-bb ( insns n -- )
[ <basic-block> swap >>number swap >>instructions ] keep set ; [ <basic-block> swap >>number swap >>instructions dup ] keep set
resolve-phis ;
: edge ( from to -- )
[ get ] bi@ 1vector >>successors drop ;
: edges ( from tos -- )
[ get ] [ [ get ] V{ } map-as ] bi* >>successors drop ;
: test-diamond ( -- ) : test-diamond ( -- )
1 get 1vector 0 get (>>successors) 0 1 edge
2 get 3 get V{ } 2sequence 1 get (>>successors) 1 { 2 3 } edges
4 get 1vector 2 get (>>successors) 2 4 edge
4 get 1vector 3 get (>>successors) ; 3 4 edge ;

View File

@ -16,11 +16,11 @@ V{ } 3 test-bb
V{ } 4 test-bb V{ } 4 test-bb
V{ } 5 test-bb V{ } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 1vector >>successors drop 1 3 edge
2 get 4 get 1vector >>successors drop 2 4 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 5 get 1vector >>successors drop 4 5 edge
[ ] [ test-dominance ] unit-test [ ] [ test-dominance ] unit-test
@ -46,11 +46,11 @@ V{ } 2 test-bb
V{ } 3 test-bb V{ } 3 test-bb
V{ } 4 test-bb V{ } 4 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 1vector >>successors drop 1 3 edge
2 get 4 get 1vector >>successors drop 2 4 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 3 get 1vector >>successors drop 4 3 edge
[ ] [ test-dominance ] unit-test [ ] [ test-dominance ] unit-test
@ -64,12 +64,12 @@ V{ } 3 test-bb
V{ } 4 test-bb V{ } 4 test-bb
V{ } 5 test-bb V{ } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 5 get 1vector >>successors drop 1 5 edge
2 get 4 get 3 get V{ } 2sequence >>successors drop 2 { 4 3 } edges
5 get 4 get 1vector >>successors drop 5 4 edge
4 get 5 get 3 get V{ } 2sequence >>successors drop 4 { 5 3 } edges
3 get 4 get 1vector >>successors drop 3 4 edge
[ ] [ test-dominance ] unit-test [ ] [ test-dominance ] unit-test

View File

@ -19,7 +19,7 @@ V{
T{ ##box-float f V int-regs 0 V int-regs 1 } T{ ##box-float f V int-regs 0 V int-regs 1 }
} 1 test-bb } 1 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
[ ] [ test-gc-checks ] unit-test [ ] [ test-gc-checks ] unit-test

View File

@ -1549,9 +1549,9 @@ V{
T{ ##return } T{ ##return }
} 3 test-bb } 3 test-bb
1 get 1vector 0 get (>>successors) 0 1 edge
2 get 3 get V{ } 2sequence 1 get (>>successors) 1 { 2 3 } edges
3 get 1vector 2 get (>>successors) 2 3 edge
SYMBOL: linear-scan-result SYMBOL: linear-scan-result
@ -1564,9 +1564,7 @@ SYMBOL: linear-scan-result
flatten-cfg 1array mr. flatten-cfg 1array mr.
] with-scope ; ] with-scope ;
! This test has a critical edge -- do we care about these? [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
! [ { 1 2 } test-linear-scan-on-cfg ] unit-test
! Bug in inactive interval handling ! Bug in inactive interval handling
! [ rot dup [ -rot ] when ] ! [ rot dup [ -rot ] when ]
@ -1896,11 +1894,11 @@ V{
T{ ##return } T{ ##return }
} 6 test-bb } 6 test-bb
0 get 1 get V{ } 1sequence >>successors drop 0 1 edge
1 get 2 get 3 get V{ } 2sequence >>successors drop 1 { 2 3 } edges
2 get 4 get V{ } 1sequence >>successors drop 2 4 edge
3 get 4 get V{ } 1sequence >>successors drop 3 4 edge
4 get 5 get 6 get V{ } 2sequence >>successors drop 4 { 5 6 } edges
[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
@ -1956,14 +1954,14 @@ V{
T{ ##return } T{ ##return }
} 9 test-bb } 9 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 7 get V{ } 2sequence >>successors drop 1 { 2 7 } edges
7 get 8 get 1vector >>successors drop 7 8 edge
8 get 9 get 1vector >>successors drop 8 9 edge
2 get 3 get 5 get V{ } 2sequence >>successors drop 2 { 3 5 } edges
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 9 get 1vector >>successors drop 4 9 edge
5 get 6 get 1vector >>successors drop 5 6 edge
[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
@ -2139,11 +2137,11 @@ V{
T{ ##return } T{ ##return }
} 5 test-bb } 5 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 4 get V{ } 2sequence >>successors drop 1 { 2 4 } edges
2 get 3 get 1vector >>successors drop 2 3 edge
3 get 5 get 1vector >>successors drop 3 5 edge
4 get 5 get 1vector >>successors drop 4 5 edge
[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
@ -2286,12 +2284,12 @@ V{
T{ ##return } T{ ##return }
} 6 test-bb } 6 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 5 get V{ } 2sequence >>successors drop 1 { 2 5 } edges
2 get 3 get 1vector >>successors drop 2 3 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 6 get 1vector >>successors drop 4 6 edge
5 get 6 get 1vector >>successors drop 5 6 edge
[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
@ -2419,8 +2417,8 @@ V{
T{ ##return } T{ ##return }
} 2 test-bb } 2 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 1vector >>successors drop 1 2 edge
[ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
@ -2444,7 +2442,7 @@ V{
T{ ##return } T{ ##return }
} 2 test-bb } 2 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
[ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test

View File

@ -26,10 +26,9 @@ SYMBOL: spill-temps
2dup = [ 2drop ] [ vreg reg-class>> add-mapping ] if ; 2dup = [ 2drop ] [ vreg reg-class>> add-mapping ] if ;
: compute-mappings ( bb to -- mappings ) : compute-mappings ( bb to -- mappings )
[ dup live-in dup assoc-empty? [ 3drop f ] [
dup live-in keys [ keys [ resolve-value-data-flow ] with with each ] { } make
[ resolve-value-data-flow ] with with each ] if ;
] { } make ;
: memory->register ( from to -- ) : memory->register ( from to -- )
swap [ first2 ] [ first n>> ] bi* _reload ; swap [ first2 ] [ first n>> ] bi* _reload ;

View File

@ -29,7 +29,7 @@ V{
T{ ##return } T{ ##return }
} 3 test-bb } 3 test-bb
1 get 2 get 3 get V{ } 2sequence >>successors drop 1 { 2 3 } edges
test-liveness test-liveness
@ -55,7 +55,7 @@ V{
T{ ##return } T{ ##return }
} 2 test-bb } 2 test-bb
1 get 2 get 1vector >>successors drop 1 2 edge
test-liveness test-liveness

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: kernel namespaces deques accessors sets sequences assocs fry USING: kernel namespaces deques accessors sets sequences assocs fry
hashtables dlists compiler.cfg.def-use compiler.cfg.instructions hashtables dlists compiler.cfg.def-use compiler.cfg.instructions
compiler.cfg.rpo compiler.cfg.liveness ; compiler.cfg.rpo compiler.cfg.liveness compiler.cfg.utilities ;
IN: compiler.cfg.liveness.ssa IN: compiler.cfg.liveness.ssa
! TODO: merge with compiler.cfg.liveness ! TODO: merge with compiler.cfg.liveness
@ -22,11 +22,9 @@ SYMBOL: work-list
[ live-out ] keep instructions>> transfer-liveness ; [ live-out ] keep instructions>> transfer-liveness ;
: compute-phi-live-in ( basic-block -- phi-live-in ) : compute-phi-live-in ( basic-block -- phi-live-in )
instructions>> [ ##phi? ] filter [ f ] [ H{ } clone [
H{ } clone [ '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
'[ inputs>> [ swap _ conjoin-at ] assoc-each ] each ] keep ;
] keep
] if-empty ;
: update-live-in ( basic-block -- changed? ) : update-live-in ( basic-block -- changed? )
[ [ compute-live-in ] keep live-ins get maybe-set-at ] [ [ compute-live-in ] keep live-ins get maybe-set-at ]

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors combinators fry sequences assocs compiler.cfg.rpo USING: kernel accessors combinators fry sequences assocs compiler.cfg.rpo
compiler.cfg.instructions ; compiler.cfg.instructions compiler.cfg.utilities ;
IN: compiler.cfg.predecessors IN: compiler.cfg.predecessors
: update-predecessors ( bb -- ) : update-predecessors ( bb -- )
@ -14,9 +14,7 @@ IN: compiler.cfg.predecessors
] change-inputs drop ; ] change-inputs drop ;
: update-phis ( bb -- ) : update-phis ( bb -- )
dup instructions>> [ dup [ update-phi ] with each-phi ;
dup ##phi? [ update-phi ] [ 2drop ] if
] with each ;
: compute-predecessors ( cfg -- cfg' ) : compute-predecessors ( cfg -- cfg' )
{ {

View File

@ -34,9 +34,9 @@ V{
T{ ##return } T{ ##return }
} 3 test-bb } 3 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 1vector >>successors drop 1 3 edge
2 get 3 get 1vector >>successors drop 2 3 edge
: test-ssa ( -- ) : test-ssa ( -- )
cfg new 0 get >>entry cfg new 0 get >>entry
@ -93,12 +93,12 @@ V{ T{ ##replace f V int-regs 0 D 0 } } 4 test-bb
V{ } 5 test-bb V{ } 5 test-bb
V{ } 6 test-bb V{ } 6 test-bb
0 get 1 get 5 get V{ } 2sequence >>successors drop 0 { 1 5 } edges
1 get 2 get 3 get V{ } 2sequence >>successors drop 1 { 2 3 } edges
2 get 4 get 1vector >>successors drop 2 4 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 6 get 1vector >>successors drop 4 6 edge
5 get 6 get 1vector >>successors drop 5 6 edge
[ ] [ test-ssa ] unit-test [ ] [ test-ssa ] unit-test

View File

@ -17,11 +17,11 @@ V{ } 3 test-bb
V{ } 4 test-bb V{ } 4 test-bb
V{ } 5 test-bb V{ } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 1vector >>successors drop 1 3 edge
2 get 4 get 1vector >>successors drop 2 4 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 5 get 1vector >>successors drop 4 5 edge
[ ] [ test-tdmsc ] unit-test [ ] [ test-tdmsc ] unit-test
@ -38,12 +38,12 @@ V{ } 4 test-bb
V{ } 5 test-bb V{ } 5 test-bb
V{ } 6 test-bb V{ } 6 test-bb
0 get 1 get 5 get V{ } 2sequence >>successors drop 0 { 1 5 } edges
1 get 2 get 3 get V{ } 2sequence >>successors drop 1 { 2 3 } edges
2 get 4 get 1vector >>successors drop 2 4 edge
3 get 4 get 1vector >>successors drop 3 4 edge
4 get 6 get 1vector >>successors drop 4 6 edge
5 get 6 get 1vector >>successors drop 5 6 edge
[ ] [ test-tdmsc ] unit-test [ ] [ test-tdmsc ] unit-test
@ -61,13 +61,13 @@ V{ } 5 test-bb
V{ } 6 test-bb V{ } 6 test-bb
V{ } 7 test-bb V{ } 7 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 1vector >>successors drop 1 2 edge
2 get 3 get 6 get V{ } 2sequence >>successors drop 2 { 3 6 } edges
3 get 4 get 1vector >>successors drop 3 4 edge
6 get 7 get 1vector >>successors drop 6 7 edge
4 get 5 get 1vector >>successors drop 4 5 edge
5 get 2 get 1vector >>successors drop 5 2 edge
[ ] [ test-tdmsc ] unit-test [ ] [ test-tdmsc ] unit-test

View File

@ -0,0 +1,21 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs kernel locals
compiler.cfg.rpo
compiler.cfg.hats
compiler.cfg.utilities
compiler.cfg.instructions ;
IN: compiler.cfg.ssa.cssa
! Convert SSA to conventional SSA.
:: insert-copy ( bb src -- bb dst )
i :> dst
bb [ dst src ##copy ] add-instructions
bb dst ;
: convert-phi ( ##phi -- )
[ [ insert-copy ] assoc-map ] change-inputs drop ;
: construct-cssa ( cfg -- )
[ [ convert-phi ] each-phi ] each-basic-block ;

View File

@ -1,28 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs hashtables fry kernel make namespaces sets
sequences compiler.cfg.ssa.destruction.state compiler.cfg.parallel-copy ;
IN: compiler.cfg.ssa.destruction.copies
ERROR: bad-copy ;
: compute-copies ( assoc -- assoc' )
dup assoc-size <hashtable> [
'[
prune [
2dup eq? [ 2drop ] [
_ 2dup key?
[ bad-copy ] [ set-at ] if
] if
] with each
] assoc-each
] keep ;
: insert-copies ( -- )
waiting get [
[ instructions>> building ] dip '[
building get pop
_ compute-copies parallel-copy
,
] with-variable
] assoc-each ;

View File

@ -1,63 +1,104 @@
! 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 fry kernel locals math math.order USING: accessors arrays assocs fry kernel namespaces
sequences namespaces sets sequences sequences.deep
sets vectors
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.def-use compiler.cfg.def-use
compiler.cfg.utilities compiler.cfg.renaming
compiler.cfg.dominance compiler.cfg.dominance
compiler.cfg.instructions compiler.cfg.instructions
compiler.cfg.liveness.ssa compiler.cfg.liveness.ssa
compiler.cfg.critical-edges compiler.cfg.ssa.cssa
compiler.cfg.ssa.destruction.state compiler.cfg.ssa.interference
compiler.cfg.ssa.destruction.forest compiler.cfg.ssa.interference.live-ranges
compiler.cfg.ssa.destruction.copies compiler.utilities ;
compiler.cfg.ssa.destruction.renaming
compiler.cfg.ssa.destruction.live-ranges
compiler.cfg.ssa.destruction.process-blocks ;
IN: compiler.cfg.ssa.destruction IN: compiler.cfg.ssa.destruction
! Based on "Fast Copy Coalescing and Live-Range Identification" ! Maps vregs to leaders.
! http://www.cs.ucsd.edu/classes/sp02/cse231/kenpldi.pdf SYMBOL: leader-map
! Dominance, liveness and def-use need to be computed : leader ( vreg -- vreg' ) leader-map get compress-path ;
: process-blocks ( cfg -- ) ! Maps leaders to equivalence class elements.
[ [ process-block ] if-has-phis ] each-basic-block ; SYMBOL: class-element-map
SYMBOL: seen : class-elements ( vreg -- elts ) class-element-map get at ;
:: visit-renaming ( dst assoc src bb -- ) ! Sequence of vreg pairs
src seen get key? [ SYMBOL: copies
src dst bb add-waiting
src assoc delete-at
] [ src seen get conjoin ] if ;
:: break-interferences ( -- ) : init-coalescing ( -- )
V{ } clone seen set H{ } clone leader-map set
renaming-sets get [| dst assoc | H{ } clone class-element-map set
assoc [| src bb | V{ } clone copies set ;
dst assoc src bb visit-renaming
] assoc-each : classes-interfere? ( vreg1 vreg2 -- ? )
[ leader ] bi@ 2dup eq? [ 2drop f ] [
[ class-elements flatten ] bi@ sets-interfere?
] if ;
: update-leaders ( vreg1 vreg2 -- )
swap leader-map get set-at ;
: merge-classes ( vreg1 vreg2 -- )
[ [ class-elements ] bi@ push ]
[ drop class-element-map get delete-at ] 2bi ;
: eliminate-copy ( vreg1 vreg2 -- )
[ leader ] bi@
2dup eq? [ 2drop ] [
[ update-leaders ] [ merge-classes ] 2bi
] if ;
: introduce-vreg ( vreg -- )
[ leader-map get conjoin ]
[ [ 1vector ] keep class-element-map get set-at ] bi ;
GENERIC: prepare-insn ( insn -- )
M: ##copy prepare-insn
[ dst>> ] [ src>> ] bi 2array copies get push ;
M: ##phi prepare-insn
[ dst>> ] [ inputs>> values ] bi
[ eliminate-copy ] with each ;
M: insn prepare-insn drop ;
: prepare-block ( bb -- )
instructions>> [ prepare-insn ] each ;
: prepare-coalescing ( cfg -- )
init-coalescing
defs get keys [ introduce-vreg ] each
[ prepare-block ] each-basic-block ;
: process-copies ( -- )
copies get [
2dup classes-interfere?
[ 2drop ] [ eliminate-copy ] if
] assoc-each ; ] assoc-each ;
: remove-phis-from-block ( bb -- ) : useless-copy? ( ##copy -- ? )
instructions>> [ ##phi? not ] filter-here ; dup ##copy? [ [ dst>> ] [ src>> ] bi eq? ] [ drop f ] if ;
: remove-phis ( cfg -- ) : perform-renaming ( cfg -- )
[ [ remove-phis-from-block ] if-has-phis ] each-basic-block ; leader-map get keys [ dup leader ] H{ } map>assoc renamings set
[
instructions>> [
[ rename-insn-defs ]
[ rename-insn-uses ]
[ [ useless-copy? ] [ ##phi? ] bi or not ] tri
] filter-here
] each-basic-block ;
: destruct-ssa ( cfg -- cfg' ) : destruct-ssa ( cfg -- cfg' )
dup cfg-has-phis? [ dup construct-cssa
init-coalescing compute-ssa-live-sets
compute-ssa-live-sets dup compute-defs
dup split-critical-edges dup compute-dominance
dup compute-def-use dup compute-live-ranges
dup compute-dominance dup prepare-coalescing
dup compute-live-ranges process-copies
dup process-blocks dup perform-renaming ;
break-interferences
dup perform-renaming
insert-copies
dup remove-phis
] when ;

View File

@ -1,86 +0,0 @@
USING: accessors compiler.cfg compiler.cfg.ssa.destruction.forest
compiler.cfg.debugger compiler.cfg.dominance compiler.cfg.instructions
compiler.cfg.predecessors compiler.cfg.registers compiler.cfg.def-use
cpu.architecture kernel namespaces sequences tools.test vectors sorting
math.order ;
IN: compiler.cfg.ssa.destruction.forest.tests
V{ T{ ##peek f V int-regs 0 D 0 } } clone 0 test-bb
V{ T{ ##peek f V int-regs 1 D 0 } } clone 1 test-bb
V{ T{ ##peek f V int-regs 2 D 0 } } clone 2 test-bb
V{ T{ ##peek f V int-regs 3 D 0 } } clone 3 test-bb
V{ T{ ##peek f V int-regs 4 D 0 } } clone 4 test-bb
V{ T{ ##peek f V int-regs 5 D 0 } } clone 5 test-bb
V{ T{ ##peek f V int-regs 6 D 0 } } clone 6 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
2 get 3 get 4 get V{ } 2sequence >>successors drop
3 get 5 get 1vector >>successors drop
4 get 5 get 1vector >>successors drop
1 get 6 get 1vector >>successors drop
5 get 6 get 1vector >>successors drop
: clean-up-forest ( forest -- forest' )
[ [ vreg>> n>> ] compare ] sort
[
[ clean-up-forest ] change-children
[ number>> ] change-bb
] V{ } map-as ;
: test-dom-forest ( vregs -- forest )
cfg new 0 get >>entry
compute-predecessors
dup compute-dominance
compute-def-use
compute-dom-forest
clean-up-forest ;
[ V{ } ] [ { } test-dom-forest ] unit-test
[ V{ T{ dom-forest-node f V int-regs 0 0 V{ } } } ]
[ { V int-regs 0 } test-dom-forest ]
unit-test
[
V{
T{ dom-forest-node
f
V int-regs 0
0
V{ T{ dom-forest-node f V int-regs 1 1 V{ } } }
}
}
]
[ { V int-regs 0 V int-regs 1 } test-dom-forest ]
unit-test
[
V{
T{ dom-forest-node
f
V int-regs 1
1
V{ }
}
T{ dom-forest-node
f
V int-regs 2
2
V{
T{ dom-forest-node f V int-regs 3 3 V{ } }
T{ dom-forest-node f V int-regs 4 4 V{ } }
T{ dom-forest-node f V int-regs 5 5 V{ } }
}
}
T{ dom-forest-node
f
V int-regs 6
6
V{ }
}
}
]
[
{ V int-regs 1 V int-regs 6 V int-regs 2 V int-regs 3 V int-regs 4 V int-regs 5 }
test-dom-forest
] unit-test

View File

@ -1,38 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs fry kernel math math.order
namespaces sequences sorting vectors compiler.cfg.def-use
compiler.cfg.dominance compiler.cfg.registers ;
IN: compiler.cfg.ssa.destruction.forest
TUPLE: dom-forest-node vreg bb children ;
<PRIVATE
: sort-vregs-by-bb ( vregs -- alist )
defs get
'[ dup _ at ] { } map>assoc
[ [ second pre-of ] compare ] sort ;
: <dom-forest-node> ( vreg bb parent -- node )
[ V{ } clone dom-forest-node boa dup ] dip children>> push ;
: <virtual-root> ( -- node )
f f V{ } clone dom-forest-node boa ;
: find-parent ( pre stack -- parent )
2dup last vreg>> def-of maxpre-of > [
dup pop* find-parent
] [ nip last ] if ;
: (compute-dom-forest) ( vreg bb stack -- )
[ dup pre-of ] dip [ find-parent <dom-forest-node> ] keep push ;
PRIVATE>
: compute-dom-forest ( vregs -- forest )
<virtual-root> [
1vector
[ sort-vregs-by-bb ] dip
'[ _ (compute-dom-forest) ] assoc-each
] keep children>> ;

View File

@ -1,44 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs combinators combinators.short-circuit
kernel math namespaces sequences locals compiler.cfg.def-use
compiler.cfg.dominance compiler.cfg.ssa.destruction.live-ranges ;
IN: compiler.cfg.ssa.destruction.interference
<PRIVATE
: kill-after-def? ( vreg1 vreg2 bb -- ? )
! If first register is used after second one is defined, they interfere.
! If they are used in the same instruction, no interference. If the
! instruction is a def-is-use-insn, then there will be a use at +1
! (instructions are 2 apart) and so outputs will interfere with
! inputs.
[ kill-index ] [ def-index ] bi-curry bi* > ;
: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
! If both are defined in the same basic block, they interfere if their
! local live ranges intersect.
drop
{ [ kill-after-def? ] [ swapd kill-after-def? ] } 3|| ;
: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
! If vreg1 dominates vreg2, then they interfere if vreg2's definition
! occurs before vreg1 is killed.
nip
kill-after-def? ;
: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
! If vreg2 dominates vreg1, then they interfere if vreg1's definition
! occurs before vreg2 is killed.
drop
swapd kill-after-def? ;
PRIVATE>
: interferes? ( vreg1 vreg2 -- ? )
2dup [ def-of ] bi@ {
{ [ 2dup eq? ] [ interferes-same-block? ] }
{ [ 2dup dominates? ] [ interferes-first-dominates? ] }
{ [ 2dup swap dominates? ] [ interferes-second-dominates? ] }
[ 2drop 2drop f ]
} cond ;

View File

@ -1,138 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs fry kernel locals math math.order arrays
namespaces sequences sorting sets combinators combinators.short-circuit make
compiler.cfg.def-use
compiler.cfg.instructions
compiler.cfg.liveness.ssa
compiler.cfg.dominance
compiler.cfg.ssa.destruction.state
compiler.cfg.ssa.destruction.forest
compiler.cfg.ssa.destruction.interference ;
IN: compiler.cfg.ssa.destruction.process-blocks
! phi-union maps a vreg to the predecessor block
! that carries it to the phi node's block
! unioned-blocks is a set of bb's which defined
! the source vregs above
SYMBOLS: phi-union unioned-blocks ;
: operand-live-into-phi-node's-block? ( src dst -- ? )
def-of live-in? ;
: phi-node-is-live-out-of-operand's-block? ( src dst -- ? )
swap def-of live-out? ;
: operand-is-phi-node-and-live-into-operand's-block? ( src dst -- ? )
drop { [ insn-of ##phi? ] [ dup def-of live-in? ] } 1&& ;
: operand-being-renamed? ( src dst -- ? )
drop processed-names get key? ;
: two-operands-in-same-block? ( src dst -- ? )
drop def-of unioned-blocks get key? ;
: trivial-interference? ( src dst -- ? )
{
[ operand-live-into-phi-node's-block? ]
[ phi-node-is-live-out-of-operand's-block? ]
[ operand-is-phi-node-and-live-into-operand's-block? ]
[ operand-being-renamed? ]
[ two-operands-in-same-block? ]
} 2|| ;
: don't-coalesce ( bb src dst -- )
2nip processed-name ;
:: trivial-interference ( bb src dst -- )
dst src bb add-waiting
src used-by-another get push ;
:: add-to-renaming-set ( bb src dst -- )
bb src phi-union get set-at
src def-of unioned-blocks get conjoin ;
: process-phi-operand ( bb src dst -- )
{
{ [ 2dup eq? ] [ don't-coalesce ] }
{ [ 2dup trivial-interference? ] [ trivial-interference ] }
[ add-to-renaming-set ]
} cond ;
: node-is-live-in-of-child? ( node child -- ? )
[ vreg>> ] [ bb>> ] bi* live-in? ;
: node-is-live-out-of-child? ( node child -- ? )
[ vreg>> ] [ bb>> ] bi* live-out? ;
:: insert-copy ( bb src dst -- )
bb src dst trivial-interference
src phi-union get delete-at ;
:: insert-copy-for-parent ( bb src dst node -- )
src node vreg>> eq? [ bb src dst insert-copy ] when ;
: insert-copies-for-parent ( ##phi node child -- )
drop
[ [ inputs>> ] [ dst>> ] bi ] dip
'[ _ _ insert-copy-for-parent ] assoc-each ;
: defined-in-same-block? ( node child -- ? ) [ bb>> ] bi@ eq? ;
: add-interference ( ##phi node child -- )
[ vreg>> ] bi@ 2array , drop ;
: process-df-child ( ##phi node child -- )
{
{ [ 2dup node-is-live-out-of-child? ] [ insert-copies-for-parent ] }
{ [ 2dup node-is-live-in-of-child? ] [ add-interference ] }
{ [ 2dup defined-in-same-block? ] [ add-interference ] }
[ 3drop ]
} cond ;
: process-df-node ( ##phi node -- )
dup children>>
[ [ process-df-child ] with with each ]
[ nip [ process-df-node ] with each ]
3bi ;
: process-phi-union ( ##phi dom-forest -- )
[ process-df-node ] with each ;
: add-local-interferences ( ##phi -- )
[ phi-union get ] dip dst>> '[ drop _ 2array , ] assoc-each ;
: compute-local-interferences ( ##phi -- pairs )
[
[ phi-union get keys compute-dom-forest process-phi-union ]
[ add-local-interferences ]
bi
] { } make ;
:: insert-copies-for-interference ( ##phi src -- )
##phi inputs>> [| bb src' |
src src' eq? [ bb src ##phi dst>> insert-copy ] when
] assoc-each ;
: process-local-interferences ( ##phi pairs -- )
[
first2 2dup interferes?
[ drop insert-copies-for-interference ] [ 3drop ] if
] with each ;
: add-renaming-set ( ##phi -- )
[ phi-union get ] dip dst>> renaming-sets get set-at
phi-union get [ drop processed-name ] assoc-each ;
: process-phi ( ##phi -- )
H{ } clone phi-union set
H{ } clone unioned-blocks set
[ [ inputs>> ] [ dst>> ] bi '[ _ process-phi-operand ] assoc-each ]
[ dup compute-local-interferences process-local-interferences ]
[ add-renaming-set ]
tri ;
: process-block ( bb -- )
instructions>>
[ dup ##phi? [ process-phi t ] [ drop f ] if ] all? drop ;

View File

@ -1,47 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs fry kernel namespaces sequences
compiler.cfg.ssa.destruction.state compiler.cfg.renaming compiler.cfg.rpo
disjoint-sets ;
IN: compiler.cfg.ssa.destruction.renaming
: build-disjoint-set ( assoc -- disjoint-set )
<disjoint-set> dup [
'[
[ _ add-atom ]
[ [ drop _ add-atom ] assoc-each ]
bi*
] assoc-each
] keep ;
: update-congruence-class ( dst assoc disjoint-set -- )
[ keys swap ] dip equate-all-with ;
: build-congruence-classes ( -- disjoint-set )
renaming-sets get
dup build-disjoint-set
[ '[ _ update-congruence-class ] assoc-each ] keep ;
: compute-renaming ( disjoint-set -- assoc )
[ parents>> ] keep
'[ drop dup _ representative ] assoc-map ;
: rename-blocks ( cfg -- )
[
instructions>> [
[ rename-insn-defs ]
[ rename-insn-uses ] bi
] each
] each-basic-block ;
: rename-copies ( -- )
waiting renamings get '[
[
[ _ [ ?at drop ] [ '[ _ ?at drop ] map ] bi-curry bi* ] assoc-map
] assoc-map
] change ;
: perform-renaming ( cfg -- )
build-congruence-classes compute-renaming renamings set
rename-blocks
rename-copies ;

View File

@ -1,18 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces sets kernel assocs ;
IN: compiler.cfg.ssa.destruction.state
SYMBOLS: processed-names waiting used-by-another renaming-sets ;
: init-coalescing ( -- )
H{ } clone renaming-sets set
H{ } clone processed-names set
H{ } clone waiting set
V{ } clone used-by-another set ;
: processed-name ( vreg -- ) processed-names get conjoin ;
: waiting-for ( bb -- assoc ) waiting get [ drop H{ } clone ] cache ;
: add-waiting ( dst src bb -- ) waiting-for push-at ;

View File

@ -0,0 +1,52 @@
USING: accessors compiler.cfg compiler.cfg.debugger
compiler.cfg.def-use compiler.cfg.dominance
compiler.cfg.instructions compiler.cfg.liveness.ssa
compiler.cfg.registers compiler.cfg.predecessors
compiler.cfg.ssa.interference
compiler.cfg.ssa.interference.live-ranges cpu.architecture
kernel namespaces tools.test ;
IN: compiler.cfg.ssa.interference.tests
: test-interference ( -- )
cfg new 0 get >>entry
compute-ssa-live-sets
compute-predecessors
dup compute-defs
dup compute-dominance
compute-live-ranges ;
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 2 D 0 }
T{ ##copy f V int-regs 1 V int-regs 0 }
T{ ##copy f V int-regs 3 V int-regs 2 }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f V int-regs 4 D 0 }
T{ ##peek f V int-regs 5 D 0 }
T{ ##replace f V int-regs 3 D 0 }
T{ ##peek f V int-regs 6 D 0 }
T{ ##replace f V int-regs 5 D 0 }
T{ ##return }
} 1 test-bb
0 1 edge
[ ] [ test-interference ] unit-test
[ f ] [ V int-regs 0 V int-regs 1 vregs-interfere? ] unit-test
[ f ] [ V int-regs 1 V int-regs 0 vregs-interfere? ] unit-test
[ f ] [ V int-regs 2 V int-regs 3 vregs-interfere? ] unit-test
[ f ] [ V int-regs 3 V int-regs 2 vregs-interfere? ] unit-test
[ t ] [ V int-regs 0 V int-regs 2 vregs-interfere? ] unit-test
[ t ] [ V int-regs 2 V int-regs 0 vregs-interfere? ] unit-test
[ f ] [ V int-regs 1 V int-regs 3 vregs-interfere? ] unit-test
[ f ] [ V int-regs 3 V int-regs 1 vregs-interfere? ] unit-test
[ t ] [ V int-regs 3 V int-regs 4 vregs-interfere? ] unit-test
[ t ] [ V int-regs 4 V int-regs 3 vregs-interfere? ] unit-test
[ t ] [ V int-regs 3 V int-regs 5 vregs-interfere? ] unit-test
[ t ] [ V int-regs 5 V int-regs 3 vregs-interfere? ] unit-test
[ f ] [ V int-regs 3 V int-regs 6 vregs-interfere? ] unit-test
[ f ] [ V int-regs 6 V int-regs 3 vregs-interfere? ] unit-test

View File

@ -0,0 +1,86 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs combinators combinators.short-circuit fry
kernel math math.order sorting namespaces sequences locals
compiler.cfg.def-use compiler.cfg.dominance
compiler.cfg.ssa.interference.live-ranges ;
IN: compiler.cfg.ssa.interference
<PRIVATE
:: kill-after-def? ( vreg1 vreg2 bb -- ? )
! If first register is used after second one is defined, they interfere.
! If they are used in the same instruction, no interference. If the
! instruction is a def-is-use-insn, then there will be a use at +1
! (instructions are 2 apart) and so outputs will interfere with
! inputs.
vreg1 bb kill-index
vreg2 bb def-index > ;
:: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
! If both are defined in the same basic block, they interfere if their
! local live ranges intersect.
vreg1 bb1 def-index
vreg2 bb1 def-index <
[ vreg1 vreg2 ] [ vreg2 vreg1 ] if
bb1 kill-after-def? ;
: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
! If vreg1 dominates vreg2, then they interfere if vreg2's definition
! occurs before vreg1 is killed.
nip
kill-after-def? ;
: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
! If vreg2 dominates vreg1, then they interfere if vreg1's definition
! occurs before vreg2 is killed.
drop
swapd kill-after-def? ;
PRIVATE>
: vregs-interfere? ( vreg1 vreg2 -- ? )
2dup [ def-of ] bi@ {
{ [ 2dup eq? ] [ interferes-same-block? ] }
{ [ 2dup dominates? ] [ interferes-first-dominates? ] }
{ [ 2dup swap dominates? ] [ interferes-second-dominates? ] }
[ 2drop 2drop f ]
} cond ;
! Debug this stuff later
<PRIVATE
: quadratic-test? ( seq1 seq2 -- ? ) [ length ] bi@ + 10 < ;
: quadratic-test ( seq1 seq2 -- ? )
'[ _ [ vregs-interfere? ] with any? ] any? ;
: sort-vregs-by-bb ( vregs -- alist )
defs get
'[ dup _ at ] { } map>assoc
[ [ second pre-of ] compare ] sort ;
: ?last ( seq -- elt/f ) [ f ] [ last ] if-empty ; inline
: find-parent ( dom current -- parent )
over empty? [ 2drop f ] [
over last over dominates? [ drop last ] [
over pop* find-parent
] if
] if ;
:: linear-test ( seq1 seq2 -- ? )
! Instead of sorting, SSA destruction should keep equivalence
! classes sorted by merging them on append
V{ } clone :> dom
seq1 seq2 append sort-vregs-by-bb [| pair |
pair first :> current
dom current find-parent
dup [ current vregs-interfere? ] when
[ t ] [ current dom push f ] if
] any? ;
PRIVATE>
: sets-interfere? ( seq1 seq2 -- ? )
quadratic-test ;

View File

@ -3,7 +3,7 @@
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.ssa compiler.cfg.rpo ;
IN: compiler.cfg.ssa.destruction.live-ranges IN: compiler.cfg.ssa.interference.live-ranges
! Live ranges for interference testing ! Live ranges for interference testing

View File

@ -31,7 +31,7 @@ V{
T{ ##replace f V int-regs 3 D 0 } T{ ##replace f V int-regs 3 D 0 }
} 3 test-bb } 3 test-bb
1 get 2 get 3 get V{ } 2sequence >>successors drop 1 { 2 3 } edges
cfg new 1 get >>entry 4 set cfg new 1 get >>entry 4 set
@ -132,35 +132,35 @@ cfg new 1 get >>entry 5 set
! This is the CFG in Figure 3 from the paper ! This is the CFG in Figure 3 from the paper
V{ } 1 test-bb V{ } 1 test-bb
V{ } 2 test-bb V{ } 2 test-bb
1 get 2 get 1vector >>successors drop 1 2 edge
V{ V{
T{ ##peek f V int-regs 0 D 0 } T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 1 D 0 } T{ ##peek f V int-regs 1 D 0 }
T{ ##peek f V int-regs 2 D 0 } T{ ##peek f V int-regs 2 D 0 }
} 3 test-bb } 3 test-bb
V{ } 11 test-bb V{ } 11 test-bb
2 get 3 get 11 get V{ } 2sequence >>successors drop 2 { 3 11 } edges
V{ V{
T{ ##replace f V int-regs 0 D 0 } T{ ##replace f V int-regs 0 D 0 }
} 4 test-bb } 4 test-bb
V{ } 8 test-bb V{ } 8 test-bb
3 get 8 get 4 get V{ } 2sequence >>successors drop 3 { 8 4 } edges
V{ V{
T{ ##replace f V int-regs 1 D 0 } T{ ##replace f V int-regs 1 D 0 }
} 9 test-bb } 9 test-bb
8 get 9 get 1vector >>successors drop 8 9 edge
V{ V{
T{ ##replace f V int-regs 2 D 0 } T{ ##replace f V int-regs 2 D 0 }
} 5 test-bb } 5 test-bb
4 get 5 get 1vector >>successors drop 4 5 edge
V{ } 10 test-bb V{ } 10 test-bb
V{ } 6 test-bb V{ } 6 test-bb
5 get 6 get 1vector >>successors drop 5 6 edge
9 get 6 get 10 get V{ } 2sequence >>successors drop 9 { 6 10 } edges
V{ } 7 test-bb V{ } 7 test-bb
6 get 5 get 7 get V{ } 2sequence >>successors drop 6 { 5 7 } edges
10 get 8 get 1vector >>successors drop 10 8 edge
7 get 2 get 1vector >>successors drop 7 2 edge
cfg new 1 get >>entry 0 set cfg new 1 get >>entry 0 set
[ ] [ 0 get compute-predecessors drop ] unit-test [ ] [ 0 get compute-predecessors drop ] unit-test

View File

@ -30,8 +30,12 @@ ERROR: bad-peek dst loc ;
[ dup n>> 0 < [ 2drop ] [ ##replace ] if ] each-insertion ; [ dup n>> 0 < [ 2drop ] [ ##replace ] if ] each-insertion ;
: visit-edge ( from to -- ) : visit-edge ( from to -- )
2dup [ [ insert-peeks ] [ insert-replaces ] 2bi ] V{ } make ! If both blocks are subroutine calls, don't bother
[ 2drop ] [ <simple-block> insert-basic-block ] if-empty ; ! computing anything.
2dup [ kill-block? ] both? [ 2drop ] [
2dup [ [ insert-peeks ] [ insert-replaces ] 2bi ] V{ } make
[ 2drop ] [ <simple-block> insert-basic-block ] if-empty
] if ;
: visit-block ( bb -- ) : visit-block ( bb -- )
[ predecessors>> ] keep '[ _ visit-edge ] each ; [ predecessors>> ] keep '[ _ visit-edge ] each ;

View File

@ -25,8 +25,8 @@ V{
T{ ##inc-d f 1 } T{ ##inc-d f 1 }
} 2 test-bb } 2 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 1vector >>successors drop 1 2 edge
[ ] [ test-uninitialized ] unit-test [ ] [ test-uninitialized ] unit-test
@ -52,9 +52,9 @@ V{
T{ ##return } T{ ##return }
} 3 test-bb } 3 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop 0 { 1 2 } edges
1 get 3 get 1vector >>successors drop 1 3 edge
2 get 3 get 1vector >>successors drop 2 3 edge
[ ] [ test-uninitialized ] unit-test [ ] [ test-uninitialized ] unit-test

View File

@ -27,19 +27,12 @@ compiler.cfg.registers cpu.architecture namespaces tools.test ;
[ [
V{ V{
T{ ##copy f V int-regs 4 V int-regs 2 } T{ ##copy f V int-regs 4 V int-regs 1 }
T{ ##sub f V int-regs 4 V int-regs 4 V int-regs 1 } T{ ##copy f V int-regs 1 V int-regs 2 }
T{ ##copy f V int-regs 1 V int-regs 4 } T{ ##sub f V int-regs 1 V int-regs 1 V int-regs 4 }
} }
] [ ] [
{ {
T{ ##sub f V int-regs 1 V int-regs 2 V int-regs 1 } T{ ##sub f V int-regs 1 V int-regs 2 V int-regs 1 }
} (convert-two-operand) } (convert-two-operand)
] unit-test ] unit-test
! This should never come up after coalescing
[
V{
T{ ##fixnum-add f V int-regs 2 V int-regs 4 V int-regs 2 }
} (convert-two-operand)
] must-fail

View File

@ -65,15 +65,11 @@ GENERIC: convert-two-operand* ( insn -- )
: case-2? ( insn -- ? ) [ dst>> ] [ src2>> ] bi = ; inline : case-2? ( insn -- ? ) [ dst>> ] [ src2>> ] bi = ; inline
ERROR: bad-case-2 insn ;
: case-2 ( insn -- ) : case-2 ( insn -- )
! This can't work with a ##fixnum-overflow since it branches
dup ##fixnum-overflow? [ bad-case-2 ] when
dup dst>> reg-class>> next-vreg dup dst>> reg-class>> next-vreg
[ swap src1>> emit-copy ] [ swap src2>> emit-copy ]
[ [ >>src1 ] [ >>dst ] bi , ] [ drop [ src2>> ] [ src1>> ] bi emit-copy ]
[ [ src2>> ] dip emit-copy ] [ >>src2 dup dst>> >>src1 , ]
2tri ; inline 2tri ; inline
: case-3 ( insn -- ) : case-3 ( insn -- )
@ -97,8 +93,10 @@ M: ##not convert-two-operand*
M: insn convert-two-operand* , ; M: insn convert-two-operand* , ;
: (convert-two-operand) ( cfg -- cfg' ) : (convert-two-operand) ( insns -- insns' )
[ [ convert-two-operand* ] each ] V{ } make ; dup first kill-vreg-insn? [
[ [ convert-two-operand* ] each ] V{ } make
] unless ;
: convert-two-operand ( cfg -- cfg' ) : convert-two-operand ( cfg -- cfg' )
two-operand? [ [ (convert-two-operand) ] local-optimization ] when ; two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;

View File

@ -43,6 +43,13 @@ SYMBOL: visited
to predecessors>> [ dup from eq? [ drop bb ] when ] change-each to predecessors>> [ dup from eq? [ drop bb ] when ] change-each
from successors>> [ dup to eq? [ drop bb ] when ] change-each ; from successors>> [ dup to eq? [ drop bb ] when ] change-each ;
: add-instructions ( bb quot -- )
[ instructions>> building ] dip '[
building get pop
@
,
] with-variable ; inline
: <simple-block> ( insns -- bb ) : <simple-block> ( insns -- bb )
<basic-block> <basic-block>
swap >vector swap >vector
@ -58,6 +65,10 @@ SYMBOL: visited
: if-has-phis ( bb quot: ( bb -- ) -- ) : if-has-phis ( bb quot: ( bb -- ) -- )
[ dup has-phis? ] dip [ drop ] if ; inline [ dup has-phis? ] dip [ drop ] if ; inline
: each-phi ( bb quot: ( ##phi -- ) -- )
[ instructions>> ] dip
'[ dup ##phi? [ @ t ] [ drop f ] if ] all? drop ; inline
: predecessor ( bb -- pred ) : predecessor ( bb -- pred )
predecessors>> first ; inline predecessors>> first ; inline

View File

@ -1175,16 +1175,11 @@ V{
} 3 test-bb } 3 test-bb
V{ V{
T{ ##phi f V int-regs 3 { } } 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 } T{ ##replace f V int-regs 3 D 0 }
T{ ##return } T{ ##return }
} 4 test-bb } 4 test-bb
4 get instructions>> first
2 get V int-regs 1 2array
3 get V int-regs 2 2array 2array
>>inputs drop
test-diamond test-diamond
[ ] [ [ ] [
@ -1296,10 +1291,10 @@ V{
T{ ##return } T{ ##return }
} 5 test-bb } 5 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 4 get V{ } 2sequence >>successors drop 1 { 2 4 } edges
2 get 3 get 1vector >>successors drop 2 3 edge
4 get 5 get 1vector >>successors drop 4 5 edge
[ ] [ [ ] [
cfg new 0 get >>entry cfg new 0 get >>entry

View File

@ -2,7 +2,8 @@ USING: generalizations accessors arrays compiler kernel kernel.private
math hashtables.private math.private namespaces sequences tools.test math hashtables.private math.private namespaces sequences tools.test
namespaces.private slots.private sequences.private byte-arrays alien namespaces.private slots.private sequences.private byte-arrays alien
alien.accessors layouts words definitions compiler.units io alien.accessors layouts words definitions compiler.units io
combinators vectors grouping make alien.c-types combinators.short-circuit ; combinators vectors grouping make alien.c-types combinators.short-circuit
math.order ;
QUALIFIED: namespaces.private QUALIFIED: namespaces.private
IN: compiler.tests.codegen IN: compiler.tests.codegen
@ -366,4 +367,29 @@ cell 4 = [
fixnum+fast 2 fixnum*fast 2 fixnum-fast 2 fixnum*fast 2 fixnum+fast ; fixnum+fast 2 fixnum*fast 2 fixnum-fast 2 fixnum*fast 2 fixnum+fast ;
[ 10 ] [ 1 coalescing-bug-2 ] unit-test [ 10 ] [ 1 coalescing-bug-2 ] unit-test
[ 86 ] [ 11 coalescing-bug-2 ] unit-test [ 86 ] [ 11 coalescing-bug-2 ] unit-test
! Regression in suffix-arrays code
: coalescing-bug-3 ( from/f to/f seq -- slice )
[
[ drop 0 or ] [ length or ] bi-curry bi*
[ min ] keep
] keep <slice> ;
[ T{ slice f 0 5 "hello" } ] [ f f "hello" coalescing-bug-3 ] unit-test
[ T{ slice f 1 5 "hello" } ] [ 1 f "hello" coalescing-bug-3 ] unit-test
[ T{ slice f 0 3 "hello" } ] [ f 3 "hello" coalescing-bug-3 ] unit-test
[ T{ slice f 1 3 "hello" } ] [ 1 3 "hello" coalescing-bug-3 ] unit-test
[ T{ slice f 3 3 "hello" } ] [ 4 3 "hello" coalescing-bug-3 ] unit-test
[ T{ slice f 5 5 "hello" } ] [ 6 f "hello" coalescing-bug-3 ] unit-test
! Reduction
: coalescing-bug-4 ( a b c -- a b c )
[ [ min ] keep ] dip vector? [ 1 ] [ 2 ] if ;
[ 2 3 2 ] [ 2 3 "" coalescing-bug-4 ] unit-test
[ 3 3 2 ] [ 4 3 "" coalescing-bug-4 ] unit-test
[ 3 3 2 ] [ 4 3 "" coalescing-bug-4 ] unit-test
[ 2 3 1 ] [ 2 3 V{ } coalescing-bug-4 ] unit-test
[ 3 3 1 ] [ 4 3 V{ } coalescing-bug-4 ] unit-test
[ 3 3 1 ] [ 4 3 V{ } coalescing-bug-4 ] unit-test

View File

@ -27,8 +27,8 @@ IN: compiler.tests.low-level-ir
T{ ##epilogue } T{ ##epilogue }
T{ ##return } T{ ##return }
} [ clone ] map 2 test-bb } [ clone ] map 2 test-bb
0 get 1 get 1vector >>successors drop 0 1 edge
1 get 2 get 1vector >>successors drop 1 2 edge
compile-test-cfg compile-test-cfg
execute( -- result ) ; execute( -- result ) ;

View File

@ -5,7 +5,8 @@ combinators sets locals columns grouping
stack-checker.branches stack-checker.branches
compiler.tree compiler.tree
compiler.tree.def-use compiler.tree.def-use
compiler.tree.combinators ; compiler.tree.combinators
compiler.utilities ;
IN: compiler.tree.propagation.copy IN: compiler.tree.propagation.copy
! Two values are copy-equivalent if they are always identical ! Two values are copy-equivalent if they are always identical
@ -15,18 +16,6 @@ IN: compiler.tree.propagation.copy
! Mapping from values to their canonical leader ! Mapping from values to their canonical leader
SYMBOL: copies SYMBOL: copies
:: compress-path ( source assoc -- destination )
[let | destination [ source assoc at ] |
source destination = [ source ] [
[let | destination' [ destination assoc compress-path ] |
destination' destination = [
destination' source assoc set-at
] unless
destination'
]
] if
] ;
: resolve-copy ( copy -- val ) copies get compress-path ; : resolve-copy ( copy -- val ) copies get compress-path ;
: is-copy-of ( val copy -- ) copies get set-at ; : is-copy-of ( val copy -- ) copies get set-at ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences sequences.private arrays vectors fry USING: kernel sequences sequences.private arrays vectors fry
math math.order namespaces assocs ; math math.order namespaces assocs locals ;
IN: compiler.utilities IN: compiler.utilities
: flattener ( seq quot -- seq vector quot' ) : flattener ( seq quot -- seq vector quot' )
@ -30,3 +30,15 @@ yield-hook [ [ ] ] initialize
[ ] [ [ [ second ] bi@ > ] most ] map-reduce ; [ ] [ [ [ second ] bi@ > ] most ] map-reduce ;
: penultimate ( seq -- elt ) [ length 2 - ] keep nth ; : penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
:: compress-path ( source assoc -- destination )
[let | destination [ source assoc at ] |
source destination = [ source ] [
[let | destination' [ destination assoc compress-path ] |
destination' destination = [
destination' source assoc set-at
] unless
destination'
]
] if
] ;

View File

@ -354,6 +354,22 @@ HELP: spread
{ bi* tri* spread } related-words { bi* tri* spread } related-words
HELP: to-fixed-point
{ $values { "object" object } { "quot" { $quotation "( object(n) -- object(n+1) )" } } { "object(n)" object } }
{ $description "Applies the quotation repeatedly with " { $snippet "object" } " as the initial input until the output of the quotation equals the input." }
{ $examples
{ $example
"USING: combinators kernel math prettyprint sequences ;"
"IN: scratchpad"
": flatten ( sequence -- sequence' )"
" \"flatten\" over index"
" [ [ 1 + swap nth ] [ nip dup 2 + ] [ drop ] 2tri replace-slice ] when* ;"
""
"{ \"flatten\" { 1 { 2 3 } \"flatten\" { 4 5 } { 6 } } } [ flatten ] to-fixed-point ."
"{ 1 { 2 3 } 4 5 { 6 } }"
}
} ;
HELP: alist>quot HELP: alist>quot
{ $values { "default" "a quotation" } { "assoc" "a sequence of quotation pairs" } { "quot" "a new quotation" } } { $values { "default" "a quotation" } { "assoc" "a sequence of quotation pairs" } { "quot" "a new quotation" } }
{ $description "Constructs a quotation which calls the first quotation in each pair of " { $snippet "assoc" } " until one of them outputs a true value, and then calls the second quotation in the corresponding pair. Quotations are called in reverse order, and if no quotation outputs a true value then " { $snippet "default" } " is called." } { $description "Constructs a quotation which calls the first quotation in each pair of " { $snippet "assoc" } " until one of them outputs a true value, and then calls the second quotation in the corresponding pair. Quotations are called in reverse order, and if no quotation outputs a true value then " { $snippet "default" } " is called." }

View File

@ -180,3 +180,6 @@ M: hashtable hashcode*
dup assoc-size 1 eq? dup assoc-size 1 eq?
[ assoc-hashcode ] [ nip assoc-size ] if [ assoc-hashcode ] [ nip assoc-size ] if
] recursive-hashcode ; ] recursive-hashcode ;
: to-fixed-point ( object quot: ( object(n) -- object(n+1) ) -- object(n) )
[ keep over = ] keep [ to-fixed-point ] curry unless ; inline recursive

View File

@ -8,7 +8,7 @@ SYMBOL: building
: make ( quot exemplar -- seq ) : make ( quot exemplar -- seq )
[ [
[ [
1024 swap new-resizable [ 100 swap new-resizable [
building set call building set call
] keep ] keep
] keep like ] keep like