2006-02-28 00:26:45 -05:00
|
|
|
! Copyright (C) 2004, 2006 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2005-09-09 00:17:19 -04:00
|
|
|
IN: optimizer
|
2006-05-02 14:16:59 -04:00
|
|
|
USING: arrays generic hashtables inference kernel
|
|
|
|
kernel-internals lists math namespaces sequences words ;
|
2005-08-01 16:22:53 -04:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
! Some utilities for splicing in dataflow IR subtrees
|
2006-03-02 01:12:32 -05:00
|
|
|
: post-inline ( #return/#values #call/#merge -- )
|
|
|
|
dup [
|
|
|
|
[
|
|
|
|
>r node-in-d r> node-out-d
|
|
|
|
2array unify-lengths first2
|
2006-03-06 23:35:32 -05:00
|
|
|
] keep subst-values
|
2006-03-02 01:12:32 -05:00
|
|
|
] [
|
|
|
|
2drop
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: subst-node ( old new -- )
|
|
|
|
#! The last node of 'new' becomes 'old', then values are
|
|
|
|
#! substituted. A subsequent optimizer phase kills the
|
|
|
|
#! last node of 'new' and the first node of 'old'.
|
|
|
|
last-node 2dup swap post-inline set-node-successor ;
|
|
|
|
|
2006-05-02 03:05:57 -04:00
|
|
|
: (inline-method) ( #call quot -- node )
|
|
|
|
dup t eq? [
|
|
|
|
2drop t
|
|
|
|
] [
|
|
|
|
over node-in-d dataflow-with
|
|
|
|
[ >r node-param r> remember-node ] 2keep
|
2006-05-02 14:16:59 -04:00
|
|
|
[ subst-node ] keep [ infer-classes ] keep
|
2006-05-02 03:05:57 -04:00
|
|
|
] if ;
|
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
! Single dispatch method inlining optimization
|
|
|
|
: dispatch# ( #call -- n )
|
|
|
|
node-param "combination" word-prop first ;
|
2005-08-02 00:25:05 -04:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
: dispatching-class ( node -- seq ) dup dispatch# node-class# ;
|
2005-08-02 00:25:05 -04:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
: already-inlined? ( node -- ? )
|
|
|
|
#! Was this node inlined from definition of 'word'?
|
|
|
|
dup node-param swap node-history memq? ;
|
|
|
|
|
|
|
|
: specific-method ( word class -- ? ) swap order min-class ;
|
|
|
|
|
|
|
|
: inlining-class ( #call -- class )
|
|
|
|
#! If the generic dispatch can be eliminated, return the
|
|
|
|
#! class of the method that will always be invoked here.
|
2006-05-02 20:26:48 -04:00
|
|
|
dup node-param swap dispatching-class specific-method ;
|
2006-05-02 14:16:59 -04:00
|
|
|
|
|
|
|
: will-inline-method ( node -- quot/t )
|
|
|
|
#! t indicates failure
|
|
|
|
dup inlining-class dup [
|
|
|
|
swap node-param "methods" word-prop hash
|
2005-08-02 00:25:05 -04:00
|
|
|
] [
|
2006-05-02 14:16:59 -04:00
|
|
|
2drop t
|
2005-09-24 15:21:17 -04:00
|
|
|
] if ;
|
2005-08-02 00:25:05 -04:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
: inline-standard-method ( node -- node )
|
|
|
|
dup will-inline-method (inline-method) ;
|
2006-03-02 01:12:32 -05:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
: inline-standard-method? ( #call -- ? )
|
|
|
|
dup already-inlined? not swap node-param standard-generic?
|
|
|
|
and ;
|
2006-05-02 03:05:57 -04:00
|
|
|
|
2006-05-02 14:16:59 -04:00
|
|
|
! Partial dispatch of 2generic words
|
2006-05-02 03:05:57 -04:00
|
|
|
: math-both-known? ( word left right -- ? )
|
|
|
|
math-class-max specific-method ;
|
2006-05-02 14:16:59 -04:00
|
|
|
|
|
|
|
: max-tag ( class -- n ) types peek 1+ num-tags min ;
|
|
|
|
|
|
|
|
: left-partial-math ( word left right -- quot/t )
|
|
|
|
#! The left type is known; dispatch on right
|
|
|
|
\ dup swap max-tag
|
|
|
|
[ >r 2dup r> math-method ] math-vtable* 2nip ;
|
|
|
|
|
|
|
|
: right-partial-math ( word left right -- quot/t )
|
|
|
|
#! The right type is known; dispatch on left
|
|
|
|
\ over rot max-tag
|
|
|
|
[ >r 2dup r> swap math-method ] math-vtable* 2nip ;
|
2006-05-02 03:05:57 -04:00
|
|
|
|
|
|
|
: will-inline-math-method ( word left right -- quot/t )
|
|
|
|
#! t indicates failure
|
|
|
|
{
|
|
|
|
{ [ 3dup math-both-known? ] [ math-method ] }
|
2006-05-02 20:26:48 -04:00
|
|
|
! { [ 3dup drop specific-method ] [ left-partial-math ] }
|
|
|
|
! { [ 3dup nip specific-method ] [ right-partial-math ] }
|
2006-05-02 03:05:57 -04:00
|
|
|
{ [ t ] [ 3drop t ] }
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
: inline-math-method ( #call -- node )
|
2006-05-02 14:16:59 -04:00
|
|
|
dup node-param over 1 node-class# pick 0 node-class#
|
2006-05-02 03:05:57 -04:00
|
|
|
will-inline-math-method (inline-method) ;
|
|
|
|
|
|
|
|
: inline-math-method? ( #call -- ? )
|
2006-05-02 20:26:48 -04:00
|
|
|
dup node-history [ 2generic? ] contains? not
|
|
|
|
swap node-param 2generic? and ;
|
2006-05-02 03:05:57 -04:00
|
|
|
|
|
|
|
: inline-method ( #call -- node )
|
|
|
|
{
|
|
|
|
{ [ dup inline-standard-method? ] [ inline-standard-method ] }
|
|
|
|
{ [ dup inline-math-method? ] [ inline-math-method ] }
|
|
|
|
{ [ t ] [ drop t ] }
|
|
|
|
} cond ;
|
2006-05-02 14:16:59 -04:00
|
|
|
|
|
|
|
! Resolve type checks at compile time where possible
|
|
|
|
: comparable? ( actual testing -- ? )
|
|
|
|
#! If actual is a subset of testing or if the two classes
|
|
|
|
#! are disjoint, return t.
|
|
|
|
2dup class< >r classes-intersect? not r> or ;
|
|
|
|
|
|
|
|
: optimize-predicate? ( #call -- ? )
|
|
|
|
dup node-param "predicating" word-prop dup [
|
2006-05-02 20:26:48 -04:00
|
|
|
>r 0 node-class# r> comparable?
|
2006-05-02 14:16:59 -04:00
|
|
|
] [
|
|
|
|
2drop f
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: inline-literals ( node literals -- node )
|
|
|
|
#! Make #shuffle -> #push -> #return -> successor
|
|
|
|
over drop-inputs [
|
|
|
|
>r >list [ literalize ] map dataflow [ subst-node ] keep
|
|
|
|
r> set-node-successor
|
|
|
|
] keep ;
|
|
|
|
|
|
|
|
: optimize-predicate ( #call -- node )
|
|
|
|
dup node-param "predicating" word-prop >r
|
|
|
|
dup 0 node-class# r> class< 1array inline-literals ;
|