working on partial evaluation

cvs
Slava Pestov 2005-08-08 19:21:14 +00:00
parent 250aabcd36
commit b8260a3de7
13 changed files with 158 additions and 95 deletions

View File

@ -89,8 +89,9 @@ parser prettyprint sequences io vectors words ;
"/library/inference/kill-literals.factor" "/library/inference/kill-literals.factor"
"/library/inference/optimizer.factor" "/library/inference/optimizer.factor"
"/library/inference/inline-methods.factor" "/library/inference/inline-methods.factor"
"/library/inference/print-dataflow.factor"
"/library/inference/known-words.factor" "/library/inference/known-words.factor"
"/library/inference/call-optimizers.factor"
"/library/inference/print-dataflow.factor"
"/library/compiler/assembler.factor" "/library/compiler/assembler.factor"
"/library/compiler/relocate.factor" "/library/compiler/relocate.factor"

View File

@ -2,7 +2,7 @@
! See http://factor.sf.net/license.txt for BSD license. ! See http://factor.sf.net/license.txt for BSD license.
IN: sequences IN: sequences
USING: generic kernel kernel-internals lists math strings USING: generic kernel kernel-internals lists math strings
vectors ; vectors words ;
! Combinators ! Combinators
M: object each ( seq quot -- ) M: object each ( seq quot -- )
@ -225,3 +225,14 @@ IN: kernel
: depth ( -- n ) : depth ( -- n )
#! Push the number of elements on the datastack. #! Push the number of elements on the datastack.
datastack length ; datastack length ;
: cond ( conditions -- )
#! Conditions is a sequence of quotation pairs.
#! { { [ X ] [ Y ] } { [ Z ] [ T ] }
#! => X [ Y ] [ Z [ T ] [ ] ifte ] ifte
#! The last condition should be a catch-all 't'.
[ first call ] find nip second call ;
: with-datastack ( stack word -- stack )
datastack >r >r set-datastack r> execute
datastack r> [ push ] keep set-datastack 2nip ;

View File

@ -221,9 +221,7 @@ M: %call-label simplify-node ( linear vop -- ? )
pick next-logical? [ pick next-logical? [
>r dup dup car next-logical car vop-label >r dup dup car next-logical car vop-label
r> execute swap cdr cons t r> execute swap cdr cons t
] [ ] [ drop f ] ifte ; inline
drop f
] ifte ; inline
: useless-jump ( linear -- linear ? ) : useless-jump ( linear -- linear ? )
#! A jump to a label immediately following is not needed. #! A jump to a label immediately following is not needed.
@ -233,38 +231,21 @@ M: %call-label simplify-node ( linear vop -- ? )
: (dead-code) ( linear -- linear ? ) : (dead-code) ( linear -- linear ? )
#! Remove all nodes until the next #label. #! Remove all nodes until the next #label.
dup [ dup [
dup car %label? [ dup car %label?
f [ f ] [ cdr (dead-code) t or ] ifte
] [ ] [ f ] ifte ;
cdr (dead-code) t or
] ifte
] [
f
] ifte ;
: dead-code ( linear -- linear ? ) : dead-code ( linear -- linear ? )
uncons (dead-code) >r cons r> ; uncons (dead-code) >r cons r> ;
M: %jump-label simplify-node ( linear vop -- linear ? ) M: %jump-label simplify-node ( linear vop -- linear ? )
drop drop {
\ %return dup double-jump [ { [ \ %return dup double-jump ] [ t ] }
t { [ \ %jump-label dup double-jump ] [ t ] }
] [ { [ \ %jump dup double-jump ] [ t ] }
\ %jump-label dup double-jump [ { [ useless-jump ] [ t ] }
t { [ t ] [ dead-code ] }
] [ } cond ;
\ %jump dup double-jump
[
t
] [
useless-jump [
t
] [
dead-code
] ifte
] ifte
] ifte
] ifte ;
M: %target-label simplify-node ( linear vop -- linear ? ) M: %target-label simplify-node ( linear vop -- linear ? )
drop drop

View File

