From 949b527ed58167bf6d667108ecb00cd678603f44 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 10 Jul 2009 07:52:20 -0500 Subject: [PATCH 1/5] Help lint fixes for urls.encoding and mongodb.driver --- basis/urls/encoding/encoding-docs.factor | 2 +- extra/mongodb/driver/driver-docs.factor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basis/urls/encoding/encoding-docs.factor b/basis/urls/encoding/encoding-docs.factor index 82ab3d1f69..a021bd6d23 100644 --- a/basis/urls/encoding/encoding-docs.factor +++ b/basis/urls/encoding/encoding-docs.factor @@ -26,7 +26,7 @@ HELP: assoc>query "USING: io urls.encoding ;" "{ { \"from\" \"Lead\" } { \"to\" \"Gold, please\" } }" "assoc>query print" - "from=Lead&to=Gold%2c%20please" + "from=Lead&to=Gold%2C%20please" } } ; diff --git a/extra/mongodb/driver/driver-docs.factor b/extra/mongodb/driver/driver-docs.factor index e8f726374c..532dfe1dce 100644 --- a/extra/mongodb/driver/driver-docs.factor +++ b/extra/mongodb/driver/driver-docs.factor @@ -76,7 +76,7 @@ HELP: count HELP: create-collection { $values - { "name" "collection name" } + { "name/collection" "collection name" } } { $description "Creates a new collection with the given name." } ; From 608fb054f26bc006037d8cb4dd2762136b8ab26b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 12 Jul 2009 22:22:46 -0500 Subject: [PATCH 2/5] compiler.cfg: Some code cleanups, update stack-analysis and phi-insertion to work on CFGs with critical edges --- .../branch-folding-tests.factor | 5 +- .../cfg/branch-folding/branch-folding.factor | 4 +- basis/compiler/cfg/cfg.factor | 36 +--------- .../cfg/optimizer/optimizer-tests.factor | 11 +++- .../phi-elimination-tests.factor | 10 ++- .../phi-elimination/phi-elimination.factor | 13 ++-- .../stack-analysis/merge/merge-tests.factor | 47 ++++++++----- .../cfg/stack-analysis/merge/merge.factor | 66 +++++++++++-------- .../stack-analysis-tests.factor | 12 ++-- .../cfg/stack-analysis/stack-analysis.factor | 22 ++++++- basis/compiler/cfg/tco/tco.factor | 5 +- .../useless-conditionals.factor | 5 +- basis/compiler/cfg/utilities/utilities.factor | 58 ++++++++++++++-- 13 files changed, 185 insertions(+), 109 deletions(-) diff --git a/basis/compiler/cfg/branch-folding/branch-folding-tests.factor b/basis/compiler/cfg/branch-folding/branch-folding-tests.factor index 964620d2d3..8ae1f6b75b 100644 --- a/basis/compiler/cfg/branch-folding/branch-folding-tests.factor +++ b/basis/compiler/cfg/branch-folding/branch-folding-tests.factor @@ -40,7 +40,10 @@ test-diamond [ 1 ] [ 1 get successors>> length ] unit-test [ t ] [ 1 get successors>> first 3 get eq? ] unit-test -[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test +[ T{ ##copy f V int-regs 3 V int-regs 2 } ] +[ 3 get successors>> first instructions>> first ] +unit-test + [ 2 ] [ 4 get instructions>> length ] unit-test V{ diff --git a/basis/compiler/cfg/branch-folding/branch-folding.factor b/basis/compiler/cfg/branch-folding/branch-folding.factor index 627db63c9f..2432849a9a 100644 --- a/basis/compiler/cfg/branch-folding/branch-folding.factor +++ b/basis/compiler/cfg/branch-folding/branch-folding.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors combinators.short-circuit kernel sequences vectors -compiler.cfg.instructions compiler.cfg.rpo ; +compiler.cfg.instructions compiler.cfg.rpo compiler.cfg ; IN: compiler.cfg.branch-folding ! Fold comparisons where both inputs are the same. Predecessors must be @@ -27,4 +27,4 @@ IN: compiler.cfg.branch-folding dup fold-branch? [ fold-branch ] [ drop ] if ] each-basic-block - f >>post-order ; \ No newline at end of file + cfg-changed ; \ No newline at end of file diff --git a/basis/compiler/cfg/cfg.factor b/basis/compiler/cfg/cfg.factor index 12a1180d40..f856efac78 100644 --- a/basis/compiler/cfg/cfg.factor +++ b/basis/compiler/cfg/cfg.factor @@ -1,9 +1,6 @@ ! Copyright (C) 2008, 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel arrays vectors accessors assocs sets -namespaces math make fry sequences -combinators.short-circuit -compiler.cfg.instructions ; +USING: kernel math vectors arrays accessors namespaces ; IN: compiler.cfg TUPLE: basic-block < identity-tuple @@ -22,39 +19,12 @@ M: basic-block hashcode* nip id>> ; V{ } clone >>predecessors \ basic-block counter >>id ; -: empty-block? ( bb -- ? ) - instructions>> { - [ length 1 = ] - [ first ##branch? ] - } 1&& ; - -SYMBOL: visited - -: (skip-empty-blocks) ( bb -- bb' ) - dup visited get key? [ - dup empty-block? [ - dup visited get conjoin - successors>> first (skip-empty-blocks) - ] when - ] unless ; - -: skip-empty-blocks ( bb -- bb' ) - H{ } clone visited [ (skip-empty-blocks) ] with-variable ; - -: add-instructions ( bb quot -- ) - [ instructions>> building ] dip '[ - building get pop - _ dip - building get push - ] with-variable ; inline - -: back-edge? ( from to -- ? ) - [ number>> ] bi@ > ; - TUPLE: cfg { entry basic-block } word label spill-counts post-order ; : ( entry word label -- cfg ) f f cfg boa ; +: cfg-changed ( cfg -- cfg ) f >>post-order ; inline + TUPLE: mr { instructions array } word label ; : ( instructions word label -- mr ) diff --git a/basis/compiler/cfg/optimizer/optimizer-tests.factor b/basis/compiler/cfg/optimizer/optimizer-tests.factor index 93adc4c0f9..f585d80d72 100755 --- a/basis/compiler/cfg/optimizer/optimizer-tests.factor +++ b/basis/compiler/cfg/optimizer/optimizer-tests.factor @@ -1,7 +1,7 @@ USING: accessors arrays compiler.cfg.checker compiler.cfg.debugger compiler.cfg.def-use compiler.cfg.instructions fry kernel kernel.private math -math.private sbufs sequences sequences.private sets +math.partial-dispatch math.private sbufs sequences sequences.private sets slots.private strings tools.test vectors layouts ; IN: compiler.cfg.optimizer.tests @@ -31,6 +31,15 @@ IN: compiler.cfg.optimizer.tests [ [ 2 fixnum+ ] when 3 ] [ [ 2 fixnum- ] when 3 ] [ 10000 [ ] times ] + [ + over integer? [ + over dup 16 <-integer-fixnum + [ 0 >=-integer-fixnum ] [ drop f ] if [ + nip dup + [ ] [ ] if + ] [ 2drop f ] if + ] [ 2drop f ] if + ] } [ [ [ ] ] dip '[ _ test-mr first check-mr ] unit-test ] each diff --git a/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor b/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor index 4577e70997..2dd75df693 100644 --- a/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor +++ b/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor @@ -35,6 +35,12 @@ test-diamond [ ] [ cfg new 0 get >>entry eliminate-phis drop ] unit-test -[ T{ ##copy f V int-regs 3 V int-regs 1 } ] [ 2 get instructions>> second ] unit-test -[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test +[ T{ ##copy f V int-regs 3 V int-regs 1 } ] +[ 2 get successors>> first instructions>> first ] +unit-test + +[ T{ ##copy f V int-regs 3 V int-regs 2 } ] +[ 3 get successors>> first instructions>> first ] +unit-test + [ 2 ] [ 4 get instructions>> length ] unit-test \ No newline at end of file diff --git a/basis/compiler/cfg/phi-elimination/phi-elimination.factor b/basis/compiler/cfg/phi-elimination/phi-elimination.factor index 9c2f0adafd..7e184a9b53 100644 --- a/basis/compiler/cfg/phi-elimination/phi-elimination.factor +++ b/basis/compiler/cfg/phi-elimination/phi-elimination.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors assocs fry kernel sequences -compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ; +USING: accessors assocs fry kernel sequences namespaces +compiler.cfg compiler.cfg.instructions compiler.cfg.rpo +compiler.cfg.utilities ; IN: compiler.cfg.phi-elimination : insert-copy ( predecessor input output -- ) @@ -11,7 +12,11 @@ IN: compiler.cfg.phi-elimination [ inputs>> ] [ dst>> ] bi '[ _ insert-copy ] assoc-each ; : eliminate-phi-step ( bb -- ) - instructions>> [ dup ##phi? [ eliminate-phi f ] [ drop t ] if ] filter-here ; + H{ } clone added-instructions set + [ instructions>> [ dup ##phi? [ eliminate-phi f ] [ drop t ] if ] filter-here ] + [ insert-basic-blocks ] + bi ; : eliminate-phis ( cfg -- cfg' ) - dup [ eliminate-phi-step ] each-basic-block ; \ No newline at end of file + dup [ eliminate-phi-step ] each-basic-block + cfg-changed ; \ No newline at end of file diff --git a/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor b/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor index 14a81958a9..e67f6b5143 100644 --- a/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor +++ b/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor @@ -2,7 +2,7 @@ IN: compiler.cfg.stack-analysis.merge.tests USING: compiler.cfg.stack-analysis.merge tools.test arrays accessors compiler.cfg.instructions compiler.cfg.stack-analysis.state compiler.cfg compiler.cfg.registers compiler.cfg.debugger -cpu.architecture make assocs +cpu.architecture make assocs namespaces sequences kernel classes ; [ @@ -11,13 +11,15 @@ sequences kernel classes ; ] [ - V{ T{ ##branch } } >>instructions - V{ T{ ##branch } } >>instructions 2array + V{ T{ ##branch } } >>instructions dup 1 set + V{ T{ ##branch } } >>instructions dup 2 set 2array H{ { D 0 V int-regs 0 } } >>locs>vregs H{ { D 0 V int-regs 1 } } >>locs>vregs 2array - [ merge-locs locs>vregs>> keys ] { } make first inputs>> values + H{ } clone added-instructions set + V{ } clone added-phis set + merge-locs locs>vregs>> keys added-phis get values first ] unit-test [ @@ -26,15 +28,16 @@ sequences kernel classes ; ] [ - V{ T{ ##branch } } >>instructions - V{ T{ ##branch } } >>instructions 2array + V{ T{ ##branch } } >>instructions dup 1 set + V{ T{ ##branch } } >>instructions dup 2 set 2array - [ - - H{ { D 0 V int-regs 1 } } >>locs>vregs 2array + + H{ { D 0 V int-regs 1 } } >>locs>vregs 2array - [ merge-locs locs>vregs>> keys ] { } make drop - ] keep first instructions>> first class + H{ } clone added-instructions set + V{ } clone added-phis set + [ merge-locs locs>vregs>> keys ] { } make drop + 1 get added-instructions get at first class ] unit-test [ @@ -42,15 +45,17 @@ sequences kernel classes ; ] [ - V{ T{ ##branch } } >>instructions - V{ T{ ##branch } } >>instructions 2array + V{ T{ ##branch } } >>instructions dup 1 set + V{ T{ ##branch } } >>instructions dup 2 set 2array - [ - -1 >>ds-height - 2array + H{ } clone added-instructions set + V{ } clone added-phis set - [ merge-ds-heights ds-height>> ] { } make drop - ] keep first instructions>> first class + -1 >>ds-height + 2array + + [ merge-ds-heights ds-height>> ] { } make drop + 1 get added-instructions get at first class ] unit-test [ @@ -63,6 +68,9 @@ sequences kernel classes ; V{ T{ ##branch } } >>instructions V{ T{ ##branch } } >>instructions 2array + H{ } clone added-instructions set + V{ } clone added-phis set + [ -1 >>ds-height H{ { D 1 V int-regs 0 } } >>locs>vregs H{ { D 0 V int-regs 1 } } >>locs>vregs 2array @@ -82,6 +90,9 @@ sequences kernel classes ; V{ T{ ##branch } } >>instructions V{ T{ ##branch } } >>instructions 2array + H{ } clone added-instructions set + V{ } clone added-phis set + [ -1 >>ds-height H{ { D -1 V int-regs 0 } } >>locs>vregs -1 >>ds-height H{ { D -1 V int-regs 1 } } >>locs>vregs 2array diff --git a/basis/compiler/cfg/stack-analysis/merge/merge.factor b/basis/compiler/cfg/stack-analysis/merge/merge.factor index b6c443a2d3..cb0ad7d615 100644 --- a/basis/compiler/cfg/stack-analysis/merge/merge.factor +++ b/basis/compiler/cfg/stack-analysis/merge/merge.factor @@ -1,12 +1,11 @@ ! Copyright (C) 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel assocs sequences accessors fry combinators grouping -sets locals compiler.cfg compiler.cfg.hats compiler.cfg.instructions -compiler.cfg.stack-analysis.state ; +USING: kernel assocs sequences accessors fry combinators grouping sets +arrays vectors locals namespaces make compiler.cfg compiler.cfg.hats +compiler.cfg.instructions compiler.cfg.stack-analysis.state +compiler.cfg.registers compiler.cfg.utilities cpu.architecture ; IN: compiler.cfg.stack-analysis.merge -! XXX critical edges - : initial-state ( bb states -- state ) 2drop ; : single-predecessor ( bb states -- state ) nip first clone ; @@ -27,14 +26,14 @@ IN: compiler.cfg.stack-analysis.merge [ nip first >>rs-height ] [ [ '[ _ save-rs-height ] add-instructions ] 2each ] if ; -: assoc-map-values ( assoc quot -- assoc' ) +: assoc-map-keys ( assoc quot -- assoc' ) '[ _ dip ] assoc-map ; inline : translate-locs ( assoc state -- assoc' ) - '[ _ translate-loc ] assoc-map-values ; + '[ _ translate-loc ] assoc-map-keys ; : untranslate-locs ( assoc state -- assoc' ) - '[ _ untranslate-loc ] assoc-map-values ; + '[ _ untranslate-loc ] assoc-map-keys ; : collect-locs ( loc-maps states -- assoc ) ! assoc maps locs to sequences @@ -45,12 +44,16 @@ IN: compiler.cfg.stack-analysis.merge : insert-peek ( predecessor loc state -- vreg ) '[ _ _ translate-loc ^^peek ] add-instructions ; +SYMBOL: added-phis + +: add-phi-later ( inputs -- vreg ) + [ int-regs next-vreg dup ] dip 2array added-phis get push ; + : merge-loc ( predecessors vregs loc state -- vreg ) ! Insert a ##phi in the current block where the input ! is the vreg storing loc from each predecessor block - [ dup ] 3dip '[ [ ] [ _ _ insert-peek ] ?if ] 2map - dup all-equal? [ nip first ] [ zip ^^phi ] if ; + dup all-equal? [ first ] [ add-phi-later ] if ; :: merge-locs ( state predecessors states -- state ) states [ locs>vregs>> ] map states collect-locs @@ -77,30 +80,35 @@ IN: compiler.cfg.stack-analysis.merge over translate-locs >>changed-locs ; -ERROR: cannot-merge-poisoned states ; +:: insert-phis ( bb -- ) + bb predecessors>> :> predecessors + [ + added-phis get [| dst inputs | + dst predecessors inputs zip ##phi + ] assoc-each + ] V{ } make bb instructions>> over push-all + bb (>>instructions) ; -: multiple-predecessors ( bb states -- state ) - dup [ not ] any? [ - 2drop +:: multiple-predecessors ( bb states -- state ) + states [ not ] any? [ + ] [ - dup [ poisoned?>> ] any? [ - cannot-merge-poisoned - ] [ - [ state new ] 2dip - [ predecessors>> ] dip - { - [ merge-ds-heights ] - [ merge-rs-heights ] - [ merge-locs ] - [ nip merge-actual-locs ] - [ nip merge-changed-locs ] - } 2cleave - ] if + [ + H{ } clone added-instructions set + V{ } clone added-phis set + bb predecessors>> :> predecessors + state new + predecessors states merge-ds-heights + predecessors states merge-rs-heights + predecessors states merge-locs + states merge-actual-locs + states merge-changed-locs + bb insert-basic-blocks + bb insert-phis + ] with-scope ] if ; : merge-states ( bb states -- state ) - ! If any states are poisoned, save all registers - ! to the stack in each branch dup length { { 0 [ initial-state ] } { 1 [ single-predecessor ] } diff --git a/basis/compiler/cfg/stack-analysis/stack-analysis-tests.factor b/basis/compiler/cfg/stack-analysis/stack-analysis-tests.factor index cbc939b1f2..23b1098cd6 100644 --- a/basis/compiler/cfg/stack-analysis/stack-analysis-tests.factor +++ b/basis/compiler/cfg/stack-analysis/stack-analysis-tests.factor @@ -99,7 +99,7 @@ IN: compiler.cfg.stack-analysis.tests ! Correct height tracking [ t ] [ [ pick [ ] [ drop ] if swap ] test-stack-analysis eliminate-dead-code - reverse-post-order 3 swap nth + reverse-post-order 4 swap nth instructions>> [ ##peek? ] filter first2 [ loc>> ] [ loc>> ] bi* 2array { D 1 D 0 } set= ] unit-test @@ -126,7 +126,7 @@ IN: compiler.cfg.stack-analysis.tests stack-analysis drop - 3 get instructions>> second loc>> + 3 get successors>> first instructions>> first loc>> ] unit-test ! Do inserted ##peeks reference the correct stack location if @@ -156,7 +156,7 @@ IN: compiler.cfg.stack-analysis.tests stack-analysis drop - 3 get instructions>> [ ##peek? ] find nip loc>> + 3 get successors>> first instructions>> [ ##peek? ] find nip loc>> ] unit-test ! Missing ##replace @@ -170,9 +170,9 @@ IN: compiler.cfg.stack-analysis.tests ! Inserted ##peeks reference the wrong stack location [ t ] [ [ [ "B" ] 2dip dup [ [ /mod ] dip ] when ] test-stack-analysis - eliminate-dead-code reverse-post-order 3 swap nth + eliminate-dead-code reverse-post-order 4 swap nth instructions>> [ ##peek? ] filter [ loc>> ] map - { R 0 D 0 D 1 } set= + { D 0 D 1 } set= ] unit-test [ D 0 ] [ @@ -200,5 +200,5 @@ IN: compiler.cfg.stack-analysis.tests stack-analysis drop - 3 get instructions>> [ ##peek? ] find nip loc>> + 3 get successors>> first instructions>> [ ##peek? ] find nip loc>> ] unit-test \ No newline at end of file diff --git a/basis/compiler/cfg/stack-analysis/stack-analysis.factor b/basis/compiler/cfg/stack-analysis/stack-analysis.factor index ab16bbea44..48a4b79783 100644 --- a/basis/compiler/cfg/stack-analysis/stack-analysis.factor +++ b/basis/compiler/cfg/stack-analysis/stack-analysis.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs kernel namespaces math sequences fry grouping -sets make combinators +sets make combinators dlists deques compiler.cfg compiler.cfg.copy-prop compiler.cfg.def-use @@ -10,9 +10,14 @@ compiler.cfg.registers compiler.cfg.rpo compiler.cfg.hats compiler.cfg.stack-analysis.state -compiler.cfg.stack-analysis.merge ; +compiler.cfg.stack-analysis.merge +compiler.cfg.utilities ; IN: compiler.cfg.stack-analysis +SYMBOL: work-list + +: add-to-work-list ( bb -- ) work-list get push-front ; + : redundant-replace? ( vreg loc -- ? ) dup state get untranslate-loc n>> 0 < [ 2drop t ] [ state get actual-locs>vregs>> at = ] if ; @@ -137,10 +142,21 @@ SYMBOLS: state-in state-out ; ] 2bi ] V{ } make >>instructions drop ; +: visit-successors ( bb -- ) + dup successors>> [ + 2dup back-edge? [ 2drop ] [ nip add-to-work-list ] if + ] with each ; + +: process-work-list ( -- ) + work-list get [ visit-block ] slurp-deque ; + : stack-analysis ( cfg -- cfg' ) [ + work-list set H{ } clone copies set H{ } clone state-in set H{ } clone state-out set - dup [ visit-block ] each-basic-block + dup [ add-to-work-list ] each-basic-block + process-work-list + cfg-changed ] with-scope ; diff --git a/basis/compiler/cfg/tco/tco.factor b/basis/compiler/cfg/tco/tco.factor index df5d962999..5fa2e1b042 100644 --- a/basis/compiler/cfg/tco/tco.factor +++ b/basis/compiler/cfg/tco/tco.factor @@ -5,7 +5,8 @@ namespaces sequences fry combinators compiler.cfg compiler.cfg.rpo compiler.cfg.hats -compiler.cfg.instructions ; +compiler.cfg.instructions +compiler.cfg.utilities ; IN: compiler.cfg.tco ! Tail call optimization. You must run compute-predecessors after this @@ -82,4 +83,4 @@ M: ##fixnum-mul convert-fixnum-tail-call* drop i i \ ##fixnum-mul-tail new-insn : optimize-tail-calls ( cfg -- cfg' ) dup cfg set dup [ optimize-tail-call ] each-basic-block - f >>post-order ; \ No newline at end of file + cfg-changed ; \ No newline at end of file diff --git a/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor b/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor index 6f4a6eea55..cc98d08042 100644 --- a/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor +++ b/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2008, 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel accessors sequences math combinators combinators.short-circuit -classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ; +classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo +compiler.cfg.utilities ; IN: compiler.cfg.useless-conditionals : delete-conditional? ( bb -- ? ) @@ -18,4 +19,4 @@ IN: compiler.cfg.useless-conditionals dup [ dup delete-conditional? [ delete-conditional ] [ drop ] if ] each-basic-block - f >>post-order ; + cfg-changed ; diff --git a/basis/compiler/cfg/utilities/utilities.factor b/basis/compiler/cfg/utilities/utilities.factor index 99a138a763..0e08607331 100644 --- a/basis/compiler/cfg/utilities/utilities.factor +++ b/basis/compiler/cfg/utilities/utilities.factor @@ -1,8 +1,8 @@ -! Copyright (C) 2008 Slava Pestov. +! Copyright (C) 2008, 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors kernel math layouts make sequences combinators -cpu.architecture namespaces compiler.cfg -compiler.cfg.instructions ; +USING: accessors assocs combinators combinators.short-circuit +compiler.cfg compiler.cfg.instructions cpu.architecture kernel +layouts locals make math namespaces sequences sets vectors ; IN: compiler.cfg.utilities : value-info-small-fixnum? ( value-info -- ? ) @@ -33,7 +33,53 @@ IN: compiler.cfg.utilities building off basic-block off ; -: stop-iterating ( -- next ) end-basic-block f ; - : emit-primitive ( node -- ) word>> ##call ##branch begin-basic-block ; + +: back-edge? ( from to -- ? ) + [ number>> ] bi@ >= ; + +: empty-block? ( bb -- ? ) + instructions>> { + [ length 1 = ] + [ first ##branch? ] + } 1&& ; + +SYMBOL: visited + +: (skip-empty-blocks) ( bb -- bb' ) + dup visited get key? [ + dup empty-block? [ + dup visited get conjoin + successors>> first (skip-empty-blocks) + ] when + ] unless ; + +: skip-empty-blocks ( bb -- bb' ) + H{ } clone visited [ (skip-empty-blocks) ] with-variable ; + +! assoc mapping predecessors to sequences +SYMBOL: added-instructions + +: add-instructions ( predecessor quot -- ) + [ + added-instructions get + [ drop V{ } clone ] cache + building + ] dip with-variable ; inline + +:: insert-basic-block ( from to bb -- ) + bb from 1vector >>predecessors drop + bb to 1vector >>successors drop + to predecessors>> [ dup from eq? [ drop bb ] when ] change-each + from successors>> [ dup to eq? [ drop bb ] when ] change-each ; + +:: insert-basic-blocks ( bb -- ) + added-instructions get + [| predecessor instructions | + \ ##branch new-insn instructions push + predecessor bb + instructions >>instructions + insert-basic-block + ] assoc-each ; + From 8ff473e42cdc6b1965703938e21be27ecd51abce Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 12 Jul 2009 23:00:33 -0500 Subject: [PATCH 3/5] compiler.cfg.linear-scan.resolve: get it to work on CFGs with critical edges --- .../cfg/linear-scan/linear-scan-tests.factor | 9 +++-- .../cfg/linear-scan/linear-scan.factor | 1 + .../linear-scan/resolve/resolve-tests.factor | 7 ---- .../cfg/linear-scan/resolve/resolve.factor | 39 +++---------------- basis/compiler/cfg/utilities/utilities.factor | 18 ++++----- 5 files changed, 21 insertions(+), 53 deletions(-) delete mode 100644 basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor diff --git a/basis/compiler/cfg/linear-scan/linear-scan-tests.factor b/basis/compiler/cfg/linear-scan/linear-scan-tests.factor index e8b4b67cf0..20f8570f84 100644 --- a/basis/compiler/cfg/linear-scan/linear-scan-tests.factor +++ b/basis/compiler/cfg/linear-scan/linear-scan-tests.factor @@ -1509,6 +1509,7 @@ SYMBOL: linear-scan-result compute-liveness dup reverse-post-order { { int-regs regs } } (linear-scan) + cfg-changed flatten-cfg 1array mr. ] with-scope ; @@ -1803,7 +1804,7 @@ test-diamond [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test -[ _spill ] [ 2 get instructions>> first class ] unit-test +[ _spill ] [ 2 get successors>> first instructions>> first class ] unit-test [ _spill ] [ 3 get instructions>> second class ] unit-test @@ -1859,7 +1860,7 @@ V{ [ t ] [ 2 get instructions>> [ _spill? ] any? ] unit-test -[ t ] [ 3 get instructions>> [ _spill? ] any? ] unit-test +[ t ] [ 3 get predecessors>> first instructions>> [ _spill? ] any? ] unit-test [ t ] [ 5 get instructions>> [ _reload? ] any? ] unit-test @@ -1926,7 +1927,7 @@ V{ [ V{ 3 2 1 } ] [ 9 get instructions>> [ _reload? ] filter [ n>> ] map ] unit-test ! Resolve pass should insert this -[ _reload ] [ 5 get instructions>> first class ] unit-test +[ _reload ] [ 5 get predecessors>> first instructions>> first class ] unit-test ! Some random bug V{ @@ -2484,7 +2485,7 @@ test-diamond [ 1 ] [ 2 get instructions>> [ _spill? ] count ] unit-test -[ 1 ] [ 3 get instructions>> [ _spill? ] count ] unit-test +[ 1 ] [ 3 get predecessors>> first instructions>> [ _spill? ] count ] unit-test [ 1 ] [ 4 get instructions>> [ _reload? ] count ] unit-test diff --git a/basis/compiler/cfg/linear-scan/linear-scan.factor b/basis/compiler/cfg/linear-scan/linear-scan.factor index 77d66c274d..c17aa23e83 100644 --- a/basis/compiler/cfg/linear-scan/linear-scan.factor +++ b/basis/compiler/cfg/linear-scan/linear-scan.factor @@ -40,4 +40,5 @@ IN: compiler.cfg.linear-scan init-mapping dup reverse-post-order machine-registers (linear-scan) spill-counts get >>spill-counts + cfg-changed ] with-scope ; diff --git a/basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor b/basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor deleted file mode 100644 index b5e95258bf..0000000000 --- a/basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor +++ /dev/null @@ -1,7 +0,0 @@ -USING: arrays compiler.cfg.linear-scan.resolve kernel -tools.test ; -IN: compiler.cfg.linear-scan.resolve.tests - -[ { 1 2 3 4 5 6 } ] [ - { 3 4 } V{ 1 2 } clone [ { 5 6 } 3append-here ] keep >array -] unit-test diff --git a/basis/compiler/cfg/linear-scan/resolve/resolve.factor b/basis/compiler/cfg/linear-scan/resolve/resolve.factor index 7b7f242e4e..f7ed994f18 100644 --- a/basis/compiler/cfg/linear-scan/resolve/resolve.factor +++ b/basis/compiler/cfg/linear-scan/resolve/resolve.factor @@ -3,6 +3,7 @@ USING: accessors arrays assocs combinators combinators.short-circuit fry kernel locals make math sequences +compiler.cfg.utilities compiler.cfg.instructions compiler.cfg.linear-scan.assignment compiler.cfg.linear-scan.mapping compiler.cfg.liveness ; @@ -30,42 +31,14 @@ IN: compiler.cfg.linear-scan.resolve [ resolve-value-data-flow ] with with each ] { } make ; -: fork? ( from to -- ? ) - { - [ drop successors>> length 1 >= ] - [ nip predecessors>> length 1 = ] - } 2&& ; inline - -: insert-position/fork ( from to -- before after ) - nip instructions>> [ >array ] [ dup delete-all ] bi swap ; - -: join? ( from to -- ? ) - { - [ drop successors>> length 1 = ] - [ nip predecessors>> length 1 >= ] - } 2&& ; inline - -: insert-position/join ( from to -- before after ) - drop instructions>> dup pop 1array ; - -: insert-position ( bb to -- before after ) - { - { [ 2dup fork? ] [ insert-position/fork ] } - { [ 2dup join? ] [ insert-position/join ] } - } cond ; - -: 3append-here ( seq2 seq1 seq3 -- ) - #! Mutate seq1 - swap '[ _ push-all ] bi@ ; - -: perform-mappings ( mappings bb to -- ) - pick empty? [ 3drop ] [ - [ mapping-instructions ] 2dip - insert-position 3append-here +: perform-mappings ( bb to mappings -- ) + dup empty? [ 3drop ] [ + mapping-instructions + insert-basic-block ] if ; : resolve-edge-data-flow ( bb to -- ) - [ compute-mappings ] [ perform-mappings ] 2bi ; + 2dup compute-mappings perform-mappings ; : resolve-block-data-flow ( bb -- ) dup successors>> [ resolve-edge-data-flow ] with each ; diff --git a/basis/compiler/cfg/utilities/utilities.factor b/basis/compiler/cfg/utilities/utilities.factor index 0e08607331..288fa403dd 100644 --- a/basis/compiler/cfg/utilities/utilities.factor +++ b/basis/compiler/cfg/utilities/utilities.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs combinators combinators.short-circuit compiler.cfg compiler.cfg.instructions cpu.architecture kernel -layouts locals make math namespaces sequences sets vectors ; +layouts locals make math namespaces sequences sets vectors fry ; IN: compiler.cfg.utilities : value-info-small-fixnum? ( value-info -- ? ) @@ -74,12 +74,12 @@ SYMBOL: added-instructions to predecessors>> [ dup from eq? [ drop bb ] when ] change-each from successors>> [ dup to eq? [ drop bb ] when ] change-each ; -:: insert-basic-blocks ( bb -- ) - added-instructions get - [| predecessor instructions | - \ ##branch new-insn instructions push - predecessor bb - instructions >>instructions - insert-basic-block - ] assoc-each ; +: ( insns -- bb ) + + swap >vector + \ ##branch new-insn over push + >>instructions ; +: insert-basic-blocks ( bb -- ) + [ added-instructions get ] dip + '[ [ _ ] dip insert-basic-block ] assoc-each ; From d7aeae45be8984bd2dc0c198758d3c9713c98dda Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 13 Jul 2009 10:44:08 -0500 Subject: [PATCH 4/5] compiler.cfg.branch-splitting: split blocks with successors --- .../branch-splitting-tests.factor | 85 +++++++++++++++++++ .../branch-splitting/branch-splitting.factor | 82 +++++++++++++----- .../cfg/optimizer/optimizer-tests.factor | 6 +- basis/compiler/cfg/optimizer/optimizer.factor | 3 +- basis/compiler/cfg/renaming/renaming.factor | 6 ++ .../stack-analysis/merge/merge-tests.factor | 6 +- 6 files changed, 162 insertions(+), 26 deletions(-) create mode 100644 basis/compiler/cfg/branch-splitting/branch-splitting-tests.factor diff --git a/basis/compiler/cfg/branch-splitting/branch-splitting-tests.factor b/basis/compiler/cfg/branch-splitting/branch-splitting-tests.factor new file mode 100644 index 0000000000..fbaaf92203 --- /dev/null +++ b/basis/compiler/cfg/branch-splitting/branch-splitting-tests.factor @@ -0,0 +1,85 @@ +USING: accessors assocs compiler.cfg +compiler.cfg.branch-splitting compiler.cfg.debugger +compiler.cfg.predecessors compiler.cfg.rpo fry kernel +tools.test namespaces sequences vectors ; +IN: compiler.cfg.branch-splitting.tests + +: get-predecessors ( cfg -- assoc ) + H{ } clone [ '[ [ predecessors>> ] keep _ set-at ] each-basic-block ] keep ; + +: check-predecessors ( cfg -- ) + [ get-predecessors ] + [ compute-predecessors drop ] + [ get-predecessors ] tri assert= ; + +: check-branch-splitting ( cfg -- ) + compute-predecessors + split-branches + check-predecessors ; + +: test-branch-splitting ( -- ) + cfg new 0 get >>entry check-branch-splitting ; + +V{ } 0 test-bb + +V{ } 1 test-bb + +V{ } 2 test-bb + +V{ } 3 test-bb + +V{ } 4 test-bb + +test-diamond + +[ ] [ test-branch-splitting ] 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 + +0 get 1 get 2 get V{ } 2sequence >>successors drop + +1 get 3 get 4 get V{ } 2sequence >>successors drop + +2 get 3 get 4 get V{ } 2sequence >>successors drop + +[ ] [ test-branch-splitting ] unit-test + +V{ } 0 test-bb + +V{ } 1 test-bb + +V{ } 2 test-bb + +V{ } 3 test-bb + +V{ } 4 test-bb + +0 get 1 get 2 get V{ } 2sequence >>successors drop + +1 get 3 get 4 get V{ } 2sequence >>successors drop + +2 get 4 get 1vector >>successors drop + +[ ] [ test-branch-splitting ] unit-test + +V{ } 0 test-bb + +V{ } 1 test-bb + +V{ } 2 test-bb + +0 get 1 get 2 get V{ } 2sequence >>successors drop + +1 get 2 get 1vector >>successors drop + +[ ] [ test-branch-splitting ] unit-test \ No newline at end of file diff --git a/basis/compiler/cfg/branch-splitting/branch-splitting.factor b/basis/compiler/cfg/branch-splitting/branch-splitting.factor index f7e9ea9cbf..0dd963125f 100644 --- a/basis/compiler/cfg/branch-splitting/branch-splitting.factor +++ b/basis/compiler/cfg/branch-splitting/branch-splitting.factor @@ -1,37 +1,79 @@ ! Copyright (C) 2009 Doug Coleman, Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors combinators.short-circuit kernel math sequences -compiler.cfg.def-use compiler.cfg compiler.cfg.rpo ; +USING: accessors combinators.short-circuit kernel math math.order +sequences assocs namespaces vectors fry arrays splitting +compiler.cfg.def-use compiler.cfg compiler.cfg.rpo +compiler.cfg.renaming compiler.cfg.instructions compiler.cfg.utilities ; IN: compiler.cfg.branch-splitting -! Predecessors must be recomputed after this +: clone-renamings ( insns -- assoc ) + [ defs-vregs ] map concat [ dup fresh-vreg ] H{ } map>assoc ; -: split-branch-for ( bb predecessor -- ) - [ +: clone-instructions ( insns -- insns' ) + dup clone-renamings renamings [ [ - - swap - [ instructions>> [ clone ] map >>instructions ] - [ successors>> clone >>successors ] - bi - ] keep - ] dip - [ [ 2dup eq? [ 2drop ] [ 2nip ] if ] with with map ] change-successors - drop ; + clone + dup rename-insn-defs + dup rename-insn-uses + dup fresh-insn-temps + ] map + ] with-variable ; + +: clone-basic-block ( bb -- bb' ) + ! The new block gets the same RPO number as the old one. + ! This is just to make 'back-edge?' work. + + swap + [ instructions>> clone-instructions >>instructions ] + [ successors>> clone >>successors ] + [ number>> >>number ] + tri ; + +: new-blocks ( bb -- copies ) + dup predecessors>> [ + [ clone-basic-block ] dip + 1vector >>predecessors + ] with map ; + +: update-predecessor-successor ( pred copy old-bb -- ) + '[ + [ _ _ 3dup nip eq? [ drop nip ] [ 2drop ] if ] map + ] change-successors drop ; + +: update-predecessor-successors ( copies old-bb -- ) + [ predecessors>> swap ] keep + '[ _ update-predecessor-successor ] 2each ; + +: update-successor-predecessor ( copies old-bb succ -- ) + [ + swap 1array split swap join V{ } like + ] change-predecessors drop ; + +: update-successor-predecessors ( copies old-bb -- ) + dup successors>> [ + update-successor-predecessor + ] with with each ; : split-branch ( bb -- ) - dup predecessors>> [ split-branch-for ] with each ; + [ new-blocks ] keep + [ update-predecessor-successors ] + [ update-successor-predecessors ] + 2bi ; + +UNION: irrelevant ##peek ##replace ##inc-d ##inc-r ; + +: split-instructions? ( insns -- ? ) + [ irrelevant? not ] count 5 <= ; : split-branches? ( bb -- ? ) { - [ successors>> empty? ] - [ predecessors>> length 1 > ] - [ instructions>> [ defs-vregs ] any? not ] - [ instructions>> [ temp-vregs ] any? not ] + [ dup successors>> [ back-edge? ] with any? not ] + [ predecessors>> length 1 4 between? ] + [ instructions>> split-instructions? ] } 1&& ; : split-branches ( cfg -- cfg' ) dup [ dup split-branches? [ split-branch ] [ drop ] if ] each-basic-block - f >>post-order ; + cfg-changed ; diff --git a/basis/compiler/cfg/optimizer/optimizer-tests.factor b/basis/compiler/cfg/optimizer/optimizer-tests.factor index f585d80d72..1eb1996da4 100755 --- a/basis/compiler/cfg/optimizer/optimizer-tests.factor +++ b/basis/compiler/cfg/optimizer/optimizer-tests.factor @@ -2,7 +2,7 @@ USING: accessors arrays compiler.cfg.checker compiler.cfg.debugger compiler.cfg.def-use compiler.cfg.instructions fry kernel kernel.private math math.partial-dispatch math.private sbufs sequences sequences.private sets -slots.private strings tools.test vectors layouts ; +slots.private strings strings.private tools.test vectors layouts ; IN: compiler.cfg.optimizer.tests ! Miscellaneous tests @@ -40,6 +40,10 @@ IN: compiler.cfg.optimizer.tests ] [ 2drop f ] if ] [ 2drop f ] if ] + [ + pick 10 fixnum>= [ [ 123 fixnum-bitand ] 2dip ] [ ] if + set-string-nth-fast + ] } [ [ [ ] ] dip '[ _ test-mr first check-mr ] unit-test ] each diff --git a/basis/compiler/cfg/optimizer/optimizer.factor b/basis/compiler/cfg/optimizer/optimizer.factor index 84eb8a84d1..5b0892a0ee 100644 --- a/basis/compiler/cfg/optimizer/optimizer.factor +++ b/basis/compiler/cfg/optimizer/optimizer.factor @@ -29,10 +29,9 @@ SYMBOL: check-optimizer? ! The passes that need this document it. [ optimize-tail-calls - compute-predecessors delete-useless-conditionals - split-branches compute-predecessors + split-branches stack-analysis compute-liveness alias-analysis diff --git a/basis/compiler/cfg/renaming/renaming.factor b/basis/compiler/cfg/renaming/renaming.factor index 4a8c6e6a4d..228d72483c 100644 --- a/basis/compiler/cfg/renaming/renaming.factor +++ b/basis/compiler/cfg/renaming/renaming.factor @@ -55,6 +55,12 @@ M: ##string-nth rename-insn-uses [ rename-value ] change-index drop ; +M: ##set-string-nth-fast rename-insn-uses + dup call-next-method + [ rename-value ] change-obj + [ rename-value ] change-index + drop ; + M: ##set-slot-imm rename-insn-uses dup call-next-method [ rename-value ] change-obj diff --git a/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor b/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor index e67f6b5143..5883777861 100644 --- a/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor +++ b/basis/compiler/cfg/stack-analysis/merge/merge-tests.factor @@ -1,8 +1,8 @@ IN: compiler.cfg.stack-analysis.merge.tests USING: compiler.cfg.stack-analysis.merge tools.test arrays accessors -compiler.cfg.instructions compiler.cfg.stack-analysis.state -compiler.cfg compiler.cfg.registers compiler.cfg.debugger -cpu.architecture make assocs namespaces + compiler.cfg.instructions compiler.cfg.stack-analysis.state +compiler.cfg.utilities compiler.cfg compiler.cfg.registers +compiler.cfg.debugger cpu.architecture make assocs namespaces sequences kernel classes ; [ From 3b244d5d4149a88516482aa2f6a784468259e655 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 13 Jul 2009 12:33:58 -0500 Subject: [PATCH 5/5] compiler.cfg.value-numbering: fix ##compare and ##compare-branch rewrites --- .../value-numbering/rewrite/rewrite.factor | 39 ++++++++++--------- core/sequences/sequences-tests.factor | 5 ++- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor index ca7a959a82..92965e40c5 100755 --- a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor +++ b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor @@ -77,13 +77,19 @@ M: ##compare-imm-branch rewrite insn cc>> swap? [ swap-cc ] when i \ ##compare-imm new-insn ; inline -! M: ##compare rewrite -! dup [ src1>> ] [ src2>> ] bi -! [ vreg>expr constant-expr? ] bi@ 2array { -! { { f t } [ f >compare-imm ] } -! { { t f } [ t >compare-imm ] } -! [ drop ] -! } case ; +: vreg-small-constant? ( vreg -- ? ) + vreg>expr { + [ constant-expr? ] + [ value>> small-enough? ] + } 1&& ; + +M: ##compare rewrite + dup [ src1>> ] [ src2>> ] bi + [ vreg-small-constant? ] bi@ 2array { + { { f t } [ f >compare-imm ] } + { { t f } [ t >compare-imm ] } + [ drop ] + } case ; :: >compare-imm-branch ( insn swap? -- insn' ) insn src1>> @@ -91,13 +97,13 @@ M: ##compare-imm-branch rewrite insn cc>> swap? [ swap-cc ] when \ ##compare-imm-branch new-insn ; inline -! M: ##compare-branch rewrite -! dup [ src1>> ] [ src2>> ] bi -! [ vreg>expr constant-expr? ] bi@ 2array { -! { { f t } [ f >compare-imm-branch ] } -! { { t f } [ t >compare-imm-branch ] } -! [ drop ] -! } case ; +M: ##compare-branch rewrite + dup [ src1>> ] [ src2>> ] bi + [ vreg-small-constant? ] bi@ 2array { + { { f t } [ f >compare-imm-branch ] } + { { t f } [ t >compare-imm-branch ] } + [ drop ] + } case ; : rewrite-redundant-comparison? ( insn -- ? ) { @@ -198,10 +204,7 @@ M: ##or-imm rewrite [ bitor ] \ ##or-imm combine-imm ; M: ##xor-imm rewrite [ bitxor ] \ ##xor-imm combine-imm ; : rewrite-add? ( insn -- ? ) - src2>> { - [ vreg>expr constant-expr? ] - [ vreg>constant small-enough? ] - } 1&& ; + src2>> vreg-small-constant? ; M: ##add rewrite dup rewrite-add? [ diff --git a/core/sequences/sequences-tests.factor b/core/sequences/sequences-tests.factor index 5e0d5597ca..2aa95b23ab 100644 --- a/core/sequences/sequences-tests.factor +++ b/core/sequences/sequences-tests.factor @@ -290,4 +290,7 @@ M: bogus-hashcode hashcode* 2drop 0 >bignum ; USE: make [ { "a" 1 "b" 1 "c" } ] -[ 1 { "a" "b" "c" } [ [ dup , ] [ , ] interleave drop ] { } make ] unit-test \ No newline at end of file +[ 1 { "a" "b" "c" } [ [ dup , ] [ , ] interleave drop ] { } make ] unit-test + +[ t ] [ 0 array-capacity? ] unit-test +[ f ] [ -1 array-capacity? ] unit-test \ No newline at end of file