]> gitweb.factorcode.org Git - factor.git/commitdiff
Change high-level IR to not use 'successor' links; add normalization pass
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 28 Jul 2008 01:25:42 +0000 (20:25 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 28 Jul 2008 01:25:42 +0000 (20:25 -0500)
26 files changed:
unfinished/compiler/tree/branch-fusion/branch-fusion.factor [new file with mode: 0644]
unfinished/compiler/tree/builder/builder.factor
unfinished/compiler/tree/cleanup/cleanup.factor [new file with mode: 0644]
unfinished/compiler/tree/combinators/combinators-tests.factor
unfinished/compiler/tree/combinators/combinators.factor
unfinished/compiler/tree/dataflow-analysis/backward/backward.factor [new file with mode: 0644]
unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor [new file with mode: 0644]
unfinished/compiler/tree/dead-code/dead-code.factor
unfinished/compiler/tree/def-use/def-use.factor
unfinished/compiler/tree/dfa/backward/backward.factor [deleted file]
unfinished/compiler/tree/dfa/dfa.factor [deleted file]
unfinished/compiler/tree/loop-detection/loop-detection.factor [new file with mode: 0644]
unfinished/compiler/tree/normalization/normalization-tests.factor [new file with mode: 0644]
unfinished/compiler/tree/normalization/normalization.factor [new file with mode: 0644]
unfinished/compiler/tree/optimizer/optimizer.factor [new file with mode: 0644]
unfinished/compiler/tree/propagation/branches/branches.factor
unfinished/compiler/tree/propagation/inlining/inlining.factor [new file with mode: 0644]
unfinished/compiler/tree/propagation/nodes/nodes.factor
unfinished/compiler/tree/propagation/propagation-tests.factor
unfinished/compiler/tree/propagation/recursive/recursive.factor
unfinished/compiler/tree/propagation/simple/simple.factor
unfinished/compiler/tree/strength-reduction/strength-reduction.factor [new file with mode: 0644]
unfinished/compiler/tree/tree.factor
unfinished/compiler/tree/untupling/untupling.factor
unfinished/stack-checker/backend/backend.factor
unfinished/stack-checker/visitor/visitor.factor

diff --git a/unfinished/compiler/tree/branch-fusion/branch-fusion.factor b/unfinished/compiler/tree/branch-fusion/branch-fusion.factor
new file mode 100644 (file)
index 0000000..b1078c8
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.branch-fusion
+
+: fuse-branches ( nodes -- nodes' ) ;
index 79a2786f64bb599a3ad715a34a7cc8ddad4259cf..c3906585976f9efa4ccc9cbefdb25100d0e8921f 100644 (file)
@@ -7,11 +7,11 @@ stack-checker.state stack-checker.visitor stack-checker.errors
 stack-checker.backend compiler.tree ;
 IN: compiler.tree.builder
 
-: with-tree-builder ( quot -- dataflow )
-    [ node-list new stack-visitor set ] prepose
-    with-infer first>> ; inline
+: with-tree-builder ( quot -- nodes )
+    [ V{ } clone stack-visitor set ] prepose
+    with-infer ; inline
 
-GENERIC# build-tree-with 1 ( quot stack -- dataflow )
+GENERIC# build-tree-with 1 ( quot stack -- nodes )
 
 M: callable build-tree-with
     #! Not safe to call from inference transforms.
@@ -20,7 +20,7 @@ M: callable build-tree-with
         f infer-quot
     ] with-tree-builder nip ;
 
-: build-tree ( quot -- dataflow ) f build-tree-with ;
+: build-tree ( quot -- nodes ) f build-tree-with ;
 
 : (make-specializer) ( class picker -- quot )
     swap "predicate" word-prop append ;
@@ -65,7 +65,7 @@ M: callable build-tree-with
         [ drop ]
     } cond ;
 
