2005-04-02 02:39:33 -05:00
|
|
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
2005-07-27 01:46:06 -04:00
|
|
|
IN: inference
|
2005-08-03 18:47:32 -04:00
|
|
|
USING: #<unknown> generic hashtables inference kernel lists
|
|
|
|
matrices namespaces sequences vectors ;
|
|
|
|
|
|
|
|
! We use the recursive-state variable here, to track nested
|
|
|
|
! label scopes, to prevent infinite loops when inlining
|
|
|
|
! recursive methods.
|
2004-12-02 22:44:36 -05:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
GENERIC: literals* ( node -- )
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: literals, ( node -- )
|
|
|
|
[ dup literals* node-successor literals, ] when* ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: literals ( node -- list )
|
|
|
|
[ literals, ] make-list ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
GENERIC: can-kill* ( literal node -- ? )
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: can-kill? ( literal node -- ? )
|
2005-05-21 16:05:39 -04:00
|
|
|
#! Return false if the literal appears in any node in the
|
|
|
|
#! list.
|
2005-05-22 02:35:38 -04:00
|
|
|
dup [
|
2005-07-28 13:07:30 -04:00
|
|
|
2dup can-kill*
|
|
|
|
[ node-successor can-kill? ] [ 2drop f ] ifte
|
2005-05-22 02:35:38 -04:00
|
|
|
] [
|
|
|
|
2drop t
|
|
|
|
] ifte ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: kill-set ( node -- list )
|
2005-05-21 16:05:39 -04:00
|
|
|
#! Push a list of literals that may be killed in the IR.
|
2005-05-22 02:35:38 -04:00
|
|
|
dup literals [ swap can-kill? ] subset-with ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-28 13:07:30 -04:00
|
|
|
: remove-value ( value node -- )
|
2005-07-28 15:17:31 -04:00
|
|
|
2dup [ node-in-d seq-diff ] keep set-node-in-d
|
|
|
|
2dup [ node-out-d seq-diff ] keep set-node-out-d
|
|
|
|
2dup [ node-in-r seq-diff ] keep set-node-in-r
|
|
|
|
[ node-out-r seq-diff ] keep set-node-out-r ;
|
2005-07-27 20:13:11 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
GENERIC: kill-node* ( literals node -- )
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-28 13:07:30 -04:00
|
|
|
M: node kill-node* ( literals node -- ) 2drop ;
|
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
DEFER: kill-node
|
|
|
|
|
|
|
|
: kill-children ( literals node -- )
|
|
|
|
node-children [ kill-node ] each-with ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
|
|
|
: kill-node ( literals node -- )
|
2005-05-22 02:35:38 -04:00
|
|
|
dup [
|
|
|
|
2dup kill-children
|
2005-07-28 13:07:30 -04:00
|
|
|
2dup kill-node*
|
|
|
|
2dup remove-value
|
|
|
|
node-successor kill-node
|
2005-05-22 02:35:38 -04:00
|
|
|
] [
|
|
|
|
2drop
|
|
|
|
] ifte ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
GENERIC: optimize-node* ( node -- node )
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
DEFER: optimize-node ( node -- node/t )
|
2005-05-22 21:07:24 -04:00
|
|
|
|
2005-08-03 18:47:32 -04:00
|
|
|
GENERIC: optimize-children
|
|
|
|
|
|
|
|
M: node optimize-children ( node -- )
|
2005-07-27 20:13:11 -04:00
|
|
|
f swap [
|
|
|
|
node-children [ optimize-node swap >r or r> ] map
|
|
|
|
] keep set-node-children ;
|
2005-05-22 21:07:24 -04:00
|
|
|
|
2005-08-03 18:47:32 -04:00
|
|
|
: optimize-label ( node -- node )
|
|
|
|
dup node-param recursive-state [ cons ] change
|
|
|
|
delegate optimize-children
|
|
|
|
recursive-state [ cdr ] change ;
|
|
|
|
|
2005-07-27 20:13:11 -04:00
|
|
|
: keep-optimizing ( node -- node ? )
|
2005-07-27 01:46:06 -04:00
|
|
|
dup optimize-node* dup t =
|
2005-07-27 20:13:11 -04:00
|
|
|
[ drop f ] [ nip keep-optimizing t or ] ifte ;
|
2005-05-22 02:35:38 -04:00
|
|
|
|
2005-07-27 20:13:11 -04:00
|
|
|
: optimize-node ( node -- node ? )
|
|
|
|
#! Outputs t if any changes were made.
|
|
|
|
keep-optimizing >r dup [
|
|
|
|
dup optimize-children >r
|
|
|
|
dup node-successor optimize-node >r
|
|
|
|
over set-node-successor r> r> r> or or
|
|
|
|
] [ r> ] ifte ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
|
|
|
: optimize ( dataflow -- dataflow )
|
|
|
|
#! Remove redundant literals from the IR. The original IR
|
|
|
|
#! is destructively modified.
|
2005-08-03 18:47:32 -04:00
|
|
|
[
|
|
|
|
recursive-state off
|
|
|
|
dup kill-set over kill-node
|
|
|
|
dup infer-classes
|
|
|
|
optimize-node
|
|
|
|
] with-scope [ optimize ] when ;
|
2005-07-27 01:46:06 -04:00
|
|
|
|
|
|
|
: prune-if ( node quot -- successor/t )
|
|
|
|
over >r call [ r> node-successor ] [ r> drop t ] ifte ;
|
2005-07-27 20:13:11 -04:00
|
|
|
inline
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! Generic nodes
|
|
|
|
M: node literals* ( node -- )
|
|
|
|
node-children [ literals, ] each ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: f can-kill* ( literal node -- ? )
|
|
|
|
2drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: node can-kill* ( literal node -- ? )
|
2005-07-28 18:20:31 -04:00
|
|
|
uses-value? not ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: node kill-node* ( literals node -- )
|
|
|
|
2drop ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
M: f optimize-node* drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
M: node optimize-node* ( node -- t )
|
|
|
|
drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #push
|
|
|
|
M: #push literals* ( node -- )
|
|
|
|
node-out-d % ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: #push can-kill* ( literal node -- ? )
|
|
|
|
2drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: #push kill-node* ( literals node -- )
|
2005-07-28 15:17:31 -04:00
|
|
|
[ node-out-d seq-diff ] keep set-node-out-d ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
M: #push optimize-node* ( node -- node/t )
|
|
|
|
[ node-out-d empty? ] prune-if ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #drop
|
|
|
|
M: #drop can-kill* ( literal node -- ? )
|
2005-07-27 20:13:11 -04:00
|
|
|
2drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
M: #drop optimize-node* ( node -- node/t )
|
|
|
|
[ node-in-d empty? ] prune-if ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #call
|
2005-05-22 21:07:24 -04:00
|
|
|
: (kill-shuffle) ( word -- map )
|
2005-05-22 02:35:38 -04:00
|
|
|
{{
|
2005-07-27 20:13:11 -04:00
|
|
|
[[ dup {{ }} ]]
|
|
|
|
[[ drop {{ }} ]]
|
|
|
|
[[ swap {{ }} ]]
|
2005-05-22 21:07:24 -04:00
|
|
|
[[ over
|
|
|
|
{{
|
2005-07-27 20:13:11 -04:00
|
|
|
[[ { f t } dup ]]
|
2005-05-22 21:07:24 -04:00
|
|
|
}}
|
|
|
|
]]
|
|
|
|
[[ pick
|
|
|
|
{{
|
2005-07-27 20:13:11 -04:00
|
|
|
[[ { f f t } over ]]
|
|
|
|
[[ { f t f } over ]]
|
|
|
|
[[ { f t t } dup ]]
|
2005-05-22 21:07:24 -04:00
|
|
|
}}
|
|
|
|
]]
|
|
|
|
[[ >r {{ }} ]]
|
|
|
|
[[ r> {{ }} ]]
|
2005-05-22 02:35:38 -04:00
|
|
|
}} hash ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 20:13:11 -04:00
|
|
|
M: #call can-kill* ( literal node -- ? )
|
|
|
|
dup node-param (kill-shuffle) >r delegate can-kill* r> or ;
|
|
|
|
|
|
|
|
: kill-mask ( killing node -- mask )
|
|
|
|
dup node-param \ r> = [ node-in-r ] [ node-in-d ] ifte
|
|
|
|
[ swap memq? ] map-with ;
|
|
|
|
|
2005-05-22 21:07:24 -04:00
|
|
|
: lookup-mask ( mask word -- word )
|
2005-07-25 01:04:33 -04:00
|
|
|
over disj [ (kill-shuffle) hash ] [ nip ] ifte ;
|
2005-05-22 21:07:24 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: kill-shuffle ( literals node -- )
|
|
|
|
#! If certain values passing through a stack op are being
|
|
|
|
#! killed, the stack op can be reduced, in extreme cases
|
|
|
|
#! to a no-op.
|
2005-07-25 01:04:33 -04:00
|
|
|
[ [ kill-mask ] keep node-param lookup-mask ] keep
|
2005-05-22 21:07:24 -04:00
|
|
|
set-node-param ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: #call kill-node* ( literals node -- )
|
2005-05-22 21:07:24 -04:00
|
|
|
dup node-param (kill-shuffle)
|
2005-05-22 02:35:38 -04:00
|
|
|
[ kill-shuffle ] [ 2drop ] ifte ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
: optimize-not? ( #call -- ? )
|
|
|
|
dup node-param \ not =
|
|
|
|
[ node-successor #ifte? ] [ drop f ] ifte ;
|
|
|
|
|
|
|
|
: flip-branches ( #ifte -- )
|
|
|
|
dup node-children 2unseq swap 2vector swap set-node-children ;
|
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #call-label
|
|
|
|
M: #call-label can-kill* ( literal node -- ? )
|
|
|
|
2drop t ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #label
|
|
|
|
M: #label can-kill* ( literal node -- ? )
|
2005-07-27 20:13:11 -04:00
|
|
|
node-children first can-kill? ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-08-03 18:47:32 -04:00
|
|
|
M: #simple-label can-kill* ( literal node -- ? )
|
|
|
|
node-children first can-kill? ;
|
|
|
|
|
|
|
|
M: #label optimize-children optimize-label ;
|
|
|
|
|
|
|
|
M: #simple-label optimize-children optimize-label ;
|
|
|
|
|
2005-07-27 20:13:11 -04:00
|
|
|
! #ifte
|
2005-05-22 02:35:38 -04:00
|
|
|
SYMBOL: branch-returns
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-05-22 21:07:24 -04:00
|
|
|
: branch-values ( branches -- )
|
2005-07-22 23:21:50 -04:00
|
|
|
[ last-node node-in-d ] map
|
2005-07-30 02:08:59 -04:00
|
|
|
unify-lengths flip branch-returns set ;
|
2005-05-22 21:07:24 -04:00
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
: can-kill-branches? ( literal node -- ? )
|
|
|
|
#! Check if the literal appears in either branch. This
|
|
|
|
#! assumes that the last element of each branch is a #values
|
|
|
|
#! node.
|
2005-07-28 15:17:31 -04:00
|
|
|
2dup uses-value? [
|
2005-05-22 02:35:38 -04:00
|
|
|
2drop f
|
|
|
|
] [
|
2005-05-22 21:07:24 -04:00
|
|
|
[
|
|
|
|
node-children dup branch-values
|
2005-05-22 02:35:38 -04:00
|
|
|
[ can-kill? ] all-with?
|
|
|
|
] with-scope
|
|
|
|
] ifte ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
: static-branch? ( node -- lit ? )
|
|
|
|
node-in-d first dup safe-literal? ;
|
|
|
|
|
|
|
|
: static-branch ( conditional n -- node )
|
2005-08-02 00:25:05 -04:00
|
|
|
>r [ drop-inputs ] keep r>
|
2005-07-27 01:46:06 -04:00
|
|
|
over node-children nth
|
|
|
|
over node-successor over last-node set-node-successor
|
|
|
|
pick set-node-successor drop ;
|
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
M: #ifte can-kill* ( literal node -- ? )
|
|
|
|
can-kill-branches? ;
|
2005-05-21 16:05:39 -04:00
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
M: #ifte optimize-node* ( node -- node )
|
|
|
|
dup static-branch?
|
|
|
|
[ f swap value= 1 0 ? static-branch ] [ 2drop t ] ifte ;
|
|
|
|
|
2005-05-22 02:35:38 -04:00
|
|
|
! #dispatch
|
|
|
|
M: #dispatch can-kill* ( literal node -- ? )
|
|
|
|
can-kill-branches? ;
|
2005-07-27 01:46:06 -04:00
|
|
|
|
|
|
|
! #values
|
2005-07-27 20:13:11 -04:00
|
|
|
M: #values can-kill* ( literal node -- ? )
|
2005-07-28 15:17:31 -04:00
|
|
|
dupd uses-value? [
|
2005-07-27 20:13:11 -04:00
|
|
|
branch-returns get
|
|
|
|
[ memq? ] subset-with
|
2005-07-28 23:33:18 -04:00
|
|
|
[ [ eq? ] every? ] all?
|
2005-07-27 20:13:11 -04:00
|
|
|
] [
|
|
|
|
drop t
|
|
|
|
] ifte ;
|
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
: subst-values ( new old node -- )
|
|
|
|
dup [
|
|
|
|
3dup [ node-in-d subst ] keep set-node-in-d
|
|
|
|
3dup [ node-in-r subst ] keep set-node-in-r
|
|
|
|
3dup [ node-out-d subst ] keep set-node-out-d
|
|
|
|
3dup [ node-out-r subst ] keep set-node-out-r
|
|
|
|
node-successor subst-values
|
|
|
|
] [
|
|
|
|
3drop
|
|
|
|
] ifte ;
|
|
|
|
|
2005-07-27 20:13:11 -04:00
|
|
|
: values/merge ( #values #merge -- new old )
|
|
|
|
>r >r node-in-d r> node-in-d 2vector unify-lengths 2unseq r> ;
|
|
|
|
|
2005-07-27 01:46:06 -04:00
|
|
|
: post-split ( #values -- node )
|
|
|
|
#! If a #values is followed by a #merge, we need to replace
|
|
|
|
#! meet values after the merge with their branch value in
|
|
|
|
#! #values.
|
|
|
|
dup node-successor dup node-successor
|
2005-07-27 20:13:11 -04:00
|
|
|
values/merge [ subst-values ] keep ;
|
2005-07-27 01:46:06 -04:00
|
|
|
|
2005-08-01 16:22:53 -04:00
|
|
|
M: #values optimize-node* ( node -- node ? )
|
2005-07-27 01:46:06 -04:00
|
|
|
dup node-successor #merge? [ post-split ] [ drop t ] ifte ;
|
2005-07-27 20:13:11 -04:00
|
|
|
|
|
|
|
! #merge
|
|
|
|
M: #merge can-kill* ( literal node -- ? ) 2drop t ;
|