compiler.tree.escape-analysis: if the output of an #introduce node has an immutable tuple class type declaration, and it is not passed to any subroutine calls, or returned from the word, then unbox it. This speeds up vector arithmetic words on specialized arrays, because the specialized array is unboxed up-front, eliminating an indirection on every loop iteration
parent
d19c403fee
commit
8a9c15ab0b
|
@ -246,3 +246,5 @@ M: #copy emit-node drop ;
|
||||||
M: #enter-recursive emit-node drop ;
|
M: #enter-recursive emit-node drop ;
|
||||||
|
|
||||||
M: #phi emit-node drop ;
|
M: #phi emit-node drop ;
|
||||||
|
|
||||||
|
M: #declare emit-node drop ;
|
|
@ -49,19 +49,18 @@ PRIVATE>
|
||||||
: build-tree ( word/quot -- nodes )
|
: build-tree ( word/quot -- nodes )
|
||||||
[ f ] dip build-tree-with ;
|
[ f ] dip build-tree-with ;
|
||||||
|
|
||||||
:: build-sub-tree ( #call word/quot -- nodes/f )
|
:: build-sub-tree ( in-d out-d word/quot -- nodes/f )
|
||||||
#! We don't want methods on mixins to have a declaration for that mixin.
|
#! We don't want methods on mixins to have a declaration for that mixin.
|
||||||
#! This slows down compiler.tree.propagation.inlining since then every
|
#! This slows down compiler.tree.propagation.inlining since then every
|
||||||
#! inlined usage of a method has an inline-dependency on the mixin, and
|
#! inlined usage of a method has an inline-dependency on the mixin, and
|
||||||
#! not the more specific type at the call site.
|
#! not the more specific type at the call site.
|
||||||
f specialize-method? [
|
f specialize-method? [
|
||||||
[
|
[
|
||||||
#call in-d>> word/quot build-tree-with unclip-last in-d>> :> in-d
|
in-d word/quot build-tree-with unclip-last in-d>> :> in-d'
|
||||||
{
|
{
|
||||||
{ [ dup not ] [ ] }
|
{ [ dup not ] [ ] }
|
||||||
{ [ dup ends-with-terminate? ] [ #call out-d>> [ f swap #push ] map append ] }
|
{ [ dup ends-with-terminate? ] [ out-d [ f swap #push ] map append ] }
|
||||||
[ in-d #call out-d>> #copy suffix ]
|
[ in-d' out-d [ [ length ] bi@ assert= ] [ #copy suffix ] 2bi ]
|
||||||
} cond
|
} cond
|
||||||
] [ dup inference-error? [ drop f ] [ rethrow ] if ] recover
|
] [ dup inference-error? [ drop f ] [ rethrow ] if ] recover
|
||||||
] with-variable ;
|
] with-variable ;
|
||||||
|
|
|
@ -89,8 +89,6 @@ M: #call cleanup*
|
||||||
[ ]
|
[ ]
|
||||||
} cond ;
|
} cond ;
|
||||||
|
|
||||||
M: #declare cleanup* drop f ;
|
|
||||||
|
|
||||||
: delete-unreachable-branches ( #branch -- )
|
: delete-unreachable-branches ( #branch -- )
|
||||||
dup live-branches>> '[
|
dup live-branches>> '[
|
||||||
_
|
_
|
||||||
|
|
|
@ -43,7 +43,7 @@ GENERIC: node-uses-values ( node -- values )
|
||||||
M: #introduce node-uses-values drop f ;
|
M: #introduce node-uses-values drop f ;
|
||||||
M: #push node-uses-values drop f ;
|
M: #push node-uses-values drop f ;
|
||||||
M: #phi node-uses-values phi-in-d>> concat remove-bottom prune ;
|
M: #phi node-uses-values phi-in-d>> concat remove-bottom prune ;
|
||||||
M: #declare node-uses-values declaration>> keys ;
|
M: #declare node-uses-values drop f ;
|
||||||
M: #terminate node-uses-values [ in-d>> ] [ in-r>> ] bi append ;
|
M: #terminate node-uses-values [ in-d>> ] [ in-r>> ] bi append ;
|
||||||
M: #shuffle node-uses-values [ in-d>> ] [ in-r>> ] bi append ;
|
M: #shuffle node-uses-values [ in-d>> ] [ in-r>> ] bi append ;
|
||||||
M: #alien-callback node-uses-values drop f ;
|
M: #alien-callback node-uses-values drop f ;
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
! Copyright (C) 2008 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: accessors assocs namespaces sequences kernel math
|
USING: accessors assocs namespaces sequences kernel math
|
||||||
combinators sets disjoint-sets fry stack-checker.values ;
|
combinators sets disjoint-sets fry stack-checker.values ;
|
||||||
IN: compiler.tree.escape-analysis.allocations
|
IN: compiler.tree.escape-analysis.allocations
|
||||||
|
|
||||||
|
! A map from values to classes. Only for #introduce outputs
|
||||||
|
SYMBOL: value-classes
|
||||||
|
|
||||||
|
: value-class ( value -- class ) value-classes get at ;
|
||||||
|
|
||||||
|
: set-value-class ( class value -- ) value-classes get set-at ;
|
||||||
|
|
||||||
! A map from values to one of the following:
|
! A map from values to one of the following:
|
||||||
! - f -- initial status, assigned to values we have not seen yet;
|
! - f -- initial status, assigned to values we have not seen yet;
|
||||||
! may potentially become an allocation later
|
! may potentially become an allocation later
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
IN: compiler.tree.escape-analysis.check.tests
|
||||||
|
USING: compiler.tree.escape-analysis.check tools.test accessors kernel
|
||||||
|
kernel.private math compiler.tree.builder compiler.tree.normalization
|
||||||
|
compiler.tree.propagation compiler.tree.cleanup ;
|
||||||
|
|
||||||
|
: test-checker ( quot -- ? )
|
||||||
|
build-tree normalize propagate cleanup run-escape-analysis? ;
|
||||||
|
|
||||||
|
[ t ] [
|
||||||
|
[ { complex } declare [ real>> ] [ imaginary>> ] bi ]
|
||||||
|
test-checker
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ t ] [
|
||||||
|
[ complex boa [ real>> ] [ imaginary>> ] bi ]
|
||||||
|
test-checker
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ t ] [
|
||||||
|
[ [ complex boa [ real>> ] [ imaginary>> ] bi ] when ]
|
||||||
|
test-checker
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ f ] [
|
||||||
|
[ swap 1 2 ? ]
|
||||||
|
test-checker
|
||||||
|
] unit-test
|
|
@ -1,22 +1,32 @@
|
||||||
! Copyright (C) 2008 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: classes classes.tuple math math.private accessors
|
USING: classes classes.tuple math math.private accessors sequences
|
||||||
combinators kernel compiler.tree compiler.tree.combinators
|
combinators.short-circuit kernel compiler.tree
|
||||||
compiler.tree.propagation.info ;
|
compiler.tree.combinators compiler.tree.propagation.info ;
|
||||||
IN: compiler.tree.escape-analysis.check
|
IN: compiler.tree.escape-analysis.check
|
||||||
|
|
||||||
GENERIC: run-escape-analysis* ( node -- ? )
|
GENERIC: run-escape-analysis* ( node -- ? )
|
||||||
|
|
||||||
M: #push run-escape-analysis*
|
: unbox-inputs? ( nodes -- ? )
|
||||||
literal>> [ class immutable-tuple-class? ] [ complex? ] bi or ;
|
|
||||||
|
|
||||||
M: #call run-escape-analysis*
|
|
||||||
{
|
{
|
||||||
{ [ dup immutable-tuple-boa? ] [ t ] }
|
[ length 2 >= ]
|
||||||
[ f ]
|
[ first #introduce? ]
|
||||||
} cond nip ;
|
[ second #declare? ]
|
||||||
|
} 1&& ;
|
||||||
M: node run-escape-analysis* drop f ;
|
|
||||||
|
|
||||||
: run-escape-analysis? ( nodes -- ? )
|
: run-escape-analysis? ( nodes -- ? )
|
||||||
[ run-escape-analysis* ] contains-node? ;
|
{ [ unbox-inputs? ] [ [ run-escape-analysis* ] any? ] } 1|| ;
|
||||||
|
|
||||||
|
M: #push run-escape-analysis*
|
||||||
|
literal>> class immutable-tuple-class? ;
|
||||||
|
|
||||||
|
M: #call run-escape-analysis*
|
||||||
|
immutable-tuple-boa? ;
|
||||||
|
|
||||||
|
M: #recursive run-escape-analysis*
|
||||||
|
child>> run-escape-analysis? ;
|
||||||
|
|
||||||
|
M: #branch run-escape-analysis*
|
||||||
|
children>> [ run-escape-analysis? ] any? ;
|
||||||
|
|
||||||
|
M: node run-escape-analysis* drop f ;
|
||||||
|
|
|
@ -9,7 +9,7 @@ quotations.private prettyprint classes.tuple.private classes
|
||||||
classes.tuple namespaces
|
classes.tuple namespaces
|
||||||
compiler.tree.propagation.info stack-checker.errors
|
compiler.tree.propagation.info stack-checker.errors
|
||||||
compiler.tree.checker
|
compiler.tree.checker
|
||||||
kernel.private ;
|
kernel.private vectors ;
|
||||||
|
|
||||||
GENERIC: count-unboxed-allocations* ( m node -- n )
|
GENERIC: count-unboxed-allocations* ( m node -- n )
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ M: #push count-unboxed-allocations*
|
||||||
dup literal>> class immutable-tuple-class?
|
dup literal>> class immutable-tuple-class?
|
||||||
[ (count-unboxed-allocations) ] [ drop ] if ;
|
[ (count-unboxed-allocations) ] [ drop ] if ;
|
||||||
|
|
||||||
|
M: #introduce count-unboxed-allocations*
|
||||||
|
out-d>> [ escaping-allocation? [ 1+ ] unless ] each ;
|
||||||
|
|
||||||
M: node count-unboxed-allocations* drop ;
|
M: node count-unboxed-allocations* drop ;
|
||||||
|
|
||||||
: count-unboxed-allocations ( quot -- sizes )
|
: count-unboxed-allocations ( quot -- sizes )
|
||||||
|
@ -328,3 +331,17 @@ C: <ro-box> ro-box
|
||||||
TUPLE: empty-tuple ;
|
TUPLE: empty-tuple ;
|
||||||
|
|
||||||
[ ] [ [ empty-tuple boa layout-of ] count-unboxed-allocations drop ] unit-test
|
[ ] [ [ empty-tuple boa layout-of ] count-unboxed-allocations drop ] unit-test
|
||||||
|
|
||||||
|
! New feature!
|
||||||
|
|
||||||
|
[ 1 ] [ [ { complex } declare real>> ] count-unboxed-allocations ] unit-test
|
||||||
|
|
||||||
|
[ 1 ] [
|
||||||
|
[ { complex } declare [ real>> ] [ imaginary>> ] bi ]
|
||||||
|
count-unboxed-allocations
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ 0 ] [
|
||||||
|
[ { vector } declare length>> ]
|
||||||
|
count-unboxed-allocations
|
||||||
|
] unit-test
|
|
@ -15,5 +15,6 @@ IN: compiler.tree.escape-analysis
|
||||||
init-escaping-values
|
init-escaping-values
|
||||||
H{ } clone allocations set
|
H{ } clone allocations set
|
||||||
H{ } clone slot-accesses set
|
H{ } clone slot-accesses set
|
||||||
|
H{ } clone value-classes set
|
||||||
dup (escape-analysis)
|
dup (escape-analysis)
|
||||||
compute-escaping-allocations ;
|
compute-escaping-allocations ;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
! Copyright (C) 2008 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
|
USING: kernel sequences fry math namespaces
|
||||||
compiler.tree
|
compiler.tree
|
||||||
compiler.tree.def-use
|
compiler.tree.def-use
|
||||||
compiler.tree.escape-analysis.allocations ;
|
compiler.tree.escape-analysis.allocations ;
|
||||||
|
@ -8,9 +8,14 @@ IN: compiler.tree.escape-analysis.nodes
|
||||||
|
|
||||||
GENERIC: escape-analysis* ( node -- )
|
GENERIC: escape-analysis* ( node -- )
|
||||||
|
|
||||||
|
SYMBOL: next-node
|
||||||
|
|
||||||
|
: each-with-next ( seq quot: ( elt -- ) -- )
|
||||||
|
dupd '[ 1 + _ ?nth next-node set @ ] each-index ; inline
|
||||||
|
|
||||||
: (escape-analysis) ( node -- )
|
: (escape-analysis) ( node -- )
|
||||||
[
|
[
|
||||||
[ node-defs-values introduce-values ]
|
[ node-defs-values introduce-values ]
|
||||||
[ escape-analysis* ]
|
[ escape-analysis* ]
|
||||||
bi
|
bi
|
||||||
] each ;
|
] each-with-next ;
|
||||||
|
|
|
@ -1,20 +1,36 @@
|
||||||
! Copyright (C) 2008 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 sequences classes.tuple
|
USING: kernel accessors sequences classes.tuple
|
||||||
classes.tuple.private arrays math math.private slots.private
|
classes.tuple.private arrays math math.private slots.private
|
||||||
combinators deques search-deques namespaces fry classes
|
combinators deques search-deques namespaces fry classes
|
||||||
classes.algebra stack-checker.state
|
classes.algebra assocs stack-checker.state
|
||||||
compiler.tree
|
compiler.tree
|
||||||
compiler.tree.propagation.info
|
compiler.tree.propagation.info
|
||||||
compiler.tree.escape-analysis.nodes
|
compiler.tree.escape-analysis.nodes
|
||||||
compiler.tree.escape-analysis.allocations ;
|
compiler.tree.escape-analysis.allocations ;
|
||||||
IN: compiler.tree.escape-analysis.simple
|
IN: compiler.tree.escape-analysis.simple
|
||||||
|
|
||||||
|
M: #declare escape-analysis* drop ;
|
||||||
|
|
||||||
M: #terminate escape-analysis* drop ;
|
M: #terminate escape-analysis* drop ;
|
||||||
|
|
||||||
M: #renaming escape-analysis* inputs/outputs copy-values ;
|
M: #renaming escape-analysis* inputs/outputs copy-values ;
|
||||||
|
|
||||||
M: #introduce escape-analysis* out-d>> unknown-allocations ;
|
: declared-class ( value -- class/f )
|
||||||
|
next-node get dup #declare? [ declaration>> at ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
: record-param-allocation ( value class -- )
|
||||||
|
dup immutable-tuple-class? [
|
||||||
|
[ swap set-value-class ] [
|
||||||
|
all-slots [
|
||||||
|
[ <slot-value> dup ] [ class>> ] bi*
|
||||||
|
record-param-allocation
|
||||||
|
] map swap record-allocation
|
||||||
|
] 2bi
|
||||||
|
] [ drop unknown-allocation ] if ;
|
||||||
|
|
||||||
|
M: #introduce escape-analysis*
|
||||||
|
out-d>> [ dup declared-class record-param-allocation ] each ;
|
||||||
|
|
||||||
DEFER: record-literal-allocation
|
DEFER: record-literal-allocation
|
||||||
|
|
||||||
|
@ -24,7 +40,6 @@ DEFER: record-literal-allocation
|
||||||
: object-slots ( object -- slots/f )
|
: object-slots ( object -- slots/f )
|
||||||
{
|
{
|
||||||
{ [ dup class immutable-tuple-class? ] [ tuple-slots ] }
|
{ [ dup class immutable-tuple-class? ] [ tuple-slots ] }
|
||||||
{ [ dup complex? ] [ [ real-part ] [ imaginary-part ] bi 2array ] }
|
|
||||||
[ drop f ]
|
[ drop f ]
|
||||||
} cond ;
|
} cond ;
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,11 @@ SYMBOL: inlining-count
|
||||||
: splicing-call ( #call word -- nodes )
|
: splicing-call ( #call word -- nodes )
|
||||||
[ [ in-d>> ] [ out-d>> ] bi ] dip #call 1array ;
|
[ [ in-d>> ] [ out-d>> ] bi ] dip #call 1array ;
|
||||||
|
|
||||||
|
: open-code-#call ( #call word/quot -- nodes/f )
|
||||||
|
[ [ in-d>> ] [ out-d>> ] bi ] dip build-sub-tree ;
|
||||||
|
|
||||||
: splicing-body ( #call quot/word -- nodes/f )
|
: splicing-body ( #call quot/word -- nodes/f )
|
||||||
build-sub-tree dup [ analyze-recursive normalize ] when ;
|
open-code-#call dup [ analyze-recursive normalize ] when ;
|
||||||
|
|
||||||
! Dispatch elimination
|
! Dispatch elimination
|
||||||
: undo-inlining ( #call -- ? )
|
: undo-inlining ( #call -- ? )
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
! Copyright (C) 2008 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: namespaces assocs accessors kernel combinators
|
USING: namespaces assocs accessors kernel kernel.private combinators
|
||||||
classes.algebra sequences slots.private fry vectors
|
classes.algebra sequences slots.private fry vectors
|
||||||
classes.tuple.private math math.private arrays
|
classes.tuple.private math math.private arrays
|
||||||
stack-checker.branches
|
stack-checker.branches stack-checker.values
|
||||||
compiler.utilities
|
compiler.utilities
|
||||||
compiler.tree
|
compiler.tree
|
||||||
|
compiler.tree.builder
|
||||||
|
compiler.tree.cleanup
|
||||||
compiler.tree.combinators
|
compiler.tree.combinators
|
||||||
|
compiler.tree.propagation
|
||||||
compiler.tree.propagation.info
|
compiler.tree.propagation.info
|
||||||
compiler.tree.escape-analysis.simple
|
compiler.tree.escape-analysis.simple
|
||||||
compiler.tree.escape-analysis.allocations ;
|
compiler.tree.escape-analysis.allocations ;
|
||||||
|
@ -72,8 +75,8 @@ M: #call unbox-tuples*
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
M: #declare unbox-tuples*
|
M: #declare unbox-tuples*
|
||||||
#! We don't look at declarations after propagation anyway.
|
#! We don't look at declarations after escape analysis anyway.
|
||||||
f >>declaration ;
|
drop f ;
|
||||||
|
|
||||||
M: #copy unbox-tuples*
|
M: #copy unbox-tuples*
|
||||||
[ flatten-values ] change-in-d
|
[ flatten-values ] change-in-d
|
||||||
|
@ -113,6 +116,44 @@ M: #return-recursive unbox-tuples*
|
||||||
[ flatten-values ] change-in-d
|
[ flatten-values ] change-in-d
|
||||||
[ flatten-values ] change-out-d ;
|
[ flatten-values ] change-out-d ;
|
||||||
|
|
||||||
|
: value-declaration ( value -- quot )
|
||||||
|
value-class [ 1array '[ _ declare ] ] [ [ ] ] if* ;
|
||||||
|
|
||||||
|
: unbox-parameter-quot ( allocation -- quot )
|
||||||
|
dup unboxed-allocation {
|
||||||
|
{ [ dup not ] [ 2drop [ ] ] }
|
||||||
|
{ [ dup array? ] [
|
||||||
|
[ value-declaration ] [
|
||||||
|
[
|
||||||
|
[ unbox-parameter-quot ] [ 2 + '[ _ slot ] ] bi*
|
||||||
|
prepose
|
||||||
|
] map-index
|
||||||
|
] bi* '[ @ _ cleave ]
|
||||||
|
] }
|
||||||
|
} cond ;
|
||||||
|
|
||||||
|
: unbox-parameters-quot ( values -- quot )
|
||||||
|
[ unbox-parameter-quot ] map
|
||||||
|
dup [ [ ] = ] all? [ drop [ ] ] [ '[ _ spread ] ] if ;
|
||||||
|
|
||||||
|
: unbox-parameters-nodes ( new-values old-values -- nodes )
|
||||||
|
[ flatten-values ] [ unbox-parameters-quot ] bi build-sub-tree ;
|
||||||
|
|
||||||
|
: new-and-old-values ( values -- new-values old-values )
|
||||||
|
[ length [ <value> ] replicate ] keep ;
|
||||||
|
|
||||||
|
: unbox-hairy-introduce ( #introduce -- nodes )
|
||||||
|
dup out-d>> new-and-old-values
|
||||||
|
[ drop >>out-d ] [ unbox-parameters-nodes ] 2bi
|
||||||
|
swap prefix propagate ;
|
||||||
|
|
||||||
|
M: #introduce unbox-tuples*
|
||||||
|
! For every output that is unboxed, insert slot accessors
|
||||||
|
! to convert the stack value into its unboxed form
|
||||||
|
dup out-d>> [ unboxed-allocation ] any? [
|
||||||
|
unbox-hairy-introduce
|
||||||
|
] when ;
|
||||||
|
|
||||||
! These nodes never participate in unboxing
|
! These nodes never participate in unboxing
|
||||||
: assert-not-unboxed ( values -- )
|
: assert-not-unboxed ( values -- )
|
||||||
dup array?
|
dup array?
|
||||||
|
@ -123,8 +164,6 @@ M: #branch unbox-tuples* dup in-d>> assert-not-unboxed ;
|
||||||
|
|
||||||
M: #return unbox-tuples* dup in-d>> assert-not-unboxed ;
|
M: #return unbox-tuples* dup in-d>> assert-not-unboxed ;
|
||||||
|
|
||||||
M: #introduce unbox-tuples* dup out-d>> assert-not-unboxed ;
|
|
||||||
|
|
||||||
M: #alien-invoke unbox-tuples* dup in-d>> assert-not-unboxed ;
|
M: #alien-invoke unbox-tuples* dup in-d>> assert-not-unboxed ;
|
||||||
|
|
||||||
M: #alien-indirect unbox-tuples* dup in-d>> assert-not-unboxed ;
|
M: #alien-indirect unbox-tuples* dup in-d>> assert-not-unboxed ;
|
||||||
|
|
|
@ -9,7 +9,7 @@ IN: compiler.utilities
|
||||||
dup
|
dup
|
||||||
'[
|
'[
|
||||||
@ [
|
@ [
|
||||||
dup array?
|
dup [ array? ] [ vector? ] bi or
|
||||||
[ _ push-all ] [ _ push ] if
|
[ _ push-all ] [ _ push ] if
|
||||||
] when*
|
] when*
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue