]> gitweb.factorcode.org Git - factor.git/commitdiff
More optimization intended to reduce compile time. Another 10% speedup on compiling...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sat, 6 Dec 2008 17:17:19 +0000 (11:17 -0600)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Sat, 6 Dec 2008 17:17:19 +0000 (11:17 -0600)
- new map-flat combinator replaces usages of 'map flatten' in compiler
- compiler.tree.def-use.simplified uses an explicit accumulator instead of flatten
- compiler.tree.tuple-unboxing uses an explicit accumulator instead of flatten
- fix inlining regression from last time: custom inlining results would sometimes be discarded
- compiler.tree's 3each and 3map combinators rewritten to not use flip
- rewrite math.partial-dispatch without locals (purely stylistic, no performance increase)
- hand-optimize flip for common arrays-of-arrays case
- don't run escape analysis and tuple unboxing if there are no allocations in the IR

18 files changed:
basis/bootstrap/compiler/compiler.factor
basis/compiler/cfg/two-operand/two-operand.factor
basis/compiler/tree/cleanup/cleanup.factor
basis/compiler/tree/combinators/combinators.factor
basis/compiler/tree/dead-code/liveness/liveness.factor
basis/compiler/tree/def-use/simplified/simplified.factor
basis/compiler/tree/escape-analysis/branches/branches.factor
basis/compiler/tree/escape-analysis/check/check.factor [new file with mode: 0644]
basis/compiler/tree/normalization/normalization.factor
basis/compiler/tree/optimizer/optimizer.factor
basis/compiler/tree/propagation/branches/branches.factor
basis/compiler/tree/propagation/copy/copy.factor
basis/compiler/tree/propagation/inlining/inlining.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor
basis/compiler/utilities/utilities.factor [new file with mode: 0644]
basis/math/partial-dispatch/partial-dispatch.factor
core/sequences/sequences.factor

index dabdeea74148d28d25b54d7e9802d6b44bb6c12a..9968af4330e6c3b752b4e117ee7a3b6d57a45eb3 100644 (file)
@@ -60,7 +60,7 @@ nl
 "." write flush
 
 {
-    new-sequence nth push pop peek
+    new-sequence nth push pop peek flip
 } compile-uncompiled
 
 "." write flush
index e943fb48280c28b6ac79979401b1c6390bed3345..dabecaeec4623888fa4be920dad61d040a6c2b09 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays kernel sequences sequences.deep
+USING: accessors arrays kernel sequences compiler.utilities
 compiler.cfg.instructions cpu.architecture ;
 IN: compiler.cfg.two-operand
 
@@ -55,6 +55,6 @@ M: insn convert-two-operand* ;
 : convert-two-operand ( mr -- mr' )
     [
         two-operand? [
-            [ convert-two-operand* ] map flatten
+            [ convert-two-operand* ] map-flat
         ] when
     ] change-instructions ;
index becac01cd5355a957e857d47849dc68c912c71e4..1b0343faa991400e09a0c2b5799b1438b31c1851 100644 (file)
@@ -1,10 +1,11 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences sequences.deep combinators fry
+USING: kernel accessors sequences combinators fry
 classes.algebra namespaces assocs words math math.private
 math.partial-dispatch math.intervals classes classes.tuple
 classes.tuple.private layouts definitions stack-checker.state
 stack-checker.branches
+compiler.utilities
 compiler.tree
 compiler.tree.combinators
 compiler.tree.propagation.info
@@ -33,7 +34,7 @@ GENERIC: cleanup* ( node -- node/nodes )
 : cleanup ( nodes -- nodes' )
     #! We don't recurse into children here, instead the methods
     #! do it since the logic is a bit more involved
-    [ cleanup* ] map flatten ;
+    [ cleanup* ] map-flat ;
 
 : cleanup-folding? ( #call -- ? )
     node-output-infos
index 40bbf81a03710a4ac7afa7c0c70258d0838f666d..030df8484fa164884320ec7345f80c744bf1b1df 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: assocs fry kernel accessors sequences sequences.deep arrays
-stack-checker.inlining namespaces compiler.tree ;
+USING: assocs fry kernel accessors sequences compiler.utilities
+arrays stack-checker.inlining namespaces compiler.tree
+math.order ;
 IN: compiler.tree.combinators
 
 : each-node ( nodes quot: ( node -- ) -- )
@@ -27,7 +28,7 @@ IN: compiler.tree.combinators
                 [ _ map-nodes ] change-child
             ] when
         ] if
-    ] map flatten ; inline recursive
+    ] map-flat ; inline recursive
 
 : contains-node? ( nodes quot: ( node -- ? ) -- ? )
     dup dup '[
