1 ! Copyright (C) 2004, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays generic hashtables inference io kernel math
5 namespaces sequences test vectors ;
7 SYMBOL: optimizer-changed
9 GENERIC: optimize-node* ( node -- node/t )
11 : keep-optimizing ( node -- node ? )
12 dup optimize-node* dup t eq?
13 [ drop f ] [ nip keep-optimizing t or ] if ;
15 : optimize-node ( node -- node )
17 keep-optimizing [ optimizer-changed on ] when
20 : optimize-1 ( node -- node ? )
21 dup kill-values dup infer-classes [
25 ] with-node-iterator ;
27 : optimize ( node -- node )
28 optimize-1 [ optimize ] when ;
30 : prune-if ( node quot -- successor/t )
31 over >r call [ r> node-successor ] [ r> drop t ] if ;
35 M: f optimize-node* drop t ;
37 M: node optimize-node* drop t ;
40 M: #shuffle optimize-node*
41 [ node-values empty? ] prune-if ;
45 dup node-successor #r>? [
46 node-successor node-successor
48 [ node-in-d empty? ] prune-if
53 dup node-successor #>r? [
54 node-successor node-successor
56 [ node-in-r empty? ] prune-if
60 M: #push optimize-node*
61 [ node-out-d empty? ] prune-if ;
64 M: #return optimize-node*
65 node-successor [ node-successor ] [ t ] if* ;
67 ! Some utilities for splicing in dataflow IR subtrees
68 : post-inline ( #return/#values #call/#merge -- )
70 >r node-in-d r> node-out-d 2array unify-lengths first2
73 : ?hash-union ( hash/f hash -- hash )
74 over [ hash-union ] [ nip ] if ;
76 : add-node-literals ( hash node -- )
77 [ node-literals ?hash-union ] keep set-node-literals ;
79 : add-node-classes ( hash node -- )
80 [ node-classes ?hash-union ] keep set-node-classes ;
82 : (subst-classes) ( literals classes node -- )
84 3dup [ add-node-classes ] keep add-node-literals
85 node-successor (subst-classes)
90 : subst-classes ( #return/#values #call/#merge -- )
91 >r dup node-literals swap node-classes r> (subst-classes) ;
93 : subst-node ( old new -- )
94 #! The last node of 'new' becomes 'old', then values are
95 #! substituted. A subsequent optimizer phase kills the
96 #! last node of 'new' and the first node of 'old'.
97 last-node 2dup swap 2dup post-inline subst-classes
100 ! Constant branch folding
101 : fold-branch ( node branch# -- node )
103 >r dup node-successor r> rot node-children nth
104 [ subst-node ] keep r> [ set-node-successor ] keep ;
107 : known-boolean-value? ( node value -- value ? )
112 { [ dup null class< ] [ drop f f ] }
113 { [ dup general-t class< ] [ drop t t ] }
114 { [ dup \ f class< ] [ drop f t ] }
115 { [ t ] [ drop f f ] }
119 M: #if optimize-node*
120 dup dup node-in-d first known-boolean-value?
121 [ 0 1 ? fold-branch ] [ 2drop t ] if ;
124 M: #dispatch optimize-node*
125 dup dup node-in-d first 2dup node-literal? [
126 node-literal fold-branch