Perform loop detection before normalization, clean up normalization pass, more aggressive recursive return value propagation. Fixes regression on nsieve benchmark

db4
Slava Pestov 2008-09-12 05:17:27 -05:00
parent 8b79eeeff2
commit 40da49bef5
16 changed files with 186 additions and 154 deletions

View File

@ -10,12 +10,13 @@ compiler.tree
compiler.tree.combinators compiler.tree.combinators
compiler.tree.cleanup compiler.tree.cleanup
compiler.tree.builder compiler.tree.builder
compiler.tree.recursive
compiler.tree.normalization compiler.tree.normalization
compiler.tree.propagation compiler.tree.propagation
compiler.tree.checker ; compiler.tree.checker ;
: cleaned-up-tree ( quot -- nodes ) : cleaned-up-tree ( quot -- nodes )
build-tree normalize propagate cleanup dup check-nodes ; build-tree analyze-recursive normalize propagate cleanup dup check-nodes ;
[ t ] [ [ [ 1 ] [ 2 ] if ] cleaned-up-tree [ #if? ] contains-node? ] unit-test [ t ] [ [ [ 1 ] [ 2 ] if ] cleaned-up-tree [ #if? ] contains-node? ] unit-test

View File

@ -3,16 +3,17 @@ compiler.tree.dead-code compiler.tree.def-use compiler.tree
compiler.tree.combinators compiler.tree.propagation compiler.tree.combinators compiler.tree.propagation
compiler.tree.cleanup compiler.tree.escape-analysis compiler.tree.cleanup compiler.tree.escape-analysis
compiler.tree.tuple-unboxing compiler.tree.debugger compiler.tree.tuple-unboxing compiler.tree.debugger
compiler.tree.normalization compiler.tree.checker tools.test compiler.tree.recursive compiler.tree.normalization
kernel math stack-checker.state accessors combinators io compiler.tree.checker tools.test kernel math stack-checker.state
prettyprint words sequences.deep sequences.private arrays accessors combinators io prettyprint words sequences.deep
classes kernel.private ; sequences.private arrays classes kernel.private ;
IN: compiler.tree.dead-code.tests IN: compiler.tree.dead-code.tests
\ remove-dead-code must-infer \ remove-dead-code must-infer
: count-live-values ( quot -- n ) : count-live-values ( quot -- n )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup
@ -64,6 +65,7 @@ IN: compiler.tree.dead-code.tests
: optimize-quot ( quot -- quot' ) : optimize-quot ( quot -- quot' )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup

View File

@ -1,9 +1,10 @@
USING: accessors namespaces assocs kernel sequences math USING: accessors namespaces assocs kernel sequences math
tools.test words sets combinators.short-circuit tools.test words sets combinators.short-circuit
stack-checker.state compiler.tree compiler.tree.builder stack-checker.state compiler.tree compiler.tree.builder
compiler.tree.normalization compiler.tree.propagation compiler.tree.recursive compiler.tree.normalization
compiler.tree.cleanup compiler.tree.def-use arrays kernel.private compiler.tree.propagation compiler.tree.cleanup
sorting math.order binary-search compiler.tree.checker ; compiler.tree.def-use arrays kernel.private sorting math.order
binary-search compiler.tree.checker ;
IN: compiler.tree.def-use.tests IN: compiler.tree.def-use.tests
\ compute-def-use must-infer \ compute-def-use must-infer
@ -18,6 +19,7 @@ IN: compiler.tree.def-use.tests
: test-def-use ( quot -- ) : test-def-use ( quot -- )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup
@ -27,7 +29,14 @@ IN: compiler.tree.def-use.tests
: too-deep ( a b -- c ) : too-deep ( a b -- c )
dup [ drop ] [ 2dup too-deep too-deep drop ] if ; inline recursive dup [ drop ] [ 2dup too-deep too-deep drop ] if ; inline recursive
[ ] [ [ too-deep ] build-tree normalize compute-def-use check-nodes ] unit-test [ ] [
[ too-deep ]
build-tree
analyze-recursive
normalize
compute-def-use
check-nodes
] unit-test
! compute-def-use checks for SSA violations, so we use that to ! compute-def-use checks for SSA violations, so we use that to
! ensure we generate some common patterns correctly. ! ensure we generate some common patterns correctly.

View File

@ -1,13 +1,14 @@
IN: compiler.tree.escape-analysis.tests IN: compiler.tree.escape-analysis.tests
USING: compiler.tree.escape-analysis USING: compiler.tree.escape-analysis
compiler.tree.escape-analysis.allocations compiler.tree.builder compiler.tree.escape-analysis.allocations compiler.tree.builder
compiler.tree.normalization math.functions compiler.tree.recursive compiler.tree.normalization
compiler.tree.propagation compiler.tree.cleanup math.functions compiler.tree.propagation compiler.tree.cleanup
compiler.tree.combinators compiler.tree sequences math math.private compiler.tree.combinators compiler.tree sequences math
kernel tools.test accessors slots.private quotations.private math.private kernel tools.test accessors slots.private
prettyprint classes.tuple.private classes classes.tuple quotations.private prettyprint classes.tuple.private classes
compiler.intrinsics namespaces compiler.tree.propagation.info classes.tuple compiler.intrinsics namespaces
stack-checker.errors kernel.private ; compiler.tree.propagation.info stack-checker.errors
kernel.private ;
\ escape-analysis must-infer \ escape-analysis must-infer
@ -28,6 +29,7 @@ M: node count-unboxed-allocations* drop ;
: count-unboxed-allocations ( quot -- sizes ) : count-unboxed-allocations ( quot -- sizes )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup

View File

@ -7,6 +7,7 @@ byte-arrays alien.accessors
compiler.intrinsics compiler.intrinsics
compiler.tree compiler.tree
compiler.tree.builder compiler.tree.builder
compiler.tree.recursive
compiler.tree.normalization compiler.tree.normalization
compiler.tree.propagation compiler.tree.propagation
compiler.tree.propagation.info compiler.tree.propagation.info
@ -39,6 +40,7 @@ M: #shuffle finalize*
: splice-quot ( quot -- nodes ) : splice-quot ( quot -- nodes )
[ [
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup

View File

@ -0,0 +1,36 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces sequences accessors math kernel
compiler.tree ;
IN: compiler.tree.normalization.introductions
SYMBOL: introductions
GENERIC: count-introductions* ( node -- )
: count-introductions ( nodes -- n )
#! Note: we use each, not each-node, since the #branch
#! method recurses into children directly and we don't
#! recurse into #recursive at all.
[
0 introductions set
[ count-introductions* ] each
introductions get
] with-scope ;
: introductions+ ( n -- ) introductions [ + ] change ;
M: #introduce count-introductions*
out-d>> length introductions+ ;
M: #branch count-introductions*
children>>
[ count-introductions ] map supremum
introductions+ ;
M: #recursive count-introductions*
[ label>> ] [ child>> count-introductions ] bi
>>introductions
drop ;
M: node count-introductions* drop ;

View File

@ -1,5 +1,8 @@
IN: compiler.tree.normalization.tests IN: compiler.tree.normalization.tests
USING: compiler.tree.builder compiler.tree.normalization USING: compiler.tree.builder compiler.tree.recursive
compiler.tree.normalization
compiler.tree.normalization.introductions
compiler.tree.normalization.renaming
compiler.tree compiler.tree.checker compiler.tree compiler.tree.checker
sequences accessors tools.test kernel math ; sequences accessors tools.test kernel math ;
@ -22,27 +25,30 @@ sequences accessors tools.test kernel math ;
[ 0 2 ] [ [ 0 2 ] [
[ foo ] build-tree [ foo ] build-tree
[ recursive-inputs ] [ recursive-inputs ]
[ normalize recursive-inputs ] bi [ analyze-recursive normalize recursive-inputs ] bi
] unit-test ] unit-test
[ ] [ [ [ 1 ] [ 2 ] if + * ] build-tree normalize check-nodes ] unit-test : test-normalization ( quot -- )
build-tree analyze-recursive normalize check-nodes ;
[ ] [ [ [ 1 ] [ 2 ] if + * ] test-normalization ] unit-test
DEFER: bbb DEFER: bbb
: aaa ( x -- ) dup [ dup >r bbb r> aaa ] [ drop ] if ; inline recursive : aaa ( x -- ) dup [ dup >r bbb r> aaa ] [ drop ] if ; inline recursive
: bbb ( x -- ) >r drop 0 r> aaa ; inline recursive : bbb ( x -- ) >r drop 0 r> aaa ; inline recursive
[ ] [ [ bbb ] build-tree normalize check-nodes ] unit-test [ ] [ [ bbb ] test-normalization ] unit-test
: ccc ( -- ) ccc drop 1 ; inline recursive : ccc ( -- ) ccc drop 1 ; inline recursive
[ ] [ [ ccc ] build-tree normalize check-nodes ] unit-test [ ] [ [ ccc ] test-normalization ] unit-test
DEFER: eee DEFER: eee
: ddd ( -- ) eee ; inline recursive : ddd ( -- ) eee ; inline recursive
: eee ( -- ) swap ddd ; inline recursive : eee ( -- ) swap ddd ; inline recursive
[ ] [ [ eee ] build-tree normalize check-nodes ] unit-test [ ] [ [ eee ] test-normalization ] unit-test
: call-recursive-5 ( -- ) call-recursive-5 ; inline recursive : call-recursive-5 ( -- ) call-recursive-5 ; inline recursive
[ ] [ [ call-recursive-5 swap ] build-tree normalize check-nodes ] unit-test [ ] [ [ call-recursive-5 swap ] test-normalization ] unit-test

View File

@ -6,7 +6,9 @@ stack-checker.backend
stack-checker.branches stack-checker.branches
stack-checker.inlining stack-checker.inlining
compiler.tree compiler.tree
compiler.tree.combinators ; compiler.tree.combinators
compiler.tree.normalization.introductions
compiler.tree.normalization.renaming ;
IN: compiler.tree.normalization IN: compiler.tree.normalization
! A transform pass done before optimization can begin to ! A transform pass done before optimization can begin to
@ -16,9 +18,6 @@ IN: compiler.tree.normalization
! replaced with a single one, at the beginning of a program. ! replaced with a single one, at the beginning of a program.
! This simplifies subsequent analysis. ! This simplifies subsequent analysis.
! !
! - We collect #return-recursive and #call-recursive nodes and
! store them in the #recursive's label slot.
!
! - We normalize #call-recursive as follows. The stack checker ! - We normalize #call-recursive as follows. The stack checker
! says that the inputs of a #call-recursive are the entire stack ! says that the inputs of a #call-recursive are the entire stack
! at the time of the call. This is a conservative estimate; we ! at the time of the call. This is a conservative estimate; we
@ -28,93 +27,6 @@ IN: compiler.tree.normalization
! #call-recursive into a #copy of the unchanged values and a ! #call-recursive into a #copy of the unchanged values and a
! #call-recursive with trimmed inputs and outputs. ! #call-recursive with trimmed inputs and outputs.
! Collect introductions
SYMBOL: introductions
GENERIC: count-introductions* ( node -- )
: count-introductions ( nodes -- n )
#! Note: we use each, not each-node, since the #branch
#! method recurses into children directly and we don't
#! recurse into #recursive at all.
[
0 introductions set
[ count-introductions* ] each
introductions get
] with-scope ;
: introductions+ ( n -- ) introductions [ + ] change ;
M: #introduce count-introductions*
out-d>> length introductions+ ;
M: #branch count-introductions*
children>>
[ count-introductions ] map supremum
introductions+ ;
M: #recursive count-introductions*
[ label>> ] [ child>> count-introductions ] bi
>>introductions
drop ;
M: node count-introductions* drop ;
! Collect label info
GENERIC: collect-label-info ( node -- )
M: #return-recursive collect-label-info
dup label>> (>>return) ;
M: #call-recursive collect-label-info
dup label>> calls>> push ;
M: #recursive collect-label-info
label>> V{ } clone >>calls drop ;
M: node collect-label-info drop ;
! Rename
SYMBOL: rename-map
: rename-value ( value -- value' )
[ rename-map get at ] keep or ;
: rename-values ( values -- values' )
rename-map get '[ [ _ at ] keep or ] map ;
GENERIC: rename-node-values* ( node -- node )
M: #introduce rename-node-values* ;
M: #shuffle rename-node-values*
[ rename-values ] change-in-d
[ [ rename-value ] assoc-map ] change-mapping ;
M: #push rename-node-values* ;
M: #r> rename-node-values*
[ rename-values ] change-in-r ;
M: #terminate rename-node-values*
[ rename-values ] change-in-d
[ rename-values ] change-in-r ;
M: #phi rename-node-values*
[ [ rename-values ] map ] change-phi-in-d ;
M: #declare rename-node-values*
[ [ [ rename-value ] dip ] assoc-map ] change-declaration ;
M: #alien-callback rename-node-values* ;
M: node rename-node-values*
[ rename-values ] change-in-d ;
: rename-node-values ( nodes -- nodes' )
dup [ rename-node-values* drop ] each-node ;
! Normalize
GENERIC: normalize* ( node -- node' ) GENERIC: normalize* ( node -- node' )
SYMBOL: introduction-stack SYMBOL: introduction-stack
@ -125,10 +37,6 @@ SYMBOL: introduction-stack
: pop-introductions ( n -- values ) : pop-introductions ( n -- values )
introduction-stack [ swap cut* swap ] change ; introduction-stack [ swap cut* swap ] change ;
: add-renamings ( old new -- )
[ rename-values ] dip
rename-map get '[ _ set-at ] 2each ;
M: #introduce normalize* M: #introduce normalize*
out-d>> [ length pop-introductions ] keep add-renamings f ; out-d>> [ length pop-introductions ] keep add-renamings f ;
@ -201,9 +109,8 @@ M: #call-recursive normalize*
M: node normalize* ; M: node normalize* ;
: normalize ( nodes -- nodes' ) : normalize ( nodes -- nodes' )
H{ } clone rename-map set
dup [ collect-label-info ] each-node
dup count-introductions make-values dup count-introductions make-values
H{ } clone rename-map set
[ (normalize) ] [ nip ] 2bi [ (normalize) ] [ nip ] 2bi
[ #introduce prefix ] unless-empty [ #introduce prefix ] unless-empty
rename-node-values ; rename-node-values ;

View File

@ -0,0 +1,48 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs kernel accessors sequences fry
compiler.tree compiler.tree.combinators ;
IN: compiler.tree.normalization.renaming
SYMBOL: rename-map
: rename-value ( value -- value' )
[ rename-map get at ] keep or ;
: rename-values ( values -- values' )
rename-map get '[ [ _ at ] keep or ] map ;
: add-renamings ( old new -- )
[ rename-values ] dip
rename-map get '[ _ set-at ] 2each ;
GENERIC: rename-node-values* ( node -- node )
M: #introduce rename-node-values* ;
M: #shuffle rename-node-values*
[ rename-values ] change-in-d
[ [ rename-value ] assoc-map ] change-mapping ;
M: #push rename-node-values* ;
M: #r> rename-node-values*
[ rename-values ] change-in-r ;
M: #terminate rename-node-values*
[ rename-values ] change-in-d
[ rename-values ] change-in-r ;
M: #phi rename-node-values*
[ [ rename-values ] map ] change-phi-in-d ;
M: #declare rename-node-values*
[ [ [ rename-value ] dip ] assoc-map ] change-declaration ;
M: #alien-callback rename-node-values* ;
M: node rename-node-values*
[ rename-values ] change-in-d ;
: rename-node-values ( nodes -- nodes' )
dup [ rename-node-values* drop ] each-node ;

View File

@ -1,6 +1,7 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces USING: kernel namespaces
compiler.tree.recursive
compiler.tree.normalization compiler.tree.normalization
compiler.tree.propagation compiler.tree.propagation
compiler.tree.cleanup compiler.tree.cleanup
@ -9,7 +10,6 @@ compiler.tree.tuple-unboxing
compiler.tree.def-use compiler.tree.def-use
compiler.tree.dead-code compiler.tree.dead-code
compiler.tree.strength-reduction compiler.tree.strength-reduction
compiler.tree.loop.detection
compiler.tree.finalization compiler.tree.finalization
compiler.tree.checker ; compiler.tree.checker ;
IN: compiler.tree.optimizer IN: compiler.tree.optimizer
@ -17,10 +17,10 @@ IN: compiler.tree.optimizer
SYMBOL: check-optimizer? SYMBOL: check-optimizer?
: optimize-tree ( nodes -- nodes' ) : optimize-tree ( nodes -- nodes' )
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup
detect-loops
escape-analysis escape-analysis
unbox-tuples unbox-tuples
compute-def-use compute-def-use

View File

@ -6,6 +6,7 @@ classes.algebra classes.union sets quotations assocs combinators
words namespaces words namespaces
compiler.tree compiler.tree
compiler.tree.builder compiler.tree.builder
compiler.tree.recursive
compiler.tree.normalization compiler.tree.normalization
compiler.tree.propagation.info compiler.tree.propagation.info
compiler.tree.propagation.nodes ; compiler.tree.propagation.nodes ;
@ -18,7 +19,7 @@ M: word splicing-nodes
[ [ in-d>> ] [ out-d>> ] bi ] dip #call 1array ; [ [ in-d>> ] [ out-d>> ] bi ] dip #call 1array ;
M: quotation splicing-nodes M: quotation splicing-nodes
build-sub-tree normalize ; build-sub-tree normalize analyze-recursive ;
: propagate-body ( #call -- ) : propagate-body ( #call -- )
body>> (propagate) ; body>> (propagate) ;

View File

@ -1,5 +1,5 @@
USING: kernel compiler.tree.builder compiler.tree USING: kernel compiler.tree.builder compiler.tree
compiler.tree.propagation compiler.tree.propagation compiler.tree.recursive
compiler.tree.normalization tools.test math math.order compiler.tree.normalization tools.test math math.order
accessors sequences arrays kernel.private vectors accessors sequences arrays kernel.private vectors
alien.accessors alien.c-types sequences.private alien.accessors alien.c-types sequences.private
@ -14,6 +14,7 @@ IN: compiler.tree.propagation.tests
: final-info ( quot -- seq ) : final-info ( quot -- seq )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
compute-def-use compute-def-use

View File

@ -70,7 +70,8 @@ M: #recursive propagate-around ( #recursive -- )
[ generalize-return-interval ] map ; [ generalize-return-interval ] map ;
: return-infos ( node -- infos ) : return-infos ( node -- infos )
label>> return>> node-input-infos generalize-return ; label>> [ return>> node-input-infos ] [ loop?>> ] bi
[ generalize-return ] unless ;
M: #call-recursive propagate-before ( #call-recursive -- ) M: #call-recursive propagate-before ( #call-recursive -- )
[ ] [ return-infos ] [ node-output-infos ] tri [ ] [ return-infos ] [ node-output-infos ] tri

View File

@ -1,5 +1,5 @@
IN: compiler.tree.loop.detection.tests IN: compiler.tree.recursive.tests
USING: compiler.tree.loop.detection tools.test USING: compiler.tree.recursive tools.test
kernel combinators.short-circuit math sequences accessors kernel combinators.short-circuit math sequences accessors
compiler.tree compiler.tree
compiler.tree.builder compiler.tree.builder
@ -10,7 +10,7 @@ compiler.tree.combinators ;
[ { f t t t } ] [ t { f f t t } (tail-calls) ] unit-test [ { f t t t } ] [ t { f f t t } (tail-calls) ] unit-test
[ { f f f t } ] [ t { f f t f } (tail-calls) ] unit-test [ { f f f t } ] [ t { f f t f } (tail-calls) ] unit-test
\ detect-loops must-infer \ analyze-recursive must-infer
: label-is-loop? ( nodes word -- ? ) : label-is-loop? ( nodes word -- ? )
[ [
@ -38,22 +38,22 @@ compiler.tree.combinators ;
dup [ 1+ loop-test-1 ] [ drop ] if ; inline recursive dup [ 1+ loop-test-1 ] [ drop ] if ; inline recursive
[ t ] [ [ t ] [
[ loop-test-1 ] build-tree detect-loops [ loop-test-1 ] build-tree analyze-recursive
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ loop-test-1 1 2 3 ] build-tree detect-loops [ loop-test-1 1 2 3 ] build-tree analyze-recursive
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ [ loop-test-1 ] each ] build-tree detect-loops [ [ loop-test-1 ] each ] build-tree analyze-recursive
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ [ loop-test-1 ] each ] build-tree detect-loops [ [ loop-test-1 ] each ] build-tree analyze-recursive
\ (each-integer) label-is-loop? \ (each-integer) label-is-loop?
] unit-test ] unit-test
@ -61,7 +61,7 @@ compiler.tree.combinators ;
dup [ 1+ loop-test-2 1- ] [ drop ] if ; inline recursive dup [ 1+ loop-test-2 1- ] [ drop ] if ; inline recursive
[ t ] [ [ t ] [
[ loop-test-2 ] build-tree detect-loops [ loop-test-2 ] build-tree analyze-recursive
\ loop-test-2 label-is-not-loop? \ loop-test-2 label-is-not-loop?
] unit-test ] unit-test
@ -69,7 +69,7 @@ compiler.tree.combinators ;
dup [ [ loop-test-3 ] each ] [ drop ] if ; inline recursive dup [ [ loop-test-3 ] each ] [ drop ] if ; inline recursive
[ t ] [ [ t ] [
[ loop-test-3 ] build-tree detect-loops [ loop-test-3 ] build-tree analyze-recursive
\ loop-test-3 label-is-not-loop? \ loop-test-3 label-is-not-loop?
] unit-test ] unit-test
@ -81,7 +81,7 @@ compiler.tree.combinators ;
] if ; inline recursive ] if ; inline recursive
[ f ] [ [ f ] [
[ [ [ ] map ] map ] build-tree detect-loops [ [ [ ] map ] map ] build-tree analyze-recursive
[ [
dup #recursive? [ label>> loop?>> not ] [ drop f ] if dup #recursive? [ label>> loop?>> not ] [ drop f ] if
] contains-node? ] contains-node?
@ -98,22 +98,22 @@ DEFER: a
blah [ b ] [ a ] if ; inline recursive blah [ b ] [ a ] if ; inline recursive
[ t ] [ [ t ] [
[ a ] build-tree detect-loops [ a ] build-tree analyze-recursive
\ a label-is-loop? \ a label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ a ] build-tree detect-loops [ a ] build-tree analyze-recursive
\ b label-is-loop? \ b label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ b ] build-tree detect-loops [ b ] build-tree analyze-recursive
\ a label-is-loop? \ a label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ a ] build-tree detect-loops [ a ] build-tree analyze-recursive
\ b label-is-loop? \ b label-is-loop?
] unit-test ] unit-test
@ -126,12 +126,12 @@ DEFER: a'
blah [ b' ] [ a' ] if ; inline recursive blah [ b' ] [ a' ] if ; inline recursive
[ f ] [ [ f ] [
[ a' ] build-tree detect-loops [ a' ] build-tree analyze-recursive
\ a' label-is-loop? \ a' label-is-loop?
] unit-test ] unit-test
[ f ] [ [ f ] [
[ b' ] build-tree detect-loops [ b' ] build-tree analyze-recursive
\ b' label-is-loop? \ b' label-is-loop?
] unit-test ] unit-test
@ -140,11 +140,11 @@ DEFER: a'
! sound. ! sound.
[ t ] [ [ t ] [
[ b' ] build-tree detect-loops [ b' ] build-tree analyze-recursive
\ a' label-is-loop? \ a' label-is-loop?
] unit-test ] unit-test
[ f ] [ [ f ] [
[ a' ] build-tree detect-loops [ a' ] build-tree analyze-recursive
\ b' label-is-loop? \ b' label-is-loop?
] unit-test ] unit-test

View File

@ -1,14 +1,27 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences namespaces assocs accessors fry USING: kernel assocs namespaces accessors sequences deques
compiler.tree deques search-deques ; search-deques compiler.tree compiler.tree.combinators ;
IN: compiler.tree.loop.detection IN: compiler.tree.recursive
! Collect label info
GENERIC: collect-label-info ( node -- )
M: #return-recursive collect-label-info
dup label>> (>>return) ;
M: #call-recursive collect-label-info
dup label>> calls>> push ;
M: #recursive collect-label-info
label>> V{ } clone >>calls drop ;
M: node collect-label-info drop ;
! A loop is a #recursive which only tail calls itself, and those ! A loop is a #recursive which only tail calls itself, and those
! calls are nested inside other loops only. We optimistically ! calls are nested inside other loops only. We optimistically
! assume all #recursive nodes are loops, disqualifying them as ! assume all #recursive nodes are loops, disqualifying them as
! we see evidence to the contrary. ! we see evidence to the contrary.
: (tail-calls) ( tail? seq -- seq' ) : (tail-calls) ( tail? seq -- seq' )
reverse [ swap [ and ] keep ] map nip reverse ; reverse [ swap [ and ] keep ] map nip reverse ;
@ -84,5 +97,6 @@ M: node collect-loop-info* 2drop ;
] [ drop ] if ] [ drop ] if
] slurp-deque ; ] slurp-deque ;
: detect-loops ( nodes -- nodes ) : analyze-recursive ( nodes -- nodes )
dup [ collect-label-info ] each-node
dup collect-loop-info disqualify-loops ; dup collect-loop-info disqualify-loops ;

View File

@ -1,16 +1,18 @@
IN: compiler.tree.tuple-unboxing.tests IN: compiler.tree.tuple-unboxing.tests
USING: tools.test compiler.tree.tuple-unboxing compiler.tree USING: tools.test compiler.tree.tuple-unboxing compiler.tree
compiler.tree.builder compiler.tree.normalization compiler.tree.builder compiler.tree.recursive
compiler.tree.propagation compiler.tree.cleanup compiler.tree.normalization compiler.tree.propagation
compiler.tree.escape-analysis compiler.tree.tuple-unboxing compiler.tree.cleanup compiler.tree.escape-analysis
compiler.tree.checker compiler.tree.def-use kernel accessors compiler.tree.tuple-unboxing compiler.tree.checker
sequences math math.private sorting math.order binary-search compiler.tree.def-use kernel accessors sequences math
sequences.private slots.private ; math.private sorting math.order binary-search sequences.private
slots.private ;
\ unbox-tuples must-infer \ unbox-tuples must-infer
: test-unboxing ( quot -- ) : test-unboxing ( quot -- )
build-tree build-tree
analyze-recursive
normalize normalize
propagate propagate
cleanup cleanup