-: build-tree-from-word ( word -- effect dataflow )
+: build-tree-from-word ( word -- effect nodes )
     [
         [
             dup +cannot-infer+ word-prop [ cannot-infer-effect ] when
diff --git a/unfinished/compiler/tree/cleanup/cleanup.factor b/unfinished/compiler/tree/cleanup/cleanup.factor
new file mode 100644 (file)
index 0000000..725d6c0
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.cleanup
+
+: cleanup ( nodes -- nodes' ) ;
index 15c07635ad0e4b7419505e99028df512c59c0555..12ab7e3563d5585e6d8c32f2e1f4d20c6d4917da 100644 (file)
@@ -1,17 +1,4 @@
 IN: compiler.tree.combinators.tests
-USING: compiler.tree.combinators compiler.tree.builder tools.test
-kernel ;
-
-[ ] [ [ 1 ] build-tree [ ] transform-nodes drop ] unit-test
-[ ] [ [ 1 2 3 ] build-tree [ ] transform-nodes drop ] unit-test
-
-{ 1 0 } [ [ iterate-next ] iterate-nodes ] must-infer-as
-
-{ 1 0 }
-[
-    [ [ iterate-next ] iterate-nodes ] with-node-iterator
-] must-infer-as
+USING: compiler.tree.combinators tools.test kernel ;
 
 { 1 0 } [ [ drop ] each-node ] must-infer-as
-
-{ 1 0 } [ [ ] map-children ] must-infer-as
index 1f626163e582a7c44e1c932d861fecf8c61936e5..94bcdb2d959048123e37e2f19a72066177bca73f 100644 (file)
@@ -1,64 +1,17 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: fry arrays generic assocs kernel math namespaces parser
-sequences words vectors math.intervals effects classes
-accessors combinators compiler.tree ;
+USING: fry kernel accessors sequences compiler.tree ;
 IN: compiler.tree.combinators
 
-SYMBOL: node-stack
-
-: >node ( node -- ) node-stack get push ;
-: node> ( -- node ) node-stack get pop ;
-: node@ ( -- node ) node-stack get peek ;
-
-: iterate-next ( -- node ) node@ successor>> ;
-
-: iterate-nodes ( node quot -- )
-    over [
-        [ swap >node call node> drop ] keep iterate-nodes
-    ] [
-        2drop
-    ] if ; inline
-
-: (each-node) ( quot -- next )
-    node@ [ swap call ] 2keep
-    children>> [
-        first>> [
-            [ (each-node) ] keep swap
-        ] iterate-nodes
-    ] each drop
-    iterate-next ; inline
-
-: with-node-iterator ( quot -- )
-    >r V{ } clone node-stack r> with-variable ; inline
-
-: each-node ( node quot -- )
-    [
-        swap [
-            [ (each-node) ] keep swap
-        ] iterate-nodes drop
-    ] with-node-iterator ; inline
-
-: map-children ( node quot -- )
-    [ children>> ] dip '[ , change-first drop ] each ; inline
-
-: (transform-nodes) ( prev node quot -- )
-    dup >r call dup [
-        >>successor
-        successor>> dup successor>>
-        r> (transform-nodes)
-    ] [
-        r> 2drop f >>successor drop
-    ] if ; inline
-
-: transform-nodes ( node quot -- new-node )
-    over [
-        [ call dup dup successor>> ] keep (transform-nodes)
-    ] [ drop ] if ; inline
-
-: tail-call? ( -- ? )
-    #! We don't consider calls which do non-local exits to be
-    #! tail calls, because this gives better error traces.
-    node-stack get [
-        successor>> [ #tail? ] [ #terminate? not ] bi and
-    ] all? ;
+: each-node ( nodes quot -- )
+    dup dup '[
+        , [
+            dup #branch? [
+                children>> [ , each-node ] each
+            ] [
+                dup #recursive? [
+                    child>> , each-node
+                ] [ drop ] if
+            ] if
+        ] bi
+    ] each ; inline
diff --git a/unfinished/compiler/tree/dataflow-analysis/backward/backward.factor b/unfinished/compiler/tree/dataflow-analysis/backward/backward.factor
new file mode 100644 (file)
index 0000000..c9caeb8
--- /dev/null
@@ -0,0 +1,40 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.dataflow-analysis.backward
+USING: accessors sequences assocs kernel compiler.tree
+compiler.tree.dataflow-analysis ;
+
+GENERIC: backward ( value node -- )
+
+M: #copy backward
+    #! If the output of a copy is live, then the corresponding
+    #! input is live also.
+    [ out-d>> index ] keep in-d>> nth look-at-value ;
+
+M: #call backward
+    #! If any of the outputs of a call are live, then all
+    #! inputs and outputs must be live.
+    nip [ look-at-inputs ] [ look-at-outputs ] bi ;
+
+M: #call-recursive backward
+    #! If the output of a copy is live, then the corresponding
+    #! inputs to #return nodes are live also.
+    [ out-d>> <reversed> index ] keep label>> returns>>
+    [ <reversed> nth look-at-value ] with each ;
+
+M: #>r backward nip in-d>> first look-at-value ;
+
+M: #r> backward nip in-r>> first look-at-value ;
+
+M: #shuffle backward mapping>> at look-at-value ;
+
+M: #phi backward
+    #! If any of the outputs of a #phi are live, then the
+    #! corresponding inputs are live too.
+    [ [ out-d>> ] [ phi-in-d>> ] bi look-at-corresponding ]
+    [ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ]
+    2bi ;
+
+M: node backward 2drop ;
+
+: backward-dfa ( node quot -- assoc ) [ backward ] dfa ; inline
diff --git a/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor b/unfinished/compiler/tree/dataflow-analysis/dataflow-analysis.factor
new file mode 100644 (file)
index 0000000..b677265
--- /dev/null
@@ -0,0 +1,40 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: fry accessors namespaces assocs dequeues search-dequeues
+kernel sequences words sets stack-checker.inlining compiler.tree
+compiler.tree.def-use compiler.tree.combinators ;
+IN: compiler.tree.dataflow-analysis
+
+! Dataflow analysis
+SYMBOL: work-list
+
+: look-at-value ( values -- )
+    work-list get push-front ;
+
+: look-at-values ( values -- )
+    work-list get '[ , push-front ] each ;
+
+: look-at-inputs ( node -- ) in-d>> look-at-values ;
+
+: look-at-outputs ( node -- ) out-d>> look-at-values ;
+
+: look-at-corresponding ( value inputs outputs -- )
+    [ index ] dip over [ nth look-at-values ] [ 2drop ] if ;
+
+: init-dfa ( -- )
+    #! We add f initially because #phi nodes can have f in their
+    #! inputs.
+    <hashed-dlist> work-list set ;
+
+: iterate-dfa ( value assoc quot -- )
+    2over key? [
+        3drop
+    ] [
+        [ dupd conjoin dup defined-by ] dip call
+    ] if ; inline
+
+: dfa ( node mark-quot iterate-quot -- assoc )
+    init-dfa
+    [ each-node ] dip
+    work-list get H{ { f f } } clone
+    [ rot '[ , , iterate-dfa ] slurp-dequeue ] keep ; inline
index fb5bc36dd71b3391c601a62f5fc31aa459203f32..ccf8a9cd09686205ef8031033a66bc744c67ab06 100644 (file)
@@ -3,8 +3,8 @@
 USING: fry accessors namespaces assocs dequeues search-dequeues
 kernel sequences words sets stack-checker.inlining
 compiler.tree
-compiler.tree.dfa
-compiler.tree.dfa.backward
+compiler.tree.dataflow-analysis
+compiler.tree.dataflow-analysis.backward
 compiler.tree.combinators ;
 IN: compiler.tree.dead-code
 
index d58a44603057c54fca83d910003b83b4afb7afe9..189dd292a278fbefa14fc99b827c668e6b043b92 100755 (executable)
@@ -1,7 +1,7 @@
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces assocs sequences kernel generic assocs classes
-vectors accessors combinators sets stack-checker.state
+USING: arrays namespaces assocs sequences kernel generic assocs
+classes vectors accessors combinators sets stack-checker.state
 compiler.tree compiler.tree.combinators ;
 IN: compiler.tree.def-use
 
@@ -9,60 +9,60 @@ SYMBOL: def-use
 
 TUPLE: definition value node uses ;
 
-: <definition> ( value -- definition )
+: <definition> ( node value -- definition )
     definition new
         swap >>value
+        swap >>node
         V{ } clone >>uses ;
 
 : def-of ( value -- definition )
-    def-use get [ <definition> ] cache ;
+    def-use get at* [ "No def" throw ] unless ;
 
 : def-value ( node value -- )
-    def-of [ [ "Multiple defs" throw ] when ] change-node drop ;
+    def-use get 2dup key? [
+        "Multiple defs" throw
+    ] [
+        [ [ <definition> ] keep ] dip set-at
+    ] if ;
 
 : used-by ( value -- nodes ) def-of uses>> ;
 
 : use-value ( node value -- ) used-by push ;
 
-: defined-by ( value -- node ) def-use get at node>> ;
+: defined-by ( value -- node ) def-of node>> ;
 
 GENERIC: node-uses-values ( node -- values )
 
-M: #declare node-uses-values declaration>> keys ;
-
-M: #phi node-uses-values
-    [ phi-in-d>> concat ] [ phi-in-r>> concat ] bi
-    append sift prune ;
-
+M: #introduce node-uses-values drop f ;
+M: #push node-uses-values drop f ;
 M: #r> node-uses-values in-r>> ;
-
+M: #phi node-uses-values
+    [ phi-in-d>> ] [ phi-in-r>> ] bi append concat sift prune ;
+M: #declare node-uses-values declaration>> keys ;
 M: node node-uses-values in-d>> ;
 
 GENERIC: node-defs-values ( node -- values )
 
-M: #introduce node-defs-values values>> ;
-
+M: #introduce node-defs-values value>> 1array ;
 M: #>r node-defs-values out-r>> ;
-
+M: #branch node-defs-values drop f ;
 M: #phi node-defs-values [ out-d>> ] [ out-r>> ] bi append ;
-
+M: #declare node-defs-values drop f ;
+M: #return node-defs-values drop f ;
+M: #recursive node-defs-values drop f ;
+M: #terminate node-defs-values drop f ;
 M: node node-defs-values out-d>> ;
 
 : node-def-use ( node -- )
     [ dup node-uses-values [ use-value ] with each ]
     [ dup node-defs-values [ def-value ] with each ] bi ;
 
-: check-def ( node -- )
-    [ "No def" throw ] unless ;
-
 : check-use ( uses -- )
     [ empty? [ "No use" throw ] when ]
     [ all-unique? [ "Uses not all unique" throw ] unless ] bi ;
 
 : check-def-use ( -- )
-    def-use get [
-        nip [ node>> check-def ] [ uses>> check-use ] bi
-    ] assoc-each ;
+    def-use get [ nip uses>> check-use ] assoc-each ;
 
 : compute-def-use ( node -- node )
     H{ } clone def-use set
diff --git a/unfinished/compiler/tree/dfa/backward/backward.factor b/unfinished/compiler/tree/dfa/backward/backward.factor
deleted file mode 100644 (file)
index cb2b13e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-IN: compiler.tree.dfa.backward
-USING: accessors sequences assocs kernel compiler.tree
-compiler.tree.dfa ;
-
-GENERIC: backward ( value node -- )
-
-M: #copy backward
-    #! If the output of a copy is live, then the corresponding
-    #! input is live also.
-    [ out-d>> index ] keep in-d>> nth look-at-value ;
-
-M: #call backward
-    #! If any of the outputs of a call are live, then all
-    #! inputs and outputs must be live.
-    nip [ look-at-inputs ] [ look-at-outputs ] bi ;
-
-M: #call-recursive backward
-    #! If the output of a copy is live, then the corresponding
-    #! inputs to #return nodes are live also.
-    [ out-d>> <reversed> index ] keep label>> returns>>
-    [ <reversed> nth look-at-value ] with each ;
-
-M: #>r backward nip in-d>> first look-at-value ;
-
-M: #r> backward nip in-r>> first look-at-value ;
-
-M: #shuffle backward mapping>> at look-at-value ;
-
-M: #phi backward
-    #! If any of the outputs of a #phi are live, then the
-    #! corresponding inputs are live too.
-    [ [ out-d>> ] [ phi-in-d>> ] bi look-at-corresponding ]
-    [ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ]
-    2bi ;
-
-M: node backward 2drop ;
-
-: backward-dfa ( node quot -- assoc ) [ backward ] dfa ; inline
diff --git a/unfinished/compiler/tree/dfa/dfa.factor b/unfinished/compiler/tree/dfa/dfa.factor
deleted file mode 100644 (file)
index 3a7770c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: fry accessors namespaces assocs dequeues search-dequeues
-kernel sequences words sets stack-checker.inlining compiler.tree
-compiler.tree.def-use compiler.tree.combinators ;
-IN: compiler.tree.dfa
-
-! Dataflow analysis
-SYMBOL: work-list
-
-: look-at-value ( values -- )
-    work-list get push-front ;
-
-: look-at-values ( values -- )
-    work-list get '[ , push-front ] each ;
-
-: look-at-inputs ( node -- ) in-d>> look-at-values ;
-
-: look-at-outputs ( node -- ) out-d>> look-at-values ;
-
-: look-at-corresponding ( value inputs outputs -- )
-    [ index ] dip over [ nth look-at-values ] [ 2drop ] if ;
-
-: init-dfa ( -- )
-    #! We add f initially because #phi nodes can have f in their
-    #! inputs.
-    <hashed-dlist> work-list set ;
-
-: iterate-dfa ( value assoc quot -- )
-    2over key? [
-        3drop
-    ] [
-        [ dupd conjoin dup defined-by ] dip call
-    ] if ; inline
-
-: dfa ( node mark-quot iterate-quot -- assoc )
-    init-dfa
-    [ each-node ] dip
-    work-list get H{ { f f } } clone
-    [ rot '[ , , iterate-dfa ] slurp-dequeue ] keep ; inline
diff --git a/unfinished/compiler/tree/loop-detection/loop-detection.factor b/unfinished/compiler/tree/loop-detection/loop-detection.factor
new file mode 100644 (file)
index 0000000..e29ae22
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.loop-detection
+
+: detect-loops ( nodes -- nodes' ) ;
diff --git a/unfinished/compiler/tree/normalization/normalization-tests.factor b/unfinished/compiler/tree/normalization/normalization-tests.factor
new file mode 100644 (file)
index 0000000..39a71ad
--- /dev/null
@@ -0,0 +1,27 @@
+IN: compiler.tree.normalization.tests
+USING: compiler.tree.builder compiler.tree.normalization
+compiler.tree sequences accessors tools.test kernel ;
+
+\ collect-introductions must-infer
+\ fixup-enter-recursive must-infer
+\ eliminate-introductions must-infer
+\ normalize must-infer
+
+[ 3 ] [ [ 3drop 1 2 3 ] build-tree collect-introductions ] unit-test
+
+[ 4 ] [ [ 3drop 1 2 3 3drop drop ] build-tree collect-introductions ] unit-test
+
+[ 3 ] [ [ [ drop ] [ 2drop 3 ] if ] build-tree collect-introductions ] unit-test
+
+[ 2 ] [ [ 3 [ drop ] [ 2drop 3 ] if ] build-tree collect-introductions ] unit-test
+
+: foo ( -- ) swap ; inline recursive
+
+: recursive-inputs ( nodes -- n )
+    [ #recursive? ] find nip child>> first in-d>> length ;
+
+[ 0 2 ] [
+    [ foo ] build-tree
+    [ recursive-inputs ]
+    [ normalize recursive-inputs ] bi
+] unit-test
diff --git a/unfinished/compiler/tree/normalization/normalization.factor b/unfinished/compiler/tree/normalization/normalization.factor
new file mode 100644 (file)
index 0000000..38fa3e1
--- /dev/null
@@ -0,0 +1,94 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: namespaces sequences math accessors kernel arrays
+stack-checker.backend compiler.tree compiler.tree.combinators ;
+IN: compiler.tree.normalization
+
+! A transform pass done before optimization can begin to
+! fix up some oddities in the tree output by the stack checker:
+!
+! - We rewrite the code is that #introduce nodes only appear
+! at the top level, and not inside #recursive. This enables more
+! accurate type inference for 'row polymorphic' combinators.
+!
+! - We collect #return-recursive and #call-recursive nodes and
+! store them in the #recursive's label slot.
+
+GENERIC: normalize* ( node -- )
+
+! Collect introductions
+SYMBOL: introductions
+
+GENERIC: collect-introductions* ( node -- )
+
+: collect-introductions ( nodes -- n )
+    [
+        0 introductions set
+        [ collect-introductions* ] each
+        introductions get
+    ] with-scope ;
+
+M: #introduce collect-introductions* drop introductions inc ;
+
+M: #branch collect-introductions*
+    children>>
+    [ collect-introductions ] map supremum
+    introductions [ + ] change ;
+
+M: node collect-introductions* drop ;
+
+! Eliminate introductions
+SYMBOL: introduction-stack
+
+: fixup-enter-recursive ( recursive -- )
+    [ child>> first ] [ in-d>> ] bi >>in-d
+    [ introduction-stack get prepend ] change-out-d
+    drop ;
+
+GENERIC: eliminate-introductions* ( node -- node' )
+
+: pop-introduction ( -- value )
+    introduction-stack [ unclip-last swap ] change ;
+
+M: #introduce eliminate-introductions*
+    pop-introduction swap value>> [ 1array ] bi@ #copy ;
+
+SYMBOL: remaining-introductions
+
+M: #branch eliminate-introductions*
+    dup children>> [
+        [
+            [ eliminate-introductions* ] change-each
+            introduction-stack get
+        ] with-scope
+    ] map
+    [ remaining-introductions set ]
+    [ [ length ] map infimum introduction-stack [ swap head ] change ]
+    bi ;
+
+M: #phi eliminate-introductions*
+    remaining-introductions get swap
+    [ flip [ over length tail append ] 2map flip ] change-phi-in-d ;
+
+M: node eliminate-introductions* ;
+
+: eliminate-introductions ( recursive n -- )
+    make-values introduction-stack set
+    [ fixup-enter-recursive ]
+    [ child>> [ eliminate-introductions* ] change-each ] bi ;
+
+M: #recursive normalize*
+    [
+        [ child>> collect-introductions ]
+        [ swap eliminate-introductions ]
+        bi
+    ] with-scope ;
+
+! Collect label info
+M: #return-recursive normalize* dup label>> (>>return) ;
+
+M: #call-recursive normalize* dup label>> calls>> push ;
+
+M: node normalize* drop ;
+
+: normalize ( node -- node ) dup [ normalize* ] each-node ;
diff --git a/unfinished/compiler/tree/optimizer/optimizer.factor b/unfinished/compiler/tree/optimizer/optimizer.factor
new file mode 100644 (file)
index 0000000..bb33deb
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: compiler.tree.normalization compiler.tree.copy-equiv
+compiler.tree.propagation compiler.tree.cleanup
+compiler.tree.def-use compiler.tree.untupling
+compiler.tree.dead-code compiler.tree.strength-reduction
+compiler.tree.loop-detection compiler.tree.branch-fusion ;
+IN: compiler.tree.optimizer
+
+: optimize-tree ( nodes -- nodes' )
+    normalize
+    compute-copy-equiv
+    propagate
+    cleanup
+    compute-def-use
+    unbox-tuples
+    compute-def-use
+    remove-dead-code
+    strength-reduce
+    detect-loops
+    fuse-branches ;
index 22f0978e22ebf99aef9bbd8720c11f729b58a0e3..a8b623eb51e6b67f533fb1e24779efbf9707b56d 100644 (file)
@@ -31,21 +31,23 @@ M: #dispatch live-children
     [ children>> ] [ in-d>> first value-info interval>> ] bi
     '[ , interval-contains? [ drop f ] unless ] map-index ;
 
-: infer-children ( node -- assocs )
+SYMBOL: infer-children-data
+
+: infer-children ( node -- )
     [ live-children ] [ child-constraints ] bi [
         [
             over [
                 value-infos [ clone ] change
                 constraints [ clone ] change
                 assume
-                first>> (propagate)
+                (propagate)
             ] [
                 2drop
                 value-infos off
                 constraints off
             ] if
         ] H{ } make-assoc
-    ] 2map ;
+    ] 2map infer-children-data set ;
 
 : (merge-value-infos) ( inputs results -- infos )
     '[ , [ [ value-info ] bind ] 2map value-infos-union ] map ;
@@ -53,7 +55,8 @@ M: #dispatch live-children
 : merge-value-infos ( results inputs outputs -- )
     [ swap (merge-value-infos) ] dip set-value-infos ;
 
-: propagate-branch-phi ( results #phi -- )
+M: #phi propagate-before ( #phi -- )
+    infer-children-data get swap
     [ [ phi-in-d>> ] [ out-d>> ] bi merge-value-infos ]
     [ [ phi-in-r>> ] [ out-r>> ] bi merge-value-infos ]
     2bi ;
@@ -67,10 +70,10 @@ M: #dispatch live-children
         ] [ 3drop ] if
     ] 2each ;
 
-: merge-children ( results node -- )
-    [ successor>> propagate-branch-phi ]
-    [ [ in-d>> first ] [ successor>> ] bi 2drop ] ! branch-phi-constraints ]
-    bi ;
+! : merge-children
+    [ successor>> propagate-branch-phi ]
+    [ [ in-d>> first ] [ successor>> ] bi 2drop ] ! branch-phi-constraints ]
+    bi ;
 
 M: #branch propagate-around
-    [ infer-children ] [ merge-children ] [ annotate-node ] tri ;
+    [ infer-children ] [ annotate-node ] bi ;
diff --git a/unfinished/compiler/tree/propagation/inlining/inlining.factor b/unfinished/compiler/tree/propagation/inlining/inlining.factor
new file mode 100644 (file)
index 0000000..a33ef00
--- /dev/null
@@ -0,0 +1,3 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.propagation.inlining
index f4712f0d5de629db8af6bfade764b2a124d4a94a..2cc98b28c64b161593e56db12c37ef0670a8d9d4 100644 (file)
@@ -14,9 +14,4 @@ GENERIC: propagate-after ( node -- )
 
 GENERIC: propagate-around ( node -- )
 
-: (propagate) ( node -- )
-    [
-        USING: classes prettyprint ; dup class .
-        [ propagate-around ] [ successor>> ] bi
-        (propagate)
-    ] when* ;
+: (propagate) ( node -- ) [ [ propagate-around ] each ] when* ;
index 531284b4fb9cfcd638b0579aa5157a75341a3cd4..f15927c8f4bdeab4669d365550eabc126502ae90 100644 (file)
@@ -1,6 +1,6 @@
 USING: kernel compiler.tree.builder compiler.tree
 compiler.tree.propagation compiler.tree.copy-equiv
-compiler.tree.def-use tools.test math math.order
+compiler.tree.normalization tools.test math math.order
 accessors sequences arrays kernel.private vectors
 alien.accessors alien.c-types sequences.private
 byte-arrays classes.algebra classes.tuple.private
@@ -13,10 +13,10 @@ IN: compiler.tree.propagation.tests
 
 : final-info ( quot -- seq )
     build-tree
-    compute-def-use
+    normalize
     compute-copy-equiv
     propagate
-    last-node node-input-infos ;
+    peek node-input-infos ;
 
 : final-classes ( quot -- seq )
     final-info [ class>> ] map ;
index f5755d77b2ab8ab9d6c1aad24b6c3bb1e5fd8302..e1905d5b44a73d57ad4c7f478a004cb39975765f 100644 (file)
@@ -59,7 +59,7 @@ M: #recursive propagate-around ( #recursive -- )
     iter-counter inc
     iter-counter get 10 > [ "Oops" throw ] when
     dup label>> t >>fixed-point drop
-    [ node-child first>> [ propagate-recursive-phi ] [ (propagate) ] bi ]
+    [ child>> [ first propagate-recursive-phi ] [ (propagate) ] bi ]
     [ dup label>> fixed-point>> [ drop ] [ propagate-around ] if ]
     bi ;
 
index 10beb6f6e0a55ce4cc4a26e63e5fc4d49ab0f6de..42468dff8d2a21c7ef95fdc5a71113f711232393 100644 (file)
@@ -13,7 +13,7 @@ compiler.tree.propagation.constraints ;
 IN: compiler.tree.propagation.simple
 
 M: #introduce propagate-before
-    object <class-info> swap values>> [ set-value-info ] with each ;
+    value>> object <class-info> swap set-value-info ;
 
 M: #push propagate-before
     [ literal>> value>> <literal-info> ] [ out-d>> first ] bi
diff --git a/unfinished/compiler/tree/strength-reduction/strength-reduction.factor b/unfinished/compiler/tree/strength-reduction/strength-reduction.factor
new file mode 100644 (file)
index 0000000..c36395b
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: compiler.tree.strength-reduction
+
+: strength-reduce ( nodes -- nodes' ) ;
index 9a41181726fc5f6eb98304196acd6123ea759b6f..b0dde22112539dbcccbb2c28e81ce34d63dcae38 100755 (executable)
@@ -6,41 +6,17 @@ accessors combinators stack-checker.state stack-checker.visitor ;
 IN: compiler.tree
 
 ! High-level tree SSA form.
-!
-! Invariants:
-! 1) Each value has exactly one definition. A "definition" means
-! the value appears in the out-d or out-r slot of a node, or the
-! values slot of an #introduce node.
-! 2) Each value appears only once in the inputs of a node, where
-! the inputs are the concatenation of in-d and in-r, or in the
-! case of a #phi node, the sequence of sequences in the phi-in-r
-! and phi-in-d slots.
-! 3) A value is never used in the same node where it is defined.
-TUPLE: node < identity-tuple
-in-d out-d in-r out-r info
-successor children ;
 
-M: node hashcode* drop node hashcode* ;
-
-: node-child ( node -- child ) children>> first ;
+TUPLE: node < identity-tuple info ;
 
-: last-node ( node -- last )
-    dup successor>> [ last-node ] [ ] ?if ;
-
-: penultimate-node ( node -- penultimate )
-    dup successor>> dup [
-        dup successor>>
-        [ nip penultimate-node ] [ drop ] if
-    ] [
-        2drop f
-    ] if ;
+M: node hashcode* drop node hashcode* ;
 
-TUPLE: #introduce < node values ;
+TUPLE: #introduce < node value ;
 
-: #introduce ( values -- node )
-    \ #introduce new swap >>values ;
+: #introduce ( value -- node )
+    \ #introduce new swap >>value ;
 
-TUPLE: #call < node word history ;
+TUPLE: #call < node word history in-d out-d ;
 
 : #call ( inputs outputs word -- node )
     \ #call new
@@ -48,7 +24,7 @@ TUPLE: #call < node word history ;
         swap >>out-d
         swap >>in-d ;
 
-TUPLE: #call-recursive < node label ;
+TUPLE: #call-recursive < node label in-d out-d ;
 
 : #call-recursive ( inputs outputs label -- node )
     \ #call-recursive new
@@ -56,14 +32,14 @@ TUPLE: #call-recursive < node label ;
         swap >>out-d
         swap >>in-d ;
 
-TUPLE: #push < node literal ;
+TUPLE: #push < node literal out-d ;
 
 : #push ( literal value -- node )
     \ #push new
         swap 1array >>out-d
         swap >>literal ;
 
-TUPLE: #shuffle < node mapping ;
+TUPLE: #shuffle < node mapping in-d out-d ;
 
 : #shuffle ( inputs outputs mapping -- node )
     \ #shuffle new
@@ -74,27 +50,27 @@ TUPLE: #shuffle < node mapping ;
 : #drop ( inputs -- node )
     { } { } #shuffle ;
 
-TUPLE: #>r < node ;
+TUPLE: #>r < node in-d out-r ;
 
 : #>r ( inputs outputs -- node )
     \ #>r new
         swap >>out-r
         swap >>in-d ;
 
-TUPLE: #r> < node ;
+TUPLE: #r> < node in-r out-d ;
 
 : #r> ( inputs outputs -- node )
     \ #r> new
         swap >>out-d
         swap >>in-r ;
 
-TUPLE: #terminate < node ;
+TUPLE: #terminate < node in-d ;
 
 : #terminate ( stack -- node )
     \ #terminate new
         swap >>in-d ;
 
-TUPLE: #branch < node ;
+TUPLE: #branch < node in-d children ;
 
 : new-branch ( value children class -- node )
     new
@@ -111,7 +87,7 @@ TUPLE: #dispatch < #branch ;
 : #dispatch ( n branches -- node )
     \ #dispatch new-branch ;
 
-TUPLE: #phi < node phi-in-d phi-in-r ;
+TUPLE: #phi < node phi-in-d phi-in-r out-d out-r ;
 
 : #phi ( d-phi-in d-phi-out r-phi-in r-phi-out -- node )
     \ #phi new
@@ -126,22 +102,22 @@ TUPLE: #declare < node declaration ;
     \ #declare new
         swap >>declaration ;
 
-TUPLE: #return < node ;
+TUPLE: #return < node in-d ;
 
 : #return ( stack -- node )
     \ #return new
         swap >>in-d ;
 
-TUPLE: #recursive < node word label loop? returns calls ;
+TUPLE: #recursive < node in-d word label loop? returns calls child ;
 
 : #recursive ( word label inputs child -- node )
     \ #recursive new
-        swap 1array >>children
+        swap >>child
         swap >>in-d
         swap >>label
         swap >>word ;
 
-TUPLE: #enter-recursive < node label ;
+TUPLE: #enter-recursive < node in-d out-d label ;
 
 : #enter-recursive ( label inputs outputs -- node )
     \ #enter-recursive new
@@ -149,7 +125,7 @@ TUPLE: #enter-recursive < node label ;
         swap >>in-d
         swap >>label ;
 
-TUPLE: #return-recursive < node label ;
+TUPLE: #return-recursive < node in-d out-d label ;
 
 : #return-recursive ( label inputs outputs -- node )
     \ #return-recursive new
@@ -157,44 +133,31 @@ TUPLE: #return-recursive < node label ;
         swap >>in-d
         swap >>label ;
 
-TUPLE: #copy < node ;
+TUPLE: #copy < node in-d out-d ;
 
 : #copy ( inputs outputs -- node )
     \ #copy new
         swap >>out-d
         swap >>in-d ;
 
-DEFER: #tail?
-
-PREDICATE: #tail-phi < #phi successor>> #tail? ;
-
-UNION: #tail POSTPONE: f #return #tail-phi #terminate ;
-
-TUPLE: node-list first last ;
-
-: node, ( node -- )
-    stack-visitor get swap
-    over last>>
-    [ [ [ last>> ] dip >>successor drop ] [ >>last drop ] 2bi ]
-    [ [ >>first ] [ >>last ] bi drop ]
-    if ;
-
-M: node-list child-visitor node-list new ;
-M: node-list #introduce, #introduce node, ;
-M: node-list #call, #call node, ;
-M: node-list #push, #push node, ;
-M: node-list #shuffle, #shuffle node, ;
-M: node-list #drop, #drop node, ;
-M: node-list #>r, #>r node, ;
-M: node-list #r>, #r> node, ;
-M: node-list #return, #return node, ;
-M: node-list #enter-recursive, #enter-recursive node, ;
-M: node-list #return-recursive, #return-recursive [ node, ] [ dup label>> (>>return) ] bi ;
-M: node-list #call-recursive, #call-recursive [ node, ] [ dup label>> calls>> push ] bi ;
-M: node-list #terminate, #terminate node, ;
-M: node-list #if, #if node, ;
-M: node-list #dispatch, #dispatch node, ;
-M: node-list #phi, #phi node, ;
-M: node-list #declare, #declare node, ;
-M: node-list #recursive, #recursive node, ;
-M: node-list #copy, #copy node, ;
+: node, ( node -- ) stack-visitor get push ;
+
+M: vector child-visitor V{ } clone ;
+M: vector #introduce, #introduce node, ;
+M: vector #call, #call node, ;
+M: vector #push, #push node, ;
+M: vector #shuffle, #shuffle node, ;
+M: vector #drop, #drop node, ;
+M: vector #>r, #>r node, ;
+M: vector #r>, #r> node, ;
+M: vector #return, #return node, ;
+M: vector #enter-recursive, #enter-recursive node, ;
+M: vector #return-recursive, #return-recursive node, ;
+M: vector #call-recursive, #call-recursive node, ;
+M: vector #terminate, #terminate node, ;
+M: vector #if, #if node, ;
+M: vector #dispatch, #dispatch node, ;
+M: vector #phi, #phi node, ;
+M: vector #declare, #declare node, ;
+M: vector #recursive, #recursive node, ;
+M: vector #copy, #copy node, ;
index ebc43ece084762af3e7b4635d58038c1eab50ffb..7286e6fb652dfe7867d5e395f7f2178cea845e10 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors slots.private kernel namespaces disjoint-sets
 math sequences assocs classes.tuple.private combinators fry sets
 compiler.tree compiler.tree.combinators compiler.tree.copy-equiv
-compiler.tree.dfa compiler.tree.dfa.backward ;
+compiler.tree.dataflow-analysis
+compiler.tree.dataflow-analysis.backward ;
 IN: compiler.tree.untupling
 
 SYMBOL: escaping-values
index 2977f2520a4f3faf67b09ee1e5f065339ab9337d..658a1e9fa1aac04229146c33295431b7f3ddbdb8 100755 (executable)
@@ -41,7 +41,7 @@ SYMBOL: visited
 
 : pop-d  ( -- obj )
     meta-d get dup empty? [
-        drop <value> dup 1array #introduce, d-in inc
+        drop <value> dup #introduce, d-in inc
     ] [ pop ] if ;
 
 : peek-d ( -- obj ) pop-d dup push-d ;
@@ -52,8 +52,11 @@ SYMBOL: visited
 
 : ensure-d ( n -- values ) consume-d dup output-d ;
 
+: make-values ( n -- values )
+    [ <value> ] replicate ;
+
 : produce-d ( n -- values )
-    [ <value> ] replicate dup meta-d get push-all ;
+    make-values dup meta-d get push-all ;
 
 : push-r ( obj -- ) meta-r get push ;
 
index 231b0ab9bf27bf13945bcf001794b8e493f9651e..ce30d12c7ea669da2861053bc2a63c05f2d6d1ba 100644 (file)
@@ -9,7 +9,7 @@ HOOK: child-visitor stack-visitor ( -- visitor )
 
 : nest-visitor ( -- ) child-visitor stack-visitor set ;
 
-HOOK: #introduce, stack-visitor ( values -- )
+HOOK: #introduce, stack-visitor ( value -- )
 HOOK: #call, stack-visitor ( inputs outputs word -- )
 HOOK: #call-recursive, stack-visitor ( inputs outputs word -- )
 HOOK: #push, stack-visitor ( literal value -- )