@ -0,0 +1,52 @@
! Copyright (C) 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
IN: inference
USING: errors generic hashtables inference kernel
kernel-internals lists math math-internals strings vectors words ;
! A system for associating dataflow optimizers with words.
: optimizer-hooks ( node -- conditions )
node-param "optimizer-hooks" word-prop ;
: optimize-hooks ( node -- node/t )
dup optimizer-hooks cond ;
: define-optimizers ( word optimizers -- )
{ [ t ] [ drop t ] } add "optimizer-hooks" set-word-prop ;
: partial-eval? ( #call -- ? )
dup node-param "stateless" word-prop [
dup node-in-d [
dup literal?
[ 2drop t ] [ swap node-literals hash* ] ifte
] all-with?
] [
drop f
] ifte ;
: literal-in-d ( #call -- inputs )
dup node-in-d [
dup literal?
[ nip literal-value ] [ swap node-literals hash ] ifte
] map-with ;
: partial-eval ( #call -- node )
dup literal-in-d over node-param
[ with-datastack ] [
[
2drop t
] [
inline-literals
] ifte
] catch ;
M: #call optimize-node* ( node -- node/t )
{
{ [ dup node-param not ] [ node-successor ] }
{ [ dup partial-eval? ] [ partial-eval ] }
{ [ dup optimizer-hooks ] [ optimize-hooks ] }
{ [ dup inlining-class ] [ inline-method ] }
{ [ dup optimize-predicate? ] [ optimize-predicate ] }
{ [ t ] [ drop t ] }
} cond ;

View File

@ -175,6 +175,21 @@ SYMBOL: current-node
: drop-inputs ( node -- #drop ) : drop-inputs ( node -- #drop )
node-in-d clone in-d-node <#drop> ; node-in-d clone in-d-node <#drop> ;
: post-inline ( #return #call -- node )
[ >r node-in-d r> node-out-d ] keep
node-successor [ subst-values ] keep ;
: subst-literals ( successor literals -- #push )
#! Make #push -> #return -> successor
[ literalize ] map dataflow
dup last-node rot post-inline swap
[ set-node-successor ] keep ;
: inline-literals ( node literals -- node )
#! See the #return optimizer.
over drop-inputs
[ >r subst-literals r> set-node-successor ] keep ;
: each-node ( node quot -- ) : each-node ( node quot -- )
over [ over [
[ call ] 2keep swap [ call ] 2keep swap

View File

@ -59,7 +59,8 @@ M: 2generic dispatching-values drop node-in-d 2 swap tail* ;
[ set-node-successor drop ] keep [ set-node-successor drop ] keep
] ifte ; ] ifte ;
: inline-method ( node class -- node ) : inline-method ( node -- node )
dup inlining-class
over node-param "methods" word-prop hash over node-param "methods" word-prop hash
over node-in-d dataflow-with dup solve-recursion over node-in-d dataflow-with dup solve-recursion
>r [ node-param ] keep r> subst-node ; >r [ node-param ] keep r> subst-node ;
@ -76,42 +77,10 @@ M: 2generic dispatching-values drop node-in-d 2 swap tail* ;
2drop f 2drop f
] ifte ; ] ifte ;
: subst-literal ( successor literal -- #push )
#! Make #push -> #return -> successor
literalize unit dataflow
[ last-node set-node-successor ] keep ;
: inline-literal ( node literal -- node )
over drop-inputs
[ >r subst-literal r> set-node-successor ] keep ;
: optimize-predicate ( #call -- node ) : optimize-predicate ( #call -- node )
dup node-param "predicating" word-prop >r dup node-param "predicating" word-prop >r
dup dup node-in-d node-classes* first r> class< dup dup node-in-d node-classes* first r> class<
inline-literal ; unit inline-literals ;
M: #call optimize-node* ( node -- node/t )
dup node-param [
dup inlining-class dup [
inline-method
] [
drop dup optimize-predicate? [
optimize-predicate
] [
dup optimize-not? [
node-successor dup flip-branches
] [
drop t
] ifte
] ifte
] ifte
] [
node-successor
] ifte ;
: post-inline ( #return #call -- node )
[ >r node-in-d r> node-out-d ] keep
node-successor [ subst-values ] keep ;
M: #return optimize-node* ( node -- node/t ) M: #return optimize-node* ( node -- node/t )
#! A #return followed by another node is a result of #! A #return followed by another node is a result of

View File

@ -44,6 +44,17 @@ math math-internals parser sequences vectors words ;
\ over [ \ over infer-shuffle ] "infer" set-word-prop \ over [ \ over infer-shuffle ] "infer" set-word-prop
\ pick [ \ pick infer-shuffle ] "infer" set-word-prop \ pick [ \ pick infer-shuffle ] "infer" set-word-prop
! Flipping branches
\ not {
{ [ dup node-successor #ifte? ] [ node-successor dup flip-branches ] }
} define-optimizers
! Partial evaluation. Most stateless words are colon defs, and
! so are marked as 'stateless'. However primitives are set here.
{
eq?
} [ t "stateless" set-word-prop ] each
! These hacks will go away soon ! These hacks will go away soon
\ delegate [ [ object ] [ object ] ] "infer-effect" set-word-prop \ delegate [ [ object ] [ object ] ] "infer-effect" set-word-prop
\ no-method t "terminator" set-word-prop \ no-method t "terminator" set-word-prop

View File

@ -60,10 +60,6 @@ M: #drop optimize-node* ( node -- node/t )
[ node-in-d empty? ] prune-if ; [ node-in-d empty? ] prune-if ;
! #call ! #call
: optimize-not? ( #call -- ? )
dup node-param \ not =
[ node-successor #ifte? ] [ drop f ] ifte ;
: flip-branches ( #ifte -- ) : flip-branches ( #ifte -- )
dup node-children 2unseq swap 2vector swap set-node-children ; dup node-children 2unseq swap 2vector swap set-node-children ;

View File

@ -143,15 +143,8 @@ M: compound apply-object ( word -- )
] ifte ] ifte
] ifte* ; ] ifte* ;
: with-datastack ( stack word -- stack )
datastack >r >r set-datastack r> execute
datastack r> [ push ] keep set-datastack 2nip ;
: apply-datastack ( word -- )
meta-d [ swap with-datastack ] change ;
: infer-shuffle ( word -- ) : infer-shuffle ( word -- )
dup #call [ dup #call [
over "infer-effect" word-prop over "infer-effect" word-prop
[ apply-datastack ] hairy-node [ meta-d [ swap with-datastack ] change ] hairy-node
] keep node, ; ] keep node, ;

View File

@ -9,16 +9,16 @@ USING: kernel math math-internals ;
! Inverse hyperbolic functions: ! Inverse hyperbolic functions:
! acosh asech asinh acosech atanh acoth ! acosh asech asinh acosech atanh acoth
: acosh dup sq 1 - sqrt + log ; : acosh dup sq 1 - sqrt + log ; stateless
: asech recip acosh ; : asech recip acosh ; stateless
: asinh dup sq 1 + sqrt + log ; : asinh dup sq 1 + sqrt + log ; stateless
: acosech recip asinh ; : acosech recip asinh ; stateless
: atanh dup 1 + swap 1 - neg / log 2 / ; : atanh dup 1 + swap 1 - neg / log 2 / ; stateless
: acoth recip atanh ; : acoth recip atanh ; stateless
: <=1 ( x -- ? ) dup complex? [ drop f ] [ abs 1 <= ] ifte ; : <=1 ( x -- ? ) dup complex? [ drop f ] [ abs 1 <= ] ifte ; stateless
: asin dup <=1 [ fasin ] [ i * asinh -i * ] ifte ; : asin dup <=1 [ fasin ] [ i * asinh -i * ] ifte ; stateless
: acos dup <=1 [ facos ] [ asin pi/2 swap - ] ifte ; : acos dup <=1 [ facos ] [ asin pi/2 swap - ] ifte ; stateless
: atan dup <=1 [ fatan ] [ i * atanh i * ] ifte ; : atan dup <=1 [ fatan ] [ i * atanh i * ] ifte ; stateless
: asec recip acos ; : asec recip acos ; stateless
: acosec recip asin ; : acosec recip asin ; stateless
: acot recip atan ; : acot recip atan ; stateless

View File

@ -17,6 +17,11 @@ words ;
#! Mark the last word to be inlined. #! Mark the last word to be inlined.
word t "inline" set-word-prop ; parsing word t "inline" set-word-prop ; parsing
: stateless ( -- )
#! Mark the last word to be evaluated at compile time if
#! all inputs are literals.
word t "stateless" set-word-prop ; parsing
! The variable "in-definition" is set inside a : ... ;. ! The variable "in-definition" is set inside a : ... ;.
! ( and #! then add "stack-effect" and "documentation" ! ( and #! then add "stack-effect" and "documentation"
! properties to the current word if it is set. ! properties to the current word if it is set.

View File

@ -1,4 +1,5 @@
IN: temporary IN: temporary
USING: alien strings ;
USE: kernel USE: kernel
USE: math USE: math
USE: test USE: test
@ -33,3 +34,26 @@ USE: namespaces
[ [ 9 8 7 6 5 4 3 2 1 ] ] [ [ 9 8 7 6 5 4 3 2 1 ] ]
[ [ 10 [ , ] [ 1 - dup dup 0 = [ drop f ] when ] while ] make-list nip ] [ [ 10 [ , ] [ 1 - dup dup 0 = [ drop f ] when ] while ] make-list nip ]
unit-test unit-test
[ "even" ] [
2 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] unit-test
[ "odd" ] [
3 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] unit-test
[ "neither" ] [
3 {
{ [ dup string? ] [ drop "string" ] }
{ [ dup float? ] [ drop "float" ] }
{ [ dup alien? ] [ drop "alien" ] }
{ [ t ] [ drop "neither" ] }
} cond
] unit-test

View File

@ -6,16 +6,21 @@ IN: words
! or single-stepping. Note that currently, words referring to ! or single-stepping. Note that currently, words referring to
! annotated words cannot be compiled; and annotating a word has ! annotated words cannot be compiled; and annotating a word has
! no effect of compiled calls to that word. ! no effect of compiled calls to that word.
USING: interpreter kernel lists prettyprint sequences USING: interpreter io kernel lists namespaces prettyprint
io strings test ; sequences strings test ;
: annotate ( word quot -- | quot: word def -- def ) : annotate ( word quot -- | quot: word def -- def )
over >r >r dup word-def r> call r> swap (define-compound) ; over >r >r dup word-def r> call r> swap (define-compound) ;
inline inline
: (watch) ( word def -- def ) : (watch) ( word def -- def )
>r "==> " swap word-name append \ print \ .s r> [
cons cons cons ; "===> Entering: " pick word-name append , \ print ,
\ .s ,
%
"===> Leaving: " swap word-name append , \ print ,
\ .s ,
] make-list ;
: watch ( word -- ) : watch ( word -- )
#! Cause a message to be printed out when the word is #! Cause a message to be printed out when the word is