@@ -48,12 +49,6 @@ IN: compiler.tree.combinators
 : sift-children ( seq flags -- seq' )
     zip [ nip ] assoc-filter keys ;
 
-: (3each) [ 3array flip ] dip '[ first3 @ ] ; inline
-
-: 3each ( seq1 seq2 seq3 quot -- seq ) (3each) each ; inline
-
-: 3map ( seq1 seq2 seq3 quot -- seq ) (3each) map ; inline
-
 : until-fixed-point ( #recursive quot: ( node -- ) -- )
     over label>> t >>fixed-point drop
     [ with-scope ] 2keep
index 44b71935c8f0fea7a6be46e18bf409329cf6bc9f..9ece5d340b60d497c1ee91b65483d48f6e3b277e 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: fry accessors namespaces assocs deques search-deques
-dlists kernel sequences sequences.deep words sets
+dlists kernel sequences compiler.utilities words sets
 stack-checker.branches compiler.tree compiler.tree.def-use
 compiler.tree.combinators ;
 IN: compiler.tree.dead-code.liveness
@@ -49,4 +49,4 @@ GENERIC: remove-dead-code* ( node -- node' )
 M: node remove-dead-code* ;
 
 : (remove-dead-code) ( nodes -- nodes' )
-    [ remove-dead-code* ] map flatten ;
+    [ remove-dead-code* ] map-flat ;
index edfe633057b72e99ad9f2b071581319f623f930f..9b2a2038da5a26512cce9a56aa09183fb7aaffba 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: sequences sequences.deep kernel
+USING: sequences kernel fry vectors
 compiler.tree compiler.tree.def-use ;
 IN: compiler.tree.def-use.simplified
 
@@ -9,8 +9,6 @@ IN: compiler.tree.def-use.simplified
 ! A 'real' usage is a usage of a value that is not a #renaming.
 TUPLE: real-usage value node ;
 
-GENERIC: actually-used-by* ( value node -- real-usages )
-
 ! Def
 GENERIC: actually-defined-by* ( value node -- real-usage )
 
@@ -25,16 +23,18 @@ M: #return-recursive actually-defined-by* real-usage boa ;
 M: node actually-defined-by* real-usage boa ;
 
 ! Use
-: (actually-used-by) ( value -- real-usages )
-    dup used-by [ actually-used-by* ] with map ;
+GENERIC# actually-used-by* 1 ( value node accum -- )
+
+: (actually-used-by) ( value accum -- )
+    [ [ used-by ] keep ] dip '[ _ swap _ actually-used-by* ] each ;
 
 M: #renaming actually-used-by*
-    inputs/outputs [ indices ] dip nths
-    [ (actually-used-by) ] map ;
+    [ inputs/outputs [ indices ] dip nths ] dip
+    '[ _ (actually-used-by) ] each ;
 
-M: #return-recursive actually-used-by* real-usage boa ;
+M: #return-recursive actually-used-by* [ real-usage boa ] dip push ;
 
-M: node actually-used-by* real-usage boa ;
+M: node actually-used-by* [ real-usage boa ] dip push ;
 
 : actually-used-by ( value -- real-usages )
-    (actually-used-by) flatten ;
+    10 <vector> [ (actually-used-by) ] keep ;
index b728e9a1ba4b597def7482835d831f3e8b476303..2eee3e698bbfe9f428dcb868f5f3ec487a5a1eab 100644 (file)
@@ -33,4 +33,4 @@ M: #branch escape-analysis*
     2bi ;
 
 M: #phi escape-analysis*
-    [ phi-in-d>> <flipped> ] [ out-d>> ] bi merge-allocations ;
+    [ phi-in-d>> flip ] [ out-d>> ] bi merge-allocations ;
diff --git a/basis/compiler/tree/escape-analysis/check/check.factor b/basis/compiler/tree/escape-analysis/check/check.factor
new file mode 100644 (file)
index 0000000..333b3fa
--- /dev/null
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: classes classes.tuple math math.private accessors
+combinators kernel compiler.tree compiler.tree.combinators
+compiler.tree.propagation.info ;
+IN: compiler.tree.escape-analysis.check
+
+GENERIC: run-escape-analysis* ( node -- ? )
+
+M: #push run-escape-analysis*
+    literal>> [ class immutable-tuple-class? ] [ complex? ] bi or ;
+
+M: #call run-escape-analysis*
+    {
+        { [ dup word>> \ <complex> eq? ] [ t ] }
+        { [ dup immutable-tuple-boa? ] [ t ] }
+        [ f ] 
+    } cond nip ;
+
+M: node run-escape-analysis* drop f ;
+
+: run-escape-analysis? ( nodes -- ? )
+    [ run-escape-analysis* ] contains-node? ;
index bebe2e91b6521eb19ac1860566371f182b00c028..8c13de296a05952f9ebe1ff17c147981fde40682 100644 (file)
@@ -1,10 +1,11 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: fry namespaces sequences math accessors kernel arrays
-combinators sequences.deep assocs
+combinators compiler.utilities assocs
 stack-checker.backend
 stack-checker.branches
 stack-checker.inlining
+compiler.utilities
 compiler.tree
 compiler.tree.combinators
 compiler.tree.normalization.introductions
@@ -46,7 +47,7 @@ M: #branch normalize*
     [
         [
             [
-                [ normalize* ] map flatten
+                [ normalize* ] map-flat
                 introduction-stack get
                 2array
             ] with-scope
@@ -70,7 +71,7 @@ M: #phi normalize*
 
 : (normalize) ( nodes introductions -- nodes )
     introduction-stack [
-        [ normalize* ] map flatten
+        [ normalize* ] map-flat
     ] with-variable ;
 
 M: #recursive normalize*
index e37323a2ec69c4991e5497a27e2e1f5e583adf94..54c6c2c117b9c48ba58355ed72c4b605ed6f7ce8 100644 (file)
@@ -6,6 +6,7 @@ compiler.tree.normalization
 compiler.tree.propagation
 compiler.tree.cleanup
 compiler.tree.escape-analysis
+compiler.tree.escape-analysis.check
 compiler.tree.tuple-unboxing
 compiler.tree.identities
 compiler.tree.def-use
@@ -22,8 +23,10 @@ SYMBOL: check-optimizer?
     normalize
     propagate
     cleanup
-    escape-analysis
-    unbox-tuples
+    dup run-escape-analysis? [
+        escape-analysis
+        unbox-tuples
+    ] when
     apply-identities
     compute-def-use
     remove-dead-code
index 424cd8a01c404c25ace5a54047621ee9764b4779..f2613022fc21be595dda41ae6bc06a48c2f5d3ed 100644 (file)
@@ -3,6 +3,7 @@
 USING: fry kernel sequences assocs accessors namespaces
 math.intervals arrays classes.algebra combinators columns
 stack-checker.branches
+compiler.utilities
 compiler.tree
 compiler.tree.combinators
 compiler.tree.propagation.info
@@ -78,7 +79,7 @@ SYMBOL: condition-value
 
 M: #phi propagate-before ( #phi -- )
     [ annotate-phi-inputs ]
-    [ [ phi-info-d>> <flipped> ] [ out-d>> ] bi merge-value-infos ]
+    [ [ phi-info-d>> flip ] [ out-d>> ] bi merge-value-infos ]
     bi ;
 
 : branch-phi-constraints ( output values booleans -- )
@@ -137,8 +138,8 @@ M: #phi propagate-before ( #phi -- )
 M: #phi propagate-after ( #phi -- )
     condition-value get [
         [ out-d>> ]
-        [ phi-in-d>> <flipped> ]
-        [ phi-info-d>> <flipped> ] tri
+        [ phi-in-d>> flip ]
+        [ phi-info-d>> flip ] tri
         [
             [ possible-boolean-values ] map
             branch-phi-constraints
index 2452aba4aa2e8e3ea706ee1b897796c368613cc6..53b7d17326bb2d90e60c42b014dd92818c90447a 100644 (file)
@@ -49,7 +49,7 @@ M: #renaming compute-copy-equiv* inputs/outputs are-copies-of ;
     ] 2each ;
 
 M: #phi compute-copy-equiv*
-    [ phi-in-d>> <flipped> ] [ out-d>> ] bi compute-phi-equiv ;
+    [ phi-in-d>> flip ] [ out-d>> ] bi compute-phi-equiv ;
 
 M: node compute-copy-equiv* drop ;
 
index 0e3b8431a6038fbe3ebc7b5062e84644336c5f3b..fcc3b01dc046cdf818ac4c4df52f1b3ddc166962 100644 (file)
@@ -184,7 +184,7 @@ SYMBOL: history
     over in-d>> second value-info literal>> dup class?
     [ "predicate" word-prop '[ drop @ ] inline-word-def ] [ 3drop f ] if ;
 
-: do-inlining ( #call word -- ? )
+: (do-inlining) ( #call word -- ? )
     #! If the generic was defined in an outer compilation unit,
     #! then it doesn't have a definition yet; the definition
     #! is built at the end of the compilation unit. We do not
@@ -193,14 +193,19 @@ SYMBOL: history
     #! of bounds value. This case comes up if a parsing word
     #! calls the compiler at parse time (doing so is
     #! discouraged, but it should still work.)
-    dup custom-inlining? [ 2dup inline-custom ] [ f ] if [ 2drop f ] [
-        {
-            { [ dup deferred? ] [ 2drop f ] }
-            { [ dup \ instance? eq? ] [ inline-instance-check ] }
-            { [ dup always-inline-word? ] [ inline-word ] }
-            { [ dup standard-generic? ] [ inline-standard-method ] }
-            { [ dup math-generic? ] [ inline-math-method ] }
-            { [ dup method-body? ] [ inline-method-body ] }
-            [ 2drop f ]
-        } cond
-    ] if ;
+    {
+        { [ dup deferred? ] [ 2drop f ] }
+        { [ dup \ instance? eq? ] [ inline-instance-check ] }
+        { [ dup always-inline-word? ] [ inline-word ] }
+        { [ dup standard-generic? ] [ inline-standard-method ] }
+        { [ dup math-generic? ] [ inline-math-method ] }
+        { [ dup method-body? ] [ inline-method-body ] }
+        [ 2drop f ]
+    } cond ;
+
+: do-inlining ( #call word -- ? )
+    #! Note the logic here: if there's a custom inlining hook,
+    #! it is permitted to return f, which means that we try the
+    #! normal inlining heuristic.
+    dup custom-inlining? [ 2dup inline-custom ] [ f ] if
+    [ 2drop t ] [ (do-inlining) ] if ;
index 2c4769abe02ef01e2b588938d39a1fdc84bf31dd..aa04b58de71b3517e77c671c4d4e58e3b1deb151 100644 (file)
@@ -8,7 +8,8 @@ math.functions math.private strings layouts
 compiler.tree.propagation.info compiler.tree.def-use
 compiler.tree.debugger compiler.tree.checker
 slots.private words hashtables classes assocs locals
-specialized-arrays.double system sorting math.libm ;
+specialized-arrays.double system sorting math.libm
+math.intervals ;
 IN: compiler.tree.propagation.tests
 
 \ propagate must-infer
@@ -599,6 +600,10 @@ MIXIN: empty-mixin
 
 [ V{ t } ] [ [ { fixnum } declare 10 mod >float -20 > ] final-literals ] unit-test
 
+[ T{ interval f { 0 t } { 127 t } } ] [
+    [ { integer } declare 127 bitand ] final-info first interval>>
+] unit-test
+
 ! [ V{ string } ] [
 !     [ dup string? t xor [ "A" throw ] [ ] if ] final-classes
 ! ] unit-test
index 52903fce8de3064ba14d6fc322f3b908720488de..f6726e44040a9f44d6a8809592f3bb9d2fa174ae 100644 (file)
@@ -1,9 +1,10 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces assocs accessors kernel combinators
-classes.algebra sequences sequences.deep slots.private
+classes.algebra sequences slots.private fry vectors
 classes.tuple.private math math.private arrays
 stack-checker.branches
+compiler.utilities
 compiler.tree
 compiler.tree.combinators
 compiler.tree.propagation.info
@@ -21,7 +22,7 @@ GENERIC: unbox-tuples* ( node -- node/nodes )
 : (expand-#push) ( object value -- nodes )
     dup unboxed-allocation dup [
         [ object-slots ] [ drop ] [ ] tri*
-        [ (expand-#push) ] 2map
+        [ (expand-#push) ] 2map-flat
     ] [
         drop #push
     ] if ;
@@ -38,11 +39,16 @@ M: #push unbox-tuples* ( #push -- nodes )
 : unbox-<complex> ( #call -- nodes )
     dup unbox-output? [ drop { } ] when ;
 
-: (flatten-values) ( values -- values' )
-    [ dup unboxed-allocation [ (flatten-values) ] [ ] ?if ] map ;
+: (flatten-values) ( values accum -- )
+    dup '[
+        dup unboxed-allocation
+        [ _ (flatten-values) ] [ _ push ] ?if
+    ] each ;
 
 : flatten-values ( values -- values' )
-    dup empty? [ (flatten-values) flatten ] unless ;
+    dup empty? [
+        10 <vector> [ (flatten-values) ] keep
+    ] unless ;
 
 : prepare-slot-access ( #call -- tuple-values outputs slot-values )
     [ in-d>> flatten-values ]
diff --git a/basis/compiler/utilities/utilities.factor b/basis/compiler/utilities/utilities.factor
new file mode 100644 (file)
index 0000000..1f488b3
--- /dev/null
@@ -0,0 +1,31 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences sequences.private arrays vectors fry
+math.order ;
+IN: compiler.utilities
+
+: flattener ( seq quot -- seq vector quot' )
+    over length <vector> [
+        dup
+        '[
+            @ [
+                dup array?
+                [ _ push-all ] [ _ push ] if
+            ] when*
+        ]
+    ] keep ; inline
+
+: flattening ( seq quot combinator -- seq' )
+    [ flattener ] dip dip { } like ; inline
+
+: map-flat ( seq quot -- seq' ) [ each ] flattening ; inline
+
+: 2map-flat ( seq quot -- seq' ) [ 2each ] flattening ; inline
+
+: (3each) ( seq1 seq2 seq3 quot -- n quot' )
+    [ [ [ length ] tri@ min min ] 3keep ] dip
+    '[ [ _ nth-unsafe ] [ _ nth-unsafe ] [ _ nth-unsafe ] tri @ ] ; inline
+
+: 3each ( seq1 seq2 seq3 quot -- seq ) (3each) each ; inline
+
+: 3map ( seq1 seq2 seq3 quot -- seq ) (3each) map ; inline
index bfa127e7e06291552ab52b3b730360b1fff6a6aa..19715357eec1c77c03349820ea1e33bc36e13e08 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel kernel.private math math.private words
-sequences parser namespaces make assocs quotations arrays locals
+sequences parser namespaces make assocs quotations arrays
 generic generic.math hashtables effects compiler.units
 classes.algebra fry combinators ;
 IN: math.partial-dispatch
@@ -45,29 +45,29 @@ M: word integer-op-input-classes
         { bitnot fixnum-bitnot }
     } at swap or ;
 
-:: integer-fixnum-op-quot ( fix-word big-word -- quot )
+: integer-fixnum-op-quot ( fix-word big-word -- quot )
     [
         [ over fixnum? ] %
-        fix-word '[ _ execute ] ,
-        big-word '[ fixnum>bignum _ execute ] ,
+        [ '[ _ execute ] , ]
+        [ '[ fixnum>bignum _ execute ] , ] bi*
         \ if ,
     ] [ ] make ;
 
-:: fixnum-integer-op-quot ( fix-word big-word -- quot )
+: fixnum-integer-op-quot ( fix-word big-word -- quot )
     [
         [ dup fixnum? ] %
-        fix-word '[ _ execute ] ,
-        big-word '[ [ fixnum>bignum ] dip _ execute ] ,
+        [ '[ _ execute ] , ]
+        [ '[ [ fixnum>bignum ] dip _ execute ] , ] bi*
         \ if ,
     ] [ ] make ;
 
-:: integer-integer-op-quot ( fix-word big-word -- quot )
+: integer-integer-op-quot ( fix-word big-word -- quot )
     [
         [ dup fixnum? ] %
-        fix-word big-word integer-fixnum-op-quot ,
+        2dup integer-fixnum-op-quot ,
         [
             [ over fixnum? [ [ fixnum>bignum ] dip ] when ] %
-            big-word ,
+            nip ,
         ] [ ] make ,
         \ if ,
     ] [ ] make ;
index 3461266081d9de2ac0d1529500d0656fe78c0cea..995a8bba4c29e864d44cb8d185f75fe72068a01a 100644 (file)
@@ -835,12 +835,35 @@ PRIVATE>
 
 : supremum ( seq -- n ) dup first [ max ] reduce ;
 
-: flip ( matrix -- newmatrix )
-    dup empty? [
-        dup [ length ] map infimum
-        swap [ [ nth-unsafe ] with { } map-as ] curry { } map-as
-    ] unless ;
-
 : sigma ( seq quot -- n ) [ + ] compose 0 swap reduce ; inline
 
 : count ( seq quot -- n ) [ 1 0 ? ] compose sigma ; inline
+
+! We hand-optimize flip to such a degree because type hints
+! cannot express that an array is an array of arrays yet, and
+! this word happens to be performance-critical since the compiler
+! itself uses it. Optimizing it like this reduced compile time.
+<PRIVATE
+
+: generic-flip ( matrix -- newmatrix )
+    [ dup first length [ length min ] reduce ] keep
+    [ [ nth-unsafe ] with { } map-as ] curry { } map-as ; inline
+
+USE: arrays
+
+: array-length ( array -- len )
+    { array } declare length>> ;
+
+: array-flip ( matrix -- newmatrix )
+    [ dup first array-length [ array-length min ] reduce ] keep
+    [ [ array-nth ] with { } map-as ] curry { } map-as ;
+
+PRIVATE>
+
+: flip ( matrix -- newmatrix )
+    dup empty? [
+        dup array? [
+            dup [ array? ] all?
+            [ array-flip ] [ generic-flip ] if
+        ] [ generic-flip ] if
+    ] unless ;