]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' into cuda-changes
authorJoe Groff <arcata@gmail.com>
Tue, 4 May 2010 19:44:59 +0000 (12:44 -0700)
committerJoe Groff <arcata@gmail.com>
Tue, 4 May 2010 19:44:59 +0000 (12:44 -0700)
181 files changed:
basis/bit-arrays/bit-arrays-tests.factor
basis/bit-arrays/bit-arrays.factor
basis/bootstrap/stage2.factor
basis/compiler/cfg/alias-analysis/alias-analysis-tests.factor [new file with mode: 0644]
basis/compiler/cfg/alias-analysis/alias-analysis.factor
basis/compiler/cfg/build-stack-frame/build-stack-frame.factor
basis/compiler/cfg/builder/builder-tests.factor
basis/compiler/cfg/builder/builder.factor
basis/compiler/cfg/cfg.factor
basis/compiler/cfg/checker/checker.factor
basis/compiler/cfg/comparisons/comparisons.factor
basis/compiler/cfg/copy-prop/copy-prop-tests.factor [new file with mode: 0644]
basis/compiler/cfg/copy-prop/copy-prop.factor
basis/compiler/cfg/dce/dce-tests.factor
basis/compiler/cfg/debugger/debugger.factor
basis/compiler/cfg/def-use/def-use.factor
basis/compiler/cfg/dependence/dependence.factor [new file with mode: 0644]
basis/compiler/cfg/empty-blocks/empty-blocks.factor [deleted file]
basis/compiler/cfg/finalization/authors.txt [new file with mode: 0644]
basis/compiler/cfg/finalization/finalization.factor [new file with mode: 0644]
basis/compiler/cfg/gc-checks/gc-checks-tests.factor
basis/compiler/cfg/gc-checks/gc-checks.factor
basis/compiler/cfg/hats/hats.factor
basis/compiler/cfg/height/height.factor [new file with mode: 0644]
basis/compiler/cfg/height/summary.txt [new file with mode: 0644]
basis/compiler/cfg/instructions/instructions.factor
basis/compiler/cfg/instructions/syntax/syntax.factor
basis/compiler/cfg/intrinsics/alien/alien.factor
basis/compiler/cfg/intrinsics/fixnum/fixnum.factor
basis/compiler/cfg/intrinsics/float/float.factor
basis/compiler/cfg/intrinsics/intrinsics.factor
basis/compiler/cfg/intrinsics/misc/misc.factor
basis/compiler/cfg/intrinsics/simd/backend/backend.factor
basis/compiler/cfg/intrinsics/simd/simd-tests.factor
basis/compiler/cfg/intrinsics/simd/simd.factor
basis/compiler/cfg/intrinsics/slots/slots.factor
basis/compiler/cfg/intrinsics/strings/authors.txt [new file with mode: 0644]
basis/compiler/cfg/intrinsics/strings/strings.factor [new file with mode: 0644]
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/cfg/linear-scan/allocation/spilling/spilling.factor
basis/compiler/cfg/linear-scan/allocation/splitting/splitting.factor
basis/compiler/cfg/linear-scan/allocation/state/state.factor
basis/compiler/cfg/linear-scan/assignment/assignment.factor
basis/compiler/cfg/linear-scan/linear-scan-tests.factor
basis/compiler/cfg/linear-scan/linear-scan.factor
basis/compiler/cfg/linear-scan/live-intervals/live-intervals.factor
basis/compiler/cfg/linear-scan/numbering/numbering.factor
basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor
basis/compiler/cfg/linear-scan/resolve/resolve.factor
basis/compiler/cfg/linearization/linearization-tests.factor [new file with mode: 0644]
basis/compiler/cfg/linearization/linearization.factor
basis/compiler/cfg/linearization/order/order-tests.factor [deleted file]
basis/compiler/cfg/linearization/order/order.factor [deleted file]
basis/compiler/cfg/linearization/summary.txt [deleted file]
basis/compiler/cfg/liveness/ssa/ssa-tests.factor [new file with mode: 0644]
basis/compiler/cfg/liveness/ssa/ssa.factor
basis/compiler/cfg/loop-detection/loop-detection.factor
basis/compiler/cfg/mr/authors.txt [deleted file]
basis/compiler/cfg/mr/mr.factor [deleted file]
basis/compiler/cfg/optimizer/optimizer.factor
basis/compiler/cfg/registers/registers.factor
basis/compiler/cfg/representations/coalescing/authors.txt [new file with mode: 0644]
basis/compiler/cfg/representations/coalescing/coalescing-tests.factor [new file with mode: 0644]
basis/compiler/cfg/representations/coalescing/coalescing.factor [new file with mode: 0644]
basis/compiler/cfg/representations/conversion/authors.txt [new file with mode: 0644]
basis/compiler/cfg/representations/conversion/conversion.factor [new file with mode: 0644]
basis/compiler/cfg/representations/peephole/authors.txt [new file with mode: 0644]
basis/compiler/cfg/representations/peephole/peephole.factor [new file with mode: 0644]
basis/compiler/cfg/representations/preferred/preferred.factor
basis/compiler/cfg/representations/representations-tests.factor
basis/compiler/cfg/representations/representations.factor
basis/compiler/cfg/representations/rewrite/authors.txt [new file with mode: 0644]
basis/compiler/cfg/representations/rewrite/rewrite.factor [new file with mode: 0644]
basis/compiler/cfg/representations/selection/authors.txt [new file with mode: 0644]
basis/compiler/cfg/representations/selection/selection.factor [new file with mode: 0644]
basis/compiler/cfg/rpo/rpo.factor
basis/compiler/cfg/save-contexts/save-contexts.factor
basis/compiler/cfg/scheduling/scheduling-tests.factor [new file with mode: 0644]
basis/compiler/cfg/scheduling/scheduling.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/construction/construction-tests.factor
basis/compiler/cfg/ssa/cssa/cssa.factor
basis/compiler/cfg/ssa/destruction/destruction.factor
basis/compiler/cfg/ssa/interference/interference-tests.factor
basis/compiler/cfg/ssa/liveness/liveness-tests.factor [deleted file]
basis/compiler/cfg/ssa/liveness/liveness.factor [deleted file]
basis/compiler/cfg/stack-frame/stack-frame.factor
basis/compiler/cfg/stacks/finalize/finalize.factor
basis/compiler/cfg/stacks/stacks.factor
basis/compiler/cfg/stacks/uninitialized/uninitialized.factor
basis/compiler/cfg/useless-conditionals/useless-conditionals.factor
basis/compiler/cfg/utilities/utilities.factor
basis/compiler/cfg/value-numbering/alien/alien.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/alien/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/comparisons/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/comparisons/comparisons.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/expressions/expressions.factor
basis/compiler/cfg/value-numbering/folding/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/folding/folding.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/graph/graph.factor
basis/compiler/cfg/value-numbering/math/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/math/math.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/misc/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/misc/misc.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/rewrite/rewrite.factor
basis/compiler/cfg/value-numbering/simd/simd.factor
basis/compiler/cfg/value-numbering/simplify/simplify.factor [deleted file]
basis/compiler/cfg/value-numbering/simplify/summary.txt [deleted file]
basis/compiler/cfg/value-numbering/slots/authors.txt [new file with mode: 0644]
basis/compiler/cfg/value-numbering/slots/slots.factor [new file with mode: 0644]
basis/compiler/cfg/value-numbering/value-numbering-tests.factor
basis/compiler/cfg/value-numbering/value-numbering.factor
basis/compiler/cfg/write-barrier/write-barrier.factor
basis/compiler/codegen/alien/alien.factor [new file with mode: 0644]
basis/compiler/codegen/alien/authors.txt [new file with mode: 0644]
basis/compiler/codegen/codegen.factor
basis/compiler/codegen/fixup/fixup.factor
basis/compiler/compiler.factor
basis/compiler/constants/constants.factor
basis/compiler/tests/codegen.factor
basis/compiler/tests/float.factor
basis/compiler/tests/low-level-ir.factor
basis/compiler/tree/propagation/known-words/known-words.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/compiler/tree/propagation/transforms/transforms.factor
basis/compression/lzw/lzw.factor [changed mode: 0644->0755]
basis/cpu/architecture/architecture.factor
basis/cpu/ppc/assembler/assembler-tests.factor
basis/cpu/ppc/assembler/assembler.factor
basis/cpu/ppc/bootstrap.factor
basis/cpu/ppc/ppc.factor
basis/cpu/x86/32/32.factor
basis/cpu/x86/64/64.factor
basis/cpu/x86/64/unix/unix.factor
basis/cpu/x86/assembler/assembler-tests.factor
basis/cpu/x86/assembler/assembler.factor
basis/cpu/x86/assembler/operands/operands.factor
basis/cpu/x86/bootstrap.factor
basis/cpu/x86/x86.factor
basis/disjoint-sets/disjoint-sets.factor
basis/game/input/xinput/xinput.factor
basis/images/ppm/ppm.factor [changed mode: 0644->0755]
basis/images/tiff/tiff.factor [changed mode: 0644->0755]
basis/io/backend/windows/nt/privileges/privileges.factor
basis/io/launcher/unix/unix-tests.factor
basis/math/blas/matrices/matrices.factor
basis/math/vectors/simd/simd-tests.factor
basis/peg/ebnf/ebnf-tests.factor
basis/peg/ebnf/ebnf.factor
basis/specialized-arrays/specialized-arrays-tests.factor
basis/stack-checker/known-words/known-words.factor
basis/tools/deploy/shaker/shaker.factor
basis/tools/deploy/shaker/strip-debugger.factor
basis/typed/debugger/debugger.factor
basis/typed/typed.factor
basis/ui/gadgets/tables/tables-docs.factor
basis/ui/gadgets/tables/tables.factor
basis/ui/tools/error-list/error-list.factor
basis/windows/directx/dinput/constants/constants.factor [changed mode: 0644->0755]
build-support/cleanup
core/alien/alien-tests.factor
core/bootstrap/primitives.factor
core/continuations/continuations.factor
core/strings/strings-tests.factor
core/strings/strings.factor
extra/benchmark/yuv-to-rgb/yuv-to-rgb.factor
extra/compiler/graphviz/graphviz.factor
vm/alien.cpp
vm/code_blocks.cpp
vm/compaction.cpp
vm/debug.cpp
vm/gc.cpp
vm/gc.hpp
vm/image.cpp
vm/instruction_operands.cpp
vm/instruction_operands.hpp
vm/layouts.hpp
vm/primitives.hpp
vm/slot_visitor.hpp
vm/strings.cpp
vm/utilities.hpp
vm/vm.hpp

index f08db68441c9484a7f17c2f3c9752abdf42719c2..46089e3f7b97d90cfe089cfe36b6198b75e045bc 100644 (file)
@@ -1,4 +1,4 @@
-USING: sequences sequences.private arrays bit-arrays kernel
+USING: alien sequences sequences.private arrays bit-arrays kernel
 tools.test math random ;
 IN: bit-arrays.tests
 
@@ -79,4 +79,8 @@ IN: bit-arrays.tests
 
 [ 49 ] [ 49 <bit-array> dup set-bits [ ] count ] unit-test
 
+[ 1 ] [ ?{ f t f t } byte-length ] unit-test
+
+[ HEX: a ] [ ?{ f t f t } bit-array>integer ] unit-test
+
 [ HEX: 100 ] [ ?{ f f f f f f f f t } bit-array>integer ] unit-test
index 798bfb8ae94cd5c2cd151b34b4799f018177d2e2..ade7d8ddac0f399c765920b7c8349625a725a6fa 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2007, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.data accessors math alien.accessors kernel
-kernel.private sequences sequences.private byte-arrays
-parser prettyprint.custom fry ;
+USING: alien alien.data accessors io.binary math math.bitwise
+alien.accessors kernel kernel.private sequences
+sequences.private byte-arrays parser prettyprint.custom fry
+locals ;
 IN: bit-arrays
 
 TUPLE: bit-array
@@ -13,11 +14,10 @@ TUPLE: bit-array
 
 : n>byte ( m -- n ) -3 shift ; inline
 
-: byte/bit ( n alien -- byte bit )
-    over n>byte alien-unsigned-1 swap 7 bitand ; inline
+: bit/byte ( n -- bit byte ) [ 7 bitand ] [ n>byte ] bi ; inline
 
-: set-bit ( ? byte bit -- byte )
-    2^ rot [ bitor ] [ bitnot bitand ] if ; inline
+: bit-index ( n bit-array -- bit# byte# byte-array )
+    [ >fixnum bit/byte ] [ underlying>> ] bi* ; inline
 
 : bits>cells ( m -- n ) 31 + -5 shift ; inline
 
@@ -25,7 +25,7 @@ TUPLE: bit-array
 
 : (set-bits) ( bit-array n -- )
     [ [ length bits>cells ] keep ] dip swap underlying>>
-    '[ 2 shift [ _ _ ] dip set-alien-unsigned-4 ] each-integer ; inline
+    '[ [ _ _ ] dip 4 * set-alien-unsigned-4 ] each-integer ; inline
 
 : clean-up ( bit-array -- )
     ! Zero bits after the end.
@@ -47,12 +47,13 @@ PRIVATE>
 M: bit-array length length>> ; inline
 
 M: bit-array nth-unsafe
-    [ >fixnum ] [ underlying>> ] bi* byte/bit bit? ; inline
+    bit-index nth-unsafe swap bit? ; inline
+
+:: toggle-bit ( ? n x -- y )
+    x n ? [ set-bit ] [ clear-bit ] if ; inline
 
 M: bit-array set-nth-unsafe
-    [ >fixnum ] [ underlying>> ] bi*
-    [ byte/bit set-bit ] 2keep
-    swap n>byte set-alien-unsigned-1 ; inline
+    bit-index [ toggle-bit ] change-nth-unsafe ; inline
 
 GENERIC: clear-bits ( bit-array -- )
 
@@ -83,25 +84,17 @@ M: bit-array resize
     bit-array boa
     dup clean-up ; inline
 
-M: bit-array byte-length length 7 + -3 shift ; inline
+M: bit-array byte-length length bits>bytes ; inline
 
 SYNTAX: ?{ \ } [ >bit-array ] parse-literal ;
 
 : integer>bit-array ( n -- bit-array )
-    dup 0 = [
-        <bit-array>
-    ] [
-        [ log2 1 + <bit-array> 0 ] keep
-        [ dup 0 = ] [
-            [ pick underlying>> pick set-alien-unsigned-1 ] keep
-            [ 1 + ] [ -8 shift ] bi*
-        ] until 2drop
-    ] if ;
+    dup 0 =
+    [ <bit-array> ]
+    [ dup log2 1 + [ nip ] [ bits>bytes >le ] 2bi bit-array boa ] if ;
 
 : bit-array>integer ( bit-array -- n )
-    0 swap underlying>> dup length iota <reversed> [
-        alien-unsigned-1 swap 8 shift bitor
-    ] with each ;
+    underlying>> le> ;
 
 INSTANCE: bit-array sequence
 
index 98b6a472edc0e0ad49b44076e790379c67d11a7c..da4fbc444b8f0cad187d96b22d3de51a9a42f32c 100644 (file)
@@ -51,9 +51,11 @@ SYMBOL: bootstrap-time
 
 : save/restore-error ( quot -- )
     error get-global
+    original-error get-global
     error-continuation get-global
-    [ call ] 2dip
+    [ call ] 3dip
     error-continuation set-global
+    original-error set-global
     error set-global ; inline
 
 
@@ -89,6 +91,7 @@ SYMBOL: bootstrap-time
     run-bootstrap-init
 
     f error set-global
+    f original-error set-global
     f error-continuation set-global
 
     nano-count swap - bootstrap-time set-global
diff --git a/basis/compiler/cfg/alias-analysis/alias-analysis-tests.factor b/basis/compiler/cfg/alias-analysis/alias-analysis-tests.factor
new file mode 100644 (file)
index 0000000..4a41129
--- /dev/null
@@ -0,0 +1,244 @@
+USING: arrays compiler.cfg.alias-analysis compiler.cfg.instructions
+compiler.cfg.registers compiler.cfg.debugger compiler.cfg.comparisons
+cpu.architecture tools.test ;
+IN: compiler.cfg.alias-analysis.tests
+
+! Redundant load elimination
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##copy f 2 1 any-rep }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##slot-imm f 2 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Store-load forwarding
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##set-slot-imm f 1 0 1 0 }
+        T{ ##copy f 2 1 any-rep }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##set-slot-imm f 1 0 1 0 }
+        T{ ##slot-imm f 2 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Dead store elimination
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##set-slot-imm f 2 0 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##set-slot-imm f 1 0 1 0 }
+        T{ ##set-slot-imm f 2 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Redundant store elimination
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##set-slot-imm f 1 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##copy f 2 1 any-rep }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##copy f 2 1 any-rep }
+        T{ ##set-slot-imm f 2 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Not a redundant load
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##set-slot-imm f 0 1 1 0 }
+        T{ ##slot-imm f 2 0 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##slot-imm f 1 0 1 0 }
+        T{ ##set-slot-imm f 0 1 1 0 }
+        T{ ##slot-imm f 2 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Not a redundant store
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##set-slot-imm f 2 1 1 0 }
+        T{ ##slot-imm f 4 0 1 0 }
+        T{ ##set-slot-imm f 3 1 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##set-slot-imm f 2 1 1 0 }
+        T{ ##slot-imm f 4 0 1 0 }
+        T{ ##set-slot-imm f 3 1 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! There's a redundant load, but not a redundant store
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##slot-imm f 4 0 1 0 }
+        T{ ##set-slot-imm f 2 0 1 0 }
+        T{ ##slot f 5 0 3 0 0 }
+        T{ ##set-slot-imm f 3 0 1 0 }
+        T{ ##copy f 6 3 any-rep }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##slot-imm f 4 0 1 0 }
+        T{ ##set-slot-imm f 2 0 1 0 }
+        T{ ##slot f 5 0 3 0 0 }
+        T{ ##set-slot-imm f 3 0 1 0 }
+        T{ ##slot-imm f 6 0 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Fresh allocations don't alias existing values
+
+! Redundant load elimination
+[
+    V{
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##set-slot-imm f 3 4 1 0 }
+        T{ ##set-slot-imm f 2 1 1 0 }
+        T{ ##copy f 5 3 any-rep }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##set-slot-imm f 3 4 1 0 }
+        T{ ##set-slot-imm f 2 1 1 0 }
+        T{ ##slot-imm f 5 4 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Redundant store elimination
+[
+    V{
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##slot-imm f 5 1 1 0 }
+        T{ ##set-slot-imm f 3 4 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##set-slot-imm f 1 4 1 0 }
+        T{ ##slot-imm f 5 1 1 0 }
+        T{ ##set-slot-imm f 3 4 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Storing a new alias class into another object means that heap-ac
+! can now alias the new ac
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##set-slot-imm f 0 4 1 0 }
+        T{ ##set-slot-imm f 4 2 1 0 }
+        T{ ##slot-imm f 5 3 1 0 }
+        T{ ##set-slot-imm f 1 5 1 0 }
+        T{ ##slot-imm f 6 4 1 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##peek f 3 D 3 }
+        T{ ##allot f 4 16 array }
+        T{ ##set-slot-imm f 0 4 1 0 }
+        T{ ##set-slot-imm f 4 2 1 0 }
+        T{ ##slot-imm f 5 3 1 0 }
+        T{ ##set-slot-imm f 1 5 1 0 }
+        T{ ##slot-imm f 6 4 1 0 }
+    } alias-analysis-step
+] unit-test
+
+! Compares between objects which cannot alias are eliminated
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##allot f 1 16 array }
+        T{ ##load-reference f 2 f }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##allot f 1 16 array }
+        T{ ##compare f 2 0 1 cc= }
+    } alias-analysis-step
+] unit-test
index 2e0684c5d0ef096b5878b9510c41954b7fa4674e..438395e2a7921d9ed0e6fa6df17ac6eff43ee8f9 100644 (file)
@@ -1,14 +1,14 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math namespaces assocs hashtables sequences arrays
 accessors words vectors combinators combinators.short-circuit
-sets classes layouts cpu.architecture
+sets classes layouts fry cpu.architecture
 compiler.cfg
 compiler.cfg.rpo
 compiler.cfg.def-use
 compiler.cfg.liveness
-compiler.cfg.copy-prop
 compiler.cfg.registers
+compiler.cfg.utilities
 compiler.cfg.comparisons
 compiler.cfg.instructions
 compiler.cfg.representations.preferred ;
@@ -68,6 +68,14 @@ IN: compiler.cfg.alias-analysis
 ! e = c
 ! x[1] = c
 
+! Local copy propagation
+SYMBOL: copies
+
+: resolve ( vreg -- vreg ) copies get ?at drop ;
+
+: record-copy ( ##copy -- )
+    [ src>> resolve ] [ dst>> ] bi copies get set-at ; inline
+
 ! Map vregs -> alias classes
 SYMBOL: vregs>acs
 
@@ -85,18 +93,22 @@ SYMBOL: acs>vregs
 
 : ac>vregs ( ac -- vregs ) acs>vregs get at ;
 
-GENERIC: aliases ( vreg -- vregs )
-
-M: integer aliases
+: aliases ( vreg -- vregs )
     #! All vregs which may contain the same value as vreg.
     vreg>ac ac>vregs ;
 
-M: word aliases
-    1array ;
-
 : each-alias ( vreg quot -- )
     [ aliases ] dip each ; inline
 
+: merge-acs ( vreg into -- )
+    [ vreg>ac ] dip
+    2dup eq? [ 2drop ] [
+        [ ac>vregs ] dip
+        [ vregs>acs get '[ [ _ ] dip _ set-at ] each ]
+        [ acs>vregs get at push-all ]
+        2bi
+    ] if ;
+
 ! Map vregs -> slot# -> vreg
 SYMBOL: live-slots
 
@@ -184,22 +196,16 @@ SYMBOL: heap-ac
 : remember-set-slot ( slot#/f vreg -- )
     over [
         [ record-constant-set-slot ]
-        [ kill-constant-set-slot ] 2bi
+        [ kill-constant-set-slot ]
+        2bi
     ] [ nip kill-computed-set-slot ] if ;
 
-SYMBOL: constants
-
-: constant ( vreg -- n/f )
-    #! Return a ##load-immediate value, or f if the vreg was not
-    #! assigned by an ##load-immediate.
-    resolve constants get at ;
-
 GENERIC: insn-slot# ( insn -- slot#/f )
 GENERIC: insn-object ( insn -- vreg )
 
-M: ##slot insn-slot# slot>> constant ;
+M: ##slot insn-slot# drop f ;
 M: ##slot-imm insn-slot# slot>> ;
-M: ##set-slot insn-slot# slot>> constant ;
+M: ##set-slot insn-slot# drop f ;
 M: ##set-slot-imm insn-slot# slot>> ;
 M: ##alien-global insn-slot# [ library>> ] [ symbol>> ] bi 2array ;
 M: ##vm-field insn-slot# offset>> ;
@@ -218,7 +224,6 @@ M: ##set-vm-field insn-object drop \ ##vm-field ;
     H{ } clone vregs>acs set
     H{ } clone acs>vregs set
     H{ } clone live-slots set
-    H{ } clone constants set
     H{ } clone copies set
 
     0 ac-counter set
@@ -238,17 +243,13 @@ M: insn analyze-aliases*
     ! a new value, except boxing instructions haven't been
     ! inserted yet.
     dup defs-vreg [
-        over defs-vreg-rep int-rep eq?
+        over defs-vreg-rep { int-rep tagged-rep } member?
         [ set-heap-ac ] [ set-new-ac ] if
     ] when* ;
 
 M: ##phi analyze-aliases*
     dup defs-vreg set-heap-ac ;
 
-M: ##load-immediate analyze-aliases*
-    call-next-method
-    dup [ val>> ] [ dst>> ] bi constants get set-at ;
-
 M: ##allocation analyze-aliases*
     #! A freshly allocated object is distinct from any other
     #! object.
@@ -257,11 +258,10 @@ M: ##allocation analyze-aliases*
 M: ##read analyze-aliases*
     call-next-method
     dup [ dst>> ] [ insn-slot# ] [ insn-object ] tri
-    2dup live-slot dup [
-        2nip any-rep \ ##copy new-insn analyze-aliases* nip
-    ] [
-        drop remember-slot
-    ] if ;
+    2dup live-slot dup
+    [ 2nip <copy> analyze-aliases* nip ]
+    [ drop remember-slot ]
+    if ;
 
 : idempotent? ( value slot#/f vreg -- ? )
     #! Are we storing a value back to the same slot it was read
@@ -271,7 +271,12 @@ M: ##read analyze-aliases*
 M: ##write analyze-aliases*
     dup
     [ src>> resolve ] [ insn-slot# ] [ insn-object ] tri
-    [ remember-set-slot drop ] [ load-slot ] 3bi ;
+    3dup idempotent? [ 3drop ] [
+        [ 2drop heap-ac get merge-acs ]
+        [ remember-set-slot drop ]
+        [ load-slot ]
+        3tri
+    ] if ;
 
 M: ##copy analyze-aliases*
     #! The output vreg gets the same alias class as the input
@@ -287,7 +292,7 @@ M: ##copy analyze-aliases*
 M: ##compare analyze-aliases*
     call-next-method
     dup useless-compare? [
-        dst>> f \ ##load-constant new-insn
+        dst>> f \ ##load-reference new-insn
         analyze-aliases*
     ] when ;
 
@@ -327,5 +332,5 @@ M: insn eliminate-dead-stores* ;
     compute-live-stores
     eliminate-dead-stores ;
 
-: alias-analysis ( cfg -- cfg' )
-    [ alias-analysis-step ] local-optimization ;
+: alias-analysis ( cfg -- cfg )
+    dup [ alias-analysis-step ] simple-optimization ;
index 670e34e5f9b4282b6b82e75a263781d09c103b4b..8f98ab7adde64162a9765a24b61b143eb9609e5b 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces accessors math.order assocs kernel sequences
-combinators make classes words cpu.architecture layouts
-compiler.cfg.instructions compiler.cfg.registers
-compiler.cfg.stack-frame ;
+combinators classes words cpu.architecture layouts compiler.cfg
+compiler.cfg.rpo compiler.cfg.instructions
+compiler.cfg.registers compiler.cfg.stack-frame ;
 IN: compiler.cfg.build-stack-frame
 
 SYMBOL: frame-required?
@@ -25,49 +25,29 @@ M: stack-frame-insn compute-stack-frame*
 
 M: ##call compute-stack-frame* drop frame-required? on ;
 
-M: ##gc compute-stack-frame*
+M: ##call-gc compute-stack-frame*
+    drop
     frame-required? on
-    stack-frame new
-        swap tagged-values>> length cells >>gc-root-size
-        t >>calls-vm?
-    request-stack-frame ;
-
-M: _spill-area-size compute-stack-frame*
-    n>> stack-frame get (>>spill-area-size) ;
+    stack-frame new t >>calls-vm? request-stack-frame ;
 
 M: insn compute-stack-frame*
-    class frame-required? word-prop [
-        frame-required? on
-    ] when ;
+    class "frame-required?" word-prop
+    [ frame-required? on ] when ;
 
-\ _spill t frame-required? set-word-prop
-\ ##unary-float-function t frame-required? set-word-prop
-\ ##binary-float-function t frame-required? set-word-prop
+: initial-stack-frame ( -- stack-frame )
+    stack-frame new cfg get spill-area-size>> >>spill-area-size ;
 
 : compute-stack-frame ( insns -- )
     frame-required? off
-    stack-frame new stack-frame set
-    [ compute-stack-frame* ] each
+    initial-stack-frame stack-frame set
+    [ instructions>> [ compute-stack-frame* ] each ] each-basic-block
     stack-frame get dup stack-frame-size >>total-size drop ;
 
-GENERIC: insert-pro/epilogues* ( insn -- )
-
-M: ##prologue insert-pro/epilogues*
-    drop frame-required? get [ stack-frame get _prologue ] when ;
-
-M: ##epilogue insert-pro/epilogues*
-    drop frame-required? get [ stack-frame get _epilogue ] when ;
-
-M: insn insert-pro/epilogues* , ;
-
-: insert-pro/epilogues ( insns -- insns )
-    [ [ insert-pro/epilogues* ] each ] { } make ;
-
-: build-stack-frame ( mr -- mr )
+: build-stack-frame ( cfg -- cfg )
     [
+        [ compute-stack-frame ]
         [
-            [ compute-stack-frame ]
-            [ insert-pro/epilogues ]
-            bi
-        ] change-instructions
+            frame-required? get stack-frame get f ?
+            >>stack-frame
+        ] bi
     ] with-scope ;
index b2c05edf7361e00d06260775db6e0457be72c15f..5d2c5e2e3c3595bed56eb8f5edc7a793188aa80e 100644 (file)
@@ -1,17 +1,19 @@
 USING: tools.test kernel sequences words sequences.private fry
-prettyprint alien alien.accessors math.private compiler.tree.builder
-compiler.tree.optimizer compiler.cfg.builder compiler.cfg.debugger
-compiler.cfg.optimizer compiler.cfg.predecessors compiler.cfg.checker
-compiler.cfg arrays locals byte-arrays kernel.private math
-slots.private vectors sbufs strings math.partial-dispatch
-hashtables assocs combinators.short-circuit
-strings.private accessors compiler.cfg.instructions ;
+prettyprint alien alien.accessors math.private
+compiler.tree.builder compiler.tree.optimizer
+compiler.cfg.builder compiler.cfg.debugger
+compiler.cfg.optimizer compiler.cfg.rpo
+compiler.cfg.predecessors compiler.cfg.checker compiler.cfg
+arrays locals byte-arrays kernel.private math slots.private
+vectors sbufs strings math.partial-dispatch hashtables assocs
+combinators.short-circuit strings.private accessors
+compiler.cfg.instructions compiler.cfg.representations ;
 FROM: alien.c-types => int ;
 IN: compiler.cfg.builder.tests
 
 ! Just ensure that various CFGs build correctly.
-: unit-test-cfg ( quot -- )
-    '[ _ test-cfg [ [ optimize-cfg check-cfg ] with-cfg ] each ] [ ] swap unit-test ;
+: unit-test-builder ( quot -- )
+    '[ _ test-builder [ [ optimize-cfg check-cfg ] with-cfg ] each ] [ ] swap unit-test ;
 
 : blahblah ( nodes -- ? )
     { fixnum } declare [
@@ -104,7 +106,7 @@ IN: compiler.cfg.builder.tests
         set-string-nth-fast
     ]
 } [
-    unit-test-cfg
+    unit-test-builder
 ] each
 
 : test-1 ( -- ) test-1 ;
@@ -115,7 +117,7 @@ IN: compiler.cfg.builder.tests
     test-1
     test-2
     test-3
-} [ unit-test-cfg ] each
+} [ unit-test-builder ] each
 
 {
     byte-array
@@ -133,8 +135,8 @@ IN: compiler.cfg.builder.tests
         alien-float
         alien-double
     } [| word |
-        { class } word '[ _ declare 10 _ execute ] unit-test-cfg
-        { class fixnum } word '[ _ declare _ execute ] unit-test-cfg
+        { class } word '[ _ declare 10 _ execute ] unit-test-builder
+        { class fixnum } word '[ _ declare _ execute ] unit-test-builder
     ] each
     
     {
@@ -145,23 +147,23 @@ IN: compiler.cfg.builder.tests
         set-alien-unsigned-2
         set-alien-unsigned-4
     } [| word |
-        { fixnum class } word '[ _ declare 10 _ execute ] unit-test-cfg
-        { fixnum class fixnum } word '[ _ declare _ execute ] unit-test-cfg
+        { fixnum class } word '[ _ declare 10 _ execute ] unit-test-builder
+        { fixnum class fixnum } word '[ _ declare _ execute ] unit-test-builder
     ] each
     
-    { float class } \ set-alien-float '[ _ declare 10 _ execute ] unit-test-cfg
-    { float class fixnum } \ set-alien-float '[ _ declare _ execute ] unit-test-cfg
+    { float class } \ set-alien-float '[ _ declare 10 _ execute ] unit-test-builder
+    { float class fixnum } \ set-alien-float '[ _ declare _ execute ] unit-test-builder
     
-    { float class } \ set-alien-double '[ _ declare 10 _ execute ] unit-test-cfg
-    { float class fixnum } \ set-alien-double '[ _ declare _ execute ] unit-test-cfg
+    { float class } \ set-alien-double '[ _ declare 10 _ execute ] unit-test-builder
+    { float class fixnum } \ set-alien-double '[ _ declare _ execute ] unit-test-builder
     
-    { pinned-c-ptr class } \ set-alien-cell '[ _ declare 10 _ execute ] unit-test-cfg
-    { pinned-c-ptr class fixnum } \ set-alien-cell '[ _ declare _ execute ] unit-test-cfg
+    { pinned-c-ptr class } \ set-alien-cell '[ _ declare 10 _ execute ] unit-test-builder
+    { pinned-c-ptr class fixnum } \ set-alien-cell '[ _ declare _ execute ] unit-test-builder
 ] each
 
 : count-insns ( quot insn-check -- ? )
-    [ test-mr [ instructions>> ] map ] dip
-    '[ _ count ] map-sum ; inline
+    [ test-regs [ post-order [ instructions>> ] map concat ] map concat ] dip
+    count ; inline
 
 : contains-insn? ( quot insn-check -- ? )
     count-insns 0 > ; inline
@@ -172,17 +174,29 @@ IN: compiler.cfg.builder.tests
 
 [ t ] [
     [ { fixnum byte-array fixnum } declare set-alien-unsigned-1 ]
-    [ ##set-alien-integer-1? ] contains-insn?
+    [ [ ##store-memory? ] [ ##store-memory-imm? ] bi or ] contains-insn?
 ] unit-test
 
 [ t ] [
     [ { fixnum byte-array fixnum } declare [ dup * dup * ] 2dip set-alien-unsigned-1 ]
-    [ ##set-alien-integer-1? ] contains-insn?
+    [ [ ##store-memory? ] [ ##store-memory-imm? ] bi or ] contains-insn?
 ] unit-test
 
 [ f ] [
     [ { byte-array fixnum } declare set-alien-unsigned-1 ]
-    [ ##set-alien-integer-1? ] contains-insn?
+    [ [ ##store-memory? ] [ ##store-memory-imm? ] bi or ] contains-insn?
+] unit-test
+
+[ t t ] [
+    [ { byte-array fixnum } declare alien-cell ]
+    [ [ [ ##load-memory? ] [ ##load-memory-imm? ] bi or ] contains-insn? ]
+    [ [ ##box-alien? ] contains-insn? ]
+    bi
+] unit-test
+
+[ f ] [
+    [ { byte-array integer } declare alien-cell ]
+    [ [ ##load-memory? ] [ ##load-memory-imm? ] bi or ] contains-insn?
 ] unit-test
 
 [ f ] [
@@ -209,7 +223,7 @@ IN: compiler.cfg.builder.tests
         [ [ ##allot? ] contains-insn? ] bi
     ] unit-test
     
-    [ 1 ] [ [ dup float+ ] [ ##alien-double? ] count-insns ] unit-test
+    [ 1 ] [ [ dup float+ ] [ ##load-memory-imm? ] count-insns ] unit-test
 ] when
 
 ! Regression. Make sure everything is inlined correctly
index 370f3d053f9a9fdda96aa57ac8c96a9ad6ab58a5..07f3c0aae4201733d143cd9f44f41599c72ee018 100644 (file)
@@ -123,7 +123,7 @@ M: #recursive emit-node
     and ;
 
 : emit-trivial-if ( -- )
-    ds-pop f cc/= ^^compare-imm ds-push ;
+    [ f cc/= ^^compare-imm ] unary-op ;
 
 : trivial-not-if? ( #if -- ? )
     children>> first2
@@ -132,7 +132,7 @@ M: #recursive emit-node
     and ;
 
 : emit-trivial-not-if ( -- )
-    ds-pop f cc= ^^compare-imm ds-push ;
+    [ f cc= ^^compare-imm ] unary-op ;
 
 : emit-actual-if ( #if -- )
     ! Inputs to the final instruction need to be copied because of
index 79f3b0d1fba658e4b25d70612ef8e8a8ddb31c5d..c49d63850962ca9e5462bae022de2ba51c39ec21 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math vectors arrays accessors namespaces ;
 IN: compiler.cfg
@@ -8,7 +8,8 @@ TUPLE: basic-block < identity-tuple
 number
 { instructions vector }
 { successors vector }
-{ predecessors vector } ;
+{ predecessors vector }
+{ unlikely? boolean } ;
 
 : <basic-block> ( -- bb )
     basic-block new
@@ -20,7 +21,8 @@ number
 M: basic-block hashcode* nip id>> ;
 
 TUPLE: cfg { entry basic-block } word label
-spill-area-size reps
+spill-area-size
+stack-frame
 post-order linear-order
 predecessors-valid? dominance-valid? loops-valid? ;
 
@@ -41,11 +43,3 @@ predecessors-valid? dominance-valid? loops-valid? ;
 
 : with-cfg ( ..a cfg quot: ( ..a cfg -- ..b ) -- ..b )
     [ dup cfg ] dip with-variable ; inline
-
-TUPLE: mr { instructions array } word label ;
-
-: <mr> ( instructions word label -- mr )
-    mr new
-        swap >>label
-        swap >>word
-        swap >>instructions ;
index d6f2702ee79873a868b3b67327d8216ec9683737..d7a48a1511a6b0ff84e4f4828090839bc710b6d2 100644 (file)
@@ -3,7 +3,8 @@
 USING: kernel combinators.short-circuit accessors math sequences
 sets assocs compiler.cfg.instructions compiler.cfg.rpo
 compiler.cfg.def-use compiler.cfg.linearization
-compiler.cfg.utilities compiler.cfg.mr compiler.utilities ;
+compiler.cfg.utilities compiler.cfg.finalization
+compiler.utilities ;
 IN: compiler.cfg.checker
 
 ! Check invariants
@@ -25,13 +26,7 @@ ERROR: last-insn-not-a-jump bb ;
     dup instructions>> last {
         [ ##branch? ]
         [ ##dispatch? ]
-        [ ##compare-branch? ]
-        [ ##compare-imm-branch? ]
-        [ ##compare-float-ordered-branch? ]
-        [ ##compare-float-unordered-branch? ]
-        [ ##fixnum-add? ]
-        [ ##fixnum-sub? ]
-        [ ##fixnum-mul? ]
+        [ conditional-branch-insn? ]
         [ ##no-tco? ]
     } 1|| [ drop ] [ last-insn-not-a-jump ] if ;
 
@@ -57,18 +52,5 @@ ERROR: bad-successors ;
     [ check-successors ]
     bi ;
 
-ERROR: bad-live-in ;
-
-ERROR: undefined-values uses defs ;
-
-: check-mr ( mr -- )
-    ! Check that every used register has a definition
-    instructions>>
-    [ [ uses-vregs ] map concat ]
-    [ [ [ temp-vregs ] [ defs-vreg ] bi [ suffix ] when* ] map concat ] bi
-    2dup subset? [ 2drop ] [ undefined-values ] if ;
-
 : check-cfg ( cfg -- )
-    [ [ check-basic-block ] each-basic-block ]
-    [ build-mr check-mr ]
-    bi ;
+    [ check-basic-block ] each-basic-block ;
index 35f25c2d40417ee2ebff7b76b7106414f6a5c3ac..019bfd7a7456f801033d38e18e0aa49299cdc993 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs math.order sequences ;
 IN: compiler.cfg.comparisons
@@ -12,6 +12,8 @@ SYMBOLS:
 SYMBOLS:
     vcc-all vcc-notall vcc-any vcc-none ;
 
+SYMBOLS: cc-o cc/o ;
+
 : negate-cc ( cc -- cc' )
     H{
         { cc<    cc/<   }
@@ -28,6 +30,8 @@ SYMBOLS:
         { cc/=   cc=    } 
         { cc/<>  cc<>   } 
         { cc/<>= cc<>=  }
+        { cc-o   cc/o   }
+        { cc/o   cc-o   }
     } at ;
 
 : negate-vcc ( cc -- cc' )
diff --git a/basis/compiler/cfg/copy-prop/copy-prop-tests.factor b/basis/compiler/cfg/copy-prop/copy-prop-tests.factor
new file mode 100644 (file)
index 0000000..8464118
--- /dev/null
@@ -0,0 +1,107 @@
+USING: compiler.cfg.copy-prop tools.test namespaces kernel
+compiler.cfg.debugger compiler.cfg accessors
+compiler.cfg.registers compiler.cfg.instructions
+cpu.architecture ;
+IN: compiler.cfg.copy-prop.tests
+
+: test-copy-propagation ( -- )
+    cfg new 0 get >>entry copy-propagation drop ;
+
+! Simple example
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 0 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##peek f 1 D 1 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##copy f 2 0 any-rep }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##phi f 3 H{ { 2 0 } { 3 2 } } }
+    T{ ##phi f 4 H{ { 2 1 } { 3 2 } } }
+    T{ ##phi f 5 H{ { 2 1 } { 3 0 } } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##copy f 6 4 any-rep }
+    T{ ##replace f 3 D 0 }
+    T{ ##replace f 5 D 1 }
+    T{ ##replace f 6 D 2 }
+    T{ ##branch }
+} 5 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 6 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 5 edge
+
+[ ] [ test-copy-propagation ] unit-test
+
+[
+    V{
+        T{ ##replace f 0 D 0 }
+        T{ ##replace f 4 D 1 }
+        T{ ##replace f 4 D 2 }
+        T{ ##branch }
+    }
+] [ 5 get instructions>> ] unit-test
+
+! Test optimistic assumption
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 0 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##phi f 1 H{ { 1 0 } { 2 2 } } }
+    T{ ##copy f 2 1 any-rep }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##replace f 2 D 1 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 4 test-bb
+
+0 1 edge
+1 2 edge
+2 { 2 3 } edges
+3 4 edge
+
+[ ] [ test-copy-propagation ] unit-test
+
+[
+    V{
+        T{ ##replace f 0 D 1 }
+        T{ ##branch }
+    }
+] [ 3 get instructions>> ] unit-test
index 23382c3dbecd22c762bac9395cc73280b1d2d574..e18c0fa792be14358fcab76e1bc6eebef2c88d71 100644 (file)
@@ -1,78 +1,90 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel namespaces assocs accessors sequences grouping
-combinators compiler.cfg.rpo compiler.cfg.renaming
-compiler.cfg.instructions compiler.cfg.predecessors ;
+USING: sets kernel namespaces assocs accessors sequences grouping
+combinators fry compiler.cfg.def-use compiler.cfg.rpo
+compiler.cfg.renaming compiler.cfg.instructions
+compiler.cfg.predecessors ;
+FROM: namespaces => set ;
 IN: compiler.cfg.copy-prop
 
-! The first three definitions are also used in compiler.cfg.alias-analysis.
+<PRIVATE
+
+SYMBOL: changed?
+
 SYMBOL: copies
 
-! Initialized per-basic-block; a mapping from inputs to dst for eliminating
-! redundant phi instructions
+! Initialized per-basic-block; a mapping from inputs to dst for
+! eliminating redundant ##phi instructions
 SYMBOL: phis
 
 : resolve ( vreg -- vreg )
-    copies get ?at drop ;
-
-: (record-copy) ( dst src -- )
-    swap copies get set-at ; inline
+    copies get at ;
 
-: record-copy ( ##copy -- )
-    [ dst>> ] [ src>> resolve ] bi (record-copy) ; inline
-
-<PRIVATE
+: record-copy ( dst src -- )
+    swap copies get maybe-set-at [ changed? on ] when ; inline
 
 GENERIC: visit-insn ( insn -- )
 
-M: ##copy visit-insn record-copy ;
+M: ##copy visit-insn
+    [ dst>> ] [ src>> resolve ] bi
+    dup [ record-copy ] [ 2drop ] if ;
 
-: useless-phi ( dst inputs -- ) first (record-copy) ;
+: useless-phi ( dst inputs -- ) first record-copy ;
 
-: redundant-phi ( dst inputs -- ) phis get at (record-copy) ;
+: redundant-phi ( dst inputs -- ) phis get at record-copy ;
 
-: record-phi ( dst inputs -- ) phis get set-at ;
+: record-phi ( dst inputs -- )
+    [ phis get set-at ] [ drop dup record-copy ] 2bi ;
 
 M: ##phi visit-insn
     [ dst>> ] [ inputs>> values [ resolve ] map ] bi
-    {
-        { [ dup all-equal? ] [ useless-phi ] }
-        { [ dup phis get key? ] [ redundant-phi ] }
-        [ record-phi ]
-    } cond ;
+    dup phis get key? [ redundant-phi ] [
+        dup sift
+        dup all-equal?
+        [ nip useless-phi ]
+        [ drop record-phi ] if
+    ] if ;
+
+M: vreg-insn visit-insn
+    defs-vreg [ dup record-copy ] when* ;
 
 M: insn visit-insn drop ;
 
-: collect-copies ( cfg -- )
-    H{ } clone copies set
+: (collect-copies) ( cfg -- )
     [
-        H{ } clone phis set
+        phis get clear-assoc
         instructions>> [ visit-insn ] each
     ] each-basic-block ;
 
+: collect-copies ( cfg -- )
+    H{ } clone copies set
+    H{ } clone phis set
+    '[
+        changed? off
+        _ (collect-copies)
+        changed? get
+    ] loop ;
+
 GENERIC: update-insn ( insn -- keep? )
 
 M: ##copy update-insn drop f ;
 
 M: ##phi update-insn
-    dup dst>> copies get key? [ drop f ] [ call-next-method ] if ;
+    dup call-next-method drop
+    [ dst>> ] [ inputs>> values ] bi [ = not ] with any? ;
+
+M: vreg-insn update-insn rename-insn-uses t ;
 
-M: insn update-insn rename-insn-uses t ;
+M: insn update-insn drop t ;
 
 : rename-copies ( cfg -- )
-    copies get dup assoc-empty? [ 2drop ] [
-        renamings set
-        [
-            instructions>> [ update-insn ] filter! drop
-        ] each-basic-block
-    ] if ;
+    copies get renamings set
+    [ [ update-insn ] filter! ] simple-optimization ;
 
 PRIVATE>
 
 : copy-propagation ( cfg -- cfg' )
     needs-predecessors
 
-    [ collect-copies ]
-    [ rename-copies ]
-    [ ]
-    tri ;
+    dup collect-copies
+    dup rename-copies ;
index 6a7ef08257a0ed0a34bd60877f7138e3ba0ed7f3..460d1a53d1c18b14356c4426ca509560e56392af 100644 (file)
@@ -11,41 +11,41 @@ IN: compiler.cfg.dce.tests
     entry>> instructions>> ; 
 
 [ V{
-    T{ ##load-immediate { dst 1 } { val 8 } }
-    T{ ##load-immediate { dst 2 } { val 16 } }
+    T{ ##load-integer { dst 1 } { val 8 } }
+    T{ ##load-integer { dst 2 } { val 16 } }
     T{ ##add { dst 3 } { src1 1 } { src2 2 } }
     T{ ##replace { src 3 } { loc D 0 } }
 } ] [ V{
-    T{ ##load-immediate { dst 1 } { val 8 } }
-    T{ ##load-immediate { dst 2 } { val 16 } }
+    T{ ##load-integer { dst 1 } { val 8 } }
+    T{ ##load-integer { dst 2 } { val 16 } }
     T{ ##add { dst 3 } { src1 1 } { src2 2 } }
     T{ ##replace { src 3 } { loc D 0 } }
 } test-dce ] unit-test
 
 [ V{ } ] [ V{
-    T{ ##load-immediate { dst 1 } { val 8 } }
-    T{ ##load-immediate { dst 2 } { val 16 } }
+    T{ ##load-integer { dst 1 } { val 8 } }
+    T{ ##load-integer { dst 2 } { val 16 } }
     T{ ##add { dst 3 } { src1 1 } { src2 2 } }
 } test-dce ] unit-test
 
 [ V{ } ] [ V{
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##allot { dst 1 } { temp 2 } }
 } test-dce ] unit-test
 
 [ V{ } ] [ V{
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##allot { dst 1 } { temp 2 } }
     T{ ##set-slot-imm { obj 1 } { src 3 } }
 } test-dce ] unit-test
 
 [ V{
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##allot { dst 1 } { temp 2 } }
     T{ ##set-slot-imm { obj 1 } { src 3 } }
     T{ ##replace { src 1 } { loc D 0 } }
 } ] [ V{
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##allot { dst 1 } { temp 2 } }
     T{ ##set-slot-imm { obj 1 } { src 3 } }
     T{ ##replace { src 1 } { loc D 0 } }
@@ -62,11 +62,11 @@ IN: compiler.cfg.dce.tests
 [ V{
     T{ ##allot { dst 1 } { temp 2 } }
     T{ ##replace { src 1 } { loc D 0 } }
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##set-slot-imm { obj 1 } { src 3 } }
 } ] [ V{
     T{ ##allot { dst 1 } { temp 2 } }
     T{ ##replace { src 1 } { loc D 0 } }
-    T{ ##load-immediate { dst 3 } { val 8 } }
+    T{ ##load-integer { dst 3 } { val 8 } }
     T{ ##set-slot-imm { obj 1 } { src 3 } }
 } test-dce ] unit-test
index d4e8c5401a4c8ef3024fe746349dae0fab033332..dc0be45cc0687f1b8307ca411a80b6b735026656 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel words sequences quotations namespaces io vectors
 arrays hashtables classes.tuple accessors prettyprint
@@ -7,45 +7,87 @@ prettyprint.sections parser compiler.tree.builder
 compiler.tree.optimizer cpu.architecture compiler.cfg.builder
 compiler.cfg.linearization compiler.cfg.registers
 compiler.cfg.stack-frame compiler.cfg.linear-scan
-compiler.cfg.optimizer compiler.cfg.instructions
-compiler.cfg.utilities compiler.cfg.def-use compiler.cfg.rpo
-compiler.cfg.mr compiler.cfg.representations.preferred
-compiler.cfg ;
+compiler.cfg.optimizer compiler.cfg.finalization
+compiler.cfg.instructions compiler.cfg.utilities
+compiler.cfg.def-use compiler.cfg.rpo
+compiler.cfg.representations compiler.cfg.gc-checks
+compiler.cfg.save-contexts compiler.cfg
+compiler.cfg.representations.preferred ;
+FROM: compiler.cfg.linearization => number-blocks ;
 IN: compiler.cfg.debugger
 
-GENERIC: test-cfg ( quot -- cfgs )
+GENERIC: test-builder ( quot -- cfgs )
 
-M: callable test-cfg
+M: callable test-builder
     0 vreg-counter set-global
     build-tree optimize-tree gensym build-cfg ;
 
-M: word test-cfg
+M: word test-builder
     0 vreg-counter set-global
     [ build-tree optimize-tree ] keep build-cfg ;
 
-: test-mr ( quot -- mrs )
-    test-cfg [
+: test-optimizer ( quot -- cfgs )
+    test-builder [ [ optimize-cfg ] with-cfg ] map ;
+
+: test-ssa ( quot -- cfgs )
+    test-builder [
         [
             optimize-cfg
-            build-mr
         ] with-cfg
     ] map ;
 
-: insn. ( insn -- )
-    tuple>array but-last [ pprint bl ] each nl ;
+: test-flat ( quot -- cfgs )
+    test-builder [
+        [
+            optimize-cfg
+            select-representations
+            insert-gc-checks
+            insert-save-contexts
+        ] with-cfg
+    ] map ;
 
-: mr. ( mrs -- )
+: test-regs ( quot -- cfgs )
+    test-builder [
+        [
+            optimize-cfg
+            finalize-cfg
+        ] with-cfg
+    ] map ;
+
+GENERIC: insn. ( insn -- )
+
+M: ##phi insn.
+    clone [ [ [ number>> ] dip ] assoc-map ] change-inputs
+    call-next-method ;
+
+M: insn insn. tuple>array but-last [ bl ] [ pprint ] interleave nl ;
+
+: block. ( bb -- )
+    "=== Basic block #" write dup block-number . nl
+    dup instructions>> [ insn. ] each nl
+    successors>> [
+        "Successors: " write
+        [ block-number unparse ] map ", " join print nl
+    ] unless-empty ;
+
+: cfg. ( cfg -- )
     [
+        dup linearization-order number-blocks
         "=== word: " write
         dup word>> pprint
         ", label: " write
         dup label>> pprint nl nl
-        instructions>> [ insn. ] each
-        nl
-    ] each ;
+        dup linearization-order [ block. ] each
+        "=== stack frame: " write
+        stack-frame>> .
+    ] with-scope ;
+
+: cfgs. ( cfgs -- )
+    [ nl ] [ cfg. ] interleave ;
 
-: test-mr. ( quot -- )
-    test-mr mr. ; inline
+: ssa. ( quot -- ) test-ssa cfgs. ;
+: flat. ( quot -- ) test-flat cfgs. ;
+: regs. ( quot -- ) test-regs cfgs. ;
 
 ! Prettyprinting
 : pprint-loc ( loc word -- ) <block pprint-word n>> pprint* block> ;
index 87758fafcd967a993d011815ec0eeff8c21f5ca1..93c1a53b44b9aaf3a0e8845865d541ebfb0578b7 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
+! Copyright (C) 2008, 2010 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs arrays classes combinators
 compiler.units fry generalizations generic kernel locals
diff --git a/basis/compiler/cfg/dependence/dependence.factor b/basis/compiler/cfg/dependence/dependence.factor
new file mode 100644 (file)
index 0000000..6e07336
--- /dev/null
@@ -0,0 +1,169 @@
+! Copyright (C) 2009, 2010 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs combinators compiler.cfg.def-use
+compiler.cfg.instructions compiler.cfg.registers fry kernel
+locals namespaces sequences sets sorting math.vectors
+make math combinators.short-circuit vectors ;
+FROM: namespaces => set ;
+IN: compiler.cfg.dependence
+
+! Dependence graph construction
+
+SYMBOL: roots
+SYMBOL: node-number
+SYMBOL: nodes
+
+SYMBOL: +data+
+SYMBOL: +control+
+
+! Nodes in the dependency graph
+! These need to be numbered so that the same instruction
+! will get distinct nodes if it occurs multiple times
+TUPLE: node
+    number insn precedes follows
+    children parent
+    registers parent-index ;
+
+M: node equal?  [ number>> ] bi@ = ;
+
+M: node hashcode* nip number>> ;
+
+: <node> ( insn -- node )
+    node new
+        node-number counter >>number
+        swap >>insn
+        H{ } clone >>precedes
+        V{ } clone >>follows ;
+
+: ready? ( node -- ? ) precedes>> assoc-empty? ;
+
+:: precedes ( first second how -- )
+    how second first precedes>> set-at ;
+
+:: add-data-edges ( nodes -- )
+    ! This builds up def-use information on the fly, since
+    ! we only care about local def-use
+    H{ } clone :> definers
+    nodes [| node |
+        node insn>> defs-vreg [ node swap definers set-at ] when*
+        node insn>> uses-vregs [ definers at [ node +data+ precedes ] when* ] each
+    ] each ;
+
+UNION: stack-insn ##peek ##replace ##replace-imm ;
+
+UNION: slot-insn
+    ##read ##write ;
+
+UNION: memory-insn
+    ##load-memory ##load-memory-imm
+    ##store-memory ##store-memory-imm ;
+
+UNION: alien-call-insn
+    ##save-context
+    ##alien-invoke ##alien-indirect ##alien-callback
+    ##unary-float-function ##binary-float-function ;
+
+: chain ( node var -- )
+    dup get [
+        pick +control+ precedes
+    ] when*
+    set ;
+
+GENERIC: add-control-edge ( node insn -- )
+
+M: stack-insn add-control-edge
+    loc>> chain ;
+
+M: memory-insn add-control-edge
+    drop memory-insn chain ;
+
+M: slot-insn add-control-edge
+    drop slot-insn chain ;
+
+M: alien-call-insn add-control-edge
+    drop alien-call-insn chain ;
+
+M: object add-control-edge 2drop ;
+
+: add-control-edges ( nodes -- )
+    [
+        [ dup insn>> add-control-edge ] each
+    ] with-scope ;
+
+: set-follows ( nodes -- )
+    [
+        dup precedes>> keys [
+            follows>> push
+        ] with each
+    ] each ;
+
+: set-roots ( nodes -- )
+    [ ready? ] V{ } filter-as roots set ;
+
+: build-dependence-graph ( instructions -- )
+    [ <node> ] map {
+        [ add-control-edges ]
+        [ add-data-edges ]
+        [ set-follows ]
+        [ set-roots ]
+        [ nodes set ]
+    } cleave ;
+
+! Sethi-Ulmann numbering
+:: calculate-registers ( node -- registers )
+    node children>> [ 0 ] [
+        [ [ calculate-registers ] map natural-sort ]
+        [ length iota ]
+        bi v+ supremum
+    ] if-empty
+    node insn>> temp-vregs length +
+    dup node (>>registers) ;
+
+! Constructing fan-in trees
+
+: attach-parent ( node parent -- )
+    [ >>parent drop ]
+    [ [ ?push ] change-children drop ] 2bi ;
+
+: keys-for ( assoc value -- keys )
+    '[ nip _ = ] assoc-filter keys ;
+
+: choose-parent ( node -- )
+    ! If a node has control dependences, it has to be a root
+    ! Otherwise, choose one of the data dependences for a parent
+    dup precedes>> +control+ keys-for empty? [
+        dup precedes>> +data+ keys-for [ drop ] [
+            first attach-parent
+        ] if-empty
+    ] [ drop ] if ;
+
+: make-trees ( -- trees )
+    nodes get
+    [ [ choose-parent ] each ]
+    [ [ parent>> not ] filter ] bi ;
+
+ERROR: node-missing-parent trees nodes ;
+ERROR: node-missing-children trees nodes ;
+
+: flatten-tree ( node -- nodes )
+    [ children>> [ flatten-tree ] map concat ] keep
+    suffix ;
+
+: verify-parents ( trees -- trees )
+    nodes get over '[ [ parent>> ] [ _ member? ] bi or ] all?
+    [ nodes get node-missing-parent ] unless ;
+
+: verify-children ( trees -- trees )
+    dup [ flatten-tree ] map concat
+    nodes get
+    { [ [ length ] bi@ = ] [ set= ] } 2&&
+    [ nodes get node-missing-children ] unless ;
+
+: verify-trees ( trees -- trees )
+    verify-parents verify-children ;
+
+: build-fan-in-trees ( -- )
+    make-trees verify-trees [
+        -1/0. >>parent-index 
+        calculate-registers drop
+    ] each ;
diff --git a/basis/compiler/cfg/empty-blocks/empty-blocks.factor b/basis/compiler/cfg/empty-blocks/empty-blocks.factor
deleted file mode 100644 (file)
index 605c572..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences namespaces combinators
-combinators.short-circuit classes vectors compiler.cfg
-compiler.cfg.instructions compiler.cfg.rpo ;
-IN: compiler.cfg.empty-blocks
-
-<PRIVATE
-
-: update-predecessor ( bb -- )
-    ! We have to replace occurrences of bb with bb's successor
-    ! in bb's predecessor's list of successors.
-    dup predecessors>> first [
-        [
-            2dup eq? [ drop successors>> first ] [ nip ] if
-        ] with map
-    ] change-successors drop ;
-: update-successor ( bb -- )
-    ! We have to replace occurrences of bb with bb's predecessor
-    ! in bb's sucessor's list of predecessors.
-    dup successors>> first [
-        [
-            2dup eq? [ drop predecessors>> first ] [ nip ] if
-        ] with map
-    ] change-predecessors drop ;
-
-SYMBOL: changed?
-
-: delete-basic-block ( bb -- )
-    [ update-predecessor ] [ update-successor ] bi
-    changed? on ;
-: delete-basic-block? ( bb -- ? )
-    {
-        [ instructions>> length 1 = ]
-        [ predecessors>> length 1 = ]
-        [ successors>> length 1 = ]
-        [ instructions>> first ##branch? ]
-    } 1&& ;
-
-PRIVATE>
-
-: delete-empty-blocks ( cfg -- cfg' )
-    changed? off
-    dup [ dup delete-basic-block? [ delete-basic-block ] [ drop ] if ] each-basic-block
-    changed? get [ cfg-changed ] when ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/finalization/authors.txt b/basis/compiler/cfg/finalization/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/finalization/finalization.factor b/basis/compiler/cfg/finalization/finalization.factor
new file mode 100644 (file)
index 0000000..5440ba6
--- /dev/null
@@ -0,0 +1,16 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: compiler.cfg.gc-checks compiler.cfg.representations
+compiler.cfg.save-contexts compiler.cfg.ssa.destruction
+compiler.cfg.build-stack-frame compiler.cfg.linear-scan
+compiler.cfg.scheduling ;
+IN: compiler.cfg.finalization
+
+: finalize-cfg ( cfg -- cfg' )
+    select-representations
+    schedule-instructions
+    insert-gc-checks
+    insert-save-contexts
+    destruct-ssa
+    linear-scan
+    build-stack-frame ;
index 27d37b115f46b6b546cd60a43369a6fead2a8d8c..496954de2c83cd87d6c51a7e1a251cc6b39b3730 100644 (file)
@@ -1,14 +1,14 @@
-USING: compiler.cfg.gc-checks compiler.cfg.debugger
+USING: arrays compiler.cfg.gc-checks
+compiler.cfg.gc-checks.private compiler.cfg.debugger
 compiler.cfg.registers compiler.cfg.instructions compiler.cfg
-compiler.cfg.predecessors cpu.architecture tools.test kernel vectors
-namespaces accessors sequences ;
+compiler.cfg.predecessors compiler.cfg.rpo cpu.architecture
+tools.test kernel vectors namespaces accessors sequences alien
+memory classes make combinators.short-circuit byte-arrays ;
 IN: compiler.cfg.gc-checks.tests
 
 : test-gc-checks ( -- )
     H{ } clone representations set
-    cfg new 0 get >>entry
-    insert-gc-checks
-    drop ;
+    cfg new 0 get >>entry cfg set ;
 
 V{
     T{ ##inc-d f 3 }
@@ -23,4 +23,184 @@ V{
 
 [ ] [ test-gc-checks ] unit-test
 
-[ V{ D 0 D 2 } ] [ 1 get instructions>> first uninitialized-locs>> ] unit-test
+[ t ] [ cfg get blocks-with-gc 1 get 1array sequence= ] unit-test
+
+[ ] [ 1 get allocation-size 123 <alien> size assert= ] unit-test
+
+2 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##load-tagged f 3 0 }
+        T{ ##replace f 3 D 0 }
+        T{ ##replace f 3 R 3 }
+    }
+] [ [ { D 0 R 3 } wipe-locs ] V{ } make ] unit-test
+
+: gc-check? ( bb -- ? )
+    instructions>>
+    {
+        [ length 1 = ]
+        [ first ##check-nursery-branch? ]
+    } 1&& ;
+
+[ t ] [ V{ } 100 <gc-check> gc-check? ] unit-test
+
+4 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##load-tagged f 5 0 }
+        T{ ##replace f 5 D 0 }
+        T{ ##replace f 5 R 3 }
+        T{ ##call-gc f { 0 1 2 } }
+        T{ ##branch }
+    }
+]
+[
+    { D 0 R 3 } { 0 1 2 } <gc-call> instructions>>
+] unit-test
+
+30 \ vreg-counter set-global
+
+V{
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##branch }
+} 4 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+3 4 edge
+
+[ ] [ test-gc-checks ] unit-test
+
+[ ] [ cfg get needs-predecessors drop ] unit-test
+
+[ ] [ { D 1 R 2 } { 10 20 } V{ } 31337 3 get (insert-gc-check) ] unit-test
+
+[ t ] [ 1 get successors>> first gc-check? ] unit-test
+
+[ t ] [ 2 get successors>> first gc-check? ] unit-test
+
+[ t ] [ 3 get predecessors>> first gc-check? ] unit-test
+
+30 \ vreg-counter set-global
+
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 2 D 0 }
+    T{ ##inc-d f 3 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##allot f 1 64 byte-array }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##replace f 2 D 1 }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 5 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 5 edge
+
+[ ] [ test-gc-checks ] unit-test
+
+H{
+    { 2 tagged-rep }
+} representations set
+
+[ ] [ cfg get insert-gc-checks drop ] unit-test
+
+[ 2 ] [ 2 get predecessors>> length ] unit-test
+
+[ t ] [ 1 get successors>> first gc-check? ] unit-test
+
+[ 64 ] [ 1 get successors>> first instructions>> first size>> ] unit-test
+
+[ t ] [ 2 get predecessors>> first gc-check? ] unit-test
+
+[
+    V{
+        T{ ##load-tagged f 31 0 }
+        T{ ##replace f 31 D 0 }
+        T{ ##replace f 31 D 1 }
+        T{ ##replace f 31 D 2 }
+        T{ ##call-gc f { 2 } }
+        T{ ##branch }
+    }
+] [ 2 get predecessors>> second instructions>> ] unit-test
+
+! Don't forget to invalidate RPO after inserting basic blocks!
+[ 8 ] [ cfg get reverse-post-order length ] unit-test
+
+! Do the right thing with ##phi instructions
+V{
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##load-reference f 1 "hi" }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##load-reference f 2 "bye" }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##phi f 3 H{ { 1 1 } { 2 2 } } }
+    T{ ##allot f 1 64 byte-array }
+    T{ ##branch }
+} 3 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+
+[ ] [ test-gc-checks ] unit-test
+
+H{
+    { 1 tagged-rep }
+    { 2 tagged-rep }
+    { 3 tagged-rep }
+} representations set
+
+[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ t ] [ 2 get successors>> first instructions>> first ##phi? ] unit-test
+[ 2 ] [ 3 get instructions>> length ] unit-test
index 6d192ec54a627d6bf44d8320a317fef9d95fb452..4d71bbe5565d9a86e39903f7e61f223bc918cc4a 100644 (file)
@@ -1,15 +1,25 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel sequences assocs fry math
-cpu.architecture layouts namespaces
+USING: accessors assocs combinators fry kernel layouts locals
+math make namespaces sequences cpu.architecture
+compiler.cfg
 compiler.cfg.rpo
+compiler.cfg.hats
 compiler.cfg.registers
+compiler.cfg.utilities
+compiler.cfg.comparisons
 compiler.cfg.instructions
+compiler.cfg.predecessors
+compiler.cfg.liveness
+compiler.cfg.liveness.ssa
 compiler.cfg.stacks.uninitialized ;
 IN: compiler.cfg.gc-checks
 
-! Garbage collection check insertion. This pass runs after representation
-! selection, so it must keep track of representations.
+<PRIVATE
+
+! Garbage collection check insertion. This pass runs after
+! representation selection, since it needs to know which vregs
+! can contain tagged pointers.
 
 : insert-gc-check? ( bb -- ? )
     instructions>> [ ##allocation? ] any? ;
@@ -17,6 +27,54 @@ IN: compiler.cfg.gc-checks
 : blocks-with-gc ( cfg -- bbs )
     post-order [ insert-gc-check? ] filter ;
 
+! A GC check for bb consists of two new basic blocks, gc-check
+! and gc-call:
+!
+!    gc-check
+!   /      \
+!  |     gc-call
+!   \      /
+!      bb
+
+! Any ##phi instructions at the start of bb are transplanted
+! into the gc-check block.
+
+: <gc-check> ( phis size -- bb )
+    [ <basic-block> ] 2dip
+    [
+        [ % ]
+        [
+            cc<= int-rep next-vreg-rep int-rep next-vreg-rep
+            ##check-nursery-branch
+        ] bi*
+    ] V{ } make >>instructions ;
+
+: wipe-locs ( uninitialized-locs -- )
+    '[
+        int-rep next-vreg-rep
+        [ 0 ##load-tagged ]
+        [ '[ [ _ ] dip ##replace ] each ] bi
+    ] unless-empty ;
+
+: <gc-call> ( uninitialized-locs gc-roots -- bb )
+    [ <basic-block> ] 2dip
+    [ [ wipe-locs ] [ ##call-gc ] bi* ##branch ] V{ } make
+    >>instructions t >>unlikely? ;
+
+:: insert-guard ( body check bb -- )
+    bb predecessors>> check (>>predecessors)
+    V{ bb body }      check (>>successors)
+
+    V{ check }        body (>>predecessors)
+    V{ bb }           body (>>successors)
+
+    V{ check body }   bb (>>predecessors)
+
+    check predecessors>> [ bb check update-successors ] each ;
+
+: (insert-gc-check) ( uninitialized-locs gc-roots phis size bb -- )
+    [ [ <gc-call> ] 2dip <gc-check> ] dip insert-guard ;
+
 GENERIC: allocation-size* ( insn -- n )
 
 M: ##allot allocation-size* size>> ;
@@ -30,20 +88,35 @@ M: ##box-displaced-alien allocation-size* drop 5 cells ;
     [ ##allocation? ] filter
     [ allocation-size* data-alignment get align ] map-sum ;
 
+: gc-live-in ( bb -- vregs )
+    [ live-in keys ] [ instructions>> [ ##phi? ] filter [ dst>> ] map ] bi
+    append ;
+
+: live-tagged ( bb -- vregs )
+    gc-live-in [ rep-of tagged-rep? ] filter ;
+
+: remove-phis ( bb -- phis )
+    [ [ ##phi? ] partition ] change-instructions drop ;
+
 : insert-gc-check ( bb -- )
-    dup dup '[
-        int-rep next-vreg-rep
-        int-rep next-vreg-rep
-        _ allocation-size
-        f
-        f
-        _ uninitialized-locs
-        \ ##gc new-insn
-        prefix
-    ] change-instructions drop ;
+    {
+        [ uninitialized-locs ]
+        [ live-tagged ]
+        [ remove-phis ]
+        [ allocation-size ]
+        [ ]
+    } cleave
+    (insert-gc-check) ;
+
+PRIVATE>
 
 : insert-gc-checks ( cfg -- cfg' )
     dup blocks-with-gc [
-        over compute-uninitialized-sets
+        [
+            needs-predecessors
+            dup compute-ssa-live-sets
+            dup compute-uninitialized-sets
+        ] dip
         [ insert-gc-check ] each
+        cfg-changed
     ] unless-empty ;
index fb89b36efa8b4e1c241f4a0ec354149144920600..a03f1f83bc74d8e153b2e6f32a3692327105a487 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays byte-arrays combinators.short-circuit
-kernel layouts math namespaces sequences combinators splitting
-parser effects words cpu.architecture compiler.cfg.registers
+USING: accessors alien arrays byte-arrays classes.algebra
+combinators.short-circuit kernel layouts math namespaces
+sequences combinators splitting parser effects words
+cpu.architecture compiler.constants compiler.cfg.registers
 compiler.cfg.instructions compiler.cfg.instructions.syntax ;
 IN: compiler.cfg.hats
 
@@ -41,21 +42,22 @@ insn-classes get [
 
 >>
 
-: immutable? ( obj -- ? )
-    { [ float? ] [ word? ] [ not ] } 1|| ; inline
-
 : ^^load-literal ( obj -- dst )
-    [ next-vreg dup ] dip {
-        { [ dup fixnum? ] [ tag-fixnum ##load-immediate ] }
-        { [ dup immutable? ] [ ##load-constant ] }
-        [ ##load-reference ]
-    } cond ;
+    dup fixnum? [ ^^load-integer ] [ ^^load-reference ] if ;
 
 : ^^offset>slot ( slot -- vreg' )
-    cell 4 = 2 1 ? ^^shr-imm ;
+    cell 4 = 2 3 ? ^^shl-imm ;
 
-: ^^tag-fixnum ( src -- dst )
-    tag-bits get ^^shl-imm ;
+: ^^unbox-f ( src -- dst )
+    drop 0 ^^load-literal ;
 
-: ^^untag-fixnum ( src -- dst )
-    tag-bits get ^^sar-imm ;
+: ^^unbox-byte-array ( src -- dst )
+    ^^tagged>integer byte-array-offset ^^add-imm ;
+
+: ^^unbox-c-ptr ( src class -- dst )
+    {
+        { [ dup \ f class<= ] [ drop ^^unbox-f ] }
+        { [ dup alien class<= ] [ drop ^^unbox-alien ] }
+        { [ dup byte-array class<= ] [ drop ^^unbox-byte-array ] }
+        [ drop ^^unbox-any-c-ptr ]
+    } cond ;
diff --git a/basis/compiler/cfg/height/height.factor b/basis/compiler/cfg/height/height.factor
new file mode 100644 (file)
index 0000000..4471508
--- /dev/null
@@ -0,0 +1,55 @@
+! Copyright (C) 2008, 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors math namespaces sequences kernel fry
+compiler.cfg compiler.cfg.registers compiler.cfg.instructions
+compiler.cfg.rpo ;
+IN: compiler.cfg.height
+
+! Combine multiple stack height changes into one at the
+! start of the basic block.
+
+SYMBOL: ds-height
+SYMBOL: rs-height
+
+GENERIC: compute-heights ( insn -- )
+
+M: ##inc-d compute-heights n>> ds-height [ + ] change ;
+M: ##inc-r compute-heights n>> rs-height [ + ] change ;
+M: insn compute-heights drop ;
+
+GENERIC: normalize-height* ( insn -- insn' )
+
+: normalize-inc-d/r ( insn stack -- insn' )
+    swap n>> '[ _ - ] change f ; inline
+
+M: ##inc-d normalize-height* ds-height normalize-inc-d/r ;
+M: ##inc-r normalize-height* rs-height normalize-inc-d/r ;
+
+GENERIC: loc-stack ( loc -- stack )
+
+M: ds-loc loc-stack drop ds-height ;
+M: rs-loc loc-stack drop rs-height ;
+
+GENERIC: <loc> ( n stack -- loc )
+
+M: ds-loc <loc> drop <ds-loc> ;
+M: rs-loc <loc> drop <rs-loc> ;
+
+: normalize-peek/replace ( insn -- insn' )
+    [ [ [ n>> ] [ loc-stack get ] bi + ] keep <loc> ] change-loc ; inline
+
+M: ##peek normalize-height* normalize-peek/replace ;
+M: ##replace normalize-height* normalize-peek/replace ;
+
+M: insn normalize-height* ;
+
+: height-step ( insns -- insns' )
+    0 ds-height set
+    0 rs-height set
+    [ [ compute-heights ] each ]
+    [ [ [ normalize-height* ] map sift ] with-scope ] bi
+    ds-height get dup 0 = [ drop ] [ \ ##inc-d new-insn prefix ] if
+    rs-height get dup 0 = [ drop ] [ \ ##inc-r new-insn prefix ] if ;
+
+: normalize-height ( cfg -- cfg' )
+    dup [ height-step ] simple-optimization ;
diff --git a/basis/compiler/cfg/height/summary.txt b/basis/compiler/cfg/height/summary.txt
new file mode 100644 (file)
index 0000000..ce1974a
--- /dev/null
@@ -0,0 +1 @@
+Stack height normalization coalesces height changes at start of basic block
index 5ddf7b4db5d51a1cf54cf234659f88b85d9a5756..d4e019d8dd7a45cdef8afb6a115fbb156a34df1f 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs accessors arrays kernel sequences namespaces words
-math math.order layouts classes.algebra classes.union
-compiler.units alien byte-arrays compiler.constants combinators
-compiler.cfg.registers compiler.cfg.instructions.syntax ;
+math math.order layouts classes.union compiler.units alien
+byte-arrays combinators compiler.cfg.registers
+compiler.cfg.instructions.syntax ;
 IN: compiler.cfg.instructions
 
 <<
@@ -20,31 +20,40 @@ TUPLE: insn ;
 ! value numbering
 TUPLE: pure-insn < insn ;
 
-! Stack operations
-INSN: ##load-immediate
+! Constants
+INSN: ##load-integer
 def: dst/int-rep
-constant: val ;
+literal: val ;
 
 INSN: ##load-reference
-def: dst/int-rep
-constant: obj ;
+def: dst/tagged-rep
+literal: obj ;
 
-INSN: ##load-constant
-def: dst/int-rep
-constant: obj ;
+! These three are inserted by representation selection
+INSN: ##load-tagged
+def: dst/tagged-rep
+literal: val ;
 
 INSN: ##load-double
 def: dst/double-rep
-constant: val ;
+literal: val ;
+
+INSN: ##load-vector
+def: dst
+literal: val rep ;
 
+! Stack operations
 INSN: ##peek
-def: dst/int-rep
+def: dst/tagged-rep
 literal: loc ;
 
 INSN: ##replace
-use: src/int-rep
+use: src/tagged-rep
 literal: loc ;
 
+INSN: ##replace-imm
+literal: src loc ;
+
 INSN: ##inc-d
 literal: n ;
 
@@ -58,6 +67,10 @@ literal: word ;
 INSN: ##jump
 literal: word ;
 
+INSN: ##prologue ;
+
+INSN: ##epilogue ;
+
 INSN: ##return ;
 
 ! Dummy instruction that simply inhibits TCO
@@ -70,36 +83,33 @@ temp: temp/int-rep ;
 
 ! Slot access
 INSN: ##slot
-def: dst/int-rep
-use: obj/int-rep slot/int-rep ;
+def: dst/tagged-rep
+use: obj/tagged-rep slot/int-rep
+literal: scale tag ;
 
 INSN: ##slot-imm
-def: dst/int-rep
-use: obj/int-rep
+def: dst/tagged-rep
+use: obj/tagged-rep
 literal: slot tag ;
 
 INSN: ##set-slot
-use: src/int-rep obj/int-rep slot/int-rep ;
+use: src/tagged-rep obj/tagged-rep slot/int-rep
+literal: scale tag ;
 
 INSN: ##set-slot-imm
-use: src/int-rep obj/int-rep
+use: src/tagged-rep obj/tagged-rep
 literal: slot tag ;
 
-! String element access
-INSN: ##string-nth
-def: dst/int-rep
-use: obj/int-rep index/int-rep
-temp: temp/int-rep ;
-
-INSN: ##set-string-nth-fast
-use: src/int-rep obj/int-rep index/int-rep
-temp: temp/int-rep ;
-
-PURE-INSN: ##copy
+! Register transfers
+INSN: ##copy
 def: dst
 use: src
 literal: rep ;
 
+PURE-INSN: ##tagged>integer
+def: dst/int-rep
+use: src/tagged-rep ;
+
 ! Integer arithmetic
 PURE-INSN: ##add
 def: dst/int-rep
@@ -108,7 +118,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##add-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##sub
 def: dst/int-rep
@@ -117,7 +127,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##sub-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##mul
 def: dst/int-rep
@@ -126,7 +136,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##mul-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##and
 def: dst/int-rep
@@ -135,7 +145,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##and-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##or
 def: dst/int-rep
@@ -144,7 +154,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##or-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##xor
 def: dst/int-rep
@@ -153,7 +163,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##xor-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##shl
 def: dst/int-rep
@@ -162,7 +172,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##shl-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##shr
 def: dst/int-rep
@@ -171,7 +181,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##shr-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##sar
 def: dst/int-rep
@@ -180,7 +190,7 @@ use: src1/int-rep src2/int-rep ;
 PURE-INSN: ##sar-imm
 def: dst/int-rep
 use: src1/int-rep
-constant: src2 ;
+literal: src2 ;
 
 PURE-INSN: ##min
 def: dst/int-rep
@@ -340,7 +350,7 @@ use: src1 src2
 literal: rep cc ;
 
 PURE-INSN: ##test-vector
-def: dst/int-rep
+def: dst/tagged-rep
 use: src1
 temp: temp/int-rep
 literal: rep vcc ;
@@ -529,135 +539,57 @@ literal: rep ;
 
 ! Boxing and unboxing aliens
 PURE-INSN: ##box-alien
-def: dst/int-rep
+def: dst/tagged-rep
 use: src/int-rep
 temp: temp/int-rep ;
 
 PURE-INSN: ##box-displaced-alien
-def: dst/int-rep
-use: displacement/int-rep base/int-rep
+def: dst/tagged-rep
+use: displacement/int-rep base/tagged-rep
 temp: temp/int-rep
 literal: base-class ;
 
 PURE-INSN: ##unbox-any-c-ptr
 def: dst/int-rep
-use: src/int-rep ;
-
-: ##unbox-f ( dst src -- ) drop 0 ##load-immediate ;
-: ##unbox-byte-array ( dst src -- ) byte-array-offset ##add-imm ;
+use: src/tagged-rep ;
 
 PURE-INSN: ##unbox-alien
 def: dst/int-rep
-use: src/int-rep ;
-
-: ##unbox-c-ptr ( dst src class -- )
-    {
-        { [ dup \ f class<= ] [ drop ##unbox-f ] }
-        { [ dup alien class<= ] [ drop ##unbox-alien ] }
-        { [ dup byte-array class<= ] [ drop ##unbox-byte-array ] }
-        [ drop ##unbox-any-c-ptr ]
-    } cond ;
-
-! Alien accessors
-INSN: ##alien-unsigned-1
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-unsigned-2
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
+use: src/tagged-rep ;
 
-INSN: ##alien-unsigned-4
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-signed-1
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-signed-2
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-signed-4
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-cell
-def: dst/int-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-float
-def: dst/float-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-double
-def: dst/double-rep
-use: src/int-rep
-literal: offset ;
-
-INSN: ##alien-vector
+! Raw memory accessors
+INSN: ##load-memory
 def: dst
-use: src/int-rep
-literal: offset rep ;
-
-INSN: ##set-alien-integer-1
-use: src/int-rep
-literal: offset
-use: value/int-rep ;
-
-INSN: ##set-alien-integer-2
-use: src/int-rep
-literal: offset
-use: value/int-rep ;
+use: base/int-rep displacement/int-rep
+literal: scale offset rep c-type ;
 
-INSN: ##set-alien-integer-4
-use: src/int-rep
-literal: offset
-use: value/int-rep ;
-
-INSN: ##set-alien-cell
-use: src/int-rep
-literal: offset
-use: value/int-rep ;
-
-INSN: ##set-alien-float
-use: src/int-rep
-literal: offset
-use: value/float-rep ;
+INSN: ##load-memory-imm
+def: dst
+use: base/int-rep
+literal: offset rep c-type ;
 
-INSN: ##set-alien-double
-use: src/int-rep
-literal: offset
-use: value/double-rep ;
+INSN: ##store-memory
+use: src base/int-rep displacement/int-rep
+literal: scale offset rep c-type ;
 
-INSN: ##set-alien-vector
-use: src/int-rep
-literal: offset
-use: value
-literal: rep ;
+INSN: ##store-memory-imm
+use: src base/int-rep
+literal: offset rep c-type ;
 
 ! Memory allocation
 INSN: ##allot
-def: dst/int-rep
+def: dst/tagged-rep
 literal: size class
 temp: temp/int-rep ;
 
 INSN: ##write-barrier
-use: src/int-rep slot/int-rep
+use: src/tagged-rep slot/int-rep
+literal: scale tag
 temp: temp1/int-rep temp2/int-rep ;
 
 INSN: ##write-barrier-imm
-use: src/int-rep
-literal: slot
+use: src/tagged-rep
+literal: slot tag
 temp: temp1/int-rep temp2/int-rep ;
 
 INSN: ##alien-global
@@ -665,11 +597,11 @@ def: dst/int-rep
 literal: symbol library ;
 
 INSN: ##vm-field
-def: dst/int-rep
+def: dst/tagged-rep
 literal: offset ;
 
 INSN: ##set-vm-field
-use: src/int-rep
+use: src/tagged-rep
 literal: offset ;
 
 ! FFI
@@ -685,39 +617,56 @@ literal: params stack-frame ;
 INSN: ##alien-callback
 literal: params stack-frame ;
 
-! Instructions used by CFG IR only.
-INSN: ##prologue ;
-INSN: ##epilogue ;
-
-INSN: ##branch ;
-
+! Control flow
 INSN: ##phi
 def: dst
 literal: inputs ;
 
-! Conditionals
+INSN: ##branch ;
+
+! Tagged conditionals
 INSN: ##compare-branch
-use: src1/int-rep src2/int-rep
+use: src1/tagged-rep src2/tagged-rep
 literal: cc ;
 
 INSN: ##compare-imm-branch
-use: src1/int-rep
-constant: src2
-literal: cc ;
+use: src1/tagged-rep
+literal: src2 cc ;
 
 PURE-INSN: ##compare
-def: dst/int-rep
-use: src1/int-rep src2/int-rep
+def: dst/tagged-rep
+use: src1/tagged-rep src2/tagged-rep
 literal: cc
 temp: temp/int-rep ;
 
 PURE-INSN: ##compare-imm
-def: dst/int-rep
+def: dst/tagged-rep
+use: src1/tagged-rep
+literal: src2 cc
+temp: temp/int-rep ;
+
+! Integer conditionals
+INSN: ##compare-integer-branch
+use: src1/int-rep src2/int-rep
+literal: cc ;
+
+INSN: ##compare-integer-imm-branch
 use: src1/int-rep
-constant: src2
+literal: src2 cc ;
+
+PURE-INSN: ##compare-integer
+def: dst/tagged-rep
+use: src1/int-rep src2/int-rep
 literal: cc
 temp: temp/int-rep ;
 
+PURE-INSN: ##compare-integer-imm
+def: dst/tagged-rep
+use: src1/int-rep
+literal: src2 cc
+temp: temp/int-rep ;
+
+! Float conditionals
 INSN: ##compare-float-ordered-branch
 use: src1/double-rep src2/double-rep
 literal: cc ;
@@ -727,123 +676,81 @@ use: src1/double-rep src2/double-rep
 literal: cc ;
 
 PURE-INSN: ##compare-float-ordered
-def: dst/int-rep
+def: dst/tagged-rep
 use: src1/double-rep src2/double-rep
 literal: cc
 temp: temp/int-rep ;
 
 PURE-INSN: ##compare-float-unordered
-def: dst/int-rep
+def: dst/tagged-rep
 use: src1/double-rep src2/double-rep
 literal: cc
 temp: temp/int-rep ;
 
 ! Overflowing arithmetic
 INSN: ##fixnum-add
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
+def: dst/tagged-rep
+use: src1/tagged-rep src2/tagged-rep
+literal: cc ;
 
 INSN: ##fixnum-sub
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
+def: dst/tagged-rep
+use: src1/tagged-rep src2/tagged-rep
+literal: cc ;
 
 INSN: ##fixnum-mul
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
-
-INSN: ##gc
-temp: temp1/int-rep temp2/int-rep
-literal: size data-values tagged-values uninitialized-locs ;
+def: dst/tagged-rep
+use: src1/tagged-rep src2/int-rep
+literal: cc ;
 
 INSN: ##save-context
 temp: temp1/int-rep temp2/int-rep ;
 
-! Instructions used by machine IR only.
-INSN: _prologue
-literal: stack-frame ;
-
-INSN: _epilogue
-literal: stack-frame ;
-
-INSN: _label
-literal: label ;
-
-INSN: _branch
-literal: label ;
-
-INSN: _loop-entry ;
-
-INSN: _dispatch
-use: src/int-rep
-temp: temp ;
-
-INSN: _dispatch-label
-literal: label ;
-
-INSN: _compare-branch
-literal: label
-use: src1/int-rep src2/int-rep
-literal: cc ;
-
-INSN: _compare-imm-branch
-literal: label
-use: src1/int-rep
-constant: src2
-literal: cc ;
-
-INSN: _compare-float-unordered-branch
-literal: label
-use: src1/int-rep src2/int-rep
-literal: cc ;
-
-INSN: _compare-float-ordered-branch
-literal: label
-use: src1/int-rep src2/int-rep
-literal: cc ;
-
-! Overflowing arithmetic
-INSN: _fixnum-add
-literal: label
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
-
-INSN: _fixnum-sub
-literal: label
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
+! GC checks
+INSN: ##check-nursery-branch
+literal: size cc
+temp: temp1/int-rep temp2/int-rep ;
 
-INSN: _fixnum-mul
-literal: label
-def: dst/int-rep
-use: src1/int-rep src2/int-rep ;
+INSN: ##call-gc
+literal: gc-roots ;
 
+! Spills and reloads, inserted by register allocator
 TUPLE: spill-slot { n integer } ;
 C: <spill-slot> spill-slot
 
-! These instructions operate on machine registers and not
-! virtual registers
-INSN: _spill
+INSN: ##spill
 use: src
 literal: rep dst ;
 
-INSN: _reload
+INSN: ##reload
 def: dst
 literal: rep src ;
 
-INSN: _spill-area-size
-literal: n ;
-
 UNION: ##allocation
 ##allot
 ##box-alien
 ##box-displaced-alien ;
 
+UNION: conditional-branch-insn
+##compare-branch
+##compare-imm-branch
+##compare-integer-branch
+##compare-integer-imm-branch
+##compare-float-ordered-branch
+##compare-float-unordered-branch
+##test-vector-branch
+##check-nursery-branch
+##fixnum-add
+##fixnum-sub
+##fixnum-mul ;
+
 ! For alias analysis
 UNION: ##read ##slot ##slot-imm ##vm-field ##alien-global ;
 UNION: ##write ##set-slot ##set-slot-imm ##set-vm-field ;
 
-! Instructions that kill all live vregs but cannot trigger GC
-UNION: partial-sync-insn
+! Instructions that clobber registers
+UNION: clobber-insn
+##call-gc
 ##unary-float-function
 ##binary-float-function ;
 
@@ -861,7 +768,6 @@ UNION: kill-vreg-insn
 UNION: def-is-use-insn
 ##box-alien
 ##box-displaced-alien
-##string-nth
 ##unbox-any-c-ptr ;
 
 SYMBOL: vreg-insn
index cd76652d06076508be8cfaa3308093cc26c23ef8..7b8327cf06cf15f1a7eecb92d65e9401e9bf64e1 100644 (file)
@@ -5,7 +5,7 @@ make fry sequences parser accessors effects namespaces
 combinators splitting classes.parser lexer quotations ;
 IN: compiler.cfg.instructions.syntax
 
-SYMBOLS: def use temp literal constant ;
+SYMBOLS: def use temp literal ;
 
 SYMBOL: scalar-rep
 
@@ -31,23 +31,22 @@ TUPLE: insn-slot-spec type name rep ;
                 { "use:" [ drop use ] }
                 { "temp:" [ drop temp ] }
                 { "literal:" [ drop literal ] }
-                { "constant:" [ drop constant ] }
                 [ dupd parse-insn-slot-spec , ]
             } case
         ] reduce drop
     ] { } make ;
 
-: insn-def-slot ( class -- slot/f )
-    "insn-slots" word-prop
+: find-def-slot ( slots -- slot/f )
     [ type>> def eq? ] find nip ;
 
+: insn-def-slot ( class -- slot/f )
+    "insn-slots" word-prop find-def-slot ;
+
 : insn-use-slots ( class -- slots )
-    "insn-slots" word-prop
-    [ type>> use eq? ] filter ;
+    "insn-slots" word-prop [ type>> use eq? ] filter ;
 
 : insn-temp-slots ( class -- slots )
-    "insn-slots" word-prop
-    [ type>> temp eq? ] filter ;
+    "insn-slots" word-prop [ type>> temp eq? ] filter ;
 
 ! We cannot reference words in compiler.cfg.instructions directly
 ! since that would create circularity.
index 320a0a08f7c89982fd0445a305ddd8b48af086b9..23143b2f8611a84b69ea38ff3747fbd24aad32b9 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel sequences alien math classes.algebra fry
 locals combinators combinators.short-circuit cpu.architecture
@@ -16,104 +16,72 @@ IN: compiler.cfg.intrinsics.alien
 
 : emit-<displaced-alien> ( node -- )
     dup emit-<displaced-alien>? [
-        [ 2inputs [ ^^untag-fixnum ] dip ] dip
-        node-input-infos second class>>
-        ^^box-displaced-alien ds-push
+        '[
+            _ node-input-infos second class>>
+            ^^box-displaced-alien
+        ] binary-op
     ] [ emit-primitive ] if ;
 
-:: inline-alien ( node quot test -- )
+:: inline-accessor ( node quot test -- )
     node node-input-infos :> infos
     infos test call
     [ infos quot call ]
     [ node emit-primitive ] if ; inline
 
-: inline-alien-getter? ( infos -- ? )
+: inline-load-memory? ( infos -- ? )
     [ first class>> c-ptr class<= ]
     [ second class>> fixnum class<= ]
     bi and ;
 
-: ^^unbox-c-ptr ( src class -- dst )
-    [ next-vreg dup ] 2dip ##unbox-c-ptr ;
+: prepare-accessor ( base offset info -- base offset )
+    class>> swap [ ^^unbox-c-ptr ] dip ^^add 0 ;
 
-: prepare-alien-accessor ( info -- ptr-vreg offset )
-    class>> [ 2inputs ^^untag-fixnum swap ] dip ^^unbox-c-ptr ^^add 0 ;
+: prepare-load-memory ( infos -- base offset )
+    [ 2inputs ] dip first prepare-accessor ;
 
-: prepare-alien-getter ( infos -- ptr-vreg offset )
-    first prepare-alien-accessor ;
+: (emit-load-memory) ( node rep c-type quot -- )
+    '[ prepare-load-memory _ _ ^^load-memory-imm @ ds-push ]
+    [ inline-load-memory? ]
+    inline-accessor ; inline
 
-: inline-alien-getter ( node quot -- )
-    '[ prepare-alien-getter @ ds-push ]
-    [ inline-alien-getter? ] inline-alien ; inline
+: emit-load-memory ( node rep c-type -- )
+    [ ] (emit-load-memory) ;
 
-: inline-alien-setter? ( infos class -- ? )
+: emit-alien-cell ( node -- )
+    int-rep f [ ^^box-alien ] (emit-load-memory) ;
+
+: inline-store-memory? ( infos class -- ? )
     '[ first class>> _ class<= ]
     [ second class>> c-ptr class<= ]
     [ third class>> fixnum class<= ]
     tri and and ;
 
-: prepare-alien-setter ( infos -- ptr-vreg offset )
-    second prepare-alien-accessor ;
-
-: inline-alien-integer-setter ( node quot -- )
-    '[ prepare-alien-setter ds-pop ^^untag-fixnum @ ]
-    [ fixnum inline-alien-setter? ]
-    inline-alien ; inline
-
-: inline-alien-cell-setter ( node quot -- )
-    '[ [ prepare-alien-setter ds-pop ] [ first class>> ] bi ^^unbox-c-ptr @ ]
-    [ pinned-c-ptr inline-alien-setter? ]
-    inline-alien ; inline
-
-: inline-alien-float-setter ( node quot -- )
-    '[ prepare-alien-setter ds-pop @ ]
-    [ float inline-alien-setter? ]
-    inline-alien ; inline
-
-: emit-alien-unsigned-getter ( node n -- )
-    '[
-        _ {
-            { 1 [ ^^alien-unsigned-1 ] }
-            { 2 [ ^^alien-unsigned-2 ] }
-            { 4 [ ^^alien-unsigned-4 ] }
-        } case ^^tag-fixnum
-    ] inline-alien-getter ;
-
-: emit-alien-signed-getter ( node n -- )
-    '[
-        _ {
-            { 1 [ ^^alien-signed-1 ] }
-            { 2 [ ^^alien-signed-2 ] }
-            { 4 [ ^^alien-signed-4 ] }
-        } case ^^tag-fixnum
-    ] inline-alien-getter ;
-
-: emit-alien-integer-setter ( node n -- )
-    '[
-        _ {
-            { 1 [ ##set-alien-integer-1 ] }
-            { 2 [ ##set-alien-integer-2 ] }
-            { 4 [ ##set-alien-integer-4 ] }
-        } case
-    ] inline-alien-integer-setter ;
-
-: emit-alien-cell-getter ( node -- )
-    [ ^^alien-cell ^^box-alien ] inline-alien-getter ;
-
-: emit-alien-cell-setter ( node -- )
-    [ ##set-alien-cell ] inline-alien-cell-setter ;
-
-: emit-alien-float-getter ( node rep -- )
-    '[
-        _ {
-            { float-rep [ ^^alien-float ] }
-            { double-rep [ ^^alien-double ] }
-        } case
-    ] inline-alien-getter ;
-
-: emit-alien-float-setter ( node rep -- )
-    '[
-        _ {
-            { float-rep [ ##set-alien-float ] }
-            { double-rep [ ##set-alien-double ] }
+: prepare-store-memory ( infos -- value base offset )
+    [ 3inputs ] dip second prepare-accessor ;
+
+:: (emit-store-memory) ( node rep c-type prepare-quot test-quot -- )
+    node
+    [ prepare-quot call rep c-type ##store-memory-imm ]
+    [ test-quot call inline-store-memory? ]
+    inline-accessor ; inline
+
+:: emit-store-memory ( node rep c-type -- )
+    node rep c-type
+    [ prepare-store-memory ]
+    [
+        rep {
+            { int-rep [ fixnum ] }
+            { float-rep [ float ] }
+            { double-rep [ float ] }
         } case
-    ] inline-alien-float-setter ;
+    ]
+    (emit-store-memory) ;
+
+: emit-set-alien-cell ( node -- )
+    int-rep f
+    [
+        [ first class>> ] [ prepare-store-memory ] bi
+        [ swap ^^unbox-c-ptr ] 2dip
+    ]
+    [ pinned-c-ptr ]
+    (emit-store-memory) ;
index ad7e02df8a6b44c120987f19159a7d8ff5fa94d7..b9cfac3b92f382daf0199c397df3dae98473712c 100644 (file)
@@ -1,9 +1,10 @@
-! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
+! Copyright (C) 2008, 2010 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: sequences accessors layouts kernel math math.intervals
 namespaces combinators fry arrays
 cpu.architecture
 compiler.tree.propagation.info
+compiler.cfg
 compiler.cfg.hats
 compiler.cfg.stacks
 compiler.cfg.instructions
@@ -14,23 +15,24 @@ compiler.cfg.comparisons ;
 IN: compiler.cfg.intrinsics.fixnum
 
 : emit-both-fixnums? ( -- )
-    2inputs
-    ^^or
-    tag-mask get ^^and-imm
-    0 cc= ^^compare-imm
-    ds-push ;
-
-: emit-fixnum-op ( insn -- )
-    [ 2inputs ] dip call ds-push ; inline
+    [
+        [ ^^tagged>integer ] bi@
+        ^^or tag-mask get ^^and-imm
+        0 cc= ^^compare-integer-imm
+    ] binary-op ;
 
 : emit-fixnum-left-shift ( -- )
-    [ ^^untag-fixnum ^^shl ] emit-fixnum-op ;
+    [ ^^shl ] binary-op ;
 
 : emit-fixnum-right-shift ( -- )
-    [ ^^untag-fixnum ^^neg ^^sar dup tag-mask get ^^and-imm ^^xor ] emit-fixnum-op ;
+    [
+        [ tag-bits get ^^shl-imm ] dip
+        ^^neg ^^sar
+        tag-bits get ^^sar-imm
+    ] binary-op ;
 
 : emit-fixnum-shift-general ( -- )
-    ds-peek 0 cc> ##compare-imm-branch
+    ds-peek 0 cc> ##compare-integer-imm-branch
     [ emit-fixnum-left-shift ] with-branch
     [ emit-fixnum-right-shift ] with-branch
     2array emit-conditional ;
@@ -42,17 +44,8 @@ IN: compiler.cfg.intrinsics.fixnum
         [ drop emit-fixnum-shift-general ]
     } cond ;
 
-: emit-fixnum-bitnot ( -- )
-    ds-pop ^^not tag-mask get ^^xor-imm ds-push ;
-
-: emit-fixnum-log2 ( -- )
-    ds-pop ^^log2 tag-bits get ^^sub-imm ^^tag-fixnum ds-push ;
-
-: emit-fixnum*fast ( -- )
-    2inputs ^^untag-fixnum ^^mul ds-push ;
-
 : emit-fixnum-comparison ( cc -- )
-    '[ _ ^^compare ] emit-fixnum-op ;
+    '[ _ ^^compare-integer ] binary-op ;
 
 : emit-no-overflow-case ( dst -- final-bb )
     [ ds-drop ds-drop ds-push ] with-branch ;
@@ -63,7 +56,7 @@ IN: compiler.cfg.intrinsics.fixnum
 : emit-fixnum-overflow-op ( quot word -- )
     ! Inputs to the final instruction need to be copied because
     ! of loc>vreg sync
-    [ [ (2inputs) [ any-rep ^^copy ] bi@ ] dip call ] dip
+    [ [ (2inputs) [ any-rep ^^copy ] bi@ cc/o ] dip call ] dip
     [ emit-no-overflow-case ] [ emit-overflow-case ] bi* 2array
     emit-conditional ; inline
 
@@ -80,4 +73,4 @@ IN: compiler.cfg.intrinsics.fixnum
     [ ^^fixnum-sub ] \ fixnum-overflow emit-fixnum-overflow-op ;
 
 : emit-fixnum* ( -- )
-    [ ^^untag-fixnum ^^fixnum-mul ] \ fixnum*overflow emit-fixnum-overflow-op ;
\ No newline at end of file
+    [ ^^fixnum-mul ] \ fixnum*overflow emit-fixnum-overflow-op ;
\ No newline at end of file
index 8a65de5805f2dfa9a0da682b831565bc92c595d2..480b46f9b3ec8525d8ce66a327f64046320c02ac 100644 (file)
@@ -1,29 +1,17 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel compiler.cfg.stacks compiler.cfg.hats
+USING: fry kernel compiler.cfg.stacks compiler.cfg.hats
 compiler.cfg.instructions compiler.cfg.utilities ;
 IN: compiler.cfg.intrinsics.float
 
-: emit-float-op ( insn -- )
-    [ 2inputs ] dip call ds-push ; inline
-
 : emit-float-ordered-comparison ( cc -- )
-    [ 2inputs ] dip ^^compare-float-ordered ds-push ; inline
+    '[ _ ^^compare-float-ordered ] binary-op ; inline
 
 : emit-float-unordered-comparison ( cc -- )
-    [ 2inputs ] dip ^^compare-float-unordered ds-push ; inline
-
-: emit-float>fixnum ( -- )
-    ds-pop ^^float>integer ^^tag-fixnum ds-push ;
-
-: emit-fixnum>float ( -- )
-    ds-pop ^^untag-fixnum ^^integer>float ds-push ;
-
-: emit-fsqrt ( -- )
-    ds-pop ^^sqrt ds-push ;
+    '[ _ ^^compare-float-unordered ] binary-op ; inline
 
 : emit-unary-float-function ( func -- )
-    [ ds-pop ] dip ^^unary-float-function ds-push ;
+    '[ _ ^^unary-float-function ] unary-op ;
 
 : emit-binary-float-function ( func -- )
-    [ 2inputs ] dip ^^binary-float-function ds-push ;
+    '[ _ ^^binary-float-function ] binary-op ;
index 2b2ae7d160d15a94cf8c76fb3243aac040bd91a7..4faa4809e5c27e782d73036f3c095f42e0409df4 100644 (file)
@@ -1,17 +1,20 @@
-! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
+! Copyright (C) 2008, 2010 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: words sequences kernel combinators cpu.architecture assocs
 compiler.cfg.hats
+compiler.cfg.stacks
 compiler.cfg.instructions
 compiler.cfg.intrinsics.alien
 compiler.cfg.intrinsics.allot
 compiler.cfg.intrinsics.fixnum
 compiler.cfg.intrinsics.float
 compiler.cfg.intrinsics.slots
+compiler.cfg.intrinsics.strings
 compiler.cfg.intrinsics.misc
 compiler.cfg.comparisons ;
 QUALIFIED: alien
 QUALIFIED: alien.accessors
+QUALIFIED: alien.c-types
 QUALIFIED: kernel
 QUALIFIED: arrays
 QUALIFIED: byte-arrays
@@ -38,22 +41,22 @@ IN: compiler.cfg.intrinsics
     { math.private:fixnum+ [ drop emit-fixnum+ ] }
     { math.private:fixnum- [ drop emit-fixnum- ] }
     { math.private:fixnum* [ drop emit-fixnum* ] }
-    { math.private:fixnum+fast [ drop [ ^^add ] emit-fixnum-op ] }
-    { math.private:fixnum-fast [ drop [ ^^sub ] emit-fixnum-op ] }
-    { math.private:fixnum*fast [ drop emit-fixnum*fast ] }
-    { math.private:fixnum-bitand [ drop [ ^^and ] emit-fixnum-op ] }
-    { math.private:fixnum-bitor [ drop [ ^^or ] emit-fixnum-op ] }
-    { math.private:fixnum-bitxor [ drop [ ^^xor ] emit-fixnum-op ] }
+    { math.private:fixnum+fast [ drop [ ^^add ] binary-op ] }
+    { math.private:fixnum-fast [ drop [ ^^sub ] binary-op ] }
+    { math.private:fixnum*fast [ drop [ ^^mul ] binary-op ] }
+    { math.private:fixnum-bitand [ drop [ ^^and ] binary-op ] }
+    { math.private:fixnum-bitor [ drop [ ^^or ] binary-op ] }
+    { math.private:fixnum-bitxor [ drop [ ^^xor ] binary-op ] }
     { math.private:fixnum-shift-fast [ emit-fixnum-shift-fast ] }
-    { math.private:fixnum-bitnot [ drop emit-fixnum-bitnot ] }
+    { math.private:fixnum-bitnot [ drop [ ^^not ] unary-op ] }
     { math.private:fixnum< [ drop cc< emit-fixnum-comparison ] }
     { math.private:fixnum<= [ drop cc<= emit-fixnum-comparison ] }
     { math.private:fixnum>= [ drop cc>= emit-fixnum-comparison ] }
     { math.private:fixnum> [ drop cc> emit-fixnum-comparison ] }
-    { kernel:eq? [ drop cc= emit-fixnum-comparison ] }
+    { kernel:eq? [ emit-eq ] }
     { slots.private:slot [ emit-slot ] }
     { slots.private:set-slot [ emit-set-slot ] }
-    { strings.private:string-nth [ drop emit-string-nth ] }
+    { strings.private:string-nth-fast [ drop emit-string-nth-fast ] }
     { strings.private:set-string-nth-fast [ drop emit-set-string-nth-fast ] }
     { classes.tuple.private:<tuple-boa> [ emit-<tuple-boa> ] }
     { arrays:<array> [ emit-<array> ] }
@@ -61,32 +64,32 @@ IN: compiler.cfg.intrinsics
     { byte-arrays:(byte-array) [ emit-(byte-array) ] }
     { kernel:<wrapper> [ emit-simple-allot ] }
     { alien:<displaced-alien> [ emit-<displaced-alien> ] }
-    { alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter ] }
-    { alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter ] }
-    { alien.accessors:alien-signed-1 [ 1 emit-alien-signed-getter ] }
-    { alien.accessors:set-alien-signed-1 [ 1 emit-alien-integer-setter ] }
-    { alien.accessors:alien-unsigned-2 [ 2 emit-alien-unsigned-getter ] }
-    { alien.accessors:set-alien-unsigned-2 [ 2 emit-alien-integer-setter ] }
-    { alien.accessors:alien-signed-2 [ 2 emit-alien-signed-getter ] }
-    { alien.accessors:set-alien-signed-2 [ 2 emit-alien-integer-setter ] }
-    { alien.accessors:alien-cell [ emit-alien-cell-getter ] }
-    { alien.accessors:set-alien-cell [ emit-alien-cell-setter ] }
+    { alien.accessors:alien-unsigned-1 [ int-rep alien.c-types:uchar emit-load-memory ] }
+    { alien.accessors:set-alien-unsigned-1 [ int-rep alien.c-types:uchar emit-store-memory ] }
+    { alien.accessors:alien-signed-1 [ int-rep alien.c-types:char emit-load-memory ] }
+    { alien.accessors:set-alien-signed-1 [ int-rep alien.c-types:char emit-store-memory ] }
+    { alien.accessors:alien-unsigned-2 [ int-rep alien.c-types:ushort emit-load-memory ] }
+    { alien.accessors:set-alien-unsigned-2 [ int-rep alien.c-types:ushort emit-store-memory ] }
+    { alien.accessors:alien-signed-2 [ int-rep alien.c-types:short emit-load-memory ] }
+    { alien.accessors:set-alien-signed-2 [ int-rep alien.c-types:short emit-store-memory ] }
+    { alien.accessors:alien-cell [ emit-alien-cell ] }
+    { alien.accessors:set-alien-cell [ emit-set-alien-cell ] }
 } enable-intrinsics
 
 : enable-alien-4-intrinsics ( -- )
     {
-        { alien.accessors:alien-unsigned-4 [ 4 emit-alien-unsigned-getter ] }
-        { alien.accessors:set-alien-unsigned-4 [ 4 emit-alien-integer-setter ] }
-        { alien.accessors:alien-signed-4 [ 4 emit-alien-signed-getter ] }
-        { alien.accessors:set-alien-signed-4 [ 4 emit-alien-integer-setter ] }
+        { alien.accessors:alien-signed-4 [ int-rep alien.c-types:int emit-load-memory ] }
+        { alien.accessors:set-alien-signed-4 [ int-rep alien.c-types:int emit-store-memory ] }
+        { alien.accessors:alien-unsigned-4 [ int-rep alien.c-types:uint emit-load-memory ] }
+        { alien.accessors:set-alien-unsigned-4 [ int-rep alien.c-types:uint emit-store-memory ] }
     } enable-intrinsics ;
 
 : enable-float-intrinsics ( -- )
     {
-        { math.private:float+ [ drop [ ^^add-float ] emit-float-op ] }
-        { math.private:float- [ drop [ ^^sub-float ] emit-float-op ] }
-        { math.private:float* [ drop [ ^^mul-float ] emit-float-op ] }
-        { math.private:float/f [ drop [ ^^div-float ] emit-float-op ] }
+        { math.private:float+ [ drop [ ^^add-float ] binary-op ] }
+        { math.private:float- [ drop [ ^^sub-float ] binary-op ] }
+        { math.private:float* [ drop [ ^^mul-float ] binary-op ] }
+        { math.private:float/f [ drop [ ^^div-float ] binary-op ] }
         { math.private:float< [ drop cc< emit-float-ordered-comparison ] }
         { math.private:float<= [ drop cc<= emit-float-ordered-comparison ] }
         { math.private:float>= [ drop cc>= emit-float-ordered-comparison ] }
@@ -96,24 +99,24 @@ IN: compiler.cfg.intrinsics
         { math.private:float-u>= [ drop cc>= emit-float-unordered-comparison ] }
         { math.private:float-u> [ drop cc> emit-float-unordered-comparison ] }
         { math.private:float= [ drop cc= emit-float-unordered-comparison ] }
-        { math.private:float>fixnum [ drop emit-float>fixnum ] }
-        { math.private:fixnum>float [ drop emit-fixnum>float ] }
+        { math.private:float>fixnum [ drop [ ^^float>integer ] unary-op ] }
+        { math.private:fixnum>float [ drop [ ^^integer>float ] unary-op ] }
         { math.floats.private:float-unordered? [ drop cc/<>= emit-float-unordered-comparison ] }
-        { alien.accessors:alien-float [ float-rep emit-alien-float-getter ] }
-        { alien.accessors:set-alien-float [ float-rep emit-alien-float-setter ] }
-        { alien.accessors:alien-double [ double-rep emit-alien-float-getter ] }
-        { alien.accessors:set-alien-double [ double-rep emit-alien-float-setter ] }
+        { alien.accessors:alien-float [ float-rep f emit-load-memory ] }
+        { alien.accessors:set-alien-float [ float-rep f emit-store-memory ] }
+        { alien.accessors:alien-double [ double-rep f emit-load-memory ] }
+        { alien.accessors:set-alien-double [ double-rep f emit-store-memory ] }
     } enable-intrinsics ;
 
 : enable-fsqrt ( -- )
     {
-        { math.libm:fsqrt [ drop emit-fsqrt ] }
+        { math.libm:fsqrt [ drop [ ^^sqrt ] unary-op ] }
     } enable-intrinsics ;
 
 : enable-float-min/max ( -- )
     {
-        { math.floats.private:float-min [ drop [ ^^min-float ] emit-float-op ] }
-        { math.floats.private:float-max [ drop [ ^^max-float ] emit-float-op ] }
+        { math.floats.private:float-min [ drop [ ^^min-float ] binary-op ] }
+        { math.floats.private:float-max [ drop [ ^^max-float ] binary-op ] }
     } enable-intrinsics ;
 
 : enable-float-functions ( -- )
@@ -143,13 +146,13 @@ IN: compiler.cfg.intrinsics
 
 : enable-min/max ( -- )
     {
-        { math.integers.private:fixnum-min [ drop [ ^^min ] emit-fixnum-op ] }
-        { math.integers.private:fixnum-max [ drop [ ^^max ] emit-fixnum-op ] }
+        { math.integers.private:fixnum-min [ drop [ ^^min ] binary-op ] }
+        { math.integers.private:fixnum-max [ drop [ ^^max ] binary-op ] }
     } enable-intrinsics ;
 
-: enable-fixnum-log2 ( -- )
+: enable-log2 ( -- )
     {
-        { math.integers.private:fixnum-log2 [ drop emit-fixnum-log2 ] }
+        { math.integers.private:fixnum-log2 [ drop [ ^^log2 ] unary-op ] }
     } enable-intrinsics ;
 
 : emit-intrinsic ( node word -- )
index da77bcaa09d69deb332739ddbe24bf00c207e0fa..31c3bac37bd39f245b99eb49ff745d0664f0c43e 100644 (file)
@@ -1,15 +1,24 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces layouts sequences kernel math accessors
-compiler.tree.propagation.info compiler.cfg.stacks
-compiler.cfg.hats compiler.cfg.instructions
+USING: accessors classes.algebra layouts kernel math namespaces
+sequences cpu.architecture
+compiler.tree.propagation.info
+compiler.cfg.stacks
+compiler.cfg.hats
+compiler.cfg.comparisons
+compiler.cfg.instructions
 compiler.cfg.builder.blocks
 compiler.cfg.utilities ;
 FROM: vm => context-field-offset vm-field-offset ;
+QUALIFIED-WITH: alien.c-types c
 IN: compiler.cfg.intrinsics.misc
 
 : emit-tag ( -- )
-    ds-pop tag-mask get ^^and-imm ^^tag-fixnum ds-push ;
+    [ ^^tagged>integer tag-mask get ^^and-imm ] unary-op ;
+
+: emit-eq ( node -- )
+    node-input-infos first2 [ class>> fixnum class<= ] both?
+    [ [ cc= ^^compare-integer ] binary-op ] [ [ cc= ^^compare ] binary-op ] if ;
 
 : special-object-offset ( n -- offset )
     cells "special-objects" vm-field-offset + ;
@@ -37,7 +46,9 @@ IN: compiler.cfg.intrinsics.misc
     ] [ emit-primitive ] ?if ;
 
 : emit-identity-hashcode ( -- )
-    ds-pop tag-mask get bitnot ^^load-immediate ^^and 0 0 ^^slot-imm
-    hashcode-shift ^^shr-imm
-    ^^tag-fixnum
-    ds-push ;
+    [
+        ^^tagged>integer
+        tag-mask get bitnot ^^load-integer ^^and
+        0 int-rep f ^^load-memory-imm
+        hashcode-shift ^^shr-imm
+    ] unary-op ;
index 2c2d1f1d3a7c31a20cab8296dab717712654d298..d9f3df000f1aaed42c7ee49b13f65ac1ddf58769 100644 (file)
@@ -19,7 +19,7 @@ M: ##zero-vector insn-available? rep>> %zero-vector-reps member? ;
 M: ##fill-vector insn-available? rep>> %fill-vector-reps member? ;
 M: ##gather-vector-2 insn-available? rep>> %gather-vector-2-reps member? ;
 M: ##gather-vector-4 insn-available? rep>> %gather-vector-4-reps member? ;
-M: ##alien-vector insn-available? rep>> %alien-vector-reps member? ;
+M: ##store-memory-imm insn-available? rep>> %alien-vector-reps member? ;
 M: ##shuffle-vector insn-available? rep>> %shuffle-vector-reps member? ;
 M: ##shuffle-vector-imm insn-available? rep>> %shuffle-vector-imm-reps member? ;
 M: ##merge-vector-head insn-available? rep>> %merge-vector-reps member? ;
index 8bd936c4f6f33d6a255357cc81d0c4124aea8696..96c8da8ace2e616f1973db8e34e246a315f98f6c 100644 (file)
@@ -127,7 +127,7 @@ unit-test
 unit-test
 
 ! vneg
-[ { ##load-constant ##sub-vector } ]
+[ { ##load-reference ##sub-vector } ]
 [ simple-ops-cpu float-4-rep [ emit-simd-vneg ] test-emit ]
 unit-test
 
@@ -153,11 +153,11 @@ M: addsub-cpu %add-sub-vector-reps { int-4-rep float-4-rep } ;
 [ addsub-cpu float-4-rep [ emit-simd-v+- ] test-emit ]
 unit-test
 
-[ { ##load-constant ##xor-vector ##add-vector } ]
+[ { ##load-reference ##xor-vector ##add-vector } ]
 [ simple-ops-cpu float-4-rep [ emit-simd-v+- ] test-emit ]
 unit-test
 
-[ { ##load-constant ##xor-vector ##sub-vector ##add-vector } ]
+[ { ##load-reference ##xor-vector ##sub-vector ##add-vector } ]
 [ simple-ops-cpu int-4-rep [ emit-simd-v+- ] test-emit ]
 unit-test
 
@@ -301,7 +301,7 @@ unit-test
 [ abs-cpu float-4-rep [ emit-simd-vabs ] test-emit ]
 unit-test
 
-[ { ##load-constant ##andn-vector } ]
+[ { ##load-reference ##andn-vector } ]
 [ simple-ops-cpu float-4-rep [ emit-simd-vabs ] test-emit ]
 unit-test
 
@@ -388,7 +388,7 @@ TUPLE: shuffle-cpu < simple-ops-cpu ;
 M: shuffle-cpu %shuffle-vector-reps signed-reps ;
 
 ! vshuffle-elements
-[ { ##load-constant ##shuffle-vector } ]
+[ { ##load-reference ##shuffle-vector } ]
 [ shuffle-cpu { 0 1 2 3 } int-4-rep [ emit-simd-vshuffle-elements ] test-emit-literal ]
 unit-test
 
@@ -420,7 +420,7 @@ unit-test
 [ minmax-cpu int-4-rep [ emit-simd-v<= ] test-emit ]
 unit-test
 
-[ { ##load-constant ##xor-vector ##xor-vector ##compare-vector } ]
+[ { ##load-reference ##xor-vector ##xor-vector ##compare-vector } ]
 [ compare-cpu uint-4-rep [ emit-simd-v<= ] test-emit ]
 unit-test
 
index 0d413f1346c7773a6289aa3840e275a2d9f4e70d..a64aa828d072f17e547626f628aba76803a46f45 100644 (file)
@@ -43,24 +43,24 @@ IN: compiler.cfg.intrinsics.simd
 
 : ^load-neg-zero-vector ( rep -- dst )
     {
-        { float-4-rep [ float-array{ -0.0 -0.0 -0.0 -0.0 } underlying>> ^^load-constant ] }
-        { double-2-rep [ double-array{ -0.0 -0.0 } underlying>> ^^load-constant ] }
+        { float-4-rep [ float-array{ -0.0 -0.0 -0.0 -0.0 } underlying>> ^^load-literal ] }
+        { double-2-rep [ double-array{ -0.0 -0.0 } underlying>> ^^load-literal ] }
     } case ;
 
 : ^load-add-sub-vector ( rep -- dst )
     signed-rep {
-        { float-4-rep    [ float-array{ -0.0  0.0 -0.0  0.0 } underlying>> ^^load-constant ] }
-        { double-2-rep   [ double-array{ -0.0  0.0 } underlying>> ^^load-constant ] }
-        { char-16-rep    [ char-array{ -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-constant ] }
-        { short-8-rep    [ short-array{ -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-constant ] }
-        { int-4-rep      [ int-array{ -1 0 -1 0 } underlying>> ^^load-constant ] }
-        { longlong-2-rep [ longlong-array{ -1 0 } underlying>> ^^load-constant ] }
+        { float-4-rep    [ float-array{ -0.0  0.0 -0.0  0.0 } underlying>> ^^load-literal ] }
+        { double-2-rep   [ double-array{ -0.0  0.0 } underlying>> ^^load-literal ] }
+        { char-16-rep    [ char-array{ -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-literal ] }
+        { short-8-rep    [ short-array{ -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-literal ] }
+        { int-4-rep      [ int-array{ -1 0 -1 0 } underlying>> ^^load-literal ] }
+        { longlong-2-rep [ longlong-array{ -1 0 } underlying>> ^^load-literal ] }
     } case ;
 
 : ^load-half-vector ( rep -- dst )
     {
-        { float-4-rep  [ float-array{  0.5 0.5 0.5 0.5 } underlying>> ^^load-constant ] }
-        { double-2-rep [ double-array{ 0.5 0.5 }         underlying>> ^^load-constant ] }
+        { float-4-rep  [ float-array{  0.5 0.5 0.5 0.5 } underlying>> ^^load-literal ] }
+        { double-2-rep [ double-array{ 0.5 0.5 }         underlying>> ^^load-literal ] }
     } case ;
 
 : >variable-shuffle ( shuffle rep -- shuffle' )
@@ -70,7 +70,7 @@ IN: compiler.cfg.intrinsics.simd
     '[ _ n*v _ v+ ] map concat ;
 
 : ^load-immediate-shuffle ( shuffle rep -- dst )
-    >variable-shuffle ^^load-constant ;
+    >variable-shuffle ^^load-literal ;
 
 :: ^blend-vector ( mask true false rep -- dst )
     true mask rep ^^and-vector
@@ -118,7 +118,7 @@ IN: compiler.cfg.intrinsics.simd
         [ ^(compare-vector) ]
         [ ^minmax-compare-vector ]
         { unsigned-int-vector-rep [| src1 src2 rep cc |
-            rep sign-bit-mask ^^load-constant :> sign-bits
+            rep sign-bit-mask ^^load-literal :> sign-bits
             src1 sign-bits rep ^^xor-vector
             src2 sign-bits rep ^^xor-vector
             rep signed-rep cc ^(compare-vector)
@@ -587,20 +587,20 @@ PREDICATE: fixnum-vector-rep < int-vector-rep
 : emit-alien-vector ( node -- )
     dup [
         '[
-            ds-drop prepare-alien-getter
-            _ ^^alien-vector ds-push
+            ds-drop prepare-load-memory
+            _ f ^^load-memory-imm ds-push
         ]
-        [ inline-alien-getter? ] inline-alien
+        [ inline-load-memory? ] inline-accessor
     ] with { [ %alien-vector-reps member? ] } if-literals-match ;
 
 : emit-set-alien-vector ( node -- )
     dup [
         '[
-            ds-drop prepare-alien-setter ds-pop
-            _ ##set-alien-vector
+            ds-drop prepare-store-memory
+            _ f ##store-memory-imm
         ]
-        [ byte-array inline-alien-setter? ]
-        inline-alien
+        [ byte-array inline-store-memory? ]
+        inline-accessor
     ] with { [ %alien-vector-reps member? ] } if-literals-match ;
 
 : enable-simd ( -- )
index 1ceac4990ace32a93fdea8342e6af3bf07474b3c..a3f532b4dbee7889d4bdd7d7baf28b37af217db5 100644 (file)
@@ -1,9 +1,10 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: layouts namespaces kernel accessors sequences math
 classes.algebra classes.builtin locals combinators
-cpu.architecture compiler.tree.propagation.info
-compiler.cfg.stacks compiler.cfg.hats compiler.cfg.registers
+combinators.short-circuit cpu.architecture
+compiler.tree.propagation.info compiler.cfg.stacks
+compiler.cfg.hats compiler.cfg.registers
 compiler.cfg.instructions compiler.cfg.utilities
 compiler.cfg.builder.blocks compiler.constants ;
 IN: compiler.cfg.intrinsics.slots
@@ -13,12 +14,13 @@ IN: compiler.cfg.intrinsics.slots
 
 : value-tag ( info -- n ) class>> class-tag ;
 
-: ^^tag-offset>slot ( slot tag -- vreg' )
-    [ ^^offset>slot ] dip ^^sub-imm ;
+: slot-indexing ( slot tag -- slot scale tag )
+    complex-addressing?
+    [ [ cell log2 ] dip ] [ [ ^^offset>slot ] dip ^^sub-imm 0 0 ] if ;
 
 : (emit-slot) ( infos -- dst )
     [ 2inputs ] [ first value-tag ] bi*
-    ^^tag-offset>slot ^^slot ;
+    slot-indexing ^^slot ;
 
 : (emit-slot-imm) ( infos -- dst )
     ds-drop
@@ -28,9 +30,9 @@ IN: compiler.cfg.intrinsics.slots
 
 : immediate-slot-offset? ( value-info -- ? )
     literal>> {
-        { [ dup fixnum? ] [ tag-fixnum immediate-arithmetic? ] }
-        [ drop f ]
-    } cond ;
+        [ fixnum? ]
+        [ cell * immediate-arithmetic? ]
+    } 1&& ;
 
 : emit-slot ( node -- )
     dup node-input-infos
@@ -47,12 +49,13 @@ IN: compiler.cfg.intrinsics.slots
 :: (emit-set-slot) ( infos -- )
     3inputs :> ( src obj slot )
 
-    slot infos second value-tag ^^tag-offset>slot :> slot
+    infos second value-tag :> tag
 
-    src obj slot ##set-slot
+    slot tag slot-indexing :> ( slot scale tag )
+    src obj slot scale tag ##set-slot
 
     infos emit-write-barrier?
-    [ obj slot next-vreg next-vreg ##write-barrier ] when ;
+    [ obj slot scale tag next-vreg next-vreg ##write-barrier ] when ;
 
 :: (emit-set-slot-imm) ( infos -- )
     ds-drop
@@ -65,7 +68,7 @@ IN: compiler.cfg.intrinsics.slots
     src obj slot tag ##set-slot-imm
 
     infos emit-write-barrier?
-    [ obj slot tag slot-offset next-vreg next-vreg ##write-barrier-imm ] when ;
+    [ obj slot tag next-vreg next-vreg ##write-barrier-imm ] when ;
 
 : emit-set-slot ( node -- )
     dup node-input-infos
@@ -74,10 +77,3 @@ IN: compiler.cfg.intrinsics.slots
         dup third immediate-slot-offset?
         [ (emit-set-slot-imm) ] [ (emit-set-slot) ] if
     ] [ drop emit-primitive ] if ;
-
-: emit-string-nth ( -- )
-    2inputs swap ^^untag-fixnum ^^string-nth ^^tag-fixnum ds-push ;
-
-: emit-set-string-nth-fast ( -- )
-    3inputs [ ^^untag-fixnum ] [ ^^untag-fixnum ] [ ] tri*
-    swap next-vreg ##set-string-nth-fast ;
diff --git a/basis/compiler/cfg/intrinsics/strings/authors.txt b/basis/compiler/cfg/intrinsics/strings/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/intrinsics/strings/strings.factor b/basis/compiler/cfg/intrinsics/strings/strings.factor
new file mode 100644 (file)
index 0000000..70d8442
--- /dev/null
@@ -0,0 +1,15 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.c-types kernel compiler.constants compiler.cfg.hats
+compiler.cfg.instructions compiler.cfg.registers
+compiler.cfg.stacks cpu.architecture ;
+IN: compiler.cfg.intrinsics.strings
+
+: (string-nth) ( n string -- base offset rep c-type )
+    ^^tagged>integer swap ^^add string-offset int-rep uchar ; inline
+
+: emit-string-nth-fast ( -- )
+    2inputs (string-nth) ^^load-memory-imm ds-push ;
+
+: emit-set-string-nth-fast ( -- )
+    3inputs (string-nth) ##store-memory-imm ;
index 8951d7a1f1e15b9e34bfc2535485755d1a13f8a2..ed7690bd773170cf54dbf6557176af23feec3a7b 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs heaps kernel namespaces sequences fry math
 math.order combinators arrays sorting compiler.utilities locals
@@ -9,11 +9,11 @@ compiler.cfg.linear-scan.allocation.state ;
 IN: compiler.cfg.linear-scan.allocation
 
 : active-positions ( new assoc -- )
-    [ vreg>> active-intervals-for ] dip
+    [ active-intervals-for ] dip
     '[ [ 0 ] dip reg>> _ add-use-position ] each ;
 
 : inactive-positions ( new assoc -- )
-    [ [ vreg>> inactive-intervals-for ] keep ] dip
+    [ [ inactive-intervals-for ] keep ] dip
     '[
         [ _ relevant-ranges intersect-live-ranges 1/0. or ] [ reg>> ] bi
         _ add-use-position
@@ -38,7 +38,8 @@ IN: compiler.cfg.linear-scan.allocation
     ! If the live interval has a usage at 'n', don't spill it,
     ! since this means its being defined by the sync point
     ! instruction. Output t if this is the case.
-    2dup [ uses>> ] dip swap member? [ 2drop t ] [ spill f ] if ;
+    2dup [ uses>> ] dip '[ n>> _ = ] any?
+    [ 2drop t ] [ spill f ] if ;
 
 : handle-sync-point ( n -- )
     [ active-intervals get values ] dip
@@ -62,18 +63,19 @@ M: sync-point handle ( sync-point -- )
 
 : smallest-heap ( heap1 heap2 -- heap )
     ! If heap1 and heap2 have the same key, favors heap1.
-    [ [ heap-peek nip ] bi@ <= ] most ;
+    {
+        { [ dup heap-empty? ] [ drop ] }
+        { [ over heap-empty? ] [ nip ] }
+        [ [ [ heap-peek nip ] bi@ <= ] most ]
+    } cond ;
 
 : (allocate-registers) ( -- )
-    {
-        { [ unhandled-intervals get heap-empty? ] [ unhandled-sync-points get ] }
-        { [ unhandled-sync-points get heap-empty? ] [ unhandled-intervals get ] }
-        ! If a live interval begins at the same location as a sync point,
-        ! process the sync point before the live interval. This ensures that the
-        ! return value of C function calls doesn't get spilled and reloaded
-        ! unnecessarily.
-        [ unhandled-sync-points get unhandled-intervals get smallest-heap ]
-    } cond dup heap-empty? [ drop ] [ heap-pop drop handle (allocate-registers) ] if ;
+    ! If a live interval begins at the same location as a sync point,
+    ! process the sync point before the live interval. This ensures that the
+    ! return value of C function calls doesn't get spilled and reloaded
+    ! unnecessarily.
+    unhandled-sync-points get unhandled-intervals get smallest-heap
+    dup heap-empty? [ drop ] [ heap-pop drop handle (allocate-registers) ] if ;
 
 : finish-allocation ( -- )
     active-intervals inactive-intervals
index 845cb14d5c8738f5fb3985e5fa25979f8be3dd47..19b0f6c5b9a8cb5c6081028da3945b452e18fb1c 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
 math sequences sets sorting splitting namespaces linked-assocs
@@ -17,19 +17,20 @@ ERROR: bad-live-ranges interval ;
     ] [ drop ] if ;
 
 : trim-before-ranges ( live-interval -- )
-    [ ranges>> ] [ uses>> last 1 + ] bi
+    [ ranges>> ] [ last-use n>> 1 + ] bi
     [ '[ from>> _ <= ] filter! drop ]
     [ swap last (>>to) ]
     2bi ;
 
 : trim-after-ranges ( live-interval -- )
-    [ ranges>> ] [ uses>> first ] bi
+    [ ranges>> ] [ first-use n>> ] bi
     [ '[ to>> _ >= ] filter! drop ]
     [ swap first (>>from) ]
     2bi ;
 
 : assign-spill ( live-interval -- )
-    dup vreg>> vreg-spill-slot >>spill-to drop ;
+    dup [ vreg>> ] [ last-use rep>> ] bi
+    assign-spill-slot >>spill-to drop ;
 
 : spill-before ( before -- before/f )
     ! If the interval does not have any usages before the spill location,
@@ -46,7 +47,8 @@ ERROR: bad-live-ranges interval ;
     ] if ;
 
 : assign-reload ( live-interval -- )
-    dup vreg>> vreg-spill-slot >>reload-from drop ;
+    dup [ vreg>> ] [ first-use rep>> ] bi
+    assign-spill-slot >>reload-from drop ;
 
 : spill-after ( after -- after/f )
     ! If the interval has no more usages after the spill location,
@@ -66,18 +68,19 @@ ERROR: bad-live-ranges interval ;
     split-interval [ spill-before ] [ spill-after ] bi* ;
 
 : find-use-position ( live-interval new -- n )
-    [ uses>> ] [ start>> '[ _ >= ] ] bi* find nip 1/0. or ;
+    [ uses>> ] [ start>> '[ n>> _ >= ] ] bi* find nip
+    [ n>> ] [ 1/0. ] if* ;
 
 : find-use-positions ( live-intervals new assoc -- )
     '[ [ _ find-use-position ] [ reg>> ] bi _ add-use-position ] each ;
 
 : active-positions ( new assoc -- )
-    [ [ vreg>> active-intervals-for ] keep ] dip
+    [ [ active-intervals-for ] keep ] dip
     find-use-positions ;
 
 : inactive-positions ( new assoc -- )
     [
-        [ vreg>> inactive-intervals-for ] keep
+        [ inactive-intervals-for ] keep
         [ '[ _ intervals-intersect? ] filter ] keep
     ] dip
     find-use-positions ;
@@ -88,7 +91,7 @@ ERROR: bad-live-ranges interval ;
     >alist alist-max ;
 
 : spill-new? ( new pair -- ? )
-    [ uses>> first ] [ second ] bi* > ;
+    [ first-use n>> ] [ second ] bi* > ;
 
 : spill-new ( new pair -- )
     drop spill-after add-unhandled ;
@@ -102,13 +105,13 @@ ERROR: bad-live-ranges interval ;
     ! If there is an active interval using 'reg' (there should be at
     ! most one) are split and spilled and removed from the inactive
     ! set.
-    new vreg>> active-intervals-for [ [ reg>> reg = ] find swap dup ] keep
+    new active-intervals-for [ [ reg>> reg = ] find swap dup ] keep
     '[ _ remove-nth! drop  new start>> spill ] [ 2drop ] if ;
 
 :: spill-intersecting-inactive ( new reg -- )
     ! Any inactive intervals using 'reg' are split and spilled
     ! and removed from the inactive set.
-    new vreg>> inactive-intervals-for [
+    new inactive-intervals-for [
         dup reg>> reg = [
             dup new intervals-intersect? [
                 new start>> spill f
index 1a2b0f2f2bdceae154b0e8b71d3a2691f1fdd1ef..b3cba3d90d26b80e9ef43beca2deca63be9f9cb9 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
 math sequences sets sorting splitting namespaces
@@ -25,7 +25,7 @@ IN: compiler.cfg.linear-scan.allocation.splitting
     ] bi ;
 
 : split-uses ( uses n -- before after )
-    '[ _ <= ] partition ;
+    '[ n>> _ <= ] partition ;
 
 ERROR: splitting-too-early ;
 
index 4c825c9d7ce62c9c6eab8be06c3e9186a67096f3..89ec1b778531815d649ad41365da536d7cc8690b 100644 (file)
@@ -1,9 +1,10 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs combinators cpu.architecture fry heaps
-kernel math math.order namespaces sequences vectors
+USING: arrays accessors assocs combinators cpu.architecture fry
+heaps kernel math math.order namespaces sequences vectors
 linked-assocs compiler.cfg compiler.cfg.registers
-compiler.cfg.instructions compiler.cfg.linear-scan.live-intervals ;
+compiler.cfg.instructions
+compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.state
 
 ! Start index of current live interval. We ensure that all
@@ -26,14 +27,14 @@ SYMBOL: registers
 ! Vector of active live intervals
 SYMBOL: active-intervals
 
-: active-intervals-for ( vreg -- seq )
-    rep-of reg-class-of active-intervals get at ;
+: active-intervals-for ( live-interval -- seq )
+    reg-class>> active-intervals get at ;
 
 : add-active ( live-interval -- )
-    dup vreg>> active-intervals-for push ;
+    dup active-intervals-for push ;
 
 : delete-active ( live-interval -- )
-    dup vreg>> active-intervals-for remove-eq! drop ;
+    dup active-intervals-for remove-eq! drop ;
 
 : assign-free-register ( new registers -- )
     pop >>reg add-active ;
@@ -41,14 +42,14 @@ SYMBOL: active-intervals
 ! Vector of inactive live intervals
 SYMBOL: inactive-intervals
 
-: inactive-intervals-for ( vreg -- seq )
-    rep-of reg-class-of inactive-intervals get at ;
+: inactive-intervals-for ( live-interval -- seq )
+    reg-class>> inactive-intervals get at ;
 
 : add-inactive ( live-interval -- )
-    dup vreg>> inactive-intervals-for push ;
+    dup inactive-intervals-for push ;
 
 : delete-inactive ( live-interval -- )
-    dup vreg>> inactive-intervals-for remove-eq! drop ;
+    dup inactive-intervals-for remove-eq! drop ;
 
 ! Vector of handled live intervals
 SYMBOL: handled-intervals
@@ -67,7 +68,7 @@ ERROR: register-already-used live-interval ;
 
 : check-activate ( live-interval -- )
     check-allocation? get [
-        dup [ reg>> ] [ vreg>> active-intervals-for [ reg>> ] map ] bi member?
+        dup [ reg>> ] [ active-intervals-for [ reg>> ] map ] bi member?
         [ register-already-used ] [ drop ] if
     ] [ drop ] if ;
 
@@ -116,8 +117,8 @@ SYMBOL: unhandled-intervals
 : reg-class-assoc ( quot -- assoc )
     [ reg-classes ] dip { } map>assoc ; inline
 
-: next-spill-slot ( rep -- n )
-    rep-size cfg get
+: next-spill-slot ( size -- n )
+    cfg get
     [ swap [ align dup ] [ + ] bi ] change-spill-area-size drop
     <spill-slot> ;
 
@@ -127,8 +128,11 @@ SYMBOL: unhandled-sync-points
 ! Mapping from vregs to spill slots
 SYMBOL: spill-slots
 
-: vreg-spill-slot ( vreg -- spill-slot )
-    spill-slots get [ rep-of next-spill-slot ] cache ;
+: assign-spill-slot ( coalesced-vreg rep -- spill-slot )
+    rep-size spill-slots get [ nip next-spill-slot ] 2cache ;
+
+: lookup-spill-slot ( coalesced-vreg rep -- spill-slot )
+    rep-size 2array spill-slots get ?at [ ] [ bad-vreg ] if ;
 
 : init-allocator ( registers -- )
     registers set
@@ -148,7 +152,7 @@ SYMBOL: spill-slots
 
 ! A utility used by register-status and spill-status words
 : free-positions ( new -- assoc )
-    vreg>> rep-of reg-class-of registers get at
+    reg-class>> registers get at
     [ 1/0. ] H{ } <linked-assoc> map>assoc ;
 
 : add-use-position ( n reg assoc -- ) [ [ min ] when* ] change-at ;
index 6acb9169ec730996d88b4d9cff035c13b9c5de8b..1682cf9eb630a7ee856c86005a657cdf78cee04b 100644 (file)
@@ -1,15 +1,17 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel math assocs namespaces sequences heaps
-fry make combinators sets locals arrays
+fry make combinators combinators.short-circuit sets locals arrays
 cpu.architecture layouts
 compiler.cfg
 compiler.cfg.def-use
 compiler.cfg.liveness
+compiler.cfg.liveness.ssa
 compiler.cfg.registers
 compiler.cfg.instructions
+compiler.cfg.linearization
+compiler.cfg.ssa.destruction
 compiler.cfg.renaming.functor
-compiler.cfg.linearization.order
 compiler.cfg.linear-scan.allocation
 compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.live-intervals ;
@@ -29,21 +31,16 @@ SYMBOL: pending-interval-assoc
 : remove-pending ( live-interval -- )
     vreg>> pending-interval-assoc get delete-at ;
 
-ERROR: bad-vreg vreg ;
-
-: (vreg>reg) ( vreg pending -- reg )
+:: vreg>reg ( vreg -- reg )
     ! If a live vreg is not in the pending set, then it must
     ! have been spilled.
-    ?at [ spill-slots get ?at [ ] [ bad-vreg ] if ] unless ;
-
-: vreg>reg ( vreg -- reg )
-    pending-interval-assoc get (vreg>reg) ;
+    vreg leader :> leader
+    leader pending-interval-assoc get at* [
+        drop leader vreg rep-of lookup-spill-slot
+    ] unless ;
 
 : vregs>regs ( vregs -- assoc )
-    dup assoc-empty? [
-        pending-interval-assoc get
-        '[ _ (vreg>reg) ] assoc-map
-    ] unless ;
+    [ f ] [ [ dup vreg>reg ] H{ } map>assoc ] if-empty ;
 
 ! Minheap of live intervals which still need a register allocation
 SYMBOL: unhandled-intervals
@@ -54,22 +51,49 @@ SYMBOL: unhandled-intervals
 : init-unhandled ( live-intervals -- )
     [ add-unhandled ] each ;
 
+! Liveness info is used by resolve pass
+
 ! Mapping from basic blocks to values which are live at the start
-SYMBOL: register-live-ins
+! on all incoming CFG edges
+SYMBOL: machine-live-ins
+
+: machine-live-in ( bb -- assoc )
+    machine-live-ins get at ;
+
+: compute-live-in ( bb -- )
+    [ live-in keys vregs>regs ] keep machine-live-ins get set-at ;
+
+! Mapping from basic blocks to predecessors to values which are
+! live on a particular incoming edge
+SYMBOL: machine-edge-live-ins
+
+: machine-edge-live-in ( predecessor bb -- assoc )
+    machine-edge-live-ins get at at ;
+
+: compute-edge-live-in ( bb -- )
+    [ edge-live-ins get at [ keys vregs>regs ] assoc-map ] keep
+    machine-edge-live-ins get set-at ;
 
 ! Mapping from basic blocks to values which are live at the end
-SYMBOL: register-live-outs
+SYMBOL: machine-live-outs
+
+: machine-live-out ( bb -- assoc )
+    machine-live-outs get at ;
+
+: compute-live-out ( bb -- )
+    [ live-out keys vregs>regs ] keep machine-live-outs get set-at ;
 
 : init-assignment ( live-intervals -- )
     <min-heap> pending-interval-heap set
     H{ } clone pending-interval-assoc set
     <min-heap> unhandled-intervals set
-    H{ } clone register-live-ins set
-    H{ } clone register-live-outs set
+    H{ } clone machine-live-ins set
+    H{ } clone machine-edge-live-ins set
+    H{ } clone machine-live-outs set
     init-unhandled ;
 
 : insert-spill ( live-interval -- )
-    [ reg>> ] [ vreg>> rep-of ] [ spill-to>> ] tri _spill ;
+    [ reg>> ] [ last-use rep>> ] [ spill-to>> ] tri ##spill ;
 
 : handle-spill ( live-interval -- )
     dup spill-to>> [ insert-spill ] [ drop ] if ;
@@ -89,10 +113,18 @@ SYMBOL: register-live-outs
     pending-interval-heap get (expire-old-intervals) ;
 
 : insert-reload ( live-interval -- )
-    [ reg>> ] [ vreg>> rep-of ] [ reload-from>> ] tri _reload ;
+    [ reg>> ] [ first-use rep>> ] [ reload-from>> ] tri ##reload ;
+
+: insert-reload? ( live-interval -- ? )
+    ! Don't insert a reload if the register will be written to
+    ! before being read again.
+    {
+        [ reload-from>> ]
+        [ first-use type>> +use+ eq? ]
+    } 1&& ;
 
 : handle-reload ( live-interval -- )
-    dup reload-from>> [ insert-reload ] [ drop ] if ;
+    dup insert-reload? [ insert-reload ] [ drop ] if ;
 
 : activate-interval ( live-interval -- )
     [ add-pending ] [ handle-reload ] bi ;
@@ -118,55 +150,19 @@ RENAMING: assign [ vreg>reg ] [ vreg>reg ] [ vreg>reg ]
 M: vreg-insn assign-registers-in-insn
     [ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ;
 
-: trace-on-gc ( assoc -- assoc' )
-    ! When a GC occurs, virtual registers which contain tagged data
-    ! are traced by the GC. Outputs a sequence physical registers.
-    [ drop rep-of int-rep eq? ] { } assoc-filter-as values ;
-
-: spill-on-gc? ( vreg reg -- ? )
-    [ rep-of int-rep? not ] [ spill-slot? not ] bi* and ;
-
-: spill-on-gc ( assoc -- assoc' )
-    ! When a GC occurs, virtual registers which contain untagged data,
-    ! and are stored in physical registers, are saved to their spill
-    ! slots. Outputs sequence of triples:
-    ! - physical register
-    ! - spill slot
-    ! - representation
-    [
-        [
-            2dup spill-on-gc?
-            [ swap [ rep-of ] [ vreg-spill-slot ] bi 3array , ] [ 2drop ] if
-        ] assoc-each
-    ] { } make ;
-
-: gc-root-offsets ( registers -- alist )
-    ! Outputs a sequence of { offset register/spill-slot } pairs
-    [ length iota [ cell * ] map ] keep zip ;
-
-M: ##gc assign-registers-in-insn
-    ! Since ##gc is always the first instruction in a block, the set of
-    ! values live at the ##gc is just live-in.
+M: ##call-gc assign-registers-in-insn
     dup call-next-method
-    basic-block get register-live-ins get at
-    [ trace-on-gc gc-root-offsets >>tagged-values ] [ spill-on-gc >>data-values ] bi
-    drop ;
+    [ [ vreg>reg ] map ] change-gc-roots drop ;
 
 M: insn assign-registers-in-insn drop ;
 
 : begin-block ( bb -- )
-    dup basic-block set
-    dup block-from activate-new-intervals
-    [ live-in vregs>regs ] keep register-live-ins get set-at ;
-
-: end-block ( bb -- )
-    [ live-out vregs>regs ] keep register-live-outs get set-at ;
-
-: vreg-at-start ( vreg bb -- state )
-    register-live-ins get at ?at [ bad-vreg ] unless ;
-
-: vreg-at-end ( vreg bb -- state )
-    register-live-outs get at ?at [ bad-vreg ] unless ;
+    {
+        [ basic-block set ]
+        [ block-from activate-new-intervals ]
+        [ compute-edge-live-in ]
+        [ compute-live-in ]
+    } cleave ;
 
 :: assign-registers-in-block ( bb -- )
     bb [
@@ -180,7 +176,7 @@ M: insn assign-registers-in-insn drop ;
                     [ , ]
                 } cleave
             ] each
-            bb end-block
+            bb compute-live-out
         ] V{ } make
     ] change-instructions drop ;
 
index dcf2e743ec96bbcaf05562a5feed30a5a06b9790..9e6ec76d2ca7d1538dc4175f99d613e24dc74c5f 100644 (file)
@@ -8,7 +8,6 @@ compiler.cfg.instructions
 compiler.cfg.registers
 compiler.cfg.predecessors
 compiler.cfg.rpo
-compiler.cfg.linearization
 compiler.cfg.debugger
 compiler.cfg.def-use
 compiler.cfg.comparisons
@@ -89,26 +88,29 @@ H{
 [
     T{ live-interval
        { vreg 1 }
+       { reg-class float-regs }
        { start 0 }
        { end 2 }
-       { uses V{ 0 1 } }
+       { uses V{ T{ vreg-use f float-rep 0 } T{ vreg-use f float-rep 1 } } }
        { ranges V{ T{ live-range f 0 2 } } }
        { spill-to T{ spill-slot f 0 } }
     }
     T{ live-interval
        { vreg 1 }
+       { reg-class float-regs }
        { start 5 }
        { end 5 }
-       { uses V{ 5 } }
+       { uses V{ T{ vreg-use f float-rep 5 } } }
        { ranges V{ T{ live-range f 5 5 } } }
        { reload-from T{ spill-slot f 0 } }
     }
 ] [
     T{ live-interval
        { vreg 1 }
+       { reg-class float-regs }
        { start 0 }
        { end 5 }
-       { uses V{ 0 1 5 } }
+       { uses V{ T{ vreg-use f float-rep 0 } T{ vreg-use f float-rep 1 } T{ vreg-use f float-rep 5 } } }
        { ranges V{ T{ live-range f 0 5 } } }
     } 2 split-for-spill
 ] unit-test
@@ -116,26 +118,29 @@ H{
 [
     T{ live-interval
        { vreg 2 }
+       { reg-class float-regs }
        { start 0 }
        { end 1 }
-       { uses V{ 0 } }
+       { uses V{ T{ vreg-use f float-rep 0 } } }
        { ranges V{ T{ live-range f 0 1 } } }
        { spill-to T{ spill-slot f 4 } }
     }
     T{ live-interval
        { vreg 2 }
+       { reg-class float-regs }
        { start 1 }
        { end 5 }
-       { uses V{ 1 5 } }
+       { uses V{ T{ vreg-use f float-rep 1 } T{ vreg-use f float-rep 5 } } }
        { ranges V{ T{ live-range f 1 5 } } }
        { reload-from T{ spill-slot f 4 } }
     }
 ] [
     T{ live-interval
        { vreg 2 }
+       { reg-class float-regs }
        { start 0 }
        { end 5 }
-       { uses V{ 0 1 5 } }
+       { uses V{ T{ vreg-use f float-rep 0 } T{ vreg-use f float-rep 1 } T{ vreg-use f float-rep 5 } } }
        { ranges V{ T{ live-range f 0 5 } } }
     } 0 split-for-spill
 ] unit-test
@@ -143,26 +148,29 @@ H{
 [
     T{ live-interval
        { vreg 3 }
+       { reg-class float-regs }
        { start 0 }
        { end 1 }
-       { uses V{ 0 } }
+       { uses V{ T{ vreg-use f float-rep 0 } } }
        { ranges V{ T{ live-range f 0 1 } } }
        { spill-to T{ spill-slot f 8 } }
     }
     T{ live-interval
        { vreg 3 }
+       { reg-class float-regs }
        { start 20 }
        { end 30 }
-       { uses V{ 20 30 } }
+       { uses V{ T{ vreg-use f float-rep 20 } T{ vreg-use f float-rep 30 } } }
        { ranges V{ T{ live-range f 20 30 } } }
        { reload-from T{ spill-slot f 8 } }
     }
 ] [
     T{ live-interval
        { vreg 3 }
+       { reg-class float-regs }
        { start 0 }
        { end 30 }
-       { uses V{ 0 20 30 } }
+       { uses V{ T{ vreg-use f float-rep 0 } T{ vreg-use f float-rep 20 } T{ vreg-use f float-rep 30 } } }
        { ranges V{ T{ live-range f 0 8 } T{ live-range f 10 18 } T{ live-range f 20 30 } } }
     } 10 split-for-spill
 ] unit-test
@@ -184,24 +192,27 @@ H{
           V{
               T{ live-interval
                  { vreg 1 }
+                 { reg-class int-regs }
                  { reg 1 }
                  { start 1 }
                  { end 15 }
-                 { uses V{ 1 3 7 10 15 } }
+                 { uses V{ T{ vreg-use f int-rep 1 } T{ vreg-use f int-rep 3 } T{ vreg-use f int-rep 7 } T{ vreg-use f int-rep 10 } T{ vreg-use f int-rep 15 } } }
               }
               T{ live-interval
                  { vreg 2 }
+                 { reg-class int-regs }
                  { reg 2 }
                  { start 3 }
                  { end 8 }
-                 { uses V{ 3 4 8 } }
+                 { uses V{ T{ vreg-use f int-rep 3 } T{ vreg-use f int-rep 4 } T{ vreg-use f int-rep 8 } } }
               }
               T{ live-interval
                  { vreg 3 }
+                 { reg-class int-regs }
                  { reg 3 }
                  { start 3 }
                  { end 10 }
-                 { uses V{ 3 10 } }
+                 { uses V{ T{ vreg-use f int-rep 3 } T{ vreg-use f int-rep 10 } } }
               }
           }
         }
@@ -209,9 +220,10 @@ H{
     H{ } inactive-intervals set
     T{ live-interval
         { vreg 1 }
+        { reg-class int-regs }
         { start 5 }
         { end 5 }
-        { uses V{ 5 } }
+        { uses V{ T{ vreg-use f int-rep 5 } } }
     }
     spill-status
 ] unit-test
@@ -227,17 +239,19 @@ H{
           V{
               T{ live-interval
                  { vreg 1 }
+                 { reg-class int-regs }
                  { reg 1 }
                  { start 1 }
                  { end 15 }
-                 { uses V{ 1 } }
+                 { uses V{ T{ vreg-use f int-rep 1 } } }
               }
               T{ live-interval
                  { vreg 2 }
+                 { reg-class int-regs }
                  { reg 2 }
                  { start 3 }
                  { end 8 }
-                 { uses V{ 3 8 } }
+                 { uses V{ T{ vreg-use f int-rep 3 } T{ vreg-use f int-rep 8 } } }
               }
           }
         }
@@ -245,9 +259,10 @@ H{
     H{ } inactive-intervals set
     T{ live-interval
         { vreg 3 }
+        { reg-class int-regs }
         { start 5 }
         { end 5 }
-        { uses V{ 5 } }
+        { uses V{ T{ vreg-use f int-rep 5 } } }
     }
     spill-status
 ] unit-test
@@ -258,9 +273,10 @@ H{ { 1 int-rep } { 2 int-rep } } representations set
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 100 }
-           { uses V{ 0 100 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 100 } } }
            { ranges V{ T{ live-range f 0 100 } } }
         }
     }
@@ -272,16 +288,18 @@ H{ { 1 int-rep } { 2 int-rep } } representations set
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 10 }
-           { uses V{ 0 10 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 10 } } }
            { ranges V{ T{ live-range f 0 10 } } }
         }
         T{ live-interval
            { vreg 2 }
+           { reg-class int-regs }
            { start 11 }
            { end 20 }
-           { uses V{ 11 20 } }
+           { uses V{ T{ vreg-use f int-rep 11 } T{ vreg-use f int-rep 20 } } }
            { ranges V{ T{ live-range f 11 20 } } }
         }
     }
@@ -293,16 +311,18 @@ H{ { 1 int-rep } { 2 int-rep } } representations set
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 100 }
-           { uses V{ 0 100 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 100 } } }
            { ranges V{ T{ live-range f 0 100 } } }
         }
         T{ live-interval
            { vreg 2 }
+           { reg-class int-regs }
            { start 30 }
            { end 60 }
-           { uses V{ 30 60 } }
+           { uses V{ T{ vreg-use f int-rep 30 } T{ vreg-use f int-rep 60 } } }
            { ranges V{ T{ live-range f 30 60 } } }
         }
     }
@@ -314,16 +334,18 @@ H{ { 1 int-rep } { 2 int-rep } } representations set
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 100 }
-           { uses V{ 0 100 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 100 } } }
            { ranges V{ T{ live-range f 0 100 } } }
         }
         T{ live-interval
            { vreg 2 }
+           { reg-class int-regs }
            { start 30 }
            { end 200 }
-           { uses V{ 30 200 } }
+           { uses V{ T{ vreg-use f int-rep 30 } T{ vreg-use f int-rep 200 } } }
            { ranges V{ T{ live-range f 30 200 } } }
         }
     }
@@ -335,16 +357,18 @@ H{ { 1 int-rep } { 2 int-rep } } representations set
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 100 }
-           { uses V{ 0 100 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 100 } } }
            { ranges V{ T{ live-range f 0 100 } } }
         }
         T{ live-interval
            { vreg 2 }
+           { reg-class int-regs }
            { start 30 }
            { end 100 }
-           { uses V{ 30 100 } }
+           { uses V{ T{ vreg-use f int-rep 30 } T{ vreg-use f int-rep 100 } } }
            { ranges V{ T{ live-range f 30 100 } } }
         }
     }
@@ -365,39 +389,44 @@ H{
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 20 }
-           { uses V{ 0 10 20 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 10 } T{ vreg-use f int-rep 20 } } }
            { ranges V{ T{ live-range f 0 2 } T{ live-range f 10 20 } } }
         }
         T{ live-interval
            { vreg 2 }
+           { reg-class int-regs }
            { start 0 }
            { end 20 }
-           { uses V{ 0 10 20 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 10 } T{ vreg-use f int-rep 20 } } }
            { ranges V{ T{ live-range f 0 2 } T{ live-range f 10 20 } } }
         }
         T{ live-interval
            { vreg 3 }
+           { reg-class int-regs }
            { start 4 }
            { end 8 }
-           { uses V{ 6 } }
+           { uses V{ T{ vreg-use f int-rep 6 } } }
            { ranges V{ T{ live-range f 4 8 } } }
         }
         T{ live-interval
            { vreg 4 }
+           { reg-class int-regs }
            { start 4 }
            { end 8 }
-           { uses V{ 8 } }
+           { uses V{ T{ vreg-use f int-rep 8 } } }
            { ranges V{ T{ live-range f 4 8 } } }
         }
 
         ! This guy will invoke the 'spill partially available' code path
         T{ live-interval
            { vreg 5 }
+           { reg-class int-regs }
            { start 4 }
            { end 8 }
-           { uses V{ 8 } }
+           { uses V{ T{ vreg-use f int-rep 8 } } }
            { ranges V{ T{ live-range f 4 8 } } }
         }
     }
@@ -411,18 +440,20 @@ H{
     {
         T{ live-interval
            { vreg 1 }
+           { reg-class int-regs }
            { start 0 }
            { end 10 }
-           { uses V{ 0 6 10 } }
+           { uses V{ T{ vreg-use f int-rep 0 } T{ vreg-use f int-rep 6 } T{ vreg-use f int-rep 10 } } }
            { ranges V{ T{ live-range f 0 10 } } }
         }
 
         ! This guy will invoke the 'spill new' code path
         T{ live-interval
            { vreg 5 }
+           { reg-class int-regs }
            { start 2 }
            { end 8 }
-           { uses V{ 8 } }
+           { uses V{ T{ vreg-use f int-rep 8 } } }
            { ranges V{ T{ live-range f 2 8 } } }
         }
     }
@@ -491,12 +522,14 @@ H{
 [ 5 ] [
     T{ live-interval
        { start 0 }
+       { reg-class int-regs }
        { end 10 }
        { uses { 0 10 } }
        { ranges V{ T{ live-range f 0 10 } } }
     }
     T{ live-interval
        { start 5 }
+       { reg-class int-regs }
        { end 10 }
        { uses { 5 10 } }
        { ranges V{ T{ live-range f 5 10 } } }
@@ -520,6 +553,7 @@ H{
           {
               T{ live-interval
                  { vreg 1 }
+                 { reg-class int-regs }
                  { start 0 }
                  { end 20 }
                  { reg 0 }
@@ -529,6 +563,7 @@ H{
 
               T{ live-interval
                  { vreg 2 }
+                 { reg-class int-regs }
                  { start 4 }
                  { end 40 }
                  { reg 0 }
@@ -543,6 +578,7 @@ H{
           {
               T{ live-interval
                  { vreg 3 }
+                 { reg-class int-regs }
                  { start 0 }
                  { end 40 }
                  { reg 1 }
@@ -554,939 +590,12 @@ H{
     } active-intervals set
 
     T{ live-interval
-       { vreg 4 }
+        { vreg 4 }
+        { reg-class int-regs }
         { start 8 }
         { end 10 }
         { ranges V{ T{ live-range f 8 10 } } }
-        { uses V{ 8 10 } }
+        { uses V{ T{ vreg-use f int-rep 8 } T{ vreg-use f int-rep 10 } } }
     }
     register-status
 ] unit-test
-
-:: test-linear-scan-on-cfg ( regs -- )
-    [
-        cfg new 0 get >>entry
-        dup cfg set
-        dup fake-representations
-        dup { { int-regs regs } } (linear-scan)
-        flatten-cfg 1array mr.
-    ] with-scope ;
-
-! Bug in live spill slots calculation
-
-V{ T{ ##prologue } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek
-       { dst 703128 }
-       { loc D 1 }
-    }
-    T{ ##peek
-       { dst 703129 }
-       { loc D 0 }
-    }
-    T{ ##copy
-       { dst 703134 }
-       { src 703128 }
-    }
-    T{ ##copy
-       { dst 703135 }
-       { src 703129 }
-    }
-    T{ ##compare-imm-branch
-       { src1 703128 }
-       { src2 5 }
-       { cc cc/= }
-    }
-} 1 test-bb
-
-V{
-    T{ ##copy
-       { dst 703134 }
-       { src 703129 }
-    }
-    T{ ##copy
-       { dst 703135 }
-       { src 703128 }
-    }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##replace
-       { src 703134 }
-       { loc D 0 }
-    }
-    T{ ##replace
-       { src 703135 }
-       { loc D 1 }
-    }
-    T{ ##epilogue }
-    T{ ##return }
-} 3 test-bb
-
-0 1 edge
-1 { 2 3 } edges
-2 3 edge
-
-! Bug in inactive interval handling
-! [ rot dup [ -rot ] when ]
-V{ T{ ##prologue } T{ ##branch } } 0 test-bb
-    
-V{
-    T{ ##peek
-       { dst 689473 }
-       { loc D 2 }
-    }
-    T{ ##peek
-       { dst 689474 }
-       { loc D 1 }
-    }
-    T{ ##peek
-       { dst 689475 }
-       { loc D 0 }
-    }
-    T{ ##compare-imm-branch
-       { src1 689473 }
-       { src2 5 }
-       { cc cc/= }
-    }
-} 1 test-bb
-
-V{
-    T{ ##copy
-       { dst 689481 }
-       { src 689475 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689482 }
-       { src 689474 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689483 }
-       { src 689473 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##copy
-       { dst 689481 }
-       { src 689473 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689482 }
-       { src 689475 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689483 }
-       { src 689474 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace
-       { src 689481 }
-       { loc D 0 }
-    }
-    T{ ##replace
-       { src 689482 }
-       { loc D 1 }
-    }
-    T{ ##replace
-       { src 689483 }
-       { loc D 2 }
-    }
-    T{ ##epilogue }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
-
-! Similar to the above
-! [ swap dup [ rot ] when ]
-
-T{ basic-block
-   { id 201537 }
-   { number 0 }
-   { instructions V{ T{ ##prologue } T{ ##branch } } }
-} 0 set
-    
-V{
-    T{ ##peek
-       { dst 689600 }
-       { loc D 1 }
-    }
-    T{ ##peek
-       { dst 689601 }
-       { loc D 0 }
-    }
-    T{ ##compare-imm-branch
-       { src1 689600 }
-       { src2 5 }
-       { cc cc/= }
-    }
-} 1 test-bb
-    
-V{
-    T{ ##peek
-       { dst 689604 }
-       { loc D 2 }
-    }
-    T{ ##copy
-       { dst 689607 }
-       { src 689604 }
-    }
-    T{ ##copy
-       { dst 689608 }
-       { src 689600 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689610 }
-       { src 689601 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 2 test-bb
-    
-V{
-    T{ ##peek
-       { dst 689609 }
-       { loc D 2 }
-    }
-    T{ ##copy
-       { dst 689607 }
-       { src 689600 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689608 }
-       { src 689601 }
-       { rep int-rep }
-    }
-    T{ ##copy
-       { dst 689610 }
-       { src 689609 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 3 test-bb
-    
-V{
-    T{ ##replace
-       { src 689607 }
-       { loc D 0 }
-    }
-    T{ ##replace
-       { src 689608 }
-       { loc D 1 }
-    }
-    T{ ##replace
-       { src 689610 }
-       { loc D 2 }
-    }
-    T{ ##epilogue }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
-
-! compute-live-registers was inaccurate since it didn't take
-! lifetime holes into account
-
-V{ T{ ##prologue } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek
-       { dst 0 }
-       { loc D 0 }
-    }
-    T{ ##compare-imm-branch
-       { src1 0 }
-       { src2 5 }
-       { cc cc/= }
-    }
-} 1 test-bb
-
-V{
-    T{ ##peek
-       { dst 1 }
-       { loc D 1 }
-    }
-    T{ ##copy
-       { dst 2 }
-       { src 1 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##peek
-       { dst 3 }
-       { loc D 2 }
-    }
-    T{ ##copy
-       { dst 2 }
-       { src 3 }
-       { rep int-rep }
-    }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace
-       { src 2 }
-       { loc D 0 }
-    }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
-
-! Inactive interval handling: splitting active interval
-! if it fits in lifetime hole only partially
-
-V{ T{ ##peek f 3 R 1 } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek f 2 R 0 }
-    T{ ##compare-imm-branch f 2 5 cc= }
-} 1 test-bb
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##branch }
-} 2 test-bb
-
-
-V{
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 0 D 0 }
-    T{ ##replace f 1 D 2 }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace f 3 R 2 }
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-! Not until splitting is finished
-! [ _copy ] [ 3 get instructions>> second class ] unit-test
-
-! Resolve pass; make sure the spilling is done correctly
-V{ T{ ##peek f 3 R 1 } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek f 2 R 0 }
-    T{ ##compare-imm-branch f 2 5 cc= }
-} 1 test-bb
-
-V{
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##replace f 3 R 1 }
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 0 D 0 }
-    T{ ##replace f 1 D 2 }
-    T{ ##replace f 0 D 2 }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace f 3 R 2 }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-[ _spill ] [ 2 get successors>> first instructions>> first class ] unit-test
-
-[ _spill ] [ 3 get instructions>> second class ] unit-test
-
-[ f ] [ 3 get instructions>> [ _reload? ] any? ] unit-test
-
-[ _reload ] [ 4 get instructions>> first class ] unit-test
-
-! Resolve pass
-V{
-    T{ ##branch }
-} 0 test-bb
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##compare-imm-branch f 0 5 cc= }
-} 1 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##peek f 1 D 0 }
-    T{ ##peek f 2 D 0 }
-    T{ ##replace f 1 D 0 }
-    T{ ##replace f 2 D 0 }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##peek f 1 D 0 }
-    T{ ##compare-imm-branch f 1 5 cc= }
-} 4 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 5 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 6 test-bb
-
-0 1 edge
-1 { 2 3 } edges
-2 4 edge
-3 4 edge
-4 { 5 6 } edges
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-[ t ] [ 2 get instructions>> [ _spill? ] any? ] unit-test
-
-[ t ] [ 3 get predecessors>> first instructions>> [ _spill? ] any? ] unit-test
-
-[ t ] [ 5 get instructions>> [ _reload? ] any? ] unit-test
-
-! A more complicated failure case with resolve that came up after the above
-! got fixed
-V{ T{ ##branch } } 0 test-bb
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 2 D 2 }
-    T{ ##peek f 3 D 3 }
-    T{ ##peek f 4 D 0 }
-    T{ ##branch }
-} 1 test-bb
-V{ T{ ##branch } } 2 test-bb
-V{ T{ ##branch } } 3 test-bb
-V{
-    
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##replace f 3 D 3 }
-    T{ ##replace f 4 D 4 }
-    T{ ##replace f 0 D 0 }
-    T{ ##branch }
-} 4 test-bb
-V{ T{ ##replace f 0 D 0 } T{ ##branch } } 5 test-bb
-V{ T{ ##return } } 6 test-bb
-V{ T{ ##branch } } 7 test-bb
-V{
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##replace f 3 D 3 }
-    T{ ##peek f 5 D 1 }
-    T{ ##peek f 6 D 2 }
-    T{ ##peek f 7 D 3 }
-    T{ ##peek f 8 D 4 }
-    T{ ##replace f 5 D 1 }
-    T{ ##replace f 6 D 2 }
-    T{ ##replace f 7 D 3 }
-    T{ ##replace f 8 D 4 }
-    T{ ##branch }
-} 8 test-bb
-V{
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##replace f 3 D 3 }
-    T{ ##return }
-} 9 test-bb
-
-0 1 edge
-1 { 2 7 } edges
-7 8 edge
-8 9 edge
-2 { 3 5 } edges
-3 4 edge
-4 9 edge
-5 6 edge
-
-[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
-
-[ _spill ] [ 1 get instructions>> second class ] unit-test
-[ _reload ] [ 4 get instructions>> 4 swap nth class ] unit-test
-[ V{ 3 2 1 } ] [ 8 get instructions>> [ _spill? ] filter [ dst>> n>> cell / ] map ] unit-test
-[ V{ 3 2 1 } ] [ 9 get instructions>> [ _reload? ] filter [ src>> n>> cell / ] map ] unit-test
-
-! Resolve pass should insert this
-[ _reload ] [ 5 get predecessors>> first instructions>> first class ] unit-test
-
-! Some random bug
-V{
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 2 D 2 }
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##peek f 3 D 0 }
-    T{ ##peek f 0 D 0 }
-    T{ ##branch }
-} 0 test-bb
-
-V{ T{ ##branch } } 1 test-bb
-
-V{
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 2 D 2 }
-    T{ ##replace f 3 D 3 }
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##replace f 0 D 3 }
-    T{ ##branch }
-} 2 test-bb
-
-V{ T{ ##branch } } 3 test-bb
-
-V{
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-! Spilling an interval immediately after its activated;
-! and the interval does not have a use at the activation point
-V{
-    T{ ##peek f 1 D 1 }
-    T{ ##peek f 2 D 2 }
-    T{ ##replace f 1 D 1 }
-    T{ ##replace f 2 D 2 }
-    T{ ##peek f 0 D 0 }
-    T{ ##branch }
-} 0 test-bb
-
-V{ T{ ##branch } } 1 test-bb
-
-V{
-    T{ ##peek f 1 D 1 }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##replace f 1 D 1 }
-    T{ ##peek f 2 D 2 }
-    T{ ##replace f 2 D 2 }
-    T{ ##branch }
-} 3 test-bb
-
-V{ T{ ##branch } } 4 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 5 test-bb
-
-0 1 edge
-1 { 2 4 } edges
-4 5 edge
-2 3 edge
-3 5 edge
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-! Reduction of push-all regression, x86-32
-V{ T{ ##prologue } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##load-immediate { dst 61 } }
-    T{ ##peek { dst 62 } { loc D 0 } }
-    T{ ##peek { dst 64 } { loc D 1 } }
-    T{ ##slot-imm
-        { dst 69 }
-        { obj 64 }
-        { slot 1 }
-        { tag 2 }
-    }
-    T{ ##copy { dst 79 } { src 69 } { rep int-rep } }
-    T{ ##slot-imm
-        { dst 85 }
-        { obj 62 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##compare-branch
-        { src1 69 }
-        { src2 85 }
-        { cc cc> }
-    }
-} 1 test-bb
-
-V{
-    T{ ##slot-imm
-        { dst 97 }
-        { obj 62 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##replace { src 79 } { loc D 3 } }
-    T{ ##replace { src 62 } { loc D 4 } }
-    T{ ##replace { src 79 } { loc D 1 } }
-    T{ ##replace { src 62 } { loc D 2 } }
-    T{ ##replace { src 61 } { loc D 5 } }
-    T{ ##replace { src 62 } { loc R 0 } }
-    T{ ##replace { src 69 } { loc R 1 } }
-    T{ ##replace { src 97 } { loc D 0 } }
-    T{ ##call { word resize-array } }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##peek { dst 98 } { loc R 0 } }
-    T{ ##peek { dst 100 } { loc D 0 } }
-    T{ ##set-slot-imm
-        { src 100 }
-        { obj 98 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##peek { dst 108 } { loc D 2 } }
-    T{ ##peek { dst 110 } { loc D 3 } }
-    T{ ##peek { dst 112 } { loc D 0 } }
-    T{ ##peek { dst 114 } { loc D 1 } }
-    T{ ##peek { dst 116 } { loc D 4 } }
-    T{ ##peek { dst 119 } { loc R 0 } }
-    T{ ##copy { dst 109 } { src 108 } { rep int-rep } }
-    T{ ##copy { dst 111 } { src 110 } { rep int-rep } }
-    T{ ##copy { dst 113 } { src 112 } { rep int-rep } }
-    T{ ##copy { dst 115 } { src 114 } { rep int-rep } }
-    T{ ##copy { dst 117 } { src 116 } { rep int-rep } }
-    T{ ##copy { dst 120 } { src 119 } { rep int-rep } }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##copy { dst 109 } { src 62 } { rep int-rep } }
-    T{ ##copy { dst 111 } { src 61 } { rep int-rep } }
-    T{ ##copy { dst 113 } { src 62 } { rep int-rep } }
-    T{ ##copy { dst 115 } { src 79 } { rep int-rep } }
-    T{ ##copy { dst 117 } { src 64 } { rep int-rep } }
-    T{ ##copy { dst 120 } { src 69 } { rep int-rep } }
-    T{ ##branch }
-} 4 test-bb
-
-V{
-    T{ ##replace { src 120 } { loc D 0 } }
-    T{ ##replace { src 109 } { loc D 3 } }
-    T{ ##replace { src 111 } { loc D 4 } }
-    T{ ##replace { src 113 } { loc D 1 } }
-    T{ ##replace { src 115 } { loc D 2 } }
-    T{ ##replace { src 117 } { loc D 5 } }
-    T{ ##epilogue }
-    T{ ##return }
-} 5 test-bb
-
-0 1 edge
-1 { 2 4 } edges
-2 3 edge
-3 5 edge
-4 5 edge
-
-[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
-
-! Another reduction of push-all
-V{ T{ ##prologue } T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek { dst 85 } { loc D 0 } }
-    T{ ##slot-imm
-        { dst 89 }
-        { obj 85 }
-        { slot 3 }
-        { tag 7 }
-    }
-    T{ ##peek { dst 91 } { loc D 1 } }
-    T{ ##slot-imm
-        { dst 96 }
-        { obj 91 }
-        { slot 1 }
-        { tag 2 }
-    }
-    T{ ##add
-        { dst 109 }
-        { src1 89 }
-        { src2 96 }
-    }
-    T{ ##slot-imm
-        { dst 115 }
-        { obj 85 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##slot-imm
-        { dst 118 }
-        { obj 115 }
-        { slot 1 }
-        { tag 2 }
-    }
-    T{ ##compare-branch
-        { src1 109 }
-        { src2 118 }
-        { cc cc> }
-    }
-} 1 test-bb
-
-V{
-    T{ ##add-imm
-        { dst 128 }
-        { src1 109 }
-        { src2 8 }
-    }
-    T{ ##load-immediate { dst 129 } { val 24 } }
-    T{ ##inc-d { n 4 } }
-    T{ ##inc-r { n 1 } }
-    T{ ##replace { src 109 } { loc D 2 } }
-    T{ ##replace { src 85 } { loc D 3 } }
-    T{ ##replace { src 128 } { loc D 0 } }
-    T{ ##replace { src 85 } { loc D 1 } }
-    T{ ##replace { src 89 } { loc D 4 } }
-    T{ ##replace { src 96 } { loc R 0 } }
-    T{ ##replace { src 129 } { loc R 0 } }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##peek { dst 134 } { loc D 1 } }
-    T{ ##slot-imm
-        { dst 140 }
-        { obj 134 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##inc-d { n 1 } }
-    T{ ##inc-r { n 1 } }
-    T{ ##replace { src 140 } { loc D 0 } }
-    T{ ##replace { src 134 } { loc R 0 } }
-    T{ ##call { word resize-array } }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##peek { dst 141 } { loc R 0 } }
-    T{ ##peek { dst 143 } { loc D 0 } }
-    T{ ##set-slot-imm
-        { src 143 }
-        { obj 141 }
-        { slot 2 }
-        { tag 7 }
-    }
-    T{ ##write-barrier-imm
-        { src 141 }
-        { slot 2 }
-        { temp1 145 }
-        { temp2 146 }
-    }
-    T{ ##inc-d { n -1 } }
-    T{ ##inc-r { n -1 } }
-    T{ ##peek { dst 156 } { loc D 2 } }
-    T{ ##peek { dst 158 } { loc D 3 } }
-    T{ ##peek { dst 160 } { loc D 0 } }
-    T{ ##peek { dst 162 } { loc D 1 } }
-    T{ ##peek { dst 164 } { loc D 4 } }
-    T{ ##peek { dst 167 } { loc R 0 } }
-    T{ ##copy { dst 157 } { src 156 } { rep int-rep } }
-    T{ ##copy { dst 159 } { src 158 } { rep int-rep } }
-    T{ ##copy { dst 161 } { src 160 } { rep int-rep } }
-    T{ ##copy { dst 163 } { src 162 } { rep int-rep } }
-    T{ ##copy { dst 165 } { src 164 } { rep int-rep } }
-    T{ ##copy { dst 168 } { src 167 } { rep int-rep } }
-    T{ ##branch }
-} 4 test-bb
-
-V{
-    T{ ##inc-d { n 3 } }
-    T{ ##inc-r { n 1 } }
-    T{ ##copy { dst 157 } { src 85 } }
-    T{ ##copy { dst 159 } { src 89 } }
-    T{ ##copy { dst 161 } { src 85 } }
-    T{ ##copy { dst 163 } { src 109 } }
-    T{ ##copy { dst 165 } { src 91 } }
-    T{ ##copy { dst 168 } { src 96 } }
-    T{ ##branch }
-} 5 test-bb
-
-V{
-    T{ ##set-slot-imm
-        { src 163 }
-        { obj 161 }
-        { slot 3 }
-        { tag 7 }
-    }
-    T{ ##inc-d { n 1 } }
-    T{ ##inc-r { n -1 } }
-    T{ ##replace { src 168 } { loc D 0 } }
-    T{ ##replace { src 157 } { loc D 3 } }
-    T{ ##replace { src 159 } { loc D 4 } }
-    T{ ##replace { src 161 } { loc D 1 } }
-    T{ ##replace { src 163 } { loc D 2 } }
-    T{ ##replace { src 165 } { loc D 5 } }
-    T{ ##epilogue }
-    T{ ##return }
-} 6 test-bb
-
-0 1 edge
-1 { 2 5 } edges
-2 3 edge
-3 4 edge
-4 6 edge
-5 6 edge
-
-[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
-
-! Fencepost error in assignment pass
-V{ T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##compare-imm-branch f 0 5 cc= }
-} 1 test-bb
-
-V{ T{ ##branch } } 2 test-bb
-
-V{
-    T{ ##peek f 1 D 0 }
-    T{ ##peek f 2 D 0 }
-    T{ ##replace f 1 D 0 }
-    T{ ##replace f 2 D 0 }
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-[ 0 ] [ 1 get instructions>> [ _spill? ] count ] unit-test
-
-[ 1 ] [ 2 get instructions>> [ _spill? ] count ] unit-test
-
-[ 1 ] [ 3 get predecessors>> first instructions>> [ _spill? ] count ] unit-test
-
-[ 1 ] [ 4 get instructions>> [ _reload? ] count ] unit-test
-
-! Another test case for fencepost error in assignment pass
-V{ T{ ##branch } } 0 test-bb
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##compare-imm-branch f 0 5 cc= }
-} 1 test-bb
-
-V{
-    T{ ##peek f 1 D 0 }
-    T{ ##peek f 2 D 0 }
-    T{ ##replace f 1 D 0 }
-    T{ ##replace f 2 D 0 }
-    T{ ##replace f 0 D 0 }
-    T{ ##branch }
-} 2 test-bb
-
-V{
-    T{ ##branch }
-} 3 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 4 test-bb
-
-test-diamond
-
-[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
-
-[ 0 ] [ 1 get instructions>> [ _spill? ] count ] unit-test
-
-[ 1 ] [ 2 get instructions>> [ _spill? ] count ] unit-test
-
-[ 1 ] [ 2 get instructions>> [ _reload? ] count ] unit-test
-
-[ 0 ] [ 3 get instructions>> [ _spill? ] count ] unit-test
-
-[ 0 ] [ 4 get instructions>> [ _reload? ] count ] unit-test
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##peek f 1 D 1 }
-    T{ ##replace f 1 D 1 }
-    T{ ##branch }
-} 0 test-bb
-
-V{
-    T{ ##gc f 2 3 }
-    T{ ##branch }
-} 1 test-bb
-
-V{
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 2 test-bb
-
-0 1 edge
-1 2 edge
-
-[ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
-
-[ { { 0 1 } } ] [ 1 get instructions>> first tagged-values>> ] unit-test
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##peek f 1 D 1 }
-    T{ ##compare-imm-branch f 1 5 cc= }
-} 0 test-bb
-
-V{
-    T{ ##gc f 2 3 }
-    T{ ##replace f 0 D 0 }
-    T{ ##return }
-} 1 test-bb
-
-V{
-    T{ ##return }
-} 2 test-bb
-
-0 { 1 2 } edges
-
-[ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
-
-[ { { 0 1 } } ] [ 1 get instructions>> first tagged-values>> ] unit-test
index 5e723f098a06dcbd9f8c7a5f675179c8864d6210..7657937d33e5a7449b4c4b4d15d79c5c723df1ee 100644 (file)
@@ -1,10 +1,9 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors namespaces make locals
 cpu.architecture
 compiler.cfg
 compiler.cfg.rpo
-compiler.cfg.liveness
 compiler.cfg.registers
 compiler.cfg.instructions
 compiler.cfg.linear-scan.numbering
@@ -29,8 +28,9 @@ IN: compiler.cfg.linear-scan
 ! by Omri Traub, Glenn Holloway, Michael D. Smith
 ! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.8435
 
+! SSA liveness must have been computed already
+
 :: (linear-scan) ( cfg machine-registers -- )
-    cfg compute-live-sets
     cfg number-instructions
     cfg compute-live-intervals machine-registers allocate-registers
     cfg assign-registers
index 00d6f73517ec3dd8949dd5fd0549dfd8547d141b..cb697c2136cbd8066e8902a47afa2f2e34b8721a 100644 (file)
@@ -1,19 +1,36 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces kernel assocs accessors sequences math math.order fry
-combinators binary-search compiler.cfg.instructions compiler.cfg.registers
-compiler.cfg.def-use compiler.cfg.liveness compiler.cfg.linearization.order
-compiler.cfg ;
+USING: namespaces kernel assocs accessors locals sequences math
+math.order fry combinators binary-search
+compiler.cfg.instructions
+compiler.cfg.registers
+compiler.cfg.def-use
+compiler.cfg.liveness
+compiler.cfg.linearization
+compiler.cfg.ssa.destruction
+compiler.cfg
+cpu.architecture ;
 IN: compiler.cfg.linear-scan.live-intervals
 
 TUPLE: live-range from to ;
 
 C: <live-range> live-range
 
+SYMBOLS: +def+ +use+ +memory+ ;
+
+TUPLE: vreg-use rep n type ;
+
+C: <vreg-use> vreg-use
+
 TUPLE: live-interval
 vreg
 reg spill-to reload-from
-start end ranges uses ;
+start end ranges uses
+reg-class ;
+
+: first-use ( live-interval -- use ) uses>> first ; inline
+
+: last-use ( live-interval -- use ) uses>> last ; inline
 
 GENERIC: covers? ( insn# obj -- ? )
 
@@ -29,7 +46,7 @@ M: live-interval covers? ( insn# live-interval -- ? )
         [ drop ] [ [ from>> <=> ] with search nip ] 2bi
         covers?
     ] if ;
-        
+
 : add-new-range ( from to live-interval -- )
     [ <live-range> ] dip ranges>> push ;
 
@@ -50,63 +67,76 @@ M: live-interval covers? ( insn# live-interval -- ? )
     2dup extend-range?
     [ extend-range ] [ add-new-range ] if ;
 
-GENERIC: operands-in-registers? ( insn -- ? )
-
-M: vreg-insn operands-in-registers? drop t ;
-
-M: partial-sync-insn operands-in-registers? drop f ;
-
-: add-def ( insn live-interval -- )
-    [ insn#>> ] [ uses>> ] bi* push ;
-
-: add-use ( insn live-interval -- )
-    ! Every use is a potential def, no SSA here baby!
-    over operands-in-registers? [ add-def ] [ 2drop ] if ;
+:: add-use ( rep n type live-interval -- )
+    type +memory+ eq? [
+        rep n type <vreg-use>
+        live-interval uses>> push
+    ] unless ;
 
-: <live-interval> ( vreg -- live-interval )
+: <live-interval> ( vreg reg-class -- live-interval )
     \ live-interval new
         V{ } clone >>uses
         V{ } clone >>ranges
+        swap >>reg-class
         swap >>vreg ;
 
 : block-from ( bb -- n ) instructions>> first insn#>> 1 - ;
 
 : block-to ( bb -- n ) instructions>> last insn#>> ;
 
-M: live-interval hashcode*
-    nip [ start>> ] [ end>> 1000 * ] bi + ;
+SYMBOLS: from to ;
 
 ! Mapping from vreg to live-interval
 SYMBOL: live-intervals
 
 : live-interval ( vreg -- live-interval )
-    live-intervals get [ <live-interval> ] cache ;
+    leader live-intervals get
+    [ dup rep-of reg-class-of <live-interval> ] cache ;
 
 GENERIC: compute-live-intervals* ( insn -- )
 
 M: insn compute-live-intervals* drop ;
 
-: handle-output ( insn vreg -- )
-    live-interval
-    [ [ insn#>> ] dip shorten-range ] [ add-def ] 2bi ;
+:: record-def ( vreg n type -- )
+    vreg rep-of :> rep
+    vreg live-interval :> live-interval
 
-: handle-input ( insn vreg -- )
-    live-interval
-    [ [ [ basic-block get block-from ] dip insn#>> ] dip add-range ] [ add-use ] 2bi ;
+    n live-interval shorten-range
+    rep n type live-interval add-use ;
 
-: handle-temp ( insn vreg -- )
-    live-interval
-    [ [ insn#>> dup ] dip add-range ] [ add-use ] 2bi ;
+:: record-use ( vreg n type -- )
+    vreg rep-of :> rep
+    vreg live-interval :> live-interval
 
-M: vreg-insn compute-live-intervals*
-    [ dup defs-vreg [ handle-output ] with when* ]
-    [ dup uses-vregs [ handle-input ] with each ]
-    [ dup temp-vregs [ handle-temp ] with each ]
-    tri ;
+    from get n live-interval add-range
+    rep n type live-interval add-use ;
+
+:: record-temp ( vreg n -- )
+    vreg rep-of :> rep
+    vreg live-interval :> live-interval
+
+    n n live-interval add-range
+    rep n +def+ live-interval add-use ;
+
+M:: vreg-insn compute-live-intervals* ( insn -- )
+    insn insn#>> :> n
+
+    insn defs-vreg [ n +def+ record-def ] when*
+    insn uses-vregs [ n +use+ record-use ] each
+    insn temp-vregs [ n record-temp ] each ;
+
+M:: clobber-insn compute-live-intervals* ( insn -- )
+    insn insn#>> :> n
+
+    insn defs-vreg [ n +use+ record-def ] when*
+    insn uses-vregs [ n +memory+ record-use ] each
+    insn temp-vregs [ n record-temp ] each ;
 
 : handle-live-out ( bb -- )
-    [ block-from ] [ block-to ] [ live-out keys ] tri
-    [ live-interval add-range ] with with each ;
+    live-out dup assoc-empty? [ drop ] [
+        [ from get to get ] dip keys
+        [ live-interval add-range ] with with each
+    ] if ;
 
 ! A location where all registers have to be spilled
 TUPLE: sync-point n ;
@@ -118,21 +148,24 @@ SYMBOL: sync-points
 
 GENERIC: compute-sync-points* ( insn -- )
 
-M: partial-sync-insn compute-sync-points*
+M: clobber-insn compute-sync-points*
     insn#>> <sync-point> sync-points get push ;
 
 M: insn compute-sync-points* drop ;
 
 : compute-live-intervals-step ( bb -- )
-    [ basic-block set ]
-    [ handle-live-out ]
-    [
-        instructions>> <reversed> [
-            [ compute-live-intervals* ]
-            [ compute-sync-points* ]
-            bi
-        ] each
-    ] tri ;
+    {
+        [ block-from from set ]
+        [ block-to to set ]
+        [ handle-live-out ]
+        [
+            instructions>> <reversed> [
+                [ compute-live-intervals* ]
+                [ compute-sync-points* ]
+                bi
+            ] each
+        ]
+    } cleave ;
 
 : init-live-intervals ( -- )
     H{ } clone live-intervals set
index 44b2ff907a19ad9400e7f525d30519935478ab1e..391edf21d6d5885ed98803ebf65a6d341536c54f 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors math sequences grouping namespaces
-compiler.cfg.linearization.order ;
+compiler.cfg.linearization ;
 IN: compiler.cfg.linear-scan.numbering
 
 ERROR: already-numbered insn ;
index e7f291d61312b5a21de70ecbd43cca4ce2f7b831..7aff066e0ba0449432373c8df1c589ac70ad6ac2 100644 (file)
@@ -7,7 +7,10 @@ IN: compiler.cfg.linear-scan.resolve.tests
 
 [
     {
-        { { T{ spill-slot f 0 } int-rep } { 1 int-rep } }
+        {
+            T{ location f T{ spill-slot f 0 } int-rep int-regs }
+            T{ location f 1 int-rep int-regs }
+        }
     }
 ] [
     [
@@ -17,21 +20,25 @@ IN: compiler.cfg.linear-scan.resolve.tests
 
 [
     {
-        T{ _reload { dst 1 } { rep int-rep } { src T{ spill-slot f 0 } } }
+        T{ ##reload { dst 1 } { rep int-rep } { src T{ spill-slot f 0 } } }
     }
 ] [
     [
-        { T{ spill-slot f 0 } int-rep } { 1 int-rep } >insn
+        T{ location f T{ spill-slot f 0 } int-rep int-regs }
+        T{ location f 1 int-rep int-regs }
+        >insn
     ] { } make
 ] unit-test
 
 [
     {
-        T{ _spill { src 1 } { rep int-rep } { dst T{ spill-slot f 0 } } }
+        T{ ##spill { src 1 } { rep int-rep } { dst T{ spill-slot f 0 } } }
     }
 ] [
     [
-        { 1 int-rep } { T{ spill-slot f 0 } int-rep } >insn
+        T{ location f 1 int-rep int-regs }
+        T{ location f T{ spill-slot f 0 } int-rep int-regs }
+        >insn
     ] { } make
 ] unit-test
 
@@ -41,27 +48,84 @@ IN: compiler.cfg.linear-scan.resolve.tests
     }
 ] [
     [
-        { 1 int-rep } { 2 int-rep } >insn
+        T{ location f 1 int-rep int-regs }
+        T{ location f 2 int-rep int-regs }
+        >insn
     ] { } make
 ] unit-test
 
-cfg new 8 >>spill-area-size cfg set
-H{ } clone spill-temps set
+[
+    {
+        T{ ##copy { src 1 } { dst 2 } { rep int-rep } }
+        T{ ##branch }
+    }
+] [
+    { { T{ location f 1 int-rep int-regs } T{ location f 2 int-rep int-regs } } }
+    mapping-instructions
+] unit-test
 
 [
-    t
+    {
+        T{ ##spill { src 0 } { rep int-rep } { dst T{ spill-slot f 0 } } }
+        T{ ##reload { dst 0 } { rep tagged-rep } { src T{ spill-slot f 1 } } }
+        T{ ##branch }
+    }
 ] [
-    { { { 0 int-rep } { 1 int-rep } } { { 1 int-rep } { 0 int-rep } } }
+    {
+        { T{ location f T{ spill-slot f 1 } tagged-rep int-regs } T{ location f 0 tagged-rep int-regs } }
+        { T{ location f 0 int-rep int-regs } T{ location f T{ spill-slot f 0 } int-rep int-regs } }
+    }
+    mapping-instructions
+] unit-test
+
+[
+    {
+        T{ ##spill { src 0 } { rep int-rep } { dst T{ spill-slot f 1 } } }
+        T{ ##reload { dst 0 } { rep tagged-rep } { src T{ spill-slot f 0 } } }
+        T{ ##branch }
+    }
+] [
+    {
+        { T{ location f T{ spill-slot f 0 } tagged-rep int-regs } T{ location f 0 tagged-rep int-regs } }
+        { T{ location f 0 int-rep int-regs } T{ location f T{ spill-slot f 1 } int-rep int-regs } }
+    }
+    mapping-instructions
+] unit-test
+
+[
+    {
+        T{ ##spill { src 0 } { rep int-rep } { dst T{ spill-slot f 1 } } }
+        T{ ##reload { dst 0 } { rep tagged-rep } { src T{ spill-slot f 0 } } }
+        T{ ##branch }
+    }
+] [
+    {
+        { T{ location f 0 int-rep int-regs } T{ location f T{ spill-slot f 1 } int-rep int-regs } }
+        { T{ location f T{ spill-slot f 0 } tagged-rep int-regs } T{ location f 0 tagged-rep int-regs } }
+    }
+    mapping-instructions
+] unit-test
+
+cfg new 8 >>spill-area-size cfg set
+H{ } clone spill-temps set
+
+[ t ] [
+    {
+        { T{ location f 0 int-rep int-regs } T{ location f 1 int-rep int-regs } }
+        { T{ location f 1 int-rep int-regs } T{ location f 0 int-rep int-regs } }
+    }
     mapping-instructions {
         {
-            T{ _spill { src 0 } { rep int-rep } { dst T{ spill-slot f 8 } } }
+            T{ ##spill { src 0 } { rep int-rep } { dst T{ spill-slot f 8 } } }
             T{ ##copy { dst 0 } { src 1 } { rep int-rep } }
-            T{ _reload { dst 1 } { rep int-rep } { src T{ spill-slot f 8 } } }
+            T{ ##reload { dst 1 } { rep int-rep } { src T{ spill-slot f 8 } } }
+            T{ ##branch }
         }
         {
-            T{ _spill { src 1 } { rep int-rep } { dst T{ spill-slot f 8 } } }
+            T{ ##spill { src 1 } { rep int-rep } { dst T{ spill-slot f 8 } } }
             T{ ##copy { dst 1 } { src 0 } { rep int-rep } }
-            T{ _reload { dst 0 } { rep int-rep } { src T{ spill-slot f 8 } } }
+            T{ ##reload { dst 0 } { rep int-rep } { src T{ spill-slot f 8 } } }
+            T{ ##branch }
         }
     } member?
 ] unit-test
index 20c9ee4e99d257dc09f42bc2df3883d7d2fd2d2c..9d3c91ca18b0a4ab86177e1dedb7260a926c24b2 100644 (file)
@@ -1,8 +1,9 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators
 combinators.short-circuit fry kernel locals namespaces
 make math sequences hashtables
+cpu.architecture
 compiler.cfg
 compiler.cfg.rpo
 compiler.cfg.liveness
@@ -11,42 +12,67 @@ compiler.cfg.utilities
 compiler.cfg.instructions
 compiler.cfg.predecessors
 compiler.cfg.parallel-copy
+compiler.cfg.ssa.destruction
 compiler.cfg.linear-scan.assignment
 compiler.cfg.linear-scan.allocation.state ;
 IN: compiler.cfg.linear-scan.resolve
 
+TUPLE: location
+{ reg read-only }
+{ rep read-only }
+{ reg-class read-only } ;
+
+: <location> ( reg rep -- location )
+    dup reg-class-of location boa ;
+
+M: location equal?
+    over location? [
+        { [ [ reg>> ] bi@ = ] [ [ reg-class>> ] bi@ = ] } 2&&
+    ] [ 2drop f ] if ;
+
+M: location hashcode*
+    reg>> hashcode* ;
+
 SYMBOL: spill-temps
 
 : spill-temp ( rep -- n )
-    spill-temps get [ next-spill-slot ] cache ;
+    rep-size spill-temps get [ next-spill-slot ] cache ;
 
 : add-mapping ( from to rep -- )
-    '[ _ 2array ] bi@ 2array , ;
+    '[ _ <location> ] bi@ 2array , ;
 
-:: resolve-value-data-flow ( bb to vreg -- )
-    vreg bb vreg-at-end
-    vreg to vreg-at-start
+:: resolve-value-data-flow ( vreg live-out live-in edge-live-in -- )
+    vreg live-out ?at [ bad-vreg ] unless
+    vreg live-in ?at [ edge-live-in ?at [ bad-vreg ] unless ] unless
     2dup = [ 2drop ] [ vreg rep-of add-mapping ] if ;
 
-: compute-mappings ( bb to -- mappings )
-    dup live-in dup assoc-empty? [ 3drop f ] [
-        [ keys [ resolve-value-data-flow ] with with each ] { } make
+:: compute-mappings ( bb to -- mappings )
+    bb machine-live-out :> live-out
+    to machine-live-in :> live-in
+    bb to machine-edge-live-in :> edge-live-in
+    live-out assoc-empty? [ f ] [
+        [
+            live-in keys edge-live-in keys append [
+                live-out live-in edge-live-in
+                resolve-value-data-flow
+            ] each
+        ] { } make
     ] if ;
 
 : memory->register ( from to -- )
-    swap [ first2 ] [ first ] bi* _reload ;
+    swap [ reg>> ] [ [ rep>> ] [ reg>> ] bi ] bi* ##reload ;
 
 : register->memory ( from to -- )
-    [ first2 ] [ first ] bi* _spill ;
+    [ [ reg>> ] [ rep>> ] bi ] [ reg>> ] bi* ##spill ;
 
 : temp->register ( from to -- )
-    nip [ first ] [ second ] [ second spill-temp ] tri _reload ;
+    nip [ reg>> ] [ rep>> ] [ rep>> spill-temp ] tri ##reload ;
 
 : register->temp ( from to -- )
-    drop [ first2 ] [ second spill-temp ] bi _spill ;
+    drop [ [ reg>> ] [ rep>> ] bi ] [ rep>> spill-temp ] bi ##spill ;
 
 : register->register ( from to -- )
-    swap [ first ] [ first2 ] bi* ##copy ;
+    swap [ reg>> ] [ [ reg>> ] [ rep>> ] bi ] bi* ##copy ;
 
 SYMBOL: temp
 
@@ -54,18 +80,18 @@ SYMBOL: temp
     {
         { [ over temp eq? ] [ temp->register ] }
         { [ dup temp eq? ] [ register->temp ] }
-        { [ over first spill-slot? ] [ memory->register ] }
-        { [ dup first spill-slot? ] [ register->memory ] }
+        { [ over reg>> spill-slot? ] [ memory->register ] }
+        { [ dup reg>> spill-slot? ] [ register->memory ] }
         [ register->register ]
     } cond ;
 
 : mapping-instructions ( alist -- insns )
     [ swap ] H{ } assoc-map-as
-    [ temp [ swap >insn ] parallel-mapping ] { } make ;
+    [ temp [ swap >insn ] parallel-mapping ##branch ] { } make ;
 
 : perform-mappings ( bb to mappings -- )
     dup empty? [ 3drop ] [
-        mapping-instructions insert-simple-basic-block
+        mapping-instructions insert-basic-block
         cfg get cfg-changed drop
     ] if ;
 
diff --git a/basis/compiler/cfg/linearization/linearization-tests.factor b/basis/compiler/cfg/linearization/linearization-tests.factor
new file mode 100644 (file)
index 0000000..edaeb72
--- /dev/null
@@ -0,0 +1,14 @@
+USING: compiler.cfg.debugger compiler.cfg compiler.cfg.linearization
+kernel accessors sequences sets tools.test namespaces ;
+IN: compiler.cfg.linearization.tests
+
+V{ } 0 test-bb
+
+V{ } 1 test-bb
+
+V{ } 2 test-bb
+
+0 { 1 1 } edges
+1 2 edge
+
+[ t ] [ cfg new 0 get >>entry linearization-order [ id>> ] map all-unique? ] unit-test
index a0360e9d9c6240d5b7655ff8c89c710bd5c9a146..c44b29d27122dcbfb7df9075a9faa7e42d176973 100644 (file)
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math accessors sequences namespaces make
-combinators assocs arrays locals layouts hashtables
-cpu.architecture generalizations
-compiler.cfg
-compiler.cfg.comparisons
-compiler.cfg.stack-frame
-compiler.cfg.instructions
-compiler.cfg.utilities
-compiler.cfg.linearization.order ;
+USING: accessors arrays assocs deques dlists hashtables kernel
+make sorting namespaces sequences combinators
+combinators.short-circuit fry math compiler.cfg.rpo
+compiler.cfg.utilities compiler.cfg.loop-detection
+compiler.cfg.predecessors sets hash-sets ;
+FROM: namespaces => set ;
 IN: compiler.cfg.linearization
 
-<PRIVATE
-
-SYMBOL: numbers
-
-: block-number ( bb -- n ) numbers get at ;
-
-: number-blocks ( bbs -- ) [ 2array ] map-index >hashtable numbers set ;
-
-! Convert CFG IR to machine IR.
-GENERIC: linearize-insn ( basic-block insn -- )
-
-: linearize-basic-block ( bb -- )
-    [ block-number _label ]
-    [ dup instructions>> [ linearize-insn ] with each ]
-    bi ;
-
-M: insn linearize-insn , drop ;
-
-: useless-branch? ( basic-block successor -- ? )
-    ! If our successor immediately follows us in linearization
-    ! order then we don't need to branch.
-    [ block-number ] bi@ 1 - = ; inline
-
-: emit-branch ( bb successor -- )
-    2dup useless-branch? [ 2drop ] [ nip block-number _branch ] if ;
-
-M: ##branch linearize-insn
-    drop dup successors>> first emit-branch ;
-
-: successors ( bb -- first second ) successors>> first2 ; inline
-
-:: conditional ( bb insn n conditional-quot negate-cc-quot -- bb successor label etc... )
-    bb insn
-    conditional-quot
-    [ drop dup successors>> second useless-branch? ] 2bi
-    [ [ swap block-number ] n ndip ]
-    [ [ block-number ] n ndip negate-cc-quot call ] if ; inline
+! This is RPO except loops are rotated and unlikely blocks go
+! at the end. Based on SBCL's src/compiler/control.lisp
 
-: (binary-conditional) ( bb insn -- bb successor1 successor2 src1 src2 cc )
-    [ dup successors ]
-    [ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline
-
-: binary-conditional ( bb insn -- bb successor label2 src1 src2 cc )
-    3 [ (binary-conditional) ] [ negate-cc ] conditional ;
-
-: (test-vector-conditional) ( bb insn -- bb successor1 successor2 src1 temp rep vcc )
-    [ dup successors ]
-    [ { [ src1>> ] [ temp>> ] [ rep>> ] [ vcc>> ] } cleave ] bi* ; inline
-
-: test-vector-conditional ( bb insn -- bb successor label src1 temp rep vcc )
-    4 [ (test-vector-conditional) ] [ negate-vcc ] conditional ;
-
-M: ##compare-branch linearize-insn
-    binary-conditional _compare-branch emit-branch ;
-
-M: ##compare-imm-branch linearize-insn
-    binary-conditional _compare-imm-branch emit-branch ;
-
-M: ##compare-float-ordered-branch linearize-insn
-    binary-conditional _compare-float-ordered-branch emit-branch ;
-
-M: ##compare-float-unordered-branch linearize-insn
-    binary-conditional _compare-float-unordered-branch emit-branch ;
-
-M: ##test-vector-branch linearize-insn
-    test-vector-conditional _test-vector-branch emit-branch ;
+<PRIVATE
 
-: overflow-conditional ( bb insn -- bb successor label2 dst src1 src2 )
-    [ dup successors block-number ]
-    [ [ dst>> ] [ src1>> ] [ src2>> ] tri ] bi* ; inline
+SYMBOLS: work-list loop-heads visited ;
+
+: visited? ( bb -- ? ) visited get in? ;
+
+: add-to-work-list ( bb -- )
+    dup visited? [ drop ] [
+        work-list get push-back
+    ] if ;
+
+: init-linearization-order ( cfg -- )
+    <dlist> work-list set
+    HS{ } clone visited set
+    entry>> add-to-work-list ;
+
+: (find-alternate-loop-head) ( bb -- bb' )
+    dup {
+        [ predecessor visited? not ]
+        [ predecessors>> length 1 = ]
+        [ predecessor successors>> length 1 = ]
+        [ [ number>> ] [ predecessor number>> ] bi > ]
+    } 1&& [ predecessor (find-alternate-loop-head) ] when ;
+
+: find-back-edge ( bb -- pred )
+    [ predecessors>> ] keep '[ _ back-edge? ] find nip ;
+
+: find-alternate-loop-head ( bb -- bb' )
+    dup find-back-edge dup visited? [ drop ] [
+        nip (find-alternate-loop-head)
+    ] if ;
+
+: predecessors-ready? ( bb -- ? )
+    [ predecessors>> ] keep '[
+        _ 2dup back-edge?
+        [ 2drop t ] [ drop visited? ] if
+    ] all? ;
+
+: process-successor ( bb -- )
+    dup predecessors-ready? [
+        dup loop-entry? [ find-alternate-loop-head ] when
+        add-to-work-list
+    ] [ drop ] if ;
+
+: sorted-successors ( bb -- seq )
+    successors>> <reversed> [ loop-nesting-at ] sort-with ;
+
+: process-block ( bb -- )
+    dup visited? [ drop ] [
+        [ , ]
+        [ visited get adjoin ]
+        [ sorted-successors [ process-successor ] each ]
+        tri
+    ] if ;
+
+: (linearization-order) ( cfg -- bbs )
+    init-linearization-order
+
+    [ work-list get [ process-block ] slurp-deque ] { } make
+    ! [ unlikely?>> not ] partition append
+    ;
 
-M: ##fixnum-add linearize-insn
-    overflow-conditional _fixnum-add emit-branch ;
+PRIVATE>
 
-M: ##fixnum-sub linearize-insn
-    overflow-conditional _fixnum-sub emit-branch ;
+: linearization-order ( cfg -- bbs )
+    needs-post-order needs-loops needs-predecessors
 
-M: ##fixnum-mul linearize-insn
-    overflow-conditional _fixnum-mul emit-branch ;
+    dup linear-order>> [ ] [
+        dup (linearization-order)
+        >>linear-order linear-order>>
+    ] ?if ;
 
-M: ##dispatch linearize-insn
-    swap
-    [ [ src>> ] [ temp>> ] bi _dispatch ]
-    [ successors>> [ block-number _dispatch-label ] each ]
-    bi* ;
+SYMBOL: numbers
 
-: linearize-basic-blocks ( cfg -- insns )
-    [
-        [
-            linearization-order
-            [ number-blocks ]
-            [ [ linearize-basic-block ] each ] bi
-        ] [ spill-area-size>> _spill-area-size ] bi
-    ] { } make ;
+: block-number ( bb -- n ) numbers get at ;
 
-PRIVATE>
-        
-: flatten-cfg ( cfg -- mr )
-    [ linearize-basic-blocks ] [ word>> ] [ label>> ] tri
-    <mr> ;
+: number-blocks ( bbs -- )
+    [ 2array ] map-index >hashtable numbers set ;
diff --git a/basis/compiler/cfg/linearization/order/order-tests.factor b/basis/compiler/cfg/linearization/order/order-tests.factor
deleted file mode 100644 (file)
index 67fb55f..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-USING: compiler.cfg.debugger compiler.cfg compiler.cfg.linearization.order
-kernel accessors sequences sets tools.test namespaces ;
-IN: compiler.cfg.linearization.order.tests
-
-V{ } 0 test-bb
-
-V{ } 1 test-bb
-
-V{ } 2 test-bb
-
-0 { 1 1 } edges
-1 2 edge
-
-[ t ] [ cfg new 0 get >>entry linearization-order [ id>> ] map all-unique? ] unit-test
diff --git a/basis/compiler/cfg/linearization/order/order.factor b/basis/compiler/cfg/linearization/order/order.factor
deleted file mode 100644 (file)
index 166a0f0..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs deques dlists kernel make sorting
-namespaces sequences combinators combinators.short-circuit
-fry math compiler.cfg.rpo compiler.cfg.utilities
-compiler.cfg.loop-detection compiler.cfg.predecessors
-sets hash-sets ;
-FROM: namespaces => set ;
-IN: compiler.cfg.linearization.order
-
-! This is RPO except loops are rotated. Based on SBCL's src/compiler/control.lisp
-
-<PRIVATE
-
-SYMBOLS: work-list loop-heads visited ;
-
-: visited? ( bb -- ? ) visited get in? ;
-
-: add-to-work-list ( bb -- )
-    dup visited? [ drop ] [
-        work-list get push-back
-    ] if ;
-
-: init-linearization-order ( cfg -- )
-    <dlist> work-list set
-    HS{ } clone visited set
-    entry>> add-to-work-list ;
-
-: (find-alternate-loop-head) ( bb -- bb' )
-    dup {
-        [ predecessor visited? not ]
-        [ predecessors>> length 1 = ]
-        [ predecessor successors>> length 1 = ]
-        [ [ number>> ] [ predecessor number>> ] bi > ]
-    } 1&& [ predecessor (find-alternate-loop-head) ] when ;
-
-: find-back-edge ( bb -- pred )
-    [ predecessors>> ] keep '[ _ back-edge? ] find nip ;
-
-: find-alternate-loop-head ( bb -- bb' )
-    dup find-back-edge dup visited? [ drop ] [
-        nip (find-alternate-loop-head)
-    ] if ;
-
-: predecessors-ready? ( bb -- ? )
-    [ predecessors>> ] keep '[
-        _ 2dup back-edge?
-        [ 2drop t ] [ drop visited? ] if
-    ] all? ;
-
-: process-successor ( bb -- )
-    dup predecessors-ready? [
-        dup loop-entry? [ find-alternate-loop-head ] when
-        add-to-work-list
-    ] [ drop ] if ;
-
-: sorted-successors ( bb -- seq )
-    successors>> <reversed> [ loop-nesting-at ] sort-with ;
-
-: process-block ( bb -- )
-    dup visited? [ drop ] [
-        [ , ]
-        [ visited get adjoin ]
-        [ sorted-successors [ process-successor ] each ]
-        tri
-    ] if ;
-
-: (linearization-order) ( cfg -- bbs )
-    init-linearization-order
-
-    [ work-list get [ process-block ] slurp-deque ] { } make ;
-
-PRIVATE>
-
-: linearization-order ( cfg -- bbs )
-    needs-post-order needs-loops needs-predecessors
-
-    dup linear-order>> [ ] [
-        dup (linearization-order)
-        >>linear-order linear-order>>
-    ] ?if ;
diff --git a/basis/compiler/cfg/linearization/summary.txt b/basis/compiler/cfg/linearization/summary.txt
deleted file mode 100644 (file)
index 96daec8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Flattening CFG into MR (machine representation)
diff --git a/basis/compiler/cfg/liveness/ssa/ssa-tests.factor b/basis/compiler/cfg/liveness/ssa/ssa-tests.factor
new file mode 100644 (file)
index 0000000..5413c65
--- /dev/null
@@ -0,0 +1,61 @@
+USING: accessors compiler.cfg compiler.cfg.debugger
+compiler.cfg.instructions compiler.cfg.liveness.ssa
+compiler.cfg.liveness arrays sequences assocs
+compiler.cfg.registers kernel namespaces tools.test ;
+IN: compiler.cfg.liveness.ssa.tests
+
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##load-integer f 0 0 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##load-integer f 1 1 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##phi f 2 H{ { 2 0 } { 3 1 } } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##branch }
+} 5 test-bb
+
+V{
+    T{ ##replace f 2 D 0 }
+    T{ ##branch }
+} 6 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 7 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 { 5 6 } edges
+5 6 edge
+6 7 edge
+
+[ ] [ cfg new 0 get >>entry dup cfg set compute-ssa-live-sets ] unit-test
+
+[ t ] [ 0 get live-in assoc-empty? ] unit-test
+
+[ H{ { 2 2 } } ] [ 4 get live-out ] unit-test
+
+[ H{ { 0 0 } } ] [ 2 get 4 get edge-live-in ] unit-test
+
+[ H{ { 1 1 } } ] [ 3 get 4 get edge-live-in ] unit-test
index 5215c9c4874f4953f0d284589b579f033052f741..84428514aa19ae4c46c8f2ebf5d378790bdfe46c 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces deques accessors sets sequences assocs fry
 hashtables dlists compiler.cfg.def-use compiler.cfg.instructions
@@ -11,9 +11,9 @@ IN: compiler.cfg.liveness.ssa
 
 ! Assoc mapping basic blocks to sequences of sets of vregs; each sequence
 ! is in correspondence with a predecessor
-SYMBOL: phi-live-ins
+SYMBOL: edge-live-ins
 
-: phi-live-in ( predecessor basic-block -- set ) phi-live-ins get at at ;
+: edge-live-in ( predecessor basic-block -- set ) edge-live-ins get at at ;
 
 SYMBOL: work-list
 
@@ -23,19 +23,19 @@ SYMBOL: work-list
 : compute-live-in ( basic-block -- live-in )
     [ live-out ] keep instructions>> transfer-liveness ;
 
-: compute-phi-live-in ( basic-block -- phi-live-in )
+: compute-edge-live-in ( basic-block -- edge-live-in )
     H{ } clone [
         '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
     ] keep ;
 
 : update-live-in ( basic-block -- changed? )
     [ [ compute-live-in ] keep live-ins get maybe-set-at ]
-    [ [ compute-phi-live-in ] keep phi-live-ins get maybe-set-at ]
+    [ [ compute-edge-live-in ] keep edge-live-ins get maybe-set-at ]
     bi or ;
 
 : compute-live-out ( basic-block -- live-out )
     [ successors>> [ live-in ] map ]
-    [ dup successors>> [ phi-live-in ] with map ] bi
+    [ dup successors>> [ edge-live-in ] with map ] bi
     append assoc-combine ;
 
 : update-live-out ( basic-block -- changed? )
@@ -48,14 +48,14 @@ SYMBOL: work-list
         [ predecessors>> add-to-work-list ] [ drop ] if
     ] [ drop ] if ;
 
-: compute-ssa-live-sets ( cfg -- cfg' )
+: compute-ssa-live-sets ( cfg -- )
     needs-predecessors
 
     <hashed-dlist> work-list set
     H{ } clone live-ins set
-    H{ } clone phi-live-ins set
+    H{ } clone edge-live-ins set
     H{ } clone live-outs set
-    dup post-order add-to-work-list
+    post-order add-to-work-list
     work-list get [ liveness-step ] slurp-deque ;
 
 : live-in? ( vreg bb -- ? ) live-in key? ;
index 2e2dab00f1e1019902371934023fe40fc62dd6a6..d8fc92aaa63ffe1f6c03f27f261f8648fba038bb 100644 (file)
@@ -79,6 +79,8 @@ PRIVATE>
 
 : loop-nesting-at ( bb -- n ) loop-nesting get at 0 or ;
 
+: current-loop-nesting ( -- n ) basic-block get loop-nesting-at ;
+
 : needs-loops ( cfg -- cfg' )
     needs-predecessors
     dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless ;
diff --git a/basis/compiler/cfg/mr/authors.txt b/basis/compiler/cfg/mr/authors.txt
deleted file mode 100644 (file)
index d4f5d6b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
\ No newline at end of file
diff --git a/basis/compiler/cfg/mr/mr.factor b/basis/compiler/cfg/mr/mr.factor
deleted file mode 100644 (file)
index a46e6c1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel namespaces accessors compiler.cfg
-compiler.cfg.linearization compiler.cfg.gc-checks
-compiler.cfg.save-contexts compiler.cfg.linear-scan
-compiler.cfg.build-stack-frame ;
-IN: compiler.cfg.mr
-
-: build-mr ( cfg -- mr )
-    insert-gc-checks
-    insert-save-contexts
-    linear-scan
-    flatten-cfg
-    build-stack-frame ;
\ No newline at end of file
index 84726a9b99de44d52f876780a53975ff3ac3945e..5881cd78ea32280068d418b9bcc726d9882e050a 100644 (file)
@@ -1,41 +1,27 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences accessors combinators namespaces
-compiler.cfg.tco
+USING: compiler.cfg.tco
 compiler.cfg.useless-conditionals
 compiler.cfg.branch-splitting
 compiler.cfg.block-joining
+compiler.cfg.height
 compiler.cfg.ssa.construction
 compiler.cfg.alias-analysis
 compiler.cfg.value-numbering
 compiler.cfg.copy-prop
 compiler.cfg.dce
-compiler.cfg.write-barrier
-compiler.cfg.representations
-compiler.cfg.ssa.destruction
-compiler.cfg.empty-blocks
-compiler.cfg.checker ;
+compiler.cfg.write-barrier ;
 IN: compiler.cfg.optimizer
 
-SYMBOL: check-optimizer?
-
-: ?check ( cfg -- cfg' )
-    check-optimizer? get [
-        dup check-cfg
-    ] when ;
-
 : optimize-cfg ( cfg -- cfg' )
     optimize-tail-calls
     delete-useless-conditionals
     split-branches
     join-blocks
+    normalize-height
     construct-ssa
     alias-analysis
     value-numbering
     copy-propagation
     eliminate-dead-code
-    eliminate-write-barriers
-    select-representations
-    destruct-ssa
-    delete-empty-blocks
-    ?check ;
+    eliminate-write-barriers ;
index 2f4f2a99e69be5735c423c0b1b048fd672b48e5a..9c7896be7e9f5cbb351300e9bac48633457ab04b 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors namespaces kernel parser assocs sequences ;
+USING: accessors namespaces kernel math parser assocs sequences ;
 IN: compiler.cfg.registers
 
 ! Virtual registers, used by CFG and machine IRs, are just integers
@@ -34,7 +34,7 @@ ERROR: bad-vreg vreg ;
 
 ! ##inc-d and ##inc-r affect locations as follows. Location D 0 before
 ! an ##inc-d 1 becomes D 1 after ##inc-d 1.
-TUPLE: loc { n read-only } ;
+TUPLE: loc { n integer read-only } ;
 
 TUPLE: ds-loc < loc ;
 C: <ds-loc> ds-loc
diff --git a/basis/compiler/cfg/representations/coalescing/authors.txt b/basis/compiler/cfg/representations/coalescing/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/representations/coalescing/coalescing-tests.factor b/basis/compiler/cfg/representations/coalescing/coalescing-tests.factor
new file mode 100644 (file)
index 0000000..cc1bde3
--- /dev/null
@@ -0,0 +1,40 @@
+USING: arrays sequences kernel namespaces accessors compiler.cfg
+compiler.cfg.instructions
+compiler.cfg.registers
+compiler.cfg.debugger
+compiler.cfg.representations.coalescing
+tools.test ;
+IN: compiler.cfg.representations.coalescing.tests
+
+: test-scc ( -- )
+    cfg new 0 get >>entry compute-components ;
+
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 2 D 0 }
+    T{ ##load-integer f 0 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##load-integer f 1 0 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##phi f 3 H{ { 1 0 } { 2 1 } } }
+} 3 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+
+[ ] [ test-scc ] unit-test
+
+[ t ] [ 0 vreg>scc 1 vreg>scc = ] unit-test
+[ t ] [ 0 vreg>scc 3 vreg>scc = ] unit-test
+[ f ] [ 2 vreg>scc 3 vreg>scc = ] unit-test
diff --git a/basis/compiler/cfg/representations/coalescing/coalescing.factor b/basis/compiler/cfg/representations/coalescing/coalescing.factor
new file mode 100644 (file)
index 0000000..2061064
--- /dev/null
@@ -0,0 +1,43 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs compiler.cfg.def-use
+compiler.cfg.instructions compiler.cfg.rpo disjoint-sets fry
+kernel namespaces sequences ;
+IN: compiler.cfg.representations.coalescing
+
+! Find all strongly connected components in the graph where the
+! edges are ##phi or ##copy vreg uses
+SYMBOL: components
+
+: init-components ( cfg components -- )
+    '[
+        instructions>> [
+            defs-vreg [ _ add-atom ] when*
+        ] each
+    ] each-basic-block ;
+
+GENERIC# visit-insn 1 ( insn disjoint-set -- )
+
+M: ##copy visit-insn
+    [ [ dst>> ] [ src>> ] bi ] dip equate ;
+
+M: ##phi visit-insn
+    [ [ inputs>> values ] [ dst>> ] bi ] dip equate-all-with ;
+
+M: insn visit-insn 2drop ;
+
+: merge-components ( cfg components -- )
+    '[
+        instructions>> [
+            _ visit-insn
+        ] each
+    ] each-basic-block ;
+
+: compute-components ( cfg -- )
+    <disjoint-set>
+    [ init-components ]
+    [ merge-components ]
+    [ components set drop ] 2tri ;
+
+: vreg>scc ( vreg -- scc )
+    components get representative ;
diff --git a/basis/compiler/cfg/representations/conversion/authors.txt b/basis/compiler/cfg/representations/conversion/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/representations/conversion/conversion.factor b/basis/compiler/cfg/representations/conversion/conversion.factor
new file mode 100644 (file)
index 0000000..b8346fe
--- /dev/null
@@ -0,0 +1,84 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays byte-arrays combinators compiler.cfg.instructions
+compiler.cfg.registers compiler.constants cpu.architecture
+kernel layouts locals math namespaces ;
+IN: compiler.cfg.representations.conversion
+
+ERROR: bad-conversion dst src dst-rep src-rep ;
+
+GENERIC: rep>tagged ( dst src rep -- )
+GENERIC: tagged>rep ( dst src rep -- )
+
+M: int-rep rep>tagged ( dst src rep -- )
+    drop tag-bits get ##shl-imm ;
+
+M: int-rep tagged>rep ( dst src rep -- )
+    drop tag-bits get ##sar-imm ;
+
+M:: float-rep rep>tagged ( dst src rep -- )
+    double-rep next-vreg-rep :> temp
+    temp src ##single>double-float
+    dst temp double-rep rep>tagged ;
+
+M:: float-rep tagged>rep ( dst src rep -- )
+    double-rep next-vreg-rep :> temp
+    temp src double-rep tagged>rep
+    dst temp ##double>single-float ;
+
+M:: double-rep rep>tagged ( dst src rep -- )
+    dst 16 float int-rep next-vreg-rep ##allot
+    src dst float-offset double-rep f ##store-memory-imm ;
+
+M: double-rep tagged>rep
+    drop float-offset double-rep f ##load-memory-imm ;
+
+M:: vector-rep rep>tagged ( dst src rep -- )
+    tagged-rep next-vreg-rep :> temp
+    dst 16 2 cells + byte-array int-rep next-vreg-rep ##allot
+    temp 16 tag-fixnum ##load-tagged
+    temp dst 1 byte-array type-number ##set-slot-imm
+    src dst byte-array-offset rep f ##store-memory-imm ;
+
+M: vector-rep tagged>rep
+    [ byte-array-offset ] dip f ##load-memory-imm ;
+
+M:: scalar-rep rep>tagged ( dst src rep -- )
+    tagged-rep next-vreg-rep :> temp
+    temp src rep ##scalar>integer
+    dst temp int-rep rep>tagged ;
+
+M:: scalar-rep tagged>rep ( dst src rep -- )
+    tagged-rep next-vreg-rep :> temp
+    temp src int-rep tagged>rep
+    dst temp rep ##integer>scalar ;
+
+GENERIC: rep>int ( dst src rep -- )
+GENERIC: int>rep ( dst src rep -- )
+
+M: scalar-rep rep>int ( dst src rep -- )
+    ##scalar>integer ;
+
+M: scalar-rep int>rep ( dst src rep -- )
+    ##integer>scalar ;
+
+: emit-conversion ( dst src dst-rep src-rep -- )
+    {
+        { [ 2dup eq? ] [ drop ##copy ] }
+        { [ dup tagged-rep? ] [ drop tagged>rep ] }
+        { [ over tagged-rep? ] [ nip rep>tagged ] }
+        { [ dup int-rep? ] [ drop int>rep ] }
+        { [ over int-rep? ] [ nip rep>int ] }
+        [
+            2dup 2array {
+                { { double-rep float-rep } [ 2drop ##single>double-float ] }
+                { { float-rep double-rep } [ 2drop ##double>single-float ] }
+                ! Punning SIMD vector types? Naughty naughty! But
+                ! it is allowed... otherwise bail out.
+                [
+                    drop 2dup [ reg-class-of ] bi@ eq?
+                    [ drop ##copy ] [ bad-conversion ] if
+                ]
+            } case
+        ]
+    } cond ;
diff --git a/basis/compiler/cfg/representations/peephole/authors.txt b/basis/compiler/cfg/representations/peephole/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/representations/peephole/peephole.factor b/basis/compiler/cfg/representations/peephole/peephole.factor
new file mode 100644 (file)
index 0000000..22366f5
--- /dev/null
@@ -0,0 +1,253 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors byte-arrays combinators
+combinators.short-circuit kernel layouts locals make math
+namespaces sequences cpu.architecture compiler.cfg.registers
+compiler.cfg.instructions
+compiler.cfg.representations.rewrite
+compiler.cfg.representations.selection ;
+IN: compiler.cfg.representations.peephole
+
+! Representation selection performs some peephole optimizations
+! when inserting conversions to optimize for a few common cases
+
+GENERIC: optimize-insn ( insn -- )
+
+SYMBOL: insn-index
+
+: here ( -- )
+    building get length 1 - insn-index set ;
+
+: finish ( insn -- ) , here ;
+
+: unchanged ( insn -- )
+    [ no-use-conversion ] [ finish ] [ no-def-conversion ] tri ;
+
+: last-insn ( -- insn ) insn-index get building get nth ;
+
+M: vreg-insn conversions-for-insn
+    init-renaming-set
+    optimize-insn
+    last-insn perform-renaming ;
+
+M: vreg-insn optimize-insn
+    [ emit-use-conversion ] [ finish ] [ emit-def-conversion ] tri ;
+
+M: ##load-integer optimize-insn
+    {
+        {
+            [ dup dst>> rep-of tagged-rep? ]
+            [ [ dst>> ] [ val>> tag-fixnum ] bi ##load-tagged here ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! When a float is unboxed, we replace the ##load-reference with a ##load-double
+! if the architecture supports it
+: convert-to-load-double? ( insn -- ? )
+    {
+        [ drop fused-unboxing? ]
+        [ dst>> rep-of double-rep? ]
+        [ obj>> float? ]
+    } 1&& ;
+
+: convert-to-load-vector? ( insn -- ? )
+    {
+        [ drop fused-unboxing? ]
+        [ dst>> rep-of vector-rep? ]
+        [ obj>> byte-array? ]
+    } 1&& ;
+
+! When a literal zeroes/ones vector is unboxed, we replace the ##load-reference
+! with a ##zero-vector or ##fill-vector instruction since this is more efficient.
+: convert-to-zero-vector? ( insn -- ? )
+    {
+        [ dst>> rep-of vector-rep? ]
+        [ obj>> B{ 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 } = ]
+    } 1&& ;
+
+: convert-to-fill-vector? ( insn -- ? )
+    {
+        [ dst>> rep-of vector-rep? ]
+        [ obj>> B{ 255 255 255 255  255 255 255 255  255 255 255 255  255 255 255 255 } = ]
+    } 1&& ;
+
+M: ##load-reference optimize-insn
+    {
+        {
+            [ dup convert-to-load-double? ]
+            [ [ dst>> ] [ obj>> ] bi ##load-double here ]
+        }
+        {
+            [ dup convert-to-zero-vector? ]
+            [ dst>> dup rep-of ##zero-vector here ]
+        }
+        {
+            [ dup convert-to-fill-vector? ]
+            [ dst>> dup rep-of ##fill-vector here ]
+        }
+        {
+            [ dup convert-to-load-vector? ]
+            [ [ dst>> ] [ obj>> ] [ dst>> rep-of ] tri ##load-vector here ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! Optimize this:
+! ##sar-imm temp src tag-bits
+! ##shl-imm dst temp X
+! Into either
+! ##shl-imm by X - tag-bits, or
+! ##sar-imm by tag-bits - X.
+: combine-shl-imm-input ( insn -- )
+    [ dst>> ] [ src1>> ] [ src2>> ] tri tag-bits get {
+        { [ 2dup < ] [ swap - ##sar-imm here ] }
+        { [ 2dup > ] [ - ##shl-imm here ] }
+        [ 2drop int-rep ##copy here ]
+    } cond ;
+
+: dst-tagged? ( insn -- ? ) dst>> rep-of tagged-rep? ;
+: src1-tagged? ( insn -- ? ) src1>> rep-of tagged-rep? ;
+: src2-tagged? ( insn -- ? ) src2>> rep-of tagged-rep? ;
+
+: src2-tagged-arithmetic? ( insn -- ? ) src2>> tag-fixnum immediate-arithmetic? ;
+: src2-tagged-bitwise? ( insn -- ? ) src2>> tag-fixnum immediate-bitwise? ;
+: src2-tagged-shift-count? ( insn -- ? ) src2>> tag-bits get + immediate-shift-count? ;
+
+: >tagged-shift ( insn -- ) [ tag-bits get + ] change-src2 finish ; inline
+
+M: ##shl-imm optimize-insn
+    {
+        {
+            [ dup { [ dst-tagged? ] [ src1-tagged? ] } 1&& ]
+            [ unchanged ]
+        }
+        {
+            [ dup { [ dst-tagged? ] [ src2-tagged-shift-count? ] } 1&& ]
+            [ [ emit-use-conversion ] [ >tagged-shift ] [ no-def-conversion ] tri ]
+        }
+        {
+            [ dup src1-tagged? ]
+            [ [ no-use-conversion ] [ combine-shl-imm-input ] [ emit-def-conversion ] tri ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! Optimize this:
+! ##sar-imm temp src tag-bits
+! ##sar-imm dst temp X
+! Into
+! ##sar-imm by X + tag-bits
+! assuming X + tag-bits is a valid shift count.
+M: ##sar-imm optimize-insn
+    {
+        {
+            [ dup { [ src1-tagged? ] [ src2-tagged-shift-count? ] } 1&& ]
+            [ [ no-use-conversion ] [ >tagged-shift ] [ emit-def-conversion ] tri ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! Peephole optimization: for X = add, sub, and, or, xor, min, max
+! we have
+! tag(untag(a) X untag(b)) = a X b
+!
+! so if all inputs and outputs of ##X or ##X-imm are tagged,
+! don't have to insert any conversions
+M: inert-tag-untag-insn optimize-insn
+    {
+        {
+            [ dup { [ dst-tagged? ] [ src1-tagged? ] [ src2-tagged? ] } 1&& ]
+            [ unchanged ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! -imm variant of above
+: >tagged-imm ( insn -- )
+    [ tag-fixnum ] change-src2 unchanged ; inline
+
+M: inert-arithmetic-tag-untag-insn optimize-insn
+    {
+        {
+            [ dup { [ dst-tagged? ] [ src1-tagged? ] [ src2-tagged-arithmetic? ] } 1&& ]
+            [ >tagged-imm ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+M: inert-bitwise-tag-untag-insn optimize-insn
+    {
+        {
+            [ dup { [ dst-tagged? ] [ src1-tagged? ] [ src2-tagged-bitwise? ] } 1&& ]
+            [ >tagged-imm ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+M: ##mul-imm optimize-insn
+    {
+        { [ dup { [ dst-tagged? ] [ src1-tagged? ] } 1&& ] [ unchanged ] }
+        { [ dup { [ dst-tagged? ] [ src2-tagged-arithmetic? ] } 1&& ] [ >tagged-imm ] }
+        [ call-next-method ]
+    } cond ;
+
+! Similar optimization for comparison operators
+M: ##compare-integer-imm optimize-insn
+    {
+        { [ dup { [ src1-tagged? ] [ src2-tagged-arithmetic? ] } 1&& ] [ >tagged-imm ] }
+        [ call-next-method ]
+    } cond ;
+
+M: ##compare-integer-imm-branch optimize-insn
+    {
+        { [ dup { [ src1-tagged? ] [ src2-tagged-arithmetic? ] } 1&& ] [ >tagged-imm ] }
+        [ call-next-method ]
+    } cond ;
+
+M: ##compare-integer optimize-insn
+    {
+        { [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
+        [ call-next-method ]
+    } cond ;
+
+M: ##compare-integer-branch optimize-insn
+    {
+        { [ dup { [ src1-tagged? ] [ src2-tagged? ] } 1&& ] [ unchanged ] }
+        [ call-next-method ]
+    } cond ;
+
+! Identities:
+! tag(neg(untag(x))) = x
+! tag(neg(x)) = x * -2^tag-bits
+: inert-tag/untag-unary? ( insn -- ? )
+    [ dst>> ] [ src>> ] bi [ rep-of tagged-rep? ] both? ;
+
+: combine-neg-tag ( insn -- )
+    [ dst>> ] [ src>> ] bi tag-bits get 2^ neg ##mul-imm here ;
+
+M: ##neg optimize-insn
+    {
+        { [ dup inert-tag/untag-unary? ] [ unchanged ] }
+        {
+            [ dup dst>> rep-of tagged-rep? ]
+            [ [ emit-use-conversion ] [ combine-neg-tag ] [ no-def-conversion ] tri ]
+        }
+        [ call-next-method ]
+    } cond ;
+
+! Identity:
+! tag(not(untag(x))) = not(x) xor tag-mask
+:: emit-tagged-not ( insn -- )
+    tagged-rep next-vreg-rep :> temp
+    temp insn src>> ##not
+    insn dst>> temp tag-mask get ##xor-imm here ;
+
+M: ##not optimize-insn
+    {
+        {
+            [ dup inert-tag/untag-unary? ]
+            [ [ no-use-conversion ] [ emit-tagged-not ] [ no-def-conversion ] tri ]
+        }
+        [ call-next-method ]
+    } cond ;
index e4114c9249a7f0593f31c0eba17bd4991355ea3e..e1a9ec0d939160575c248575d794f68f93f2c1dc 100644 (file)
@@ -80,7 +80,7 @@ PRIVATE>
 : each-rep ( insn vreg-quot: ( vreg rep -- ) -- )
     [ each-def-rep ] [ each-use-rep ] [ each-temp-rep ] 2tri ; inline
 
-: with-vreg-reps ( ..a cfg vreg-quot: ( ..a vreg rep -- ..b ) -- ..b )
+: with-vreg-reps ( cfg vreg-quot: ( vreg rep -- ) -- )
     '[
         [ basic-block set ] [
             [
index a00f65e0754c91d24469ccf221af56ed6e6ee12c..ef64908f7814c2610d393e6c8dd2b0683f6c5d7e 100644 (file)
@@ -1,7 +1,11 @@
 USING: accessors compiler.cfg compiler.cfg.debugger
 compiler.cfg.instructions compiler.cfg.registers
 compiler.cfg.representations.preferred cpu.architecture kernel
-namespaces tools.test sequences arrays system ;
+namespaces tools.test sequences arrays system literals layouts
+math compiler.constants compiler.cfg.representations.conversion
+compiler.cfg.representations.rewrite
+compiler.cfg.comparisons
+make ;
 IN: compiler.cfg.representations
 
 [ { double-rep double-rep } ] [
@@ -13,12 +17,39 @@ IN: compiler.cfg.representations
 ] unit-test
 
 [ double-rep ] [
-    T{ ##alien-double
+    T{ ##load-memory-imm
        { dst 5 }
-       { src 3 }
+       { base 3 }
+       { offset 0 }
+       { rep double-rep }
     } defs-vreg-rep
 ] unit-test
 
+H{ } clone representations set
+
+3 \ vreg-counter set-global
+
+[
+    {
+        T{ ##allot f 2 16 float 4 }
+        T{ ##store-memory-imm f 1 2 $[ float-offset ] double-rep f }
+    }
+] [
+    [
+        2 1 tagged-rep double-rep emit-conversion
+    ] { } make
+] unit-test
+
+[
+    {
+        T{ ##load-memory-imm f 2 1 $[ float-offset ] double-rep f }
+    }
+] [
+    [
+        2 1 double-rep tagged-rep emit-conversion
+    ] { } make
+] unit-test
+
 : test-representations ( -- )
     cfg new 0 get >>entry dup cfg set select-representations drop ;
 
@@ -50,6 +81,240 @@ V{
 
 [ 1 ] [ 1 get instructions>> [ ##allot? ] count ] unit-test
 
+! Don't dereference the result of a peek
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 1 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##add-float f 2 1 1 }
+    T{ ##replace f 2 D 0 }
+    T{ ##epilogue }
+    T{ ##return }
+} 2 test-bb
+
+V{
+    T{ ##add-float f 3 1 1 }
+    T{ ##replace f 3 D 0 }
+    T{ ##epilogue }
+    T{ ##return }
+} 3 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+
+[ ] [ test-representations ] unit-test
+
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##branch }
+    }
+] [ 1 get instructions>> ] unit-test
+
+! We cannot untag-fixnum the result of a peek if there are usages
+! of it as a tagged-rep
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 1 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##replace f 1 R 0 }
+    T{ ##epilogue }
+    T{ ##return }
+} 2 test-bb
+
+V{
+    T{ ##mul f 2 1 1 }
+    T{ ##replace f 2 D 0 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 4 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+3 { 3 4 } edges
+2 4 edge
+
+[ ] [ test-representations ] unit-test
+
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##branch }
+    }
+] [ 1 get instructions>> ] unit-test
+
+! But its ok to untag-fixnum the result of a peek if all usages use
+! it as int-rep
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 1 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 2 test-bb
+
+V{
+    T{ ##add f 2 1 1 }
+    T{ ##mul f 3 1 1 }
+    T{ ##replace f 2 D 0 }
+    T{ ##replace f 3 D 1 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 4 test-bb
+
+0 1 edge
+1 { 2 3 } edges
+3 { 3 4 } edges
+2 4 edge
+
+3 \ vreg-counter set-global
+
+[ ] [ test-representations ] unit-test
+
+[
+    V{
+        T{ ##peek f 4 D 0 }
+        T{ ##sar-imm f 1 4 $[ tag-bits get ] }
+        T{ ##branch }
+    }
+] [ 1 get instructions>> ] unit-test
+
+! scalar-rep => int-rep conversion
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 1 D 0 }
+    T{ ##peek f 2 D 0 }
+    T{ ##vector>scalar f 3 2 int-4-rep }
+    T{ ##replace f 3 D 0 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 2 test-bb
+
+0 1 edge
+1 2 edge
+
+[ ] [ test-representations ] unit-test
+
+[ t ] [ 1 get instructions>> 4 swap nth ##scalar>integer? ] unit-test
+
+! Test phi node behavior
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##load-integer f 1 1 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##load-integer f 2 2 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##phi f 3 H{ { 1 1 } { 2 2 } } }
+    T{ ##replace f 3 D 0 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 4 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+3 4 edge
+
+[ ] [ test-representations ] unit-test
+
+[ T{ ##load-tagged f 1 $[ 1 tag-fixnum ] } ]
+[ 1 get instructions>> first ]
+unit-test
+
+[ T{ ##load-tagged f 2 $[ 2 tag-fixnum ] } ]
+[ 2 get instructions>> first ]
+unit-test
+
+! ##load-reference corner case
+V{
+    T{ ##prologue }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f 0 D 0 }
+    T{ ##peek f 1 D 1 }
+    T{ ##add f 2 0 1 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##load-reference f 3 f }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##phi f 4 H{ { 1 2 } { 2 3 } } }
+    T{ ##replace f 4 D 0 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##epilogue }
+    T{ ##return }
+} 4 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+3 4 edge
+
+[ ] [ test-representations ] unit-test
+
+! Don't untag the f!
+[ 2 ] [ 2 get instructions>> length ] unit-test
+
 cpu x86.32? [
 
     ! Make sure load-constant is converted into load-double
@@ -60,7 +325,7 @@ cpu x86.32? [
 
     V{
         T{ ##peek f 1 D 0 }
-        T{ ##load-constant f 2 0.5 }
+        T{ ##load-reference f 2 0.5 }
         T{ ##add-float f 3 1 2 }
         T{ ##replace f 3 D 0 }
         T{ ##branch }
@@ -86,21 +351,21 @@ cpu x86.32? [
 
     V{
         T{ ##peek f 1 D 0 }
-        T{ ##compare-imm-branch f 1 2 }
+        T{ ##compare-imm-branch f 1 2 cc= }
     } 1 test-bb
 
     V{
-        T{ ##load-constant f 2 1.5 }
+        T{ ##load-reference f 2 1.5 }
         T{ ##branch }
     } 2 test-bb
 
     V{
-        T{ ##load-constant f 3 2.5 }
+        T{ ##load-reference f 3 2.5 }
         T{ ##branch }
     } 3 test-bb
 
     V{
-        T{ ##phi f 4 }
+        T{ ##phi f 4 H{ { 2 2 } { 3 3 } } }
         T{ ##peek f 5 D 0 }
         T{ ##add-float f 6 4 5 }
         T{ ##replace f 6 D 0 }
@@ -114,9 +379,6 @@ cpu x86.32? [
     test-diamond
     4 5 edge
 
-    2 get 2 2array
-    3 get 3 2array 2array 4 get instructions>> first (>>inputs)
-
     [ ] [ test-representations ] unit-test
 
     [ t ] [ 2 get instructions>> first ##load-double? ] unit-test
@@ -124,4 +386,348 @@ cpu x86.32? [
     [ t ] [ 3 get instructions>> first ##load-double? ] unit-test
 
     [ t ] [ 4 get instructions>> first ##phi? ] unit-test
-] when
\ No newline at end of file
+] when
+
+: test-peephole ( insns -- insns )
+    0 test-bb
+    test-representations
+    0 get instructions>> ;
+
+! Don't convert the def site into anything but tagged-rep since
+! we might lose precision
+5 \ vreg-counter set-global
+
+[ f ] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 1 }
+        T{ ##add-float f 3 0 0 }
+        T{ ##store-memory-imm f 3 2 0 float-rep f }
+        T{ ##store-memory-imm f 3 2 4 float-rep f }
+        T{ ##mul-float f 4 0 0 }
+        T{ ##replace f 4 D 0 }
+    } test-peephole
+    [ ##single>double-float? ] any?
+] unit-test
+
+! Converting a ##load-integer into a ##load-tagged
+[
+    V{
+        T{ ##load-tagged f 1 $[ 100 tag-fixnum ] }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    V{
+        T{ ##load-integer f 1 100 }
+        T{ ##replace f 1 D 0 }
+    } test-peephole
+] unit-test
+
+! Peephole optimization if input to ##shl-imm is tagged
+3 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##sar-imm f 2 1 1 }
+        T{ ##add f 4 2 2 }
+        T{ ##shl-imm f 3 4 $[ tag-bits get ] }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##shl-imm f 2 1 3 }
+        T{ ##add f 3 2 2 }
+        T{ ##replace f 3 D 0 }
+    } test-peephole
+] unit-test
+
+3 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##shl-imm f 2 1 $[ 10 tag-bits get - ] }
+        T{ ##add f 4 2 2 }
+        T{ ##shl-imm f 3 4 $[ tag-bits get ] }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##shl-imm f 2 1 10 }
+        T{ ##add f 3 2 2 }
+        T{ ##replace f 3 D 0 }
+    } test-peephole
+] unit-test
+
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##copy f 2 1 int-rep }
+        T{ ##add f 5 2 2 }
+        T{ ##shl-imm f 3 5 $[ tag-bits get ] }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##shl-imm f 2 1 $[ tag-bits get ] }
+        T{ ##add f 3 2 2 }
+        T{ ##replace f 3 D 0 }
+    } test-peephole
+] unit-test
+
+! Peephole optimization if output of ##shl-imm needs to be tagged
+[
+    V{
+        T{ ##load-integer f 1 100 }
+        T{ ##shl-imm f 2 1 $[ 3 tag-bits get + ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    V{
+        T{ ##load-integer f 1 100 }
+        T{ ##shl-imm f 2 1 3 }
+        T{ ##replace f 2 D 0 }
+    } test-peephole
+] unit-test
+
+! Peephole optimization if both input and output of ##shl-imm
+! needs to be tagged
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 3 }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 3 }
+        T{ ##replace f 1 D 0 }
+    } test-peephole
+] unit-test
+
+6 \ vreg-counter set-global
+
+! Peephole optimization if input to ##sar-imm is tagged
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##sar-imm f 7 1 $[ 3 tag-bits get + ] }
+        T{ ##shl-imm f 2 7 $[ tag-bits get ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##sar-imm f 2 1 3 }
+        T{ ##replace f 2 D 0 }
+    } test-peephole
+] unit-test
+
+! Tag/untag elimination
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##add-imm f 2 1 $[ 100 tag-fixnum ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##add-imm f 2 1 100 }
+        T{ ##replace f 2 D 0 }
+    } test-peephole
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##add f 2 0 1 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##add f 2 0 1 }
+        T{ ##replace f 2 D 0 }
+    } test-peephole
+] unit-test
+
+! Make sure we don't exceed immediate bounds
+cpu x86.64? [
+    4 \ vreg-counter set-global
+
+    [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##sar-imm f 5 0 $[ tag-bits get ] }
+            T{ ##add-imm f 6 5 $[ 30 2^ ] }
+            T{ ##shl-imm f 2 6 $[ tag-bits get ] }
+            T{ ##replace f 2 D 0 }
+        }
+    ] [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##add-imm f 2 0 $[ 30 2^ ] }
+            T{ ##replace f 2 D 0 }
+        } test-peephole
+    ] unit-test
+
+    [
+        V{
+            T{ ##load-integer f 0 100 }
+            T{ ##mul-imm f 7 0 $[ 30 2^ ] }
+            T{ ##shl-imm f 1 7 $[ tag-bits get ] }
+            T{ ##replace f 1 D 0 }
+        }
+    ] [
+        V{
+            T{ ##load-integer f 0 100 }
+            T{ ##mul-imm f 1 0 $[ 30 2^ ] }
+            T{ ##replace f 1 D 0 }
+        } test-peephole
+    ] unit-test
+] when
+
+! Tag/untag elimination for ##mul-imm
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##mul-imm f 1 0 100 }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##mul-imm f 1 0 100 }
+        T{ ##replace f 1 D 0 }
+    } test-peephole
+] unit-test
+
+4 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##sar-imm f 5 1 $[ tag-bits get ] }
+        T{ ##add-imm f 2 5 30 }
+        T{ ##mul-imm f 3 2 $[ 100 tag-fixnum ] }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##add-imm f 2 1 30 }
+        T{ ##mul-imm f 3 2 100 }
+        T{ ##replace f 3 D 0 }
+    } test-peephole
+] unit-test
+
+! Tag/untag elimination for ##compare-integer
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer f 2 0 1 cc= }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer f 2 0 1 cc= }
+        T{ ##replace f 2 D 0 }
+    } test-peephole
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-branch f 0 1 cc= }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-branch f 0 1 cc= }
+    } test-peephole
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-imm-branch f 0 $[ 10 tag-fixnum ] cc= }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-imm-branch f 0 10 cc= }
+    } test-peephole
+] unit-test
+
+! Tag/untag elimination for ##neg
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##neg f 1 0 }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##neg f 1 0 }
+        T{ ##replace f 1 D 0 }
+    } test-peephole
+] unit-test
+
+4 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##peek f 5 D 0 }
+        T{ ##sar-imm f 0 5 $[ tag-bits get ] }
+        T{ ##peek f 6 D 1 }
+        T{ ##sar-imm f 1 6 $[ tag-bits get ] }
+        T{ ##mul f 2 0 1 }
+        T{ ##mul-imm f 3 2 -16 }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##mul f 2 0 1 }
+        T{ ##neg f 3 2 }
+        T{ ##replace f 3 D 0 }
+    } test-peephole
+] unit-test
+
+! Tag/untag elimination for ##not
+2 \ vreg-counter set-global
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##not f 3 0 }
+        T{ ##xor-imm f 1 3 $[ tag-mask get ] }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##not f 1 0 }
+        T{ ##replace f 1 D 0 }
+    } test-peephole
+] unit-test
\ No newline at end of file
index f202dc4c6a3097cb040a16a22508df765ab47404..2160ad26e6e7e2f2fe14aa66fa78013f5d48a9d8 100644 (file)
 ! Copyright (C) 2009, 2010 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel fry accessors sequences assocs sets namespaces
-arrays combinators combinators.short-circuit math make locals
-deques dlists layouts byte-arrays cpu.architecture
-compiler.utilities
-compiler.constants
+USING: combinators
 compiler.cfg
-compiler.cfg.rpo
-compiler.cfg.hats
 compiler.cfg.registers
-compiler.cfg.instructions
-compiler.cfg.def-use
-compiler.cfg.utilities
+compiler.cfg.predecessors
 compiler.cfg.loop-detection
-compiler.cfg.renaming.functor
-compiler.cfg.representations.preferred ;
-FROM: namespaces => set ;
+compiler.cfg.representations.rewrite
+compiler.cfg.representations.peephole
+compiler.cfg.representations.selection
+compiler.cfg.representations.coalescing ;
 IN: compiler.cfg.representations
 
-! Virtual register representation selection.
-
-ERROR: bad-conversion dst src dst-rep src-rep ;
-
-GENERIC: emit-box ( dst src rep -- )
-GENERIC: emit-unbox ( dst src rep -- )
-
-M:: float-rep emit-box ( dst src rep -- )
-    double-rep next-vreg-rep :> temp
-    temp src ##single>double-float
-    dst temp double-rep emit-box ;
-
-M:: float-rep emit-unbox ( dst src rep -- )
-    double-rep next-vreg-rep :> temp
-    temp src double-rep emit-unbox
-    dst temp ##double>single-float ;
-
-M: double-rep emit-box
-    drop
-    [ drop 16 float int-rep next-vreg-rep ##allot ]
-    [ float-offset swap ##set-alien-double ]
-    2bi ;
-
-M: double-rep emit-unbox
-    drop float-offset ##alien-double ;
-
-M:: vector-rep emit-box ( dst src rep -- )
-    int-rep next-vreg-rep :> temp
-    dst 16 2 cells + byte-array int-rep next-vreg-rep ##allot
-    temp 16 tag-fixnum ##load-immediate
-    temp dst 1 byte-array type-number ##set-slot-imm
-    dst byte-array-offset src rep ##set-alien-vector ;
-
-M: vector-rep emit-unbox
-    [ byte-array-offset ] dip ##alien-vector ;
-
-M:: scalar-rep emit-box ( dst src rep -- )
-    int-rep next-vreg-rep :> temp
-    temp src rep ##scalar>integer
-    dst temp tag-bits get ##shl-imm ;
-
-M:: scalar-rep emit-unbox ( dst src rep -- )
-    int-rep next-vreg-rep :> temp
-    temp src tag-bits get ##sar-imm
-    dst temp rep ##integer>scalar ;
-
-: emit-conversion ( dst src dst-rep src-rep -- )
-    {
-        { [ 2dup eq? ] [ drop ##copy ] }
-        { [ dup int-rep eq? ] [ drop emit-unbox ] }
-        { [ over int-rep eq? ] [ nip emit-box ] }
-        [
-            2dup 2array {
-                { { double-rep float-rep } [ 2drop ##single>double-float ] }
-                { { float-rep double-rep } [ 2drop ##double>single-float ] }
-                ! Punning SIMD vector types? Naughty naughty! But
-                ! it is allowed... otherwise bail out.
-                [
-                    drop 2dup [ reg-class-of ] bi@ eq?
-                    [ drop ##copy ] [ bad-conversion ] if
-                ]
-            } case
-        ]
-    } cond ;
-
-<PRIVATE
-
-! For every vreg, compute possible representations.
-SYMBOL: possibilities
-
-: possible ( vreg -- reps ) possibilities get at ;
-
-: compute-possibilities ( cfg -- )
-    H{ } clone [ '[ swap _ adjoin-at ] with-vreg-reps ] keep
-    [ members ] assoc-map possibilities set ;
-
-! Compute vregs which must remain tagged for their lifetime.
-SYMBOL: always-boxed
-
-:: (compute-always-boxed) ( vreg rep assoc -- )
-    rep int-rep eq? [
-        int-rep vreg assoc set-at
-    ] when ;
-
-: compute-always-boxed ( cfg -- assoc )
-    H{ } clone [
-        '[
-            [
-                dup [ ##load-reference? ] [ ##load-constant? ] bi or
-                [ drop ] [ [ _ (compute-always-boxed) ] each-def-rep ] if
-            ] each-non-phi
-        ] each-basic-block
-    ] keep ;
-
-! For every vreg, compute the cost of keeping it in every possible
-! representation.
-
-! Cost map maps vreg to representation to cost.
-SYMBOL: costs
-
-: init-costs ( -- )
-    possibilities get [ drop H{ } clone ] assoc-map costs set ;
-
-: record-possibility ( rep vreg -- )
-    costs get at [ 0 or ] change-at ;
-
-: increase-cost ( rep vreg -- )
-    ! Increase cost of keeping vreg in rep, making a choice of rep less
-    ! likely.
-    costs get at [ 0 or basic-block get loop-nesting-at 1 + + ] change-at ;
-
-: maybe-increase-cost ( possible vreg preferred -- )
-    pick eq? [ record-possibility ] [ increase-cost ] if ;
-
-: representation-cost ( vreg preferred -- )
-    ! 'preferred' is a representation that the instruction can accept with no cost.
-    ! So, for each representation that's not preferred, increase the cost of keeping
-    ! the vreg in that representation.
-    [ drop possible ]
-    [ '[ _ _ maybe-increase-cost ] ]
-    2bi each ;
-
-GENERIC: compute-insn-costs ( insn -- )
-
-M: ##load-constant compute-insn-costs
-    ! There's no cost to unboxing the result of a ##load-constant
-    drop ;
-
-M: insn compute-insn-costs [ representation-cost ] each-rep ;
-
-: compute-costs ( cfg -- costs )
-    init-costs
-    [
-        [ basic-block set ]
-        [
-            [
-                compute-insn-costs
-            ] each-non-phi
-        ] bi
-    ] each-basic-block
-    costs get ;
-
-! For every vreg, compute preferred representation, that minimizes costs.
-: minimize-costs ( costs -- representations )
-    [ nip assoc-empty? not ] assoc-filter
-    [ >alist alist-min first ] assoc-map ;
-
-: compute-representations ( cfg -- )
-    [ compute-costs minimize-costs ]
-    [ compute-always-boxed ]
-    bi assoc-union
-    representations set ;
-
-! PHI nodes require special treatment
-! If the output of a phi instruction is only used as the input to another
-! phi instruction, then we want to use the same representation for both
-! if possible.
-SYMBOL: phis
-
-: collect-phis ( cfg -- )
-    H{ } clone phis set
-    [
-        phis get
-        '[ [ inputs>> values ] [ dst>> ] bi _ set-at ] each-phi
-    ] each-basic-block ;
-
-SYMBOL: work-list
-
-: add-to-work-list ( vregs -- )
-    work-list get push-all-front ;
-
-: rep-assigned ( vregs -- vregs' )
-    representations get '[ _ key? ] filter ;
-
-: rep-not-assigned ( vregs -- vregs' )
-    representations get '[ _ key? not ] filter ;
-
-: add-ready-phis ( -- )
-    phis get keys rep-assigned add-to-work-list ;
-
-: process-phi ( dst -- )
-    ! If dst = phi(src1,src2,...) and dst's representation has been
-    ! determined, assign that representation to each one of src1,...
-    ! that does not have a representation yet, and process those, too.
-    dup phis get at* [
-        [ rep-of ] [ rep-not-assigned ] bi*
-        [ [ set-rep-of ] with each ] [ add-to-work-list ] bi
-    ] [ 2drop ] if ;
-
-: remaining-phis ( -- )
-    phis get keys rep-not-assigned { } assert-sequence= ;
-
-: process-phis ( -- )
-    <hashed-dlist> work-list set
-    add-ready-phis
-    work-list get [ process-phi ] slurp-deque
-    remaining-phis ;
-
-: compute-phi-representations ( cfg -- )
-    collect-phis process-phis ;
-
-! Insert conversions. This introduces new temporaries, so we need
-! to rename opearands too.
-
-! Mapping from vreg,rep pairs to vregs
-SYMBOL: alternatives
-
-:: emit-def-conversion ( dst preferred required -- new-dst' )
-    ! If an instruction defines a register with representation 'required',
-    ! but the register has preferred representation 'preferred', then
-    ! we rename the instruction's definition to a new register, which
-    ! becomes the input of a conversion instruction.
-    dst required next-vreg-rep [ preferred required emit-conversion ] keep ;
-
-:: emit-use-conversion ( src preferred required -- new-src' )
-    ! If an instruction uses a register with representation 'required',
-    ! but the register has preferred representation 'preferred', then
-    ! we rename the instruction's input to a new register, which
-    ! becomes the output of a conversion instruction.
-    preferred required eq? [ src ] [
-        src required alternatives get [
-            required next-vreg-rep :> new-src
-            [ new-src ] 2dip preferred emit-conversion
-            new-src
-        ] 2cache
-    ] if ;
-
-SYMBOLS: renaming-set needs-renaming? ;
-
-: init-renaming-set ( -- )
-    needs-renaming? off
-    V{ } clone renaming-set set ;
-
-: no-renaming ( vreg -- )
-    dup 2array renaming-set get push ;
-
-: record-renaming ( from to -- )
-    2array renaming-set get push needs-renaming? on ;
-
-:: (compute-renaming-set) ( vreg required quot: ( vreg preferred required -- new-vreg ) -- )
-    vreg rep-of :> preferred
-    preferred required eq?
-    [ vreg no-renaming ]
-    [ vreg vreg preferred required quot call record-renaming ] if ; inline
-
-: compute-renaming-set ( insn -- )
-    ! temp vregs don't need conversions since they're always in their
-    ! preferred representation
-    init-renaming-set
-    [ [ [ emit-use-conversion ] (compute-renaming-set) ] each-use-rep ]
-    [ , ]
-    [ [ [ emit-def-conversion ] (compute-renaming-set) ] each-def-rep ]
-    tri ;
-
-: converted-value ( vreg -- vreg' )
-    renaming-set get pop first2 [ assert= ] dip ;
-
-RENAMING: convert [ converted-value ] [ converted-value ] [ ]
-
-: perform-renaming ( insn -- )
-    needs-renaming? get [
-        renaming-set get reverse! drop
-        [ convert-insn-uses ] [ convert-insn-defs ] bi
-        renaming-set get length 0 assert=
-    ] [ drop ] if ;
-
-GENERIC: conversions-for-insn ( insn -- )
-
-M: ##phi conversions-for-insn , ;
-
-! When a float is unboxed, we replace the ##load-constant with a ##load-double
-! if the architecture supports it
-: convert-to-load-double? ( insn -- ? )
-    {
-        [ drop load-double? ]
-        [ dst>> rep-of double-rep? ]
-        [ obj>> float? ]
-    } 1&& ;
-
-! When a literal zeroes/ones vector is unboxed, we replace the ##load-reference
-! with a ##zero-vector or ##fill-vector instruction since this is more efficient.
-: convert-to-zero-vector? ( insn -- ? )
-    {
-        [ dst>> rep-of vector-rep? ]
-        [ obj>> B{ 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 } = ]
-    } 1&& ;
-
-: convert-to-fill-vector? ( insn -- ? )
-    {
-        [ dst>> rep-of vector-rep? ]
-        [ obj>> B{ 255 255 255 255  255 255 255 255  255 255 255 255  255 255 255 255 } = ]
-    } 1&& ;
-
-: (convert-to-load-double) ( insn -- dst val )
-    [ dst>> ] [ obj>> ] bi ; inline
-
-: (convert-to-zero/fill-vector) ( insn -- dst rep )
-    dst>> dup rep-of ; inline
-
-: conversions-for-load-insn ( insn -- ?insn )
-    {
-        {
-            [ dup convert-to-load-double? ]
-            [ (convert-to-load-double) ##load-double f ]
-        }
-        {
-            [ dup convert-to-zero-vector? ]
-            [ (convert-to-zero/fill-vector) ##zero-vector f ]
-        }
-        {
-            [ dup convert-to-fill-vector? ]
-            [ (convert-to-zero/fill-vector) ##fill-vector f ]
-        }
-        [ ]
-    } cond ;
-
-M: ##load-reference conversions-for-insn
-    conversions-for-load-insn [ call-next-method ] when* ;
-
-M: ##load-constant conversions-for-insn
-    conversions-for-load-insn [ call-next-method ] when* ;
-
-M: vreg-insn conversions-for-insn
-    [ compute-renaming-set ] [ perform-renaming ] bi ;
-
-M: insn conversions-for-insn , ;
-
-: conversions-for-block ( bb -- )
-    dup kill-block? [ drop ] [
-        [
-            [
-                H{ } clone alternatives set
-                [ conversions-for-insn ] each
-            ] V{ } make
-        ] change-instructions drop
-    ] if ;
-
-: insert-conversions ( cfg -- )
-    [ conversions-for-block ] each-basic-block ;
-
-PRIVATE>
+! Virtual register representation selection. This is where
+! decisions about integer tagging and float and vector boxing
+! are made. The appropriate conversion operations inserted
+! after a cost analysis.
 
 : select-representations ( cfg -- cfg' )
     needs-loops
+    needs-predecessors
 
     {
+        [ compute-components ]
         [ compute-possibilities ]
         [ compute-representations ]
-        [ compute-phi-representations ]
         [ insert-conversions ]
         [ ]
-    } cleave
-    representations get cfg get (>>reps) ;
+    } cleave ;
diff --git a/basis/compiler/cfg/representations/rewrite/authors.txt b/basis/compiler/cfg/representations/rewrite/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/representations/rewrite/rewrite.factor b/basis/compiler/cfg/representations/rewrite/rewrite.factor
new file mode 100644 (file)
index 0000000..b0da0d1
--- /dev/null
@@ -0,0 +1,104 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs combinators
+combinators.short-circuit layouts kernel locals make math
+namespaces sequences
+compiler.cfg.instructions
+compiler.cfg.registers
+compiler.cfg.renaming.functor
+compiler.cfg.representations.conversion
+compiler.cfg.representations.preferred
+compiler.cfg.rpo
+compiler.cfg.utilities
+cpu.architecture ;
+IN: compiler.cfg.representations.rewrite
+
+! Insert conversions. This introduces new temporaries, so we need
+! to rename opearands too.
+
+! Mapping from vreg,rep pairs to vregs
+SYMBOL: alternatives
+
+:: (emit-def-conversion) ( dst preferred required -- new-dst' )
+    ! If an instruction defines a register with representation 'required',
+    ! but the register has preferred representation 'preferred', then
+    ! we rename the instruction's definition to a new register, which
+    ! becomes the input of a conversion instruction.
+    dst required next-vreg-rep [ preferred required emit-conversion ] keep ;
+
+:: (emit-use-conversion) ( src preferred required -- new-src' )
+    ! If an instruction uses a register with representation 'required',
+    ! but the register has preferred representation 'preferred', then
+    ! we rename the instruction's input to a new register, which
+    ! becomes the output of a conversion instruction.
+    preferred required eq? [ src ] [
+        src required alternatives get [
+            required next-vreg-rep :> new-src
+            [ new-src ] 2dip preferred emit-conversion
+            new-src
+        ] 2cache
+    ] if ;
+
+SYMBOLS: renaming-set needs-renaming? ;
+
+: init-renaming-set ( -- )
+    needs-renaming? off
+    renaming-set get delete-all ;
+
+: no-renaming ( vreg -- )
+    dup 2array renaming-set get push ;
+
+: record-renaming ( from to -- )
+    2array renaming-set get push needs-renaming? on ;
+
+:: (compute-renaming-set) ( vreg required quot: ( vreg preferred required -- new-vreg ) -- )
+    vreg rep-of :> preferred
+    preferred required eq?
+    [ vreg no-renaming ]
+    [ vreg vreg preferred required quot call record-renaming ] if ; inline
+
+: emit-use-conversion ( insn -- )
+    [ [ (emit-use-conversion) ] (compute-renaming-set) ] each-use-rep ;
+
+: no-use-conversion ( insn -- )
+    [ drop no-renaming ] each-use-rep ;
+
+: emit-def-conversion ( insn -- )
+    [ [ (emit-def-conversion) ] (compute-renaming-set) ] each-def-rep ;
+
+: no-def-conversion ( insn -- )
+    [ drop no-renaming ] each-def-rep ;
+
+: converted-value ( vreg -- vreg' )
+    renaming-set get pop first2 [ assert= ] dip ;
+
+RENAMING: convert [ converted-value ] [ converted-value ] [ ]
+
+: perform-renaming ( insn -- )
+    needs-renaming? get [
+        renaming-set get reverse! drop
+        [ convert-insn-uses ] [ convert-insn-defs ] bi
+        renaming-set get length 0 assert=
+    ] [ drop ] if ;
+
+GENERIC: conversions-for-insn ( insn -- )
+
+M: ##phi conversions-for-insn , ;
+
+M: ##copy conversions-for-insn , ;
+
+M: insn conversions-for-insn , ;
+
+: conversions-for-block ( bb -- )
+    dup kill-block? [ drop ] [
+        [
+            [
+                H{ } clone alternatives set
+                [ conversions-for-insn ] each
+            ] V{ } make
+        ] change-instructions drop
+    ] if ;
+
+: insert-conversions ( cfg -- )
+    V{ } clone renaming-set set
+    [ conversions-for-block ] each-basic-block ;
diff --git a/basis/compiler/cfg/representations/selection/authors.txt b/basis/compiler/cfg/representations/selection/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/representations/selection/selection.factor b/basis/compiler/cfg/representations/selection/selection.factor
new file mode 100644 (file)
index 0000000..6cabe27
--- /dev/null
@@ -0,0 +1,150 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs byte-arrays combinators
+disjoint-sets fry kernel locals math namespaces sequences sets
+compiler.cfg
+compiler.cfg.instructions
+compiler.cfg.loop-detection
+compiler.cfg.registers
+compiler.cfg.representations.preferred
+compiler.cfg.representations.coalescing
+compiler.cfg.rpo
+compiler.cfg.utilities
+compiler.utilities
+cpu.architecture ;
+FROM: namespaces => set ;
+IN: compiler.cfg.representations.selection
+
+! vregs which must be tagged at the definition site because
+! there is at least one usage that is not int-rep. If all usages
+! are int-rep it is safe to untag at the definition site.
+SYMBOL: tagged-vregs
+
+SYMBOL: vreg-reps
+
+: handle-def ( vreg rep -- )
+    swap vreg>scc vreg-reps get
+    [ [ intersect ] when* ] change-at ;
+
+: handle-use ( vreg rep -- )
+    int-rep eq? [ drop ] [ vreg>scc tagged-vregs get adjoin ] if ;
+
+GENERIC: (collect-vreg-reps) ( insn -- )
+
+M: ##load-reference (collect-vreg-reps)
+    [ dst>> ] [ obj>> ] bi {
+        { [ dup float? ] [ drop { float-rep double-rep } ] }
+        { [ dup byte-array? ] [ drop vector-reps ] }
+        [ drop { } ]
+    } cond handle-def ;
+
+M: vreg-insn (collect-vreg-reps)
+    [ [ handle-use ] each-use-rep ]
+    [ [ 1array handle-def ] each-def-rep ]
+    [ [ 1array handle-def ] each-temp-rep ]
+    tri ;
+
+M: insn (collect-vreg-reps) drop ;
+
+: collect-vreg-reps ( cfg -- )
+    H{ } clone vreg-reps set
+    HS{ } clone tagged-vregs set
+    [ [ (collect-vreg-reps) ] each-non-phi ] each-basic-block ;
+
+SYMBOL: possibilities
+
+: possible-reps ( vreg reps -- vreg reps )
+    { tagged-rep } union
+    2dup [ tagged-vregs get in? not ] [ { tagged-rep } = ] bi* and
+    [ drop { tagged-rep int-rep } ] [ ] if ;
+
+: compute-possibilities ( cfg -- )
+    collect-vreg-reps
+    vreg-reps get [ possible-reps ] assoc-map possibilities set ;
+
+! For every vreg, compute the cost of keeping it in every possible
+! representation.
+
+! Cost map maps vreg to representation to cost.
+SYMBOL: costs
+
+: init-costs ( -- )
+    ! Initialize cost as 0 for each possibility.
+    possibilities get [ [ 0 ] H{ } map>assoc ] assoc-map costs set ;
+
+: 10^ ( n -- x ) 10 <repetition> product ;
+
+: increase-cost ( rep scc factor -- )
+    ! Increase cost of keeping vreg in rep, making a choice of rep less
+    ! likely. If the rep is not in the cost alist, it means this
+    ! representation is prohibited.
+    [ costs get at 2dup key? ] dip
+    '[ [ current-loop-nesting 10^ _ * + ] change-at ] [ 2drop ] if ;
+
+:: increase-costs ( vreg preferred factor -- )
+    vreg vreg>scc :> scc
+    scc possibilities get at [
+        dup preferred eq? [ drop ] [ scc factor increase-cost ] if
+    ] each ; inline
+
+UNION: inert-tag-untag-insn
+##add
+##sub
+##and
+##or
+##xor
+##min
+##max ;
+
+UNION: inert-arithmetic-tag-untag-insn
+##add-imm
+##sub-imm ;
+
+UNION: inert-bitwise-tag-untag-insn
+##and-imm
+##or-imm
+##xor-imm ;
+
+GENERIC: has-peephole-opts? ( insn -- ? )
+
+M: insn has-peephole-opts? drop f ;
+M: ##load-integer has-peephole-opts? drop t ;
+M: ##load-reference has-peephole-opts? drop t ;
+M: ##neg has-peephole-opts? drop t ;
+M: ##not has-peephole-opts? drop t ;
+M: inert-tag-untag-insn has-peephole-opts? drop t ;
+M: inert-arithmetic-tag-untag-insn has-peephole-opts? drop t ;
+M: inert-bitwise-tag-untag-insn has-peephole-opts? drop t ;
+M: ##mul-imm has-peephole-opts? drop t ;
+M: ##shl-imm has-peephole-opts? drop t ;
+M: ##shr-imm has-peephole-opts? drop t ;
+M: ##sar-imm has-peephole-opts? drop t ;
+M: ##compare-integer-imm has-peephole-opts? drop t ;
+M: ##compare-integer has-peephole-opts? drop t ;
+M: ##compare-integer-imm-branch has-peephole-opts? drop t ;
+M: ##compare-integer-branch has-peephole-opts? drop t ;
+
+GENERIC: compute-insn-costs ( insn -- )
+
+M: insn compute-insn-costs drop ;
+
+M: vreg-insn compute-insn-costs
+    dup has-peephole-opts? 2 5 ? '[ _ increase-costs ] each-rep ;
+
+: compute-costs ( cfg -- )
+    init-costs
+    [
+        [ basic-block set ]
+        [ [ compute-insn-costs ] each-non-phi ] bi
+    ] each-basic-block ;
+
+! For every vreg, compute preferred representation, that minimizes costs.
+: minimize-costs ( costs -- representations )
+    [ nip assoc-empty? not ] assoc-filter
+    [ >alist alist-min first ] assoc-map ;
+
+: compute-representations ( cfg -- )
+    compute-costs costs get minimize-costs
+    [ components get [ disjoint-set-members ] keep ] dip
+    '[ dup _ representative _ at ] H{ } map>assoc
+    representations set ;
index 6e09d9885f32078a8cc74750d3f8647a0e5ed706..a76beca1811d045d331b2c877dd5e8c5a9dbaa13 100644 (file)
@@ -39,8 +39,8 @@ SYMBOL: visited
     [ drop basic-block set ]
     [ change-instructions drop ] 2bi ; inline
 
-: local-optimization ( ... cfg quot: ( ... insns -- ... insns' ) -- ... cfg' )
-    dupd '[ _ optimize-basic-block ] each-basic-block ; inline
+: simple-optimization ( ... cfg quot: ( ... insns -- ... insns' ) -- ... )
+    '[ _ optimize-basic-block ] each-basic-block ; inline
 
 : needs-post-order ( cfg -- cfg' )
     dup post-order drop ;
index c7b6db06715000941bc0255c73fd769d382ab4df..e5edd7cdffb37fa296b9d28d0139df313e8ba2e1 100644 (file)
@@ -10,6 +10,7 @@ IN: compiler.cfg.save-contexts
 : needs-save-context? ( insns -- ? )
     [
         {
+            [ ##call-gc? ]
             [ ##unary-float-function? ]
             [ ##binary-float-function? ]
             [ ##alien-invoke? ]
@@ -20,8 +21,8 @@ IN: compiler.cfg.save-contexts
 
 : insert-save-context ( bb -- )
     dup instructions>> dup needs-save-context? [
-        int-rep next-vreg-rep
-        int-rep next-vreg-rep
+        tagged-rep next-vreg-rep
+        tagged-rep next-vreg-rep
         \ ##save-context new-insn prefix
         >>instructions drop
     ] [ 2drop ] if ;
diff --git a/basis/compiler/cfg/scheduling/scheduling-tests.factor b/basis/compiler/cfg/scheduling/scheduling-tests.factor
new file mode 100644 (file)
index 0000000..fd61790
--- /dev/null
@@ -0,0 +1,11 @@
+USING: compiler.cfg.scheduling vocabs.loader namespaces tools.test ;
+IN: compiler.cfg.scheduling.tests
+
+! Recompile compiler.cfg.scheduling with extra tests,
+! and see if any errors come up. Back when there were
+! errors of this kind, they always surfaced this way.
+
+t check-scheduling? [
+    [ ] [ "compiler.cfg.scheduling" reload ] unit-test
+    [ ] [ "compiler.cfg.dependence" reload ] unit-test
+] with-variable
diff --git a/basis/compiler/cfg/scheduling/scheduling.factor b/basis/compiler/cfg/scheduling/scheduling.factor
new file mode 100644 (file)
index 0000000..1c6c698
--- /dev/null
@@ -0,0 +1,134 @@
+! Copyright (C) 2009, 2010 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs compiler.cfg.def-use
+compiler.cfg.dependence compiler.cfg.instructions
+compiler.cfg.liveness compiler.cfg.rpo cpu.architecture fry
+kernel locals make math namespaces sequences sets ;
+IN: compiler.cfg.scheduling
+
+! Instruction scheduling to reduce register pressure, from:
+! "Register-sensitive selection, duplication, and
+!  sequencing of instructions"
+! by Vivek Sarkar, et al.
+! http://portal.acm.org/citation.cfm?id=377849
+
+ERROR: bad-delete-at key assoc ;
+
+: check-delete-at ( key assoc -- )
+    2dup key? [ delete-at ] [ bad-delete-at ] if ;
+
+: set-parent-indices ( node -- )
+    children>> building get length
+    '[ _ >>parent-index drop ] each ;
+
+: remove-node ( node -- )
+    [ follows>> members ] keep
+    '[ [ precedes>> _ swap check-delete-at ] each ]
+    [ [ ready? ] filter roots get push-all ] bi ;
+
+: score ( insn -- n )
+    [ parent-index>> ] [ registers>> neg ] [ insn>> insn#>> ] tri 3array ;
+
+: pull-out-nth ( n seq -- elt )
+    [ nth ] [ remove-nth! drop ] 2bi ;
+
+: select ( vector quot -- elt )
+    ! This could be sped up by a constant factor
+    [ dup <enum> ] dip '[ _ call( insn -- score ) ] assoc-map
+    dup values supremum '[ nip _ = ] assoc-find
+    2drop swap pull-out-nth ; inline
+
+: select-instruction ( -- insn/f )
+    roots get [ f ] [
+        [ score ] select 
+        [ insn>> ]
+        [ set-parent-indices ]
+        [ remove-node ] tri
+    ] if-empty ;
+
+: (reorder) ( -- )
+    select-instruction [
+        , (reorder)
+    ] when* ;
+
+: cut-by ( seq quot -- before after )
+    dupd find drop [ cut ] [ f ] if* ; inline
+
+UNION: initial-insn
+    ##phi ##inc-d ##inc-r ;
+
+: split-3-ways ( insns -- first middle last )
+    [ initial-insn? not ] cut-by unclip-last ;
+
+: reorder ( insns -- insns' )
+    split-3-ways [
+        build-dependence-graph
+        build-fan-in-trees
+        [ (reorder) ] V{ } make reverse
+    ] dip suffix append ;
+
+ERROR: not-all-instructions-were-scheduled old-bb new-bb ;
+
+SYMBOL: check-scheduling?
+f check-scheduling? set-global
+
+:: check-instructions ( new-bb old-bb -- )
+    new-bb old-bb [ instructions>> ] bi@
+    [ [ length ] bi@ = ] [ [ unique ] bi@ = ] 2bi and
+    [ old-bb new-bb not-all-instructions-were-scheduled ] unless ;
+
+ERROR: definition-after-usage vreg old-bb new-bb ;
+
+:: check-usages ( new-bb old-bb -- )
+    HS{ } clone :> useds
+    new-bb instructions>> split-3-ways drop nip
+    [| insn |
+        insn uses-vregs [ useds adjoin ] each
+        insn defs-vreg :> def-reg
+        def-reg useds in?
+        [ def-reg old-bb new-bb definition-after-usage ] when
+    ] each ;
+
+: check-scheduling ( new-bb old-bb -- )
+    [ check-instructions ] [ check-usages ] 2bi ;
+
+: with-scheduling-check ( bb quot: ( bb -- ) -- )
+    check-scheduling? get [
+        over dup clone
+        [ call( bb -- ) ] 2dip
+        check-scheduling
+    ] [
+        call( bb -- )
+    ] if ; inline
+
+: number-insns ( insns -- )
+    [ >>insn# drop ] each-index ;
+
+: clear-numbers ( insns -- )
+    [ f >>insn# drop ] each ;
+
+: schedule-block ( bb -- )
+    [
+        [
+            [ number-insns ]
+            [ reorder ]
+            [ clear-numbers ] tri
+        ] change-instructions drop
+    ] with-scheduling-check ;
+
+! Really, instruction scheduling should be aware that there are
+! multiple types of registers, but this number is just used
+! to decide whether to schedule instructions
+: num-registers ( -- x ) int-regs machine-registers at length ;
+
+: might-spill? ( bb -- ? )
+    [ live-in assoc-size ]
+    [ instructions>> [ defs-vreg ] count ] bi
+    + num-registers >= ;
+
+: schedule-instructions ( cfg -- cfg' )
+    dup [
+        dup might-spill?
+        [ schedule-block ]
+        [ drop ] if
+    ] each-basic-block ;
index 3d743176b139338df8a6ec33c432c3a5f5d03f35..54b02b74509c3e98eb7b5d0d89a1f35f962bc52c 100644 (file)
@@ -13,19 +13,19 @@ IN: compiler.cfg.ssa.construction.tests
 reset-counters
 
 V{
-    T{ ##load-immediate f 1 100 }
+    T{ ##load-integer f 1 100 }
     T{ ##add-imm f 2 1 50 }
     T{ ##add-imm f 2 2 10 }
     T{ ##branch }
 } 0 test-bb
 
 V{
-    T{ ##load-immediate f 3 3 }
+    T{ ##load-integer f 3 3 }
     T{ ##branch }
 } 1 test-bb
 
 V{
-    T{ ##load-immediate f 3 4 }
+    T{ ##load-integer f 3 4 }
     T{ ##branch }
 } 2 test-bb
 
@@ -48,7 +48,7 @@ V{
 
 [
     V{
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add-imm f 2 1 50 }
         T{ ##add-imm f 3 2 10 }
         T{ ##branch }
@@ -57,14 +57,14 @@ V{
 
 [
     V{
-        T{ ##load-immediate f 4 3 }
+        T{ ##load-integer f 4 3 }
         T{ ##branch }
     }
 ] [ 1 get instructions>> ] unit-test
 
 [
     V{
-        T{ ##load-immediate f 5 4 }
+        T{ ##load-integer f 5 4 }
         T{ ##branch }
     }
 ] [ 2 get instructions>> ] unit-test
index d58cebac654d41c1b001d3f70d8f26ea6d10457d..06ae6767cae9e7f5e7471a7b1b261344f31048fa 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs kernel locals fry sequences
 cpu.architecture
@@ -6,8 +6,7 @@ compiler.cfg.rpo
 compiler.cfg.def-use
 compiler.cfg.utilities
 compiler.cfg.registers
-compiler.cfg.instructions
-compiler.cfg.representations ;
+compiler.cfg.instructions ;
 IN: compiler.cfg.ssa.cssa
 
 ! Convert SSA to conventional SSA. This pass runs after representation
@@ -24,7 +23,7 @@ IN: compiler.cfg.ssa.cssa
 :: insert-copy ( bb src rep -- bb dst )
     bb src insert-copy? [
         rep next-vreg-rep :> dst
-        bb [ dst src rep src rep-of emit-conversion ] add-instructions
+        bb [ dst src rep ##copy ] add-instructions
         bb dst
     ] [ bb src ] if ;
 
index 8b766c8114330bd542f4dd3584b56885ea07ca2e..ede012eb2fe88b485c16952e5c584efde0bc7332 100644 (file)
@@ -1,11 +1,11 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs fry kernel namespaces
 sequences sequences.deep
 sets vectors
+cpu.architecture
 compiler.cfg.rpo
 compiler.cfg.def-use
-compiler.cfg.renaming
 compiler.cfg.registers
 compiler.cfg.dominance
 compiler.cfg.instructions
@@ -18,7 +18,20 @@ compiler.utilities ;
 FROM: namespaces => set ;
 IN: compiler.cfg.ssa.destruction
 
-! Maps vregs to leaders.
+! Because of the design of the register allocator, this pass
+! has three peculiar properties.
+!
+! 1) Instead of renaming vreg usages in the CFG, a map from
+! vregs to canonical representatives is computed. This allows
+! the register allocator to use the original SSA names to get
+! reaching definitions.
+! 2) Useless ##copy instructions, and all ##phi instructions,
+! are eliminated, so the register allocator does not have to
+! remove any redundant operations.
+! 3) A side effect of running this pass is that SSA liveness
+! information is computed, so the register allocator does not
+! need to compute it again.
+
 SYMBOL: leader-map
 
 : leader ( vreg -- vreg' ) leader-map get compress-path ;
@@ -28,12 +41,15 @@ SYMBOL: class-element-map
 
 : class-elements ( vreg -- elts ) class-element-map get at ;
 
+<PRIVATE
+
 ! Sequence of vreg pairs
 SYMBOL: copies
 
 : init-coalescing ( -- )
-    H{ } clone leader-map set
-    H{ } clone class-element-map set
+    defs get keys
+    [ [ dup ] H{ } map>assoc leader-map set ]
+    [ [ dup 1vector ] H{ } map>assoc class-element-map set ] bi
     V{ } clone copies set ;
 
 : classes-interfere? ( vreg1 vreg2 -- ? )
@@ -56,25 +72,27 @@ SYMBOL: copies
         2bi
     ] if ;
 
-: introduce-vreg ( vreg -- )
-    [ leader-map get conjoin ]
-    [ [ 1vector ] keep class-element-map get set-at ] bi ;
-
 GENERIC: prepare-insn ( insn -- )
 
 : try-to-coalesce ( dst src -- ) 2array copies get push ;
 
 M: insn prepare-insn
-    [ defs-vreg ] [ uses-vregs ] bi
-    2dup empty? not and [
-        first 
-        2dup [ rep-of ] bi@ eq?
-        [ try-to-coalesce ] [ 2drop ] if
-    ] [ 2drop ] if ;
+    [ temp-vregs [ leader-map get conjoin ] each ]
+    [
+        [ defs-vreg ] [ uses-vregs ] bi
+        2dup empty? not and [
+            first
+            2dup [ rep-of reg-class-of ] bi@ eq?
+            [ try-to-coalesce ] [ 2drop ] if
+        ] [ 2drop ] if
+    ] bi ;
 
 M: ##copy prepare-insn
     [ dst>> ] [ src>> ] bi try-to-coalesce ;
 
+M: ##tagged>integer prepare-insn
+    [ dst>> ] [ src>> ] bi eliminate-copy ;
+
 M: ##phi prepare-insn
     [ dst>> ] [ inputs>> values ] bi
     [ eliminate-copy ] with each ;
@@ -84,7 +102,6 @@ M: ##phi prepare-insn
 
 : prepare-coalescing ( cfg -- )
     init-coalescing
-    defs get keys [ introduce-vreg ] each
     [ prepare-block ] each-basic-block ;
 
 : process-copies ( -- )
@@ -93,26 +110,31 @@ M: ##phi prepare-insn
         [ 2drop ] [ eliminate-copy ] if
     ] assoc-each ;
 
-: useless-copy? ( ##copy -- ? )
-    dup ##copy? [ [ dst>> ] [ src>> ] bi eq? ] [ drop f ] if ;
+GENERIC: useful-insn? ( insn -- ? )
 
-: perform-renaming ( cfg -- )
-    leader-map get keys [ dup leader ] H{ } map>assoc renamings set
-    [
-        instructions>> [
-            [ rename-insn-defs ]
-            [ rename-insn-uses ]
-            [ [ useless-copy? ] [ ##phi? ] bi or not ] tri
-        ] filter! drop
-    ] each-basic-block ;
+: useful-copy? ( insn -- ? )
+    [ dst>> leader ] [ src>> leader ] bi eq? not ; inline
+
+M: ##copy useful-insn? useful-copy? ;
+
+M: ##tagged>integer useful-insn? useful-copy? ;
+
+M: ##phi useful-insn? drop f ;
+
+M: insn useful-insn? drop t ;
+
+: cleanup-cfg ( cfg -- )
+    [ [ useful-insn? ] filter! ] simple-optimization ;
+
+PRIVATE>
 
 : destruct-ssa ( cfg -- cfg' )
     needs-dominance
 
     dup construct-cssa
     dup compute-defs
-    compute-ssa-live-sets
+    dup compute-ssa-live-sets
     dup compute-live-ranges
     dup prepare-coalescing
     process-copies
-    dup perform-renaming ;
+    dup cleanup-cfg ;
index 2f13331024c3a957baff7e1e1736c5124d9642d8..c48ae4ad58b1aca61cc64a3a5676fce30f999486 100644 (file)
@@ -9,7 +9,7 @@ IN: compiler.cfg.ssa.interference.tests
 
 : test-interference ( -- )
     cfg new 0 get >>entry
-    compute-ssa-live-sets
+    dup compute-ssa-live-sets
     dup compute-defs
     compute-live-ranges ;
 
diff --git a/basis/compiler/cfg/ssa/liveness/liveness-tests.factor b/basis/compiler/cfg/ssa/liveness/liveness-tests.factor
deleted file mode 100644 (file)
index bc58070..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-! Copyright (C) 2009 Daniel Ehrenberg
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel tools.test namespaces sequences vectors accessors sets
-arrays math.ranges assocs
-cpu.architecture
-compiler.cfg
-compiler.cfg.ssa.liveness.private
-compiler.cfg.ssa.liveness 
-compiler.cfg.debugger
-compiler.cfg.instructions
-compiler.cfg.predecessors
-compiler.cfg.registers
-compiler.cfg.dominance
-compiler.cfg.def-use ;
-IN: compiler.cfg.ssa.liveness
-
-[ t ] [ { 1 } 1 only? ] unit-test
-[ t ] [ { } 1 only? ] unit-test
-[ f ] [ { 2 1 } 1 only? ] unit-test
-[ f ] [ { 2 } 1 only? ] unit-test
-
-: test-liveness ( -- )
-    cfg new 0 get >>entry
-    dup compute-defs
-    dup compute-uses
-    needs-dominance
-    precompute-liveness ;
-
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##replace f 0 D 0 }
-    T{ ##replace f 1 D 1 }
-} 0 test-bb
-
-V{
-    T{ ##replace f 2 D 0 }
-} 1 test-bb
-
-V{
-    T{ ##replace f 3 D 0 }
-} 2 test-bb
-
-0 { 1 2 } edges
-
-[ ] [ test-liveness ] unit-test
-
-[ H{ } ] [ back-edge-targets get ] unit-test
-[ t ] [ 0 get R_q { 0 1 2 } [ get ] map unique = ] unit-test
-[ t ] [ 1 get R_q { 1 } [ get ] map unique = ] unit-test
-[ t ] [ 2 get R_q { 2 } [ get ] map unique = ] unit-test
-
-: self-T_q ( n -- ? )
-    get [ T_q ] [ 1array unique ] bi = ;
-
-[ t ] [ 0 self-T_q ] unit-test
-[ t ] [ 1 self-T_q ] unit-test
-[ t ] [ 2 self-T_q ] unit-test
-
-[ f ] [ 0 0 get live-in? ] unit-test
-[ t ] [ 1 0 get live-in? ] unit-test
-[ t ] [ 2 0 get live-in? ] unit-test
-[ t ] [ 3 0 get live-in? ] unit-test
-
-[ f ] [ 0 0 get live-out? ] unit-test
-[ f ] [ 1 0 get live-out? ] unit-test
-[ t ] [ 2 0 get live-out? ] unit-test
-[ t ] [ 3 0 get live-out? ] unit-test
-
-[ f ] [ 0 1 get live-in? ] unit-test
-[ f ] [ 1 1 get live-in? ] unit-test
-[ t ] [ 2 1 get live-in? ] unit-test
-[ f ] [ 3 1 get live-in? ] unit-test
-
-[ f ] [ 0 1 get live-out? ] unit-test
-[ f ] [ 1 1 get live-out? ] unit-test
-[ f ] [ 2 1 get live-out? ] unit-test
-[ f ] [ 3 1 get live-out? ] unit-test
-
-[ f ] [ 0 2 get live-in? ] unit-test
-[ f ] [ 1 2 get live-in? ] unit-test
-[ f ] [ 2 2 get live-in? ] unit-test
-[ t ] [ 3 2 get live-in? ] unit-test
-
-[ f ] [ 0 2 get live-out? ] unit-test
-[ f ] [ 1 2 get live-out? ] unit-test
-[ f ] [ 2 2 get live-out? ] unit-test
-[ f ] [ 3 2 get live-out? ] unit-test
-
-V{ } 0 test-bb
-V{ } 1 test-bb
-V{ } 2 test-bb
-V{ } 3 test-bb
-V{
-    T{ ##phi f 2 H{ { 2 0 } { 3 1 } } }
-} 4 test-bb
-test-diamond
-
-[ ] [ test-liveness ] unit-test
-
-[ t ] [ 0 1 get live-in? ] unit-test
-[ t ] [ 1 1 get live-in? ] unit-test
-[ f ] [ 2 1 get live-in? ] unit-test
-
-[ t ] [ 0 1 get live-out? ] unit-test
-[ t ] [ 1 1 get live-out? ] unit-test
-[ f ] [ 2 1 get live-out? ] unit-test
-
-[ t ] [ 0 2 get live-in? ] unit-test
-[ f ] [ 1 2 get live-in? ] unit-test
-[ f ] [ 2 2 get live-in? ] unit-test
-
-[ f ] [ 0 2 get live-out? ] unit-test
-[ f ] [ 1 2 get live-out? ] unit-test
-[ f ] [ 2 2 get live-out? ] unit-test
-
-[ f ] [ 0 3 get live-in? ] unit-test
-[ t ] [ 1 3 get live-in? ] unit-test
-[ f ] [ 2 3 get live-in? ] unit-test
-
-[ f ] [ 0 3 get live-out? ] unit-test
-[ f ] [ 1 3 get live-out? ] unit-test
-[ f ] [ 2 3 get live-out? ] unit-test
-
-[ f ] [ 0 4 get live-in? ] unit-test
-[ f ] [ 1 4 get live-in? ] unit-test
-[ f ] [ 2 4 get live-in? ] unit-test
-
-[ f ] [ 0 4 get live-out? ] unit-test
-[ f ] [ 1 4 get live-out? ] unit-test
-[ f ] [ 2 4 get live-out? ] unit-test
-
-! This is the CFG in Figure 3 from the paper
-V{ } 0 test-bb
-V{ } 1 test-bb
-0 1 edge
-V{ } 2 test-bb
-1 2 edge
-V{
-    T{ ##peek f 0 D 0 }
-    T{ ##peek f 1 D 0 }
-    T{ ##peek f 2 D 0 }
-} 3 test-bb
-V{ } 11 test-bb
-2 { 3 11 } edges
-V{
-    T{ ##replace f 0 D 0 }
-} 4 test-bb
-V{ } 8 test-bb
-3 { 8 4 } edges
-V{
-    T{ ##replace f 1 D 0 }
-} 9 test-bb
-8 9 edge
-V{
-    T{ ##replace f 2 D 0 }
-} 5 test-bb
-4 5 edge
-V{ } 10 test-bb
-V{ } 6 test-bb
-5 6 edge
-9 { 6 10 } edges
-V{ } 7 test-bb
-6 { 5 7 } edges
-10 8 edge
-7 2 edge
-
-[ ] [ test-liveness ] unit-test
-
-[ t ] [ 1 get R_q 1 11 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 2 get R_q 2 11 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 3 get R_q 3 10 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 4 get R_q 4 7 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 5 get R_q 5 7 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 6 get R_q 6 7 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 7 get R_q 7 7 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 8 get R_q 6 10 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 9 get R_q 8 6 10 [a,b] remove [ get ] map unique = ] unit-test
-[ t ] [ 10 get R_q 10 10 [a,b] [ get ] map unique = ] unit-test
-[ t ] [ 11 get R_q 11 11 [a,b] [ get ] map unique = ] unit-test
-
-[ t ] [ 1 get T_q 1 get 1array unique = ] unit-test
-[ t ] [ 2 get T_q 2 get 1array unique = ] unit-test
-[ t ] [ 3 get T_q 3 get 2 get 2array unique = ] unit-test
-[ t ] [ 4 get T_q 4 get 2 get 2array unique = ] unit-test
-[ t ] [ 5 get T_q 5 get 2 get 2array unique = ] unit-test
-[ t ] [ 6 get T_q { 6 2 5 } [ get ] map unique = ] unit-test
-[ t ] [ 7 get T_q { 7 2 } [ get ] map unique = ] unit-test
-[ t ] [ 8 get T_q { 8 2 5 } [ get ] map unique = ] unit-test
-[ t ] [ 9 get T_q { 2 5 8 9 } [ get ] map unique = ] unit-test
-[ t ] [ 10 get T_q { 2 5 8 10 } [ get ] map unique = ] unit-test
-[ t ] [ 11 get T_q 11 get 1array unique = ] unit-test
-
-[ f ] [ 1 get back-edge-target? ] unit-test
-[ t ] [ 2 get back-edge-target? ] unit-test
-[ f ] [ 3 get back-edge-target? ] unit-test
-[ f ] [ 4 get back-edge-target? ] unit-test
-[ t ] [ 5 get back-edge-target? ] unit-test
-[ f ] [ 6 get back-edge-target? ] unit-test
-[ f ] [ 7 get back-edge-target? ] unit-test
-[ t ] [ 8 get back-edge-target? ] unit-test
-[ f ] [ 9 get back-edge-target? ] unit-test
-[ f ] [ 10 get back-edge-target? ] unit-test
-[ f ] [ 11 get back-edge-target? ] unit-test
-
-[ f ] [ 0 1 get live-in? ] unit-test
-[ f ] [ 1 1 get live-in? ] unit-test
-[ f ] [ 2 1 get live-in? ] unit-test
-
-[ f ] [ 0 1 get live-out? ] unit-test
-[ f ] [ 1 1 get live-out? ] unit-test
-[ f ] [ 2 1 get live-out? ] unit-test
-
-[ f ] [ 0 2 get live-in? ] unit-test
-[ f ] [ 1 2 get live-in? ] unit-test
-[ f ] [ 2 2 get live-in? ] unit-test
-
-[ f ] [ 0 2 get live-out? ] unit-test
-[ f ] [ 1 2 get live-out? ] unit-test
-[ f ] [ 2 2 get live-out? ] unit-test
-
-[ f ] [ 0 3 get live-in? ] unit-test
-[ f ] [ 1 3 get live-in? ] unit-test
-[ f ] [ 2 3 get live-in? ] unit-test
-
-[ t ] [ 0 3 get live-out? ] unit-test
-[ t ] [ 1 3 get live-out? ] unit-test
-[ t ] [ 2 3 get live-out? ] unit-test
-
-[ t ] [ 0 4 get live-in? ] unit-test
-[ f ] [ 1 4 get live-in? ] unit-test
-[ t ] [ 2 4 get live-in? ] unit-test
-
-[ f ] [ 0 4 get live-out? ] unit-test
-[ f ] [ 1 4 get live-out? ] unit-test
-[ t ] [ 2 4 get live-out? ] unit-test
-
-[ f ] [ 0 5 get live-in? ] unit-test
-[ f ] [ 1 5 get live-in? ] unit-test
-[ t ] [ 2 5 get live-in? ] unit-test
-
-[ f ] [ 0 5 get live-out? ] unit-test
-[ f ] [ 1 5 get live-out? ] unit-test
-[ t ] [ 2 5 get live-out? ] unit-test
-
-[ f ] [ 0 6 get live-in? ] unit-test
-[ f ] [ 1 6 get live-in? ] unit-test
-[ t ] [ 2 6 get live-in? ] unit-test
-
-[ f ] [ 0 6 get live-out? ] unit-test
-[ f ] [ 1 6 get live-out? ] unit-test
-[ t ] [ 2 6 get live-out? ] unit-test
-
-[ f ] [ 0 7 get live-in? ] unit-test
-[ f ] [ 1 7 get live-in? ] unit-test
-[ f ] [ 2 7 get live-in? ] unit-test
-
-[ f ] [ 0 7 get live-out? ] unit-test
-[ f ] [ 1 7 get live-out? ] unit-test
-[ f ] [ 2 7 get live-out? ] unit-test
-
-[ f ] [ 0 8 get live-in? ] unit-test
-[ t ] [ 1 8 get live-in? ] unit-test
-[ t ] [ 2 8 get live-in? ] unit-test
-
-[ f ] [ 0 8 get live-out? ] unit-test
-[ t ] [ 1 8 get live-out? ] unit-test
-[ t ] [ 2 8 get live-out? ] unit-test
-
-[ f ] [ 0 9 get live-in? ] unit-test
-[ t ] [ 1 9 get live-in? ] unit-test
-[ t ] [ 2 9 get live-in? ] unit-test
-
-[ f ] [ 0 9 get live-out? ] unit-test
-[ t ] [ 1 9 get live-out? ] unit-test
-[ t ] [ 2 9 get live-out? ] unit-test
-
-[ f ] [ 0 10 get live-in? ] unit-test
-[ t ] [ 1 10 get live-in? ] unit-test
-[ t ] [ 2 10 get live-in? ] unit-test
-
-[ f ] [ 0 10 get live-out? ] unit-test
-[ t ] [ 1 10 get live-out? ] unit-test
-[ t ] [ 2 10 get live-out? ] unit-test
-
-[ f ] [ 0 11 get live-in? ] unit-test
-[ f ] [ 1 11 get live-in? ] unit-test
-[ f ] [ 2 11 get live-in? ] unit-test
-
-[ f ] [ 0 11 get live-out? ] unit-test
-[ f ] [ 1 11 get live-out? ] unit-test
-[ f ] [ 2 11 get live-out? ] unit-test
diff --git a/basis/compiler/cfg/ssa/liveness/liveness.factor b/basis/compiler/cfg/ssa/liveness/liveness.factor
deleted file mode 100644 (file)
index 6e84b8b..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-! Copyright (C) 2009 Daniel Ehrenberg
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences assocs accessors
-namespaces fry math sets combinators locals
-compiler.cfg.rpo
-compiler.cfg.dominance
-compiler.cfg.def-use
-compiler.cfg.instructions ;
-FROM: namespaces => set ;
-IN: compiler.cfg.ssa.liveness
-
-! Liveness checking on SSA IR, as described in
-! "Fast Liveness Checking for SSA-Form Programs", Sebastian Hack et al.
-! http://hal.archives-ouvertes.fr/docs/00/19/22/19/PDF/fast_liveness.pdf
-
-<PRIVATE
-
-! The sets T_q and R_q are described there
-SYMBOL: T_q-sets
-SYMBOL: R_q-sets
-
-! Targets of back edges
-SYMBOL: back-edge-targets
-
-: T_q ( q -- T_q )
-    T_q-sets get at ;
-
-: R_q ( q -- R_q )
-    R_q-sets get at ;
-
-: back-edge-target? ( block -- ? )
-    back-edge-targets get key? ;
-
-: next-R_q ( q -- R_q )
-    [ ] [ successors>> ] [ number>> ] tri
-    '[ number>> _ >= ] filter
-    [ R_q ] map assoc-combine
-    [ conjoin ] keep ;
-
-: set-R_q ( q -- )
-    [ next-R_q ] keep R_q-sets get set-at ;
-
-: set-back-edges ( q -- )
-    [ successors>> ] [ number>> ] bi '[
-        dup number>> _ < 
-        [ back-edge-targets get conjoin ] [ drop ] if
-    ] each ;
-
-: init-R_q ( -- )
-    H{ } clone R_q-sets set
-    H{ } clone back-edge-targets set ;
-
-: compute-R_q ( cfg -- )
-    init-R_q
-    post-order [
-        [ set-R_q ] [ set-back-edges ] bi
-    ] each ;
-
-! This algorithm for computing T_q uses equation (1)
-! but not the faster algorithm described in the paper
-
-: back-edges-from ( q -- edges )
-    R_q keys [
-        [ successors>> ] [ number>> ] bi
-        '[ number>> _ < ] filter
-    ] gather ;
-
-: T^_q ( q -- T^_q )
-    [ back-edges-from ] [ R_q ] bi
-    '[ _ key? not ] filter ;
-
-: next-T_q ( q -- T_q )
-    dup dup T^_q [ next-T_q keys ] map 
-    concat unique [ conjoin ] keep
-    [ swap T_q-sets get set-at ] keep ;
-
-: compute-T_q ( cfg -- )
-    H{ } T_q-sets set
-    [ next-T_q drop ] each-basic-block ;
-
-PRIVATE>
-
-: precompute-liveness ( cfg -- )
-    [ compute-R_q ] [ compute-T_q ] bi ;
-
-<PRIVATE
-
-! This doesn't take advantage of ordering T_q,a so you 
-! only have to check one if the CFG is reducible.
-! It should be changed to be more efficient.
-
-: only? ( seq obj -- ? )
-    '[ _ eq? ] all? ;
-
-: strictly-dominates? ( bb1 bb2 -- ? )
-    [ dominates? ] [ eq? not ] 2bi and ;
-
-: T_q,a ( a q -- T_q,a )
-    ! This could take advantage of the structure of dominance,
-    ! but probably I'll replace it with the algorithm that works
-    ! on reducible CFGs anyway
-    T_q keys swap def-of 
-    [ '[ _ swap strictly-dominates? ] filter ] when* ;
-
-: live? ( vreg node quot -- ? )
-    [ [ T_q,a ] [ drop uses-of ] 2bi ] dip
-    '[ [ R_q keys _ ] keep @ intersects? ] any? ; inline
-
-PRIVATE>
-
-: live-in? ( vreg node -- ? )
-    [ drop ] live? ;
-
-<PRIVATE
-
-: (live-out?) ( vreg node -- ? )
-    dup dup dup '[
-        _ = _ back-edge-target? not and
-        [ _ swap remove ] when
-    ] live? ;
-
-PRIVATE>
-
-:: live-out? ( vreg node -- ? )
-    vreg def-of :> def
-    {
-        { [ node def eq? ] [ vreg uses-of def only? not ] }
-        { [ def node strictly-dominates? ] [ vreg node (live-out?) ] }
-        [ f ]
-    } cond ;
index 3cfade23e1c94720277a75762d211d0424dd2c17..8ad55d76d81e86a63a2f20b46fa988585c54ed05 100644 (file)
@@ -1,15 +1,15 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: math math.order namespaces accessors kernel layouts combinators
-combinators.smart assocs sequences cpu.architecture ;
+USING: math math.order namespaces accessors kernel layouts
+combinators combinators.smart assocs sequences cpu.architecture
+words compiler.cfg.instructions ;
 IN: compiler.cfg.stack-frame
 
 TUPLE: stack-frame
 { params integer }
 { return integer }
-{ total-size integer }
-{ gc-root-size integer }
 { spill-area-size integer }
+{ total-size integer }
 { calls-vm? boolean } ;
 
 ! Stack frame utilities
@@ -19,19 +19,9 @@ TUPLE: stack-frame
 : spill-offset ( n -- offset )
     param-base + ;
 
-: gc-root-base ( -- n )
-    stack-frame get spill-area-size>> param-base + ;
-
-: gc-root-offset ( n -- n' ) gc-root-base + ;
-
 : (stack-frame-size) ( stack-frame -- n )
     [
-        {
-            [ params>> ]
-            [ return>> ]
-            [ gc-root-size>> ]
-            [ spill-area-size>> ]
-        } cleave
+        [ params>> ] [ return>> ] [ spill-area-size>> ] tri
     ] sum-outputs ;
 
 : max-stack-frame ( frame1 frame2 -- frame3 )
@@ -39,6 +29,11 @@ TUPLE: stack-frame
     {
         [ [ params>> ] bi@ max >>params ]
         [ [ return>> ] bi@ max >>return ]
-        [ [ gc-root-size>> ] bi@ max >>gc-root-size ]
+        [ [ spill-area-size>> ] bi@ max >>spill-area-size ]
         [ [ calls-vm?>> ] bi@ or >>calls-vm? ]
-    } 2cleave ;
\ No newline at end of file
+    } 2cleave ;
+
+! PowerPC backend sets frame-required? for ##integer>float too
+\ ##spill t "frame-required?" set-word-prop
+\ ##unary-float-function t "frame-required?" set-word-prop
+\ ##binary-float-function t "frame-required?" set-word-prop
\ No newline at end of file
index ad3453704bdebee743924575f9e477bca1fbbc4d..41512f206febd08865a3af7ebab00166782615f6 100644 (file)
@@ -44,8 +44,8 @@ ERROR: bad-peek dst loc ;
     ! If both blocks are subroutine calls, don't bother
     ! computing anything.
     2dup [ kill-block? ] both? [ 2drop ] [
-        2dup [ [ insert-replaces ] [ insert-peeks ] 2bi ] V{ } make
-        [ 2drop ] [ insert-simple-basic-block ] if-empty
+        2dup [ [ insert-replaces ] [ insert-peeks ] 2bi ##branch ] V{ } make
+        [ 2drop ] [ insert-basic-block ] if-empty
     ] if ;
 
 : visit-block ( bb -- )
index 6cf362c2308a4f278c09e04db1dc48cbf63c7691..fdd6e405f56a97d328fbfdc0b5c22023da56772b 100644 (file)
@@ -68,9 +68,14 @@ IN: compiler.cfg.stacks
 : 3inputs ( -- vreg1 vreg2 vreg3 )
     (3inputs) -3 inc-d ;
 
+: binary-op ( quot -- )
+    [ 2inputs ] dip call ds-push ; inline
+
+: unary-op ( quot -- )
+    [ ds-pop ] dip call ds-push ; inline
+
 ! adjust-d/adjust-r: these are called when other instructions which
 ! internally adjust the stack height are emitted, such as ##call and
 ! ##alien-invoke
 : adjust-d ( n -- ) current-height get [ + ] change-d drop ;
 : adjust-r ( n -- ) current-height get [ + ] change-r drop ;
-
index 5b2bbf3765baf0583b6e48cac2670f9e3c9db67d..3d7519e14ba9e79dcbaeba863af4ece84c793c74 100644 (file)
@@ -33,14 +33,19 @@ M: ##inc-r visit-insn n>> rs-loc handle-inc ;
 
 ERROR: uninitialized-peek insn ;
 
-M: ##peek visit-insn
+: visit-peek ( ##peek -- )
     dup loc>> [ n>> ] [ class get ] bi ?nth 0 =
-    [ uninitialized-peek ] [ drop ] if ;
+    [ uninitialized-peek ] [ drop ] if ; inline
 
-M: ##replace visit-insn
+M: ##peek visit-insn visit-peek ;
+
+: visit-replace ( ##replace -- )
     loc>> [ n>> ] [ class get ] bi
     2dup length < [ [ 1 ] 2dip set-nth ] [ 2drop ] if ;
 
+M: ##replace visit-insn visit-replace ;
+M: ##replace-imm visit-insn visit-replace ;
+
 M: insn visit-insn drop ;
 
 : prepare ( pair -- )
index a2885ae26e775ed6b1a6e3a426e5aa1672397cfe..b2529655bb9762c3ebaa1c12404647edc1ccb44d 100644 (file)
@@ -1,19 +1,22 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences math combinators combinators.short-circuit
-classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo
+USING: kernel accessors sequences math combinators
+combinators.short-circuit vectors compiler.cfg
+compiler.cfg.instructions compiler.cfg.rpo
 compiler.cfg.utilities ;
 IN: compiler.cfg.useless-conditionals
 
 : delete-conditional? ( bb -- ? )
     {
         [
-            instructions>> last class {
-                ##compare-branch
-                ##compare-imm-branch
-                ##compare-float-ordered-branch
-                ##compare-float-unordered-branch
-            } member-eq?
+            instructions>> last {
+                [ ##compare-branch? ]
+                [ ##compare-imm-branch? ]
+                [ ##compare-integer-branch? ]
+                [ ##compare-integer-imm-branch? ]
+                [ ##compare-float-ordered-branch? ]
+                [ ##compare-float-unordered-branch? ]
+            } 1||
         ]
         [ successors>> first2 [ skip-empty-blocks ] bi@ eq? ]
     } 1&& ;
index bee2226ec46c07475ac5d45f3923d87deeed276c..ae860c52ce93e378e9dda99800bab2ce53beff8a 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs combinators combinators.short-circuit
 cpu.architecture kernel layouts locals make math namespaces sequences
@@ -37,11 +37,24 @@ SYMBOL: visited
 : skip-empty-blocks ( bb -- bb' )
     H{ } clone visited [ (skip-empty-blocks) ] with-variable ;
 
-:: insert-basic-block ( froms to bb -- )
-    bb froms V{ } like >>predecessors drop
-    bb to 1vector >>successors drop
-    to predecessors>> [ dup froms member-eq? [ drop bb ] when ] map! drop
-    froms [ successors>> [ dup to eq? [ drop bb ] when ] map! drop ] each ;
+:: update-predecessors ( from to bb -- )
+    ! Update 'to' predecessors for insertion of 'bb' between
+    ! 'from' and 'to'.
+    to predecessors>> [ dup from eq? [ drop bb ] when ] map! drop ;
+
+:: update-successors ( from to bb -- )
+    ! Update 'from' successors for insertion of 'bb' between
+    ! 'from' and 'to'.
+    from successors>> [ dup to eq? [ drop bb ] when ] map! drop ;
+
+:: insert-basic-block ( from to insns -- )
+    ! Insert basic block on the edge between 'from' and 'to'.
+    <basic-block> :> bb
+    insns V{ } like bb (>>instructions)
+    V{ from } bb (>>predecessors)
+    V{ to } bb (>>successors)
+    from to bb update-predecessors
+    from to bb update-successors ;
 
 : add-instructions ( bb quot -- )
     [ instructions>> building ] dip '[
@@ -50,15 +63,6 @@ SYMBOL: visited
         ,
     ] with-variable ; inline
 
-: <simple-block> ( insns -- bb )
-    <basic-block>
-    swap >vector
-    \ ##branch new-insn over push
-    >>instructions ;
-
-: insert-simple-basic-block ( from to insns -- )
-    [ 1vector ] 2dip <simple-block> insert-basic-block ;
-
 : has-phis? ( bb -- ? )
     instructions>> first ##phi? ;
 
@@ -79,3 +83,5 @@ SYMBOL: visited
 : predecessor ( bb -- pred )
     predecessors>> first ; inline
 
+: <copy> ( dst src -- insn )
+    any-rep \ ##copy new-insn ;
diff --git a/basis/compiler/cfg/value-numbering/alien/alien.factor b/basis/compiler/cfg/value-numbering/alien/alien.factor
new file mode 100644 (file)
index 0000000..5867460
--- /dev/null
@@ -0,0 +1,131 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators combinators.short-circuit fry
+kernel make math sequences
+cpu.architecture
+compiler.cfg.hats
+compiler.cfg.utilities
+compiler.cfg.registers
+compiler.cfg.instructions
+compiler.cfg.value-numbering.math
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.alien
+
+M: ##box-displaced-alien rewrite
+    dup displacement>> vreg>insn zero-insn?
+    [ [ dst>> ] [ base>> ] bi <copy> ] [ drop f ] if ;
+
+! ##box-displaced-alien f 1 2 3 <class>
+! ##unbox-c-ptr 4 1 <class>
+! =>
+! ##box-displaced-alien f 1 2 3 <class>
+! ##unbox-c-ptr 5 3 <class>
+! ##add 4 5 2
+
+: rewrite-unbox-alien ( insn box-insn -- insn )
+    [ dst>> ] [ src>> ] bi* <copy> ;
+
+: rewrite-unbox-displaced-alien ( insn box-insn -- insns )
+    [
+        [ dst>> ]
+        [ [ base>> ] [ base-class>> ] [ displacement>> ] tri ] bi*
+        [ ^^unbox-c-ptr ] dip
+        ##add
+    ] { } make ;
+
+: rewrite-unbox-any-c-ptr ( insn -- insn/f )
+    dup src>> vreg>insn
+    {
+        { [ dup ##box-alien? ] [ rewrite-unbox-alien ] }
+        { [ dup ##box-displaced-alien? ] [ rewrite-unbox-displaced-alien ] }
+        [ 2drop f ]
+    } cond ;
+
+M: ##unbox-any-c-ptr rewrite rewrite-unbox-any-c-ptr ;
+
+M: ##unbox-alien rewrite rewrite-unbox-any-c-ptr ;
+
+! Fuse ##add-imm into ##load-memory(-imm) and ##store-memory(-imm)
+! just update the offset in the instruction
+: fuse-base-offset? ( insn -- ? )
+    base>> vreg>insn ##add-imm? ;
+
+: fuse-base-offset ( insn -- insn' )
+    dup base>> vreg>insn
+    [ src1>> ] [ src2>> ] bi
+    [ >>base ] [ '[ _ + ] change-offset ] bi* ;
+
+! Fuse ##add-imm into ##load-memory and ##store-memory
+! just update the offset in the instruction
+: fuse-displacement-offset? ( insn -- ? )
+    { [ scale>> 0 = ] [ displacement>> vreg>insn ##add-imm? ] } 1&& ;
+
+: fuse-displacement-offset ( insn -- insn' )
+    dup displacement>> vreg>insn
+    [ src1>> ] [ src2>> ] bi
+    [ >>displacement ] [ '[ _ + ] change-offset ] bi* ;
+
+! Fuse ##add into ##load-memory-imm and ##store-memory-imm
+! construct a new ##load-memory or ##store-memory with the
+! ##add's operand as the displacement
+: fuse-displacement? ( insn -- ? )
+    {
+        [ offset>> 0 = complex-addressing? or ]
+        [ base>> vreg>insn ##add? ]
+    } 1&& ;
+
+GENERIC: alien-insn-value ( insn -- value )
+
+M: ##load-memory-imm alien-insn-value dst>> ;
+M: ##store-memory-imm alien-insn-value src>> ;
+
+GENERIC: new-alien-insn ( value base displacement scale offset rep c-type insn -- insn )
+
+M: ##load-memory-imm new-alien-insn drop \ ##load-memory new-insn ;
+M: ##store-memory-imm new-alien-insn drop \ ##store-memory new-insn ;
+
+: fuse-displacement ( insn -- insn' )
+    {
+        [ alien-insn-value ]
+        [ base>> vreg>insn [ src1>> ] [ src2>> ] bi ]
+        [ drop 0 ]
+        [ offset>> ]
+        [ rep>> ]
+        [ c-type>> ]
+        [ ]
+    } cleave new-alien-insn ;
+
+! Fuse ##shl-imm into ##load-memory or ##store-memory
+: scale-insn? ( insn -- ? )
+    { [ ##shl-imm? ] [ src2>> { 1 2 3 } member? ] } 1&& ;
+
+: fuse-scale? ( insn -- ? )
+    { [ scale>> 0 = ] [ displacement>> vreg>insn scale-insn? ] } 1&& ;
+
+: fuse-scale ( insn -- insn' )
+    dup displacement>> vreg>insn
+    [ src1>> ] [ src2>> ] bi
+    [ >>displacement ] [ >>scale ] bi* ;
+
+: rewrite-memory-op ( insn -- insn/f )
+    complex-addressing? [
+        {
+            { [ dup fuse-base-offset? ] [ fuse-base-offset ] }
+            { [ dup fuse-displacement-offset? ] [ fuse-displacement-offset ] }
+            { [ dup fuse-scale? ] [ fuse-scale ] }
+            [ drop f ]
+        } cond
+    ] [ drop f ] if ;
+
+: rewrite-memory-imm-op ( insn -- insn/f )
+    {
+        { [ dup fuse-base-offset? ] [ fuse-base-offset ] }
+        { [ dup fuse-displacement? ] [ fuse-displacement ] }
+        [ drop f ]
+    } cond ;
+
+M: ##load-memory rewrite rewrite-memory-op ;
+M: ##load-memory-imm rewrite rewrite-memory-imm-op ;
+M: ##store-memory rewrite rewrite-memory-op ;
+M: ##store-memory-imm rewrite rewrite-memory-imm-op ;
diff --git a/basis/compiler/cfg/value-numbering/alien/authors.txt b/basis/compiler/cfg/value-numbering/alien/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/comparisons/authors.txt b/basis/compiler/cfg/value-numbering/comparisons/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor b/basis/compiler/cfg/value-numbering/comparisons/comparisons.factor
new file mode 100644 (file)
index 0000000..f28092d
--- /dev/null
@@ -0,0 +1,209 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators kernel math math.order namespaces
+sequences vectors combinators.short-circuit compiler.cfg
+compiler.cfg.comparisons compiler.cfg.instructions
+compiler.cfg.registers
+compiler.cfg.value-numbering.math
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.comparisons
+
+! Optimizations performed here:
+!
+! 1) Eliminating intermediate boolean values when the result of
+! a comparison is used by a compare-branch
+! 2) Folding comparisons where both inputs are literal
+! 3) Folding comparisons where both inputs are congruent
+! 4) Converting compare instructions into compare-imm instructions
+
+: fold-compare-imm? ( insn -- ? )
+    src1>> vreg>insn literal-insn? ;
+
+: evaluate-compare-imm ( insn -- ? )
+    [ src1>> vreg>literal ] [ src2>> ] [ cc>> ] tri
+    {
+        { cc= [ eq? ] }
+        { cc/= [ eq? not ] }
+    } case ;
+
+: fold-compare-integer-imm? ( insn -- ? )
+    src1>> vreg>insn ##load-integer? ;
+
+: evaluate-compare-integer-imm ( insn -- ? )
+    [ src1>> vreg>integer ] [ src2>> ] [ cc>> ] tri
+    [ <=> ] dip evaluate-cc ;
+
+: >compare< ( insn -- in1 in2 cc )
+    [ src1>> ] [ src2>> ] [ cc>> ] tri ; inline
+
+: >test-vector< ( insn -- src1 temp rep vcc )
+    {
+        [ src1>> ]
+        [ drop next-vreg ]
+        [ rep>> ]
+        [ vcc>> ]
+    } cleave ; inline
+
+UNION: scalar-compare-insn
+    ##compare
+    ##compare-imm
+    ##compare-integer
+    ##compare-integer-imm
+    ##compare-float-unordered
+    ##compare-float-ordered ;
+
+UNION: general-compare-insn scalar-compare-insn ##test-vector ;
+
+: rewrite-boolean-comparison? ( insn -- ? )
+    {
+        [ src1>> vreg>insn general-compare-insn? ]
+        [ src2>> not ]
+        [ cc>> cc/= eq? ]
+    } 1&& ; inline
+
+: rewrite-boolean-comparison ( insn -- insn )
+    src1>> vreg>insn {
+        { [ dup ##compare? ] [ >compare< \ ##compare-branch new-insn ] }
+        { [ dup ##compare-imm? ] [ >compare< \ ##compare-imm-branch new-insn ] }
+        { [ dup ##compare-integer? ] [ >compare< \ ##compare-integer-branch new-insn ] }
+        { [ dup ##compare-integer-imm? ] [ >compare< \ ##compare-integer-imm-branch new-insn ] }
+        { [ dup ##compare-float-unordered? ] [ >compare< \ ##compare-float-unordered-branch new-insn ] }
+        { [ dup ##compare-float-ordered? ] [ >compare< \ ##compare-float-ordered-branch new-insn ] }
+        { [ dup ##test-vector? ] [ >test-vector< \ ##test-vector-branch new-insn ] }
+    } cond ;
+
+: fold-branch ( ? -- insn )
+    0 1 ?
+    basic-block get [ nth 1vector ] change-successors drop
+    \ ##branch new-insn ;
+
+: fold-compare-imm-branch ( insn -- insn/f )
+    evaluate-compare-imm fold-branch ;
+
+M: ##compare-imm-branch rewrite
+    {
+        { [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] }
+        { [ dup fold-compare-imm? ] [ fold-compare-imm-branch ] }
+        [ drop f ]
+    } cond ;
+
+: fold-compare-integer-imm-branch ( insn -- insn/f )
+    evaluate-compare-integer-imm fold-branch ;
+
+M: ##compare-integer-imm-branch rewrite
+    {
+        { [ dup fold-compare-integer-imm? ] [ fold-compare-integer-imm-branch ] }
+        [ drop f ]
+    } cond ;
+
+: swap-compare ( src1 src2 cc swap? -- src1 src2 cc )
+    [ [ swap ] dip swap-cc ] when ; inline
+
+: (>compare-imm-branch) ( insn swap? -- src1 src2 cc )
+    [ [ src1>> ] [ src2>> ] [ cc>> ] tri ] dip swap-compare ; inline
+
+: >compare-imm-branch ( insn swap? -- insn' )
+    (>compare-imm-branch)
+    [ vreg>literal ] dip
+    \ ##compare-imm-branch new-insn ; inline
+
+: >compare-integer-imm-branch ( insn swap? -- insn' )
+    (>compare-imm-branch)
+    [ vreg>integer ] dip
+    \ ##compare-integer-imm-branch new-insn ; inline
+
+: evaluate-self-compare ( insn -- ? )
+    cc>> { cc= cc<= cc>= } member-eq? ;
+
+: rewrite-self-compare-branch ( insn -- insn' )
+    evaluate-self-compare fold-branch ;
+
+M: ##compare-branch rewrite
+    {
+        { [ dup src1>> vreg-immediate-comparand? ] [ t >compare-imm-branch ] }
+        { [ dup src2>> vreg-immediate-comparand? ] [ f >compare-imm-branch ] }
+        { [ dup diagonal? ] [ rewrite-self-compare-branch ] }
+        [ drop f ]
+    } cond ;
+
+M: ##compare-integer-branch rewrite
+    {
+        { [ dup src1>> vreg-immediate-arithmetic? ] [ t >compare-integer-imm-branch ] }
+        { [ dup src2>> vreg-immediate-arithmetic? ] [ f >compare-integer-imm-branch ] }
+        { [ dup diagonal? ] [ rewrite-self-compare-branch ] }
+        [ drop f ]
+    } cond ;
+
+: (>compare-imm) ( insn swap? -- dst src1 src2 cc )
+    [ { [ dst>> ] [ src1>> ] [ src2>> ] [ cc>> ] } cleave ] dip
+    swap-compare ; inline
+
+: >compare-imm ( insn swap? -- insn' )
+    (>compare-imm)
+    [ vreg>literal ] dip
+    next-vreg \ ##compare-imm new-insn ; inline
+
+: >compare-integer-imm ( insn swap? -- insn' )
+    (>compare-imm)
+    [ vreg>integer ] dip
+    next-vreg \ ##compare-integer-imm new-insn ; inline
+
+: >boolean-insn ( insn ? -- insn' )
+    [ dst>> ] dip \ ##load-reference new-insn ;
+
+: rewrite-self-compare ( insn -- insn' )
+    dup evaluate-self-compare >boolean-insn ;
+
+M: ##compare rewrite
+    {
+        { [ dup src1>> vreg-immediate-comparand? ] [ t >compare-imm ] }
+        { [ dup src2>> vreg-immediate-comparand? ] [ f >compare-imm ] }
+        { [ dup diagonal? ] [ rewrite-self-compare ] }
+        [ drop f ]
+    } cond ;
+
+M: ##compare-integer rewrite
+    {
+        { [ dup src1>> vreg-immediate-arithmetic? ] [ t >compare-integer-imm ] }
+        { [ dup src2>> vreg-immediate-arithmetic? ] [ f >compare-integer-imm ] }
+        { [ dup diagonal? ] [ rewrite-self-compare ] }
+        [ drop f ]
+    } cond ;
+
+: rewrite-redundant-comparison? ( insn -- ? )
+    {
+        [ src1>> vreg>insn scalar-compare-insn? ]
+        [ src2>> not ]
+        [ cc>> { cc= cc/= } member? ]
+    } 1&& ; inline
+
+: rewrite-redundant-comparison ( insn -- insn' )
+    [ cc>> ] [ dst>> ] [ src1>> vreg>insn ] tri {
+        { [ dup ##compare? ] [ >compare< next-vreg \ ##compare new-insn ] }
+        { [ dup ##compare-imm? ] [ >compare< next-vreg \ ##compare-imm new-insn ] }
+        { [ dup ##compare-integer? ] [ >compare< next-vreg \ ##compare-integer new-insn ] }
+        { [ dup ##compare-integer-imm? ] [ >compare< next-vreg \ ##compare-integer-imm new-insn ] }
+        { [ dup ##compare-float-unordered? ] [ >compare< next-vreg \ ##compare-float-unordered new-insn ] }
+        { [ dup ##compare-float-ordered? ] [ >compare< next-vreg \ ##compare-float-ordered new-insn ] }
+    } cond
+    swap cc= eq? [ [ negate-cc ] change-cc ] when ;
+
+: fold-compare-imm ( insn -- insn' )
+    dup evaluate-compare-imm >boolean-insn ;
+
+M: ##compare-imm rewrite
+    {
+        { [ dup rewrite-redundant-comparison? ] [ rewrite-redundant-comparison ] }
+        { [ dup fold-compare-imm? ] [ fold-compare-imm ] }
+        [ drop f ]
+    } cond ;
+
+: fold-compare-integer-imm ( insn -- insn' )
+    dup evaluate-compare-integer-imm >boolean-insn ;
+
+M: ##compare-integer-imm rewrite
+    {
+        { [ dup fold-compare-integer-imm? ] [ fold-compare-integer-imm ] }
+        [ drop f ]
+    } cond ;
index d2e7c2ac864fd48a0ff07e0ffb3265ead010cdd1..46e5a099072955228943d4f3edd88c0ece2a2c32 100644 (file)
@@ -1,77 +1,84 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors classes classes.algebra classes.parser
-classes.tuple combinators combinators.short-circuit fry
+USING: accessors arrays classes classes.algebra combinators fry
 generic.parser kernel math namespaces quotations sequences slots
-splitting words compiler.cfg.instructions
+words make
+compiler.cfg.instructions
 compiler.cfg.instructions.syntax
 compiler.cfg.value-numbering.graph ;
+FROM: sequences.private => set-array-nth ;
 IN: compiler.cfg.value-numbering.expressions
 
-TUPLE: constant-expr < expr value ;
-
-C: <constant> constant-expr
-
-M: constant-expr equal?
-    over constant-expr? [
-        [ value>> ] bi@
-        2dup [ float? ] both? [ fp-bitwise= ] [
-            { [ [ class ] bi@ = ] [ = ] } 2&&
-        ] if
-    ] [ 2drop f ] if ;
-
-TUPLE: reference-expr < expr value ;
-
-C: <reference> reference-expr
-
-M: reference-expr equal?
-    over reference-expr? [ [ value>> ] bi@ eq? ] [ 2drop f ] if ;
-
-M: reference-expr hashcode*
-    nip value>> identity-hashcode ;
-
-: constant>vn ( constant -- vn ) <constant> expr>vn ; inline
+<<
 
 GENERIC: >expr ( insn -- expr )
 
-M: insn >expr drop next-input-expr ;
-
-M: ##load-immediate >expr val>> <constant> ;
+: input-values ( slot-specs -- slot-specs' )
+    [ type>> { use literal } member-eq? ] filter ;
+
+: slot->expr-quot ( slot-spec -- quot )
+    [ name>> reader-word 1quotation ]
+    [
+        type>> {
+            { use [ [ vreg>vn ] ] }
+            { literal [ [ ] ] }
+        } case
+    ] bi append ;
+
+: narray-quot ( length -- quot )
+    [
+        [ , [ f <array> ] % ]
+        [ 
+            dup iota [
+                - 1 - , [ swap [ set-array-nth ] keep ] %
+            ] with each
+        ] bi
+    ] [ ] make ;
+
+: >expr-quot ( insn slot-specs -- quot )
+    [
+        [ literalize , \ swap , ]
+        [
+            [ [ slot->expr-quot ] map cleave>quot % ]
+            [ length 1 + narray-quot % ]
+            bi
+        ] bi*
+    ] [ ] make ;
+
+: define->expr-method ( insn slot-specs -- )
+    [ drop \ >expr create-method-in ] [ >expr-quot ] 2bi define ;
+
+insn-classes get
+[ pure-insn class<= ] filter
+[
+    dup "insn-slots" word-prop input-values
+    define->expr-method
+] each
 
-M: ##load-reference >expr obj>> <reference> ;
+>>
 
-M: ##load-constant >expr obj>> <constant> ;
+TUPLE: integer-expr value ;
 
-<<
+C: <integer-expr> integer-expr
 
-: input-values ( slot-specs -- slot-specs' )
-    [ type>> { use literal constant } member-eq? ] filter ;
+TUPLE: reference-expr value ;
 
-: expr-class ( insn -- expr )
-    name>> "##" ?head drop "-expr" append create-class-in ;
+C: <reference-expr> reference-expr
 
-: define-expr-class ( insn expr slot-specs -- )
-    [ nip expr ] dip [ name>> ] map define-tuple-class ;
+M: reference-expr equal?
+    over reference-expr? [
+        [ value>> ] bi@
+        2dup [ float? ] both?
+        [ fp-bitwise= ] [ eq? ] if
+    ] [ 2drop f ] if ;
 
-: >expr-quot ( expr slot-specs -- quot )
-     [
-        [ name>> reader-word 1quotation ]
-        [
-            type>> {
-                { use [ [ vreg>vn ] ] }
-                { literal [ [ ] ] }
-                { constant [ [ constant>vn ] ] }
-            } case
-        ] bi append
-    ] map cleave>quot swap suffix \ boa suffix ;
+M: reference-expr hashcode*
+    nip value>> dup float? [ double>bits ] [ identity-hashcode ] if ;
 
-: define->expr-method ( insn expr slot-specs -- )
-    [ 2drop \ >expr create-method-in ] [ >expr-quot nip ] 3bi define ;
+M: insn >expr drop input-expr-counter counter neg ;
 
-: handle-pure-insn ( insn -- )
-    [ ] [ expr-class ] [ "insn-slots" word-prop input-values ] tri
-    [ define-expr-class ] [ define->expr-method ] 3bi ;
+M: ##copy >expr "Fail" throw ;
 
-insn-classes get [ pure-insn class<= ] filter [ handle-pure-insn ] each
+M: ##load-integer >expr val>> <integer-expr> ;
 
->>
+M: ##load-reference >expr obj>> <reference-expr> ;
diff --git a/basis/compiler/cfg/value-numbering/folding/authors.txt b/basis/compiler/cfg/value-numbering/folding/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/folding/folding.factor b/basis/compiler/cfg/value-numbering/folding/folding.factor
new file mode 100644 (file)
index 0000000..4d79ed5
--- /dev/null
@@ -0,0 +1,39 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel layouts math math.bitwise
+compiler.cfg.instructions
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.folding
+
+: binary-constant-fold? ( insn -- ? )
+    src1>> vreg>insn ##load-integer? ; inline
+
+GENERIC: binary-constant-fold* ( x y insn -- z )
+
+M: ##add-imm binary-constant-fold* drop + ;
+M: ##sub-imm binary-constant-fold* drop - ;
+M: ##mul-imm binary-constant-fold* drop * ;
+M: ##and-imm binary-constant-fold* drop bitand ;
+M: ##or-imm binary-constant-fold* drop bitor ;
+M: ##xor-imm binary-constant-fold* drop bitxor ;
+M: ##shr-imm binary-constant-fold* drop [ cell-bits 2^ wrap ] dip neg shift ;
+M: ##sar-imm binary-constant-fold* drop neg shift ;
+M: ##shl-imm binary-constant-fold* drop shift ;
+
+: binary-constant-fold ( insn -- insn' )
+    [ dst>> ]
+    [ [ src1>> vreg>integer ] [ src2>> ] [ ] tri binary-constant-fold* ] bi
+    \ ##load-integer new-insn ; inline
+
+: unary-constant-fold? ( insn -- ? )
+    src>> vreg>insn ##load-integer? ; inline
+
+GENERIC: unary-constant-fold* ( x insn -- y )
+
+M: ##not unary-constant-fold* drop bitnot ;
+M: ##neg unary-constant-fold* drop neg ;
+
+: unary-constant-fold ( insn -- insn' )
+    [ dst>> ] [ [ src>> vreg>integer ] [ ] bi unary-constant-fold* ] bi
+    \ ##load-integer new-insn ; inline
index f380ecd02f885acfa74737f6255cfe3d8365a871..1ea1a52d02b5ecbb0ed615758c1653281d8b8500 100644 (file)
@@ -1,46 +1,30 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel math namespaces assocs biassocs ;
+USING: accessors kernel math namespaces assocs ;
 IN: compiler.cfg.value-numbering.graph
 
-SYMBOL: vn-counter
-
-: next-vn ( -- vn ) vn-counter [ dup 1 + ] change ;
-
-! biassoc mapping expressions to value numbers
-SYMBOL: exprs>vns
-
-TUPLE: expr ;
-
-: expr>vn ( expr -- vn ) exprs>vns get [ drop next-vn ] cache ;
-
-: vn>expr ( vn -- expr ) exprs>vns get value-at ;
-
-! Expressions whose values are inputs to the basic block.
-TUPLE: input-expr < expr n ;
-
 SYMBOL: input-expr-counter
 
-: next-input-expr ( -- expr )
-    input-expr-counter counter input-expr boa ;
-
+! assoc mapping vregs to value numbers
+! this is the identity on canonical representatives
 SYMBOL: vregs>vns
 
-: vreg>vn ( vreg -- vn )
-    vregs>vns get [ drop next-input-expr expr>vn ] cache ;
+! assoc mapping expressions to value numbers
+SYMBOL: exprs>vns
 
-: vn>vreg ( vn -- vreg ) vregs>vns get value-at ;
+! assoc mapping value numbers to instructions
+SYMBOL: vns>insns
 
-: set-vn ( vn vreg -- ) vregs>vns get set-at ;
+: vn>insn ( vn -- insn ) vns>insns get at ;
 
-: vreg>expr ( vreg -- expr ) vreg>vn vn>expr ; inline
+: vreg>vn ( vreg -- vn ) vregs>vns get [ ] cache ;
 
-: vn>constant ( vn -- constant ) vn>expr value>> ; inline
+: set-vn ( vn vreg -- ) vregs>vns get set-at ;
 
-: vreg>constant ( vreg -- constant ) vreg>vn vn>constant ; inline
+: vreg>insn ( vreg -- insn ) vreg>vn vn>insn ;
 
 : init-value-graph ( -- )
-    0 vn-counter set
     0 input-expr-counter set
-    <bihash> exprs>vns set
-    <bihash> vregs>vns set ;
+    H{ } clone vregs>vns set
+    H{ } clone exprs>vns set
+    H{ } clone vns>insns set ;
diff --git a/basis/compiler/cfg/value-numbering/math/authors.txt b/basis/compiler/cfg/value-numbering/math/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/math/math.factor b/basis/compiler/cfg/value-numbering/math/math.factor
new file mode 100644 (file)
index 0000000..c2f6369
--- /dev/null
@@ -0,0 +1,287 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators combinators.short-circuit
+cpu.architecture fry kernel layouts locals make math sequences
+compiler.cfg.instructions
+compiler.cfg.registers
+compiler.cfg.utilities
+compiler.cfg.value-numbering.folding
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.math
+
+: f-insn? ( insn -- ? )
+    { [ ##load-reference? ] [ obj>> not ] } 1&& ; inline
+
+: zero-insn? ( insn -- ? )
+    { [ ##load-integer? ] [ val>> 0 = ] } 1&& ; inline
+
+M: ##tagged>integer rewrite
+    [ dst>> ] [ src>> vreg>insn ] bi {
+        { [ dup ##load-integer? ] [ val>> tag-fixnum \ ##load-integer new-insn ] }
+        { [ dup f-insn? ] [ drop \ f type-number \ ##load-integer new-insn ] }
+        [ 2drop f ]
+    } cond ;
+
+: self-inverse ( insn -- insn' )
+    [ dst>> ] [ src>> vreg>insn src>> ] bi <copy> ;
+
+: identity ( insn -- insn' )
+    [ dst>> ] [ src1>> ] bi <copy> ;
+
+M: ##neg rewrite
+    {
+        { [ dup src>> vreg>insn ##neg? ] [ self-inverse ] }
+        { [ dup unary-constant-fold? ] [ unary-constant-fold ] }
+        [ drop f ]
+    } cond ;
+
+M: ##not rewrite
+    {
+        { [ dup src>> vreg>insn ##not? ] [ self-inverse ] }
+        { [ dup unary-constant-fold? ] [ unary-constant-fold ] }
+        [ drop f ]
+    } cond ;
+
+! Reassociation converts
+! ## *-imm 2 1 X
+! ## *-imm 3 2 Y
+! into
+! ## *-imm 3 1 (X $ Y)
+! If * is associative, then $ is the same operation as *.
+! In the case of shifts, $ is addition.
+: (reassociate) ( insn -- dst src1 src2' src2'' )
+    {
+        [ dst>> ]
+        [ src1>> vreg>insn [ src1>> ] [ src2>> ] bi ]
+        [ src2>> ]
+    } cleave ; inline
+
+: reassociate ( insn -- dst src1 src2 )
+    [ (reassociate) ] keep binary-constant-fold* ;
+
+: ?new-insn ( dst src1 src2 ? class -- insn/f )
+    '[ _ new-insn ] [ 3drop f ] if ; inline
+
+: reassociate-arithmetic ( insn new-insn -- insn/f )
+    [ reassociate dup immediate-arithmetic? ] dip ?new-insn ; inline
+
+: reassociate-bitwise ( insn new-insn -- insn/f )
+    [ reassociate dup immediate-bitwise? ] dip ?new-insn ; inline
+
+: reassociate-shift ( insn new-insn -- insn/f )
+    [ (reassociate) + dup immediate-shift-count? ] dip ?new-insn ; inline
+
+M: ##add-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##add-imm? ] [ \ ##add-imm reassociate-arithmetic ] }
+        [ drop f ]
+    } cond ;
+
+: sub-imm>add-imm ( insn -- insn' )
+    [ dst>> ] [ src1>> ] [ src2>> neg ] tri
+    dup immediate-arithmetic?
+    \ ##add-imm ?new-insn ;
+
+M: ##sub-imm rewrite sub-imm>add-imm ;
+
+! Convert ##mul-imm -1 => ##neg
+: mul-to-neg? ( insn -- ? )
+    src2>> -1 = ;
+
+: mul-to-neg ( insn -- insn' )
+    [ dst>> ] [ src1>> ] bi \ ##neg new-insn ;
+
+! Convert ##mul-imm 2^X => ##shl-imm X
+: mul-to-shl? ( insn -- ? )
+    src2>> power-of-2? ;
+
+: mul-to-shl ( insn -- insn' )
+    [ [ dst>> ] [ src1>> ] bi ] [ src2>> log2 ] bi \ ##shl-imm new-insn ;
+
+! Distribution converts
+! ##+-imm 2 1 X
+! ##*-imm 3 2 Y
+! Into
+! ##*-imm 4 1 Y
+! ##+-imm 3 4 X*Y
+! Where * is mul or shl, + is add or sub
+! Have to make sure that X*Y fits in an immediate
+:: (distribute) ( outer inner imm temp add-op mul-op -- new-outers/f )
+    imm immediate-arithmetic? [
+        [
+            temp inner src1>> outer src2>> mul-op execute
+            outer dst>> temp imm add-op execute
+        ] { } make
+    ] [ f ] if ; inline
+
+: distribute-over-add? ( insn -- ? )
+    src1>> vreg>insn ##add-imm? ;
+
+: distribute-over-sub? ( insn -- ? )
+    src1>> vreg>insn ##sub-imm? ;
+
+: distribute ( insn add-op mul-op -- new-insns/f )
+    [
+        dup src1>> vreg>insn
+        2dup src2>> swap [ src2>> ] keep binary-constant-fold*
+        next-vreg
+    ] 2dip (distribute) ; inline
+
+M: ##mul-imm rewrite
+    {
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup mul-to-neg? ] [ mul-to-neg ] }
+        { [ dup mul-to-shl? ] [ mul-to-shl ] }
+        { [ dup src1>> vreg>insn ##mul-imm? ] [ \ ##mul-imm reassociate-arithmetic ] }
+        { [ dup distribute-over-add? ] [ \ ##add-imm \ ##mul-imm distribute ] }
+        { [ dup distribute-over-sub? ] [ \ ##sub-imm \ ##mul-imm distribute ] }
+        [ drop f ]
+    } cond ;
+
+M: ##and-imm rewrite
+    {
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##and-imm? ] [ \ ##and-imm reassociate-bitwise ] }
+        { [ dup src2>> 0 = ] [ dst>> 0 \ ##load-integer new-insn ] }
+        { [ dup src2>> -1 = ] [ identity ] }
+        [ drop f ]
+    } cond ;
+
+M: ##or-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup src2>> -1 = ] [ dst>> -1 \ ##load-integer new-insn ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##or-imm? ] [ \ ##or-imm reassociate-bitwise ] }
+        [ drop f ]
+    } cond ;
+
+M: ##xor-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup src2>> -1 = ] [ [ dst>> ] [ src1>> ] bi \ ##not new-insn ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##xor-imm? ] [ \ ##xor-imm reassociate-bitwise ] }
+        [ drop f ]
+    } cond ;
+
+M: ##shl-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##shl-imm? ] [ \ ##shl-imm reassociate-shift ] }
+        { [ dup distribute-over-add? ] [ \ ##add-imm \ ##shl-imm distribute ] }
+        { [ dup distribute-over-sub? ] [ \ ##sub-imm \ ##shl-imm distribute ] }
+        [ drop f ]
+    } cond ;
+
+M: ##shr-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##shr-imm? ] [ \ ##shr-imm reassociate-shift ] }
+        [ drop f ]
+    } cond ;
+
+M: ##sar-imm rewrite
+    {
+        { [ dup src2>> 0 = ] [ identity ] }
+        { [ dup binary-constant-fold? ] [ binary-constant-fold ] }
+        { [ dup src1>> vreg>insn ##sar-imm? ] [ \ ##sar-imm reassociate-shift ] }
+        [ drop f ]
+    } cond ;
+
+! Convert
+! ##load-integer 2 X
+! ##* 3 1 2
+! Where * is an operation with an -imm equivalent into
+! ##*-imm 3 1 X
+: insn>imm-insn ( insn op swap? -- new-insn )
+    swap [
+        [ [ dst>> ] [ src1>> ] [ src2>> ] tri ] dip
+        [ swap ] when vreg>integer
+    ] dip new-insn ; inline
+
+M: ##add rewrite
+    {
+        { [ dup src2>> vreg-immediate-arithmetic? ] [ \ ##add-imm f insn>imm-insn ] }
+        { [ dup src1>> vreg-immediate-arithmetic? ] [ \ ##add-imm t insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+: diagonal? ( insn -- ? )
+    [ src1>> vreg>vn ] [ src2>> vreg>vn ] bi = ; inline
+
+! ##sub 2 1 1 => ##load-integer 2 0
+: rewrite-subtraction-identity ( insn -- insn' )
+    dst>> 0 \ ##load-integer new-insn ;
+
+! ##load-integer 1 0
+! ##sub 3 1 2
+! =>
+! ##neg 3 2
+: sub-to-neg? ( ##sub -- ? )
+    src1>> vreg>insn zero-insn? ;
+
+: sub-to-neg ( ##sub -- insn )
+    [ dst>> ] [ src2>> ] bi \ ##neg new-insn ;
+
+M: ##sub rewrite
+    {
+        { [ dup sub-to-neg? ] [ sub-to-neg ] }
+        { [ dup diagonal? ] [ rewrite-subtraction-identity ] }
+        { [ dup src2>> vreg-immediate-arithmetic? ] [ \ ##sub-imm f insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##mul rewrite
+    {
+        { [ dup src2>> vreg-immediate-arithmetic? ] [ \ ##mul-imm f insn>imm-insn ] }
+        { [ dup src1>> vreg-immediate-arithmetic? ] [ \ ##mul-imm t insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##and rewrite
+    {
+        { [ dup diagonal? ] [ identity ] }
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##and-imm f insn>imm-insn ] }
+        { [ dup src1>> vreg-immediate-bitwise? ] [ \ ##and-imm t insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##or rewrite
+    {
+        { [ dup diagonal? ] [ identity ] }
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##or-imm f insn>imm-insn ] }
+        { [ dup src1>> vreg-immediate-bitwise? ] [ \ ##or-imm t insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##xor rewrite
+    {
+        { [ dup diagonal? ] [ dst>> 0 \ ##load-integer new-insn ] }
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##xor-imm f insn>imm-insn ] }
+        { [ dup src1>> vreg-immediate-bitwise? ] [ \ ##xor-imm t insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##shl rewrite
+    {
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##shl-imm f insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##shr rewrite
+    {
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##shr-imm f insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
+
+M: ##sar rewrite
+    {
+        { [ dup src2>> vreg-immediate-bitwise? ] [ \ ##sar-imm f insn>imm-insn ] }
+        [ drop f ]
+    } cond ;
diff --git a/basis/compiler/cfg/value-numbering/misc/authors.txt b/basis/compiler/cfg/value-numbering/misc/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/misc/misc.factor b/basis/compiler/cfg/value-numbering/misc/misc.factor
new file mode 100644 (file)
index 0000000..2624b29
--- /dev/null
@@ -0,0 +1,14 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors cpu.architecture kernel
+compiler.cfg.instructions
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.misc
+
+M: ##replace rewrite
+    [ loc>> ] [ src>> vreg>insn ] bi
+    dup literal-insn? [
+        insn>literal dup immediate-store?
+        [ swap \ ##replace-imm new-insn ] [ 2drop f ] if
+    ] [ 2drop f ] if ;
index 81f39d7da2af07b594d45c6a57a4c841fe5bdea3..4f22c5bec2243c3b43f366af87e3a1e7d7e62c46 100644 (file)
-! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman, Daniel Ehrenberg.
+! Copyright (C) 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors combinators combinators.short-circuit arrays
-fry kernel layouts math namespaces sequences cpu.architecture
-math.bitwise math.order classes
-vectors locals make alien.c-types io.binary grouping
-compiler.cfg
-compiler.cfg.registers
-compiler.cfg.comparisons
+USING: accessors combinators combinators.short-circuit kernel
+layouts math cpu.architecture
 compiler.cfg.instructions
-compiler.cfg.value-numbering.expressions
-compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.simplify ;
+compiler.cfg.value-numbering.graph ;
 IN: compiler.cfg.value-numbering.rewrite
 
-: vreg-immediate-arithmetic? ( vreg -- ? )
-    vreg>expr {
-        [ constant-expr? ]
-        [ value>> fixnum? ]
-        [ value>> immediate-arithmetic? ]
-    } 1&& ;
-
-: vreg-immediate-bitwise? ( vreg -- ? )
-    vreg>expr {
-        [ constant-expr? ]
-        [ value>> fixnum? ]
-        [ value>> immediate-bitwise? ]
-    } 1&& ;
-
-: vreg-immediate-comparand? ( vreg -- ? )
-    vreg>expr {
-        [ constant-expr? ]
-        [ value>> immediate-comparand? ]
-    } 1&& ;
-
 ! Outputs f to mean no change
-
 GENERIC: rewrite ( insn -- insn/f )
 
 M: insn rewrite drop f ;
 
-: ##branch-t? ( insn -- ? )
-    dup ##compare-imm-branch? [
-        { [ cc>> cc/= eq? ] [ src2>> not ] } 1&&
-    ] [ drop f ] if ; inline
-
-: general-compare-expr? ( insn -- ? )
-    {
-        [ compare-expr? ]
-        [ compare-imm-expr? ]
-        [ compare-float-unordered-expr? ]
-        [ compare-float-ordered-expr? ]
-    } 1|| ;
-
-: general-or-vector-compare-expr? ( insn -- ? )
-    {
-        [ compare-expr? ]
-        [ compare-imm-expr? ]
-        [ compare-float-unordered-expr? ]
-        [ compare-float-ordered-expr? ]
-        [ test-vector-expr? ]
-    } 1|| ;
-
-: rewrite-boolean-comparison? ( insn -- ? )
-    dup ##branch-t? [
-        src1>> vreg>expr general-or-vector-compare-expr?
-    ] [ drop f ] if ; inline
-: >compare-expr< ( expr -- in1 in2 cc )
-    [ src1>> vn>vreg ] [ src2>> vn>vreg ] [ cc>> ] tri ; inline
-
-: >compare-imm-expr< ( expr -- in1 in2 cc )
-    [ src1>> vn>vreg ] [ src2>> vn>constant ] [ cc>> ] tri ; inline
-
-: >test-vector-expr< ( expr -- src1 temp rep vcc )
-    {
-        [ src1>> vn>vreg ]
-        [ drop next-vreg ]
-        [ rep>> ]
-        [ vcc>> ]
-    } cleave ; inline
-
-: rewrite-boolean-comparison ( expr -- insn )
-    src1>> vreg>expr {
-        { [ dup compare-expr? ] [ >compare-expr< \ ##compare-branch new-insn ] }
-        { [ dup compare-imm-expr? ] [ >compare-imm-expr< \ ##compare-imm-branch new-insn ] }
-        { [ dup compare-float-unordered-expr? ] [ >compare-expr< \ ##compare-float-unordered-branch new-insn ] }
-        { [ dup compare-float-ordered-expr? ] [ >compare-expr< \ ##compare-float-ordered-branch new-insn ] }
-        { [ dup test-vector-expr? ] [ >test-vector-expr< \ ##test-vector-branch new-insn ] }
-    } cond ;
-
-: tag-fixnum-expr? ( expr -- ? )
-    dup shl-imm-expr?
-    [ src2>> vn>constant tag-bits get = ] [ drop f ] if ;
-
-: rewrite-tagged-comparison? ( insn -- ? )
-    #! Are we comparing two tagged fixnums? Then untag them.
-    {
-        [ src1>> vreg>expr tag-fixnum-expr? ]
-        [ src2>> tag-mask get bitand 0 = ]
-    } 1&& ; inline
-
-: tagged>constant ( n -- n' )
-    tag-bits get neg shift ; inline
-
-: (rewrite-tagged-comparison) ( insn -- src1 src2 cc )
-    [ src1>> vreg>expr src1>> vn>vreg ]
-    [ src2>> tagged>constant ]
-    [ cc>> ]
-    tri ; inline
-
-GENERIC: rewrite-tagged-comparison ( insn -- insn/f )
-
-M: ##compare-imm-branch rewrite-tagged-comparison
-    (rewrite-tagged-comparison) \ ##compare-imm-branch new-insn ;
-
-M: ##compare-imm rewrite-tagged-comparison
-    [ dst>> ] [ (rewrite-tagged-comparison) ] bi
-    next-vreg \ ##compare-imm new-insn ;
-
-: rewrite-redundant-comparison? ( insn -- ? )
-    {
-        [ src1>> vreg>expr general-compare-expr? ]
-        [ src2>> not ]
-        [ cc>> { cc= cc/= } member? ]
-    } 1&& ; inline
-
-: rewrite-redundant-comparison ( insn -- insn' )
-    [ cc>> ] [ dst>> ] [ src1>> vreg>expr ] tri {
-        { [ dup compare-expr? ] [ >compare-expr< next-vreg \ ##compare new-insn ] }
-        { [ dup compare-imm-expr? ] [ >compare-imm-expr< next-vreg \ ##compare-imm new-insn ] }
-        { [ dup compare-float-unordered-expr? ] [ >compare-expr< next-vreg \ ##compare-float-unordered new-insn ] }
-        { [ dup compare-float-ordered-expr? ] [ >compare-expr< next-vreg \ ##compare-float-ordered new-insn ] }
-    } cond
-    swap cc= eq? [ [ negate-cc ] change-cc ] when ;
-
-: (fold-compare-imm) ( insn -- ? )
-    [ src1>> vreg>constant ] [ src2>> ] [ cc>> ] tri
-    2over [ integer? ] both? [ [ <=> ] dip evaluate-cc ] [
-        {
-            { cc= [ eq? ] }
-            { cc/= [ eq? not ] }
-        } case
-    ] if ;
-
-: fold-compare-imm? ( insn -- ? )
-    src1>> vreg>expr [ constant-expr? ] [ reference-expr? ] bi or ;
-
-: fold-branch ( ? -- insn )
-    0 1 ?
-    basic-block get [ nth 1vector ] change-successors drop
-    \ ##branch new-insn ;
-
-: fold-compare-imm-branch ( insn -- insn/f )
-    (fold-compare-imm) fold-branch ;
-
-M: ##compare-imm-branch rewrite
-    {
-        { [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] }
-        { [ dup rewrite-tagged-comparison? ] [ rewrite-tagged-comparison ] }
-        { [ dup fold-compare-imm? ] [ fold-compare-imm-branch ] }
-        [ drop f ]
-    } cond ;
-
-: swap-compare ( src1 src2 cc swap? -- src1 src2 cc )
-    [ [ swap ] dip swap-cc ] when ; inline
-
-: >compare-imm-branch ( insn swap? -- insn' )
-    [
-        [ src1>> ]
-        [ src2>> ]
-        [ cc>> ]
-        tri
-    ] dip
-    swap-compare
-    [ vreg>constant ] dip
-    \ ##compare-imm-branch new-insn ; inline
-
-: self-compare? ( insn -- ? )
-    [ src1>> ] [ src2>> ] bi [ vreg>vn ] bi@ = ; inline
-
-: (rewrite-self-compare) ( insn -- ? )
-    cc>> { cc= cc<= cc>= } member-eq? ;
-
-: rewrite-self-compare-branch ( insn -- insn' )
-    (rewrite-self-compare) fold-branch ;
-
-M: ##compare-branch rewrite
-    {
-        { [ dup src1>> vreg-immediate-comparand? ] [ t >compare-imm-branch ] }
-        { [ dup src2>> vreg-immediate-comparand? ] [ f >compare-imm-branch ] }
-        { [ dup self-compare? ] [ rewrite-self-compare-branch ] }
-        [ drop f ]
-    } cond ;
-
-: >compare-imm ( insn swap? -- insn' )
-    [
-        {
-            [ dst>> ]
-            [ src1>> ]
-            [ src2>> ]
-            [ cc>> ]
-        } cleave
-    ] dip
-    swap-compare
-    [ vreg>constant ] dip
-    next-vreg \ ##compare-imm new-insn ; inline
-
-: >boolean-insn ( insn ? -- insn' )
-    [ dst>> ] dip \ ##load-constant new-insn ;
-
-: rewrite-self-compare ( insn -- insn' )
-    dup (rewrite-self-compare) >boolean-insn ;
-
-M: ##compare rewrite
-    {
-        { [ dup src1>> vreg-immediate-comparand? ] [ t >compare-imm ] }
-        { [ dup src2>> vreg-immediate-comparand? ] [ f >compare-imm ] }
-        { [ dup self-compare? ] [ rewrite-self-compare ] }
-        [ drop f ]
-    } cond ;
-
-: fold-compare-imm ( insn -- insn' )
-    dup (fold-compare-imm) >boolean-insn ;
-
-M: ##compare-imm rewrite
-    {
-        { [ dup rewrite-redundant-comparison? ] [ rewrite-redundant-comparison ] }
-        { [ dup rewrite-tagged-comparison? ] [ rewrite-tagged-comparison ] }
-        { [ dup fold-compare-imm? ] [ fold-compare-imm ] }
-        [ drop f ]
-    } cond ;
-
-: constant-fold? ( insn -- ? )
-    src1>> vreg>expr constant-expr? ; inline
-
-GENERIC: constant-fold* ( x y insn -- z )
-
-M: ##add-imm constant-fold* drop + ;
-M: ##sub-imm constant-fold* drop - ;
-M: ##mul-imm constant-fold* drop * ;
-M: ##and-imm constant-fold* drop bitand ;
-M: ##or-imm constant-fold* drop bitor ;
-M: ##xor-imm constant-fold* drop bitxor ;
-M: ##shr-imm constant-fold* drop [ cell-bits 2^ wrap ] dip neg shift ;
-M: ##sar-imm constant-fold* drop neg shift ;
-M: ##shl-imm constant-fold* drop shift ;
-
-: constant-fold ( insn -- insn' )
-    [ dst>> ]
-    [
-        [ src1>> vreg>constant \ f type-number or ]
-        [ src2>> ]
-        [ ]
-        tri constant-fold*
-    ] bi
-    \ ##load-immediate new-insn ; inline
-
-: unary-constant-fold? ( insn -- ? )
-    src>> vreg>expr constant-expr? ; inline
-
-GENERIC: unary-constant-fold* ( x insn -- y )
+! Utilities
+GENERIC: insn>integer ( insn -- n )
 
-M: ##not unary-constant-fold* drop bitnot ;
-M: ##neg unary-constant-fold* drop neg ;
+M: ##load-integer insn>integer val>> ;
 
-: unary-constant-fold ( insn -- insn' )
-    [ dst>> ]
-    [ [ src>> vreg>constant ] [ ] bi unary-constant-fold* ] bi
-    \ ##load-immediate new-insn ; inline
+: vreg>integer ( vreg -- n ) vreg>insn insn>integer ; inline
 
-: maybe-unary-constant-fold ( insn -- insn' )
-    dup unary-constant-fold? [ unary-constant-fold ] [ drop f ] if ;
-
-M: ##neg rewrite
-    maybe-unary-constant-fold ;
-
-M: ##not rewrite
-    maybe-unary-constant-fold ;
-
-: arithmetic-op? ( op -- ? )
-    {
-        ##add
-        ##add-imm
-        ##sub
-        ##sub-imm
-        ##mul
-        ##mul-imm
-    } member-eq? ;
-
-: immediate? ( value op -- ? )
-    arithmetic-op? [ immediate-arithmetic? ] [ immediate-bitwise? ] if ;
-
-: reassociate ( insn op -- insn )
-    [
-        {
-            [ dst>> ]
-            [ src1>> vreg>expr [ src1>> vn>vreg ] [ src2>> vn>constant ] bi ]
-            [ src2>> ]
-            [ ]
-        } cleave constant-fold*
-    ] dip
-    2dup immediate? [ new-insn ] [ 2drop 2drop f ] if ; inline
-
-M: ##add-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        { [ dup src1>> vreg>expr add-imm-expr? ] [ \ ##add-imm reassociate ] }
-        [ drop f ]
-    } cond ;
-
-: sub-imm>add-imm ( insn -- insn' )
-    [ dst>> ] [ src1>> ] [ src2>> neg ] tri dup immediate-arithmetic?
-    [ \ ##add-imm new-insn ] [ 3drop f ] if ;
-
-M: ##sub-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        [ sub-imm>add-imm ]
-    } cond ;
-
-: mul-to-neg? ( insn -- ? )
-    src2>> -1 = ;
-
-: mul-to-neg ( insn -- insn' )
-    [ dst>> ] [ src1>> ] bi \ ##neg new-insn ;
-
-: mul-to-shl? ( insn -- ? )
-    src2>> power-of-2? ;
-
-: mul-to-shl ( insn -- insn' )
-    [ [ dst>> ] [ src1>> ] bi ] [ src2>> log2 ] bi \ ##shl-imm new-insn ;
+: vreg-immediate-arithmetic? ( vreg -- ? )
+    vreg>insn {
+        [ ##load-integer? ]
+        [ val>> immediate-arithmetic? ]
+    } 1&& ;
 
-M: ##mul-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        { [ dup mul-to-neg? ] [ mul-to-neg ] }
-        { [ dup mul-to-shl? ] [ mul-to-shl ] }
-        { [ dup src1>> vreg>expr mul-imm-expr? ] [ \ ##mul-imm reassociate ] }
-        [ drop f ]
-    } cond ;
+: vreg-immediate-bitwise? ( vreg -- ? )
+    vreg>insn {
+        [ ##load-integer? ]
+        [ val>> immediate-bitwise? ]
+    } 1&& ;
 
-M: ##and-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        { [ dup src1>> vreg>expr and-imm-expr? ] [ \ ##and-imm reassociate ] }
-        [ drop f ]
-    } cond ;
+UNION: literal-insn ##load-integer ##load-reference ;
 
-M: ##or-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        { [ dup src1>> vreg>expr or-imm-expr? ] [ \ ##or-imm reassociate ] }
-        [ drop f ]
-    } cond ;
+GENERIC: insn>literal ( insn -- n )
 
-M: ##xor-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        { [ dup src1>> vreg>expr xor-imm-expr? ] [ \ ##xor-imm reassociate ] }
-        [ drop f ]
-    } cond ;
+M: ##load-integer insn>literal val>> >fixnum ;
 
-M: ##shl-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        [ drop f ]
-    } cond ;
+M: ##load-reference insn>literal obj>> ;
 
-M: ##shr-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
-        [ drop f ]
-    } cond ;
+: vreg>literal ( vreg -- n ) vreg>insn insn>literal ; inline
 
-M: ##sar-imm rewrite
-    {
-        { [ dup constant-fold? ] [ constant-fold ] }
+: vreg-immediate-comparand? ( vreg -- ? )
+    vreg>insn {
+        { [ dup ##load-integer? ] [ val>> tag-fixnum immediate-comparand? ] }
+        { [ dup ##load-reference? ] [ obj>> immediate-comparand? ] }
         [ drop f ]
     } cond ;
-
-: insn>imm-insn ( insn op swap? -- new-insn )
-    swap [
-        [ [ dst>> ] [ src1>> ] [ src2>> ] tri ] dip
-        [ swap ] when vreg>constant
-    ] dip new-insn ; inline
-
-: vreg-immediate? ( vreg op -- ? )
-    arithmetic-op?
-    [ vreg-immediate-arithmetic? ] [ vreg-immediate-bitwise? ] if ;
-
-: rewrite-arithmetic ( insn op -- insn/f )
-    {
-        { [ over src2>> over vreg-immediate? ] [ f insn>imm-insn ] }
-        [ 2drop f ]
-    } cond ; inline
-
-: rewrite-arithmetic-commutative ( insn op -- insn/f )
-    {
-        { [ over src2>> over vreg-immediate? ] [ f insn>imm-insn ] }
-        { [ over src1>> over vreg-immediate? ] [ t insn>imm-insn ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: ##add rewrite \ ##add-imm rewrite-arithmetic-commutative ;
-
-: subtraction-identity? ( insn -- ? )
-    [ src1>> ] [ src2>> ] bi [ vreg>vn ] bi@ eq?  ;
-
-: rewrite-subtraction-identity ( insn -- insn' )
-    dst>> 0 \ ##load-immediate new-insn ;
-
-: sub-to-neg? ( ##sub -- ? )
-    src1>> vn>expr expr-zero? ;
-
-: sub-to-neg ( ##sub -- insn )
-    [ dst>> ] [ src2>> ] bi \ ##neg new-insn ;
-
-M: ##sub rewrite
-    {
-        { [ dup sub-to-neg? ] [ sub-to-neg ] }
-        { [ dup subtraction-identity? ] [ rewrite-subtraction-identity ] }
-        [ \ ##sub-imm rewrite-arithmetic ]
-    } cond ;
-
-M: ##mul rewrite \ ##mul-imm rewrite-arithmetic-commutative ;
-
-M: ##and rewrite \ ##and-imm rewrite-arithmetic-commutative ;
-
-M: ##or rewrite \ ##or-imm rewrite-arithmetic-commutative ;
-
-M: ##xor rewrite \ ##xor-imm rewrite-arithmetic-commutative ;
-
-M: ##shl rewrite \ ##shl-imm rewrite-arithmetic ;
-
-M: ##shr rewrite \ ##shr-imm rewrite-arithmetic ;
-
-M: ##sar rewrite \ ##sar-imm rewrite-arithmetic ;
-
-! ##box-displaced-alien f 1 2 3 <class>
-! ##unbox-c-ptr 4 1 <class>
-! =>
-! ##box-displaced-alien f 1 2 3 <class>
-! ##unbox-c-ptr 5 3 <class>
-! ##add 4 5 2
-
-:: rewrite-unbox-displaced-alien ( insn expr -- insns )
-    [
-        next-vreg :> temp
-        temp expr base>> vn>vreg expr base-class>> ##unbox-c-ptr
-        insn dst>> temp expr displacement>> vn>vreg ##add
-    ] { } make ;
-
-M: ##unbox-any-c-ptr rewrite
-    dup src>> vreg>expr dup box-displaced-alien-expr?
-    [ rewrite-unbox-displaced-alien ] [ 2drop f ] if ;
-
-! More efficient addressing for alien intrinsics
-: rewrite-alien-addressing ( insn -- insn' )
-    dup src>> vreg>expr dup add-imm-expr? [
-        [ src1>> vn>vreg ] [ src2>> vn>constant ] bi
-        [ >>src ] [ '[ _ + ] change-offset ] bi*
-    ] [ 2drop f ] if ;
-
-M: ##alien-unsigned-1 rewrite rewrite-alien-addressing ;
-M: ##alien-unsigned-2 rewrite rewrite-alien-addressing ;
-M: ##alien-unsigned-4 rewrite rewrite-alien-addressing ;
-M: ##alien-signed-1 rewrite rewrite-alien-addressing ;
-M: ##alien-signed-2 rewrite rewrite-alien-addressing ;
-M: ##alien-signed-4 rewrite rewrite-alien-addressing ;
-M: ##alien-float rewrite rewrite-alien-addressing ;
-M: ##alien-double rewrite rewrite-alien-addressing ;
-M: ##set-alien-integer-1 rewrite rewrite-alien-addressing ;
-M: ##set-alien-integer-2 rewrite rewrite-alien-addressing ;
-M: ##set-alien-integer-4 rewrite rewrite-alien-addressing ;
-M: ##set-alien-float rewrite rewrite-alien-addressing ;
-M: ##set-alien-double rewrite rewrite-alien-addressing ;
-
index 16d38bc5bb0ea75830a1372999c8353534063e54..1983c0719076ae58a8dad7e300493daf78dc7281 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors combinators combinators.short-circuit arrays
 fry kernel layouts math namespaces sequences cpu.architecture
@@ -7,23 +7,23 @@ vectors locals make alien.c-types io.binary grouping
 math.vectors.simd.intrinsics
 compiler.cfg
 compiler.cfg.registers
+compiler.cfg.utilities
 compiler.cfg.comparisons
 compiler.cfg.instructions
-compiler.cfg.value-numbering.expressions
+compiler.cfg.value-numbering.math
 compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.rewrite
-compiler.cfg.value-numbering.simplify ;
+compiler.cfg.value-numbering.rewrite ;
 IN: compiler.cfg.value-numbering.simd
 
-M: ##alien-vector rewrite rewrite-alien-addressing ;
-M: ##set-alien-vector rewrite rewrite-alien-addressing ;
-
 ! Some lame constant folding for SIMD intrinsics. Eventually this
 ! should be redone completely.
 
-: rewrite-shuffle-vector-imm ( insn expr -- insn' )
+: useless-shuffle-vector-imm? ( insn -- ? )
+    [ shuffle>> ] [ rep>> rep-length iota ] bi sequence= ;
+
+: compose-shuffle-vector-imm ( outer inner -- insn' )
     2dup [ rep>> ] bi@ eq? [
-        [ [ dst>> ] [ src>> vn>vreg ] bi* ]
+        [ [ dst>> ] [ src>> ] bi* ]
         [ [ shuffle>> ] bi@ nths ]
         [ drop rep>> ]
         2tri \ ##shuffle-vector-imm new-insn
@@ -32,65 +32,71 @@ M: ##set-alien-vector rewrite rewrite-alien-addressing ;
 : (fold-shuffle-vector-imm) ( shuffle bytes -- bytes' )
     2dup length swap length /i group nths concat ;
 
-: fold-shuffle-vector-imm ( insn expr -- insn' )
-    [ [ dst>> ] [ shuffle>> ] bi ] dip value>>
-    (fold-shuffle-vector-imm) \ ##load-constant new-insn ;
+: fold-shuffle-vector-imm ( outer inner -- insn' )
+    [ [ dst>> ] [ shuffle>> ] bi ] [ obj>> ] bi*
+    (fold-shuffle-vector-imm) \ ##load-reference new-insn ;
 
 M: ##shuffle-vector-imm rewrite
-    dup src>> vreg>expr {
-        { [ dup shuffle-vector-imm-expr? ] [ rewrite-shuffle-vector-imm ] }
-        { [ dup reference-expr? ] [ fold-shuffle-vector-imm ] }
-        { [ dup constant-expr? ] [ fold-shuffle-vector-imm ] }
+    dup src>> vreg>insn {
+        { [ over useless-shuffle-vector-imm? ] [ drop [ dst>> ] [ src>> ] bi <copy> ] }
+        { [ dup ##shuffle-vector-imm? ] [ compose-shuffle-vector-imm ] }
+        { [ dup ##load-reference? ] [ fold-shuffle-vector-imm ] }
         [ 2drop f ]
     } cond ;
 
 : (fold-scalar>vector) ( insn bytes -- insn' )
     [ [ dst>> ] [ rep>> rep-length ] bi ] dip <repetition> concat
-    \ ##load-constant new-insn ;
+    \ ##load-reference new-insn ;
 
-: fold-scalar>vector ( insn expr -- insn' )
-    value>> over rep>> {
+: fold-scalar>vector ( outer inner -- insn' )
+    obj>> over rep>> {
         { float-4-rep [ float>bits 4 >le (fold-scalar>vector) ] }
         { double-2-rep [ double>bits 8 >le (fold-scalar>vector) ] }
         [ [ untag-fixnum ] dip rep-component-type heap-size >le (fold-scalar>vector) ]
     } case ;
 
 M: ##scalar>vector rewrite
-    dup src>> vreg>expr dup constant-expr?
-    [ fold-scalar>vector ] [ 2drop f ] if ;
+    dup src>> vreg>insn {
+        { [ dup ##load-reference? ] [ fold-scalar>vector ] }
+        { [ dup ##vector>scalar? ] [ [ dst>> ] [ src>> ] bi* <copy> ] }
+        [ 2drop f ]
+    } cond ;
 
 M: ##xor-vector rewrite
-    dup [ src1>> vreg>vn ] [ src2>> vreg>vn ] bi eq?
+    dup diagonal?
     [ [ dst>> ] [ rep>> ] bi \ ##zero-vector new-insn ] [ drop f ] if ;
 
-: vector-not? ( expr -- ? )
+: vector-not? ( insn -- ? )
     {
-        [ not-vector-expr? ]
+        [ ##not-vector? ]
         [ {
-            [ xor-vector-expr? ]
-            [ [ src1>> ] [ src2>> ] bi [ vn>expr fill-vector-expr? ] either? ]
+            [ ##xor-vector? ]
+            [ [ src1>> ] [ src2>> ] bi [ vreg>insn ##fill-vector? ] either? ]
         } 1&& ]
     } 1|| ;
 
-GENERIC: vector-not-src ( expr -- vreg )
-M: not-vector-expr vector-not-src src>> vn>vreg ;
-M: xor-vector-expr vector-not-src
-    dup src1>> vn>expr fill-vector-expr? [ src2>> ] [ src1>> ] if vn>vreg ;
+GENERIC: vector-not-src ( insn -- vreg )
+
+M: ##not-vector vector-not-src
+    src>> ;
+
+M: ##xor-vector vector-not-src
+    dup src1>> vreg>insn ##fill-vector? [ src2>> ] [ src1>> ] if ;
 
 M: ##and-vector rewrite 
     {
-        { [ dup src1>> vreg>expr vector-not? ] [
+        { [ dup src1>> vreg>insn vector-not? ] [
             {
                 [ dst>> ]
-                [ src1>> vreg>expr vector-not-src ]
+                [ src1>> vreg>insn vector-not-src ]
                 [ src2>> ]
                 [ rep>> ]
             } cleave \ ##andn-vector new-insn
         ] }
-        { [ dup src2>> vreg>expr vector-not? ] [
+        { [ dup src2>> vreg>insn vector-not? ] [
             {
                 [ dst>> ]
-                [ src2>> vreg>expr vector-not-src ]
+                [ src2>> vreg>insn vector-not-src ]
                 [ src1>> ]
                 [ rep>> ]
             } cleave \ ##andn-vector new-insn
@@ -99,22 +105,11 @@ M: ##and-vector rewrite
     } cond ;
 
 M: ##andn-vector rewrite
-    dup src1>> vreg>expr vector-not? [
+    dup src1>> vreg>insn vector-not? [
         {
             [ dst>> ]
-            [ src1>> vreg>expr vector-not-src ]
+            [ src1>> vreg>insn vector-not-src ]
             [ src2>> ]
             [ rep>> ]
         } cleave \ ##and-vector new-insn
     ] [ drop f ] if ;
-
-M: scalar>vector-expr simplify*
-    src>> vn>expr {
-        { [ dup vector>scalar-expr? ] [ src>> ] }
-        [ drop f ]
-    } cond ;
-
-M: shuffle-vector-imm-expr simplify*
-    [ src>> ] [ shuffle>> ] [ rep>> rep-length iota ] tri
-    sequence= [ drop f ] unless ;
-
diff --git a/basis/compiler/cfg/value-numbering/simplify/simplify.factor b/basis/compiler/cfg/value-numbering/simplify/simplify.factor
deleted file mode 100644 (file)
index 7a95711..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors combinators classes math layouts
-sequences 
-compiler.cfg.instructions
-compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.expressions ;
-IN: compiler.cfg.value-numbering.simplify
-
-! Return value of f means we didn't simplify.
-GENERIC: simplify* ( expr -- vn/expr/f )
-
-M: copy-expr simplify* src>> ;
-
-: simplify-unbox-alien ( expr -- vn/expr/f )
-    src>> vn>expr dup box-alien-expr? [ src>> ] [ drop f ] if ;
-
-M: unbox-alien-expr simplify* simplify-unbox-alien ;
-
-M: unbox-any-c-ptr-expr simplify* simplify-unbox-alien ;
-
-: expr-zero? ( expr -- ? ) T{ constant-expr f 0 } = ; inline
-
-: expr-one? ( expr -- ? ) T{ constant-expr f 1 } = ; inline
-
-: expr-neg-one? ( expr -- ? ) T{ constant-expr f -1 } = ; inline
-
-: >unary-expr< ( expr -- in ) src>> vn>expr ; inline
-
-M: neg-expr simplify*
-    >unary-expr< {
-        { [ dup neg-expr? ] [ src>> ] }
-        [ drop f ]
-    } cond ;
-
-M: not-expr simplify*
-    >unary-expr< {
-        { [ dup not-expr? ] [ src>> ] }
-        [ drop f ]
-    } cond ;
-
-: >binary-expr< ( expr -- in1 in2 )
-    [ src1>> vn>expr ] [ src2>> vn>expr ] bi ; inline
-
-: simplify-add ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ over expr-zero? ] [ nip ] }
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: add-expr simplify* simplify-add ;
-M: add-imm-expr simplify* simplify-add ;
-
-: simplify-sub ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: sub-expr simplify* simplify-sub ;
-M: sub-imm-expr simplify* simplify-sub ;
-
-: simplify-mul ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ over expr-one? ] [ drop ] }
-        { [ dup expr-one? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: mul-expr simplify* simplify-mul ;
-M: mul-imm-expr simplify* simplify-mul ;
-
-: simplify-and ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ 2dup eq? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: and-expr simplify* simplify-and ;
-M: and-imm-expr simplify* simplify-and ;
-
-: simplify-or ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ 2dup eq? ] [ drop ] }
-        { [ over expr-zero? ] [ nip ] }
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: or-expr simplify* simplify-or ;
-M: or-imm-expr simplify* simplify-or ;
-
-: simplify-xor ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ over expr-zero? ] [ nip ] }
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: xor-expr simplify* simplify-xor ;
-M: xor-imm-expr simplify* simplify-xor ;
-
-: useless-shr? ( in1 in2 -- ? )
-    over shl-imm-expr?
-    [ [ src2>> ] [ expr>vn ] bi* = ] [ 2drop f ] if ; inline
-
-: simplify-shr ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ 2dup useless-shr? ] [ drop src1>> ] }
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: shr-expr simplify* simplify-shr ;
-M: shr-imm-expr simplify* simplify-shr ;
-
-: simplify-shl ( expr -- vn/expr/f )
-    >binary-expr< {
-        { [ dup expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ; inline
-
-M: shl-expr simplify* simplify-shl ;
-M: shl-imm-expr simplify* simplify-shl ;
-
-M: box-displaced-alien-expr simplify*
-    [ base>> ] [ displacement>> ] bi {
-        { [ dup vn>expr expr-zero? ] [ drop ] }
-        [ 2drop f ]
-    } cond ;
-
-M: expr simplify* drop f ;
-
-: simplify ( expr -- vn )
-    dup simplify* {
-        { [ dup not ] [ drop expr>vn ] }
-        { [ dup expr? ] [ expr>vn nip ] }
-        { [ dup integer? ] [ nip ] }
-    } cond ;
-
-: number-values ( insn -- )
-    [ >expr simplify ] [ dst>> ] bi set-vn ;
diff --git a/basis/compiler/cfg/value-numbering/simplify/summary.txt b/basis/compiler/cfg/value-numbering/simplify/summary.txt
deleted file mode 100644 (file)
index 1027c83..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Algebraic simplification of expressions
diff --git a/basis/compiler/cfg/value-numbering/slots/authors.txt b/basis/compiler/cfg/value-numbering/slots/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/compiler/cfg/value-numbering/slots/slots.factor b/basis/compiler/cfg/value-numbering/slots/slots.factor
new file mode 100644 (file)
index 0000000..7c2b562
--- /dev/null
@@ -0,0 +1,24 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators.short-circuit cpu.architecture fry
+kernel math
+compiler.cfg.instructions
+compiler.cfg.value-numbering.graph
+compiler.cfg.value-numbering.rewrite ;
+IN: compiler.cfg.value-numbering.slots
+
+: simplify-slot-addressing? ( insn -- ? )
+    complex-addressing?
+    [ slot>> vreg>insn ##add-imm? ] [ drop f ] if ;
+
+: simplify-slot-addressing ( insn -- insn/f )
+    dup simplify-slot-addressing? [
+        dup slot>> vreg>insn
+        [ src1>> >>slot ]
+        [ src2>> over scale>> '[ _ _ shift - ] change-tag ]
+        bi
+    ] [ drop f ] if ;
+
+M: ##slot rewrite simplify-slot-addressing ;
+M: ##set-slot rewrite simplify-slot-addressing ;
+M: ##write-barrier rewrite simplify-slot-addressing ;
index f835200702efc2d5f9e20188e8e4790d446c33d2..00d8652279c4d9f401c1cf6a2055f7a2113b367c 100644 (file)
@@ -6,6 +6,7 @@ compiler.cfg.ssa.destruction compiler.cfg.loop-detection
 compiler.cfg.representations compiler.cfg assocs vectors arrays
 layouts literals namespaces alien compiler.cfg.value-numbering.simd
 system ;
+QUALIFIED-WITH: alien.c-types c
 IN: compiler.cfg.value-numbering.tests
 
 : trim-temps ( insns -- insns )
@@ -13,6 +14,8 @@ IN: compiler.cfg.value-numbering.tests
         dup {
             [ ##compare? ]
             [ ##compare-imm? ]
+            [ ##compare-integer? ]
+            [ ##compare-integer-imm? ]
             [ ##compare-float-unordered? ]
             [ ##compare-float-ordered? ]
             [ ##test-vector? ]
@@ -23,66 +26,156 @@ IN: compiler.cfg.value-numbering.tests
 ! Folding constants together
 [
     {
-        T{ ##load-constant f 0 0.0 }
-        T{ ##load-constant f 1 -0.0 }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
+        T{ ##load-reference f 0 0.0 }
+        T{ ##load-reference f 1 -0.0 }
     }
 ] [
     {
-        T{ ##load-constant f 0 0.0 }
-        T{ ##load-constant f 1 -0.0 }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
+        T{ ##load-reference f 0 0.0 }
+        T{ ##load-reference f 1 -0.0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##load-constant f 0 0.0 }
+        T{ ##load-reference f 0 0.0 }
         T{ ##copy f 1 0 any-rep }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
     }
 ] [
     {
-        T{ ##load-constant f 0 0.0 }
-        T{ ##load-constant f 1 0.0 }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
+        T{ ##load-reference f 0 0.0 }
+        T{ ##load-reference f 1 0.0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##load-constant f 0 t }
+        T{ ##load-reference f 0 t }
         T{ ##copy f 1 0 any-rep }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
     }
 ] [
     {
-        T{ ##load-constant f 0 t }
-        T{ ##load-constant f 1 t }
-        T{ ##replace f 0 D 0 }
-        T{ ##replace f 1 D 1 }
+        T{ ##load-reference f 0 t }
+        T{ ##load-reference f 1 t }
     } value-numbering-step
 ] unit-test
 
-! Compare propagation
+! ##load-reference/##replace fusion
+cpu x86? [
+    [
+        {
+            T{ ##load-integer f 0 10 }
+            T{ ##replace-imm f 10 D 0 }
+        }
+    ] [
+        {
+            T{ ##load-integer f 0 10 }
+            T{ ##replace f 0 D 0 }
+        } value-numbering-step
+    ] unit-test
+
+    [
+        {
+            T{ ##load-reference f 0 f }
+            T{ ##replace-imm f f D 0 }
+        }
+    ] [
+        {
+            T{ ##load-reference f 0 f }
+            T{ ##replace f 0 D 0 }
+        } value-numbering-step
+    ] unit-test
+] when
+
+cpu x86.32? [
+    [
+        {
+            T{ ##load-reference f 0 + }
+            T{ ##replace-imm f + D 0 }
+        }
+    ] [
+        {
+            T{ ##load-reference f 0 + }
+            T{ ##replace f 0 D 0 }
+        } value-numbering-step
+    ] unit-test
+] when
+
+cpu x86.64? [
+    [
+        {
+            T{ ##load-integer f 0 10,000,000,000 }
+            T{ ##replace f 0 D 0 }
+        }
+    ] [
+        {
+            T{ ##load-integer f 0 10,000,000,000 }
+            T{ ##replace f 0 D 0 }
+        } value-numbering-step
+    ] unit-test
+
+    ! Boundary case
+    [
+        {
+            T{ ##load-integer f 0 HEX: 7fffffff }
+            T{ ##replace f 0 D 0 }
+        }
+    ] [
+        {
+            T{ ##load-integer f 0 HEX: 7fffffff }
+            T{ ##replace f 0 D 0 }
+        } value-numbering-step
+    ] unit-test
+] when
+
+! Double compare elimination
+[
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare f 4 2 1 cc= }
+        T{ ##copy f 6 4 any-rep }
+        T{ ##replace f 6 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare f 4 2 1 cc= }
+        T{ ##compare-imm f 6 4 f cc/= }
+        T{ ##replace f 6 D 0 }
+    } value-numbering-step trim-temps
+] unit-test
+
+[
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-imm f 2 1 16 cc= }
+        T{ ##copy f 3 2 any-rep }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-imm f 2 1 16 cc= }
+        T{ ##compare-imm f 3 2 f cc/= }
+        T{ ##replace f 3 D 0 }
+    } value-numbering-step trim-temps
+] unit-test
+
 [
     {
-        T{ ##load-reference f 1 + }
-        T{ ##peek f 2 D 0 }
-        T{ ##compare f 4 2 1 cc> }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare-integer f 4 2 1 cc> }
         T{ ##copy f 6 4 any-rep }
         T{ ##replace f 6 D 0 }
     }
 ] [
     {
-        T{ ##load-reference f 1 + }
-        T{ ##peek f 2 D 0 }
-        T{ ##compare f 4 2 1 cc> }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare-integer f 4 2 1 cc> }
         T{ ##compare-imm f 6 4 f cc/= }
         T{ ##replace f 6 D 0 }
     } value-numbering-step trim-temps
@@ -90,22 +183,38 @@ IN: compiler.cfg.value-numbering.tests
 
 [
     {
-        T{ ##load-reference f 1 + }
-        T{ ##peek f 2 D 0 }
-        T{ ##compare f 4 2 1 cc<= }
-        T{ ##compare f 6 2 1 cc/<= }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare-integer f 4 2 1 cc<= }
+        T{ ##compare-integer f 6 2 1 cc/<= }
         T{ ##replace f 6 D 0 }
     }
 ] [
     {
-        T{ ##load-reference f 1 + }
-        T{ ##peek f 2 D 0 }
-        T{ ##compare f 4 2 1 cc<= }
+        T{ ##peek f 1 D 1 }
+        T{ ##peek f 2 D 2 }
+        T{ ##compare-integer f 4 2 1 cc<= }
         T{ ##compare-imm f 6 4 f cc= }
         T{ ##replace f 6 D 0 }
     } value-numbering-step trim-temps
 ] unit-test
 
+[
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-imm f 2 1 100 cc<= }
+        T{ ##compare-integer-imm f 3 1 100 cc/<= }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 1 D 1 }
+        T{ ##compare-integer-imm f 2 1 100 cc<= }
+        T{ ##compare-imm f 3 2 f cc= }
+        T{ ##replace f 3 D 0 }
+    } value-numbering-step trim-temps
+] unit-test
+
 [
     {
         T{ ##peek f 8 D 0 }
@@ -128,14 +237,30 @@ IN: compiler.cfg.value-numbering.tests
     {
         T{ ##peek f 29 D -1 }
         T{ ##peek f 30 D -2 }
-        T{ ##compare f 33 29 30 cc<= }
-        T{ ##compare-branch f 29 30 cc<= }
+        T{ ##compare f 33 29 30 cc= }
+        T{ ##compare-branch f 29 30 cc= }
+    }
+] [
+    {
+        T{ ##peek f 29 D -1 }
+        T{ ##peek f 30 D -2 }
+        T{ ##compare f 33 29 30 cc= }
+        T{ ##compare-imm-branch f 33 f cc/= }
+    } value-numbering-step trim-temps
+] unit-test
+
+[
+    {
+        T{ ##peek f 29 D -1 }
+        T{ ##peek f 30 D -2 }
+        T{ ##compare-integer f 33 29 30 cc<= }
+        T{ ##compare-integer-branch f 29 30 cc<= }
     }
 ] [
     {
         T{ ##peek f 29 D -1 }
         T{ ##peek f 30 D -2 }
-        T{ ##compare f 33 29 30 cc<= }
+        T{ ##compare-integer f 33 29 30 cc<= }
         T{ ##compare-imm-branch f 33 f cc/= }
     } value-numbering-step trim-temps
 ] unit-test
@@ -154,17 +279,33 @@ IN: compiler.cfg.value-numbering.tests
     } value-numbering-step trim-temps
 ] unit-test
 
-! Immediate operand conversion
+cpu x86.32? [
+    [
+        {
+            T{ ##peek f 1 D 0 }
+            T{ ##compare-imm f 2 1 + cc= }
+            T{ ##compare-imm-branch f 1 + cc= }
+        }
+    ] [
+        {
+            T{ ##peek f 1 D 0 }
+            T{ ##compare-imm f 2 1 + cc= }
+            T{ ##compare-imm-branch f 2 f cc/= }
+        } value-numbering-step trim-temps
+    ] unit-test
+] when
+
+! Immediate operand fusion
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -172,13 +313,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -186,13 +327,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##add-imm f 2 0 -100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##sub f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -200,7 +341,7 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 0 }
+        T{ ##load-integer f 1 0 }
     }
 ] [
     {
@@ -212,13 +353,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##mul-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##mul f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -226,13 +367,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##mul-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##mul f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -252,13 +393,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -1 }
+        T{ ##load-integer f 1 -1 }
         T{ ##neg f 2 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -1 }
+        T{ ##load-integer f 1 -1 }
         T{ ##mul f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -266,13 +407,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -1 }
+        T{ ##load-integer f 1 -1 }
         T{ ##neg f 2 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -1 }
+        T{ ##load-integer f 1 -1 }
         T{ ##mul f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -280,13 +421,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 0 }
+        T{ ##load-integer f 1 0 }
         T{ ##neg f 2 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 0 }
+        T{ ##load-integer f 1 0 }
         T{ ##sub f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -294,19 +435,33 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 0 }
+        T{ ##load-integer f 1 0 }
         T{ ##neg f 2 0 }
         T{ ##copy f 3 0 any-rep }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 0 }
+        T{ ##load-integer f 1 0 }
         T{ ##sub f 2 1 0 }
         T{ ##sub f 3 1 2 }
     } value-numbering-step
 ] unit-test
 
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##neg f 1 0 }
+        T{ ##copy f 2 0 any-rep }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##neg f 1 0 }
+        T{ ##neg f 2 1 }
+    } value-numbering-step
+] unit-test
+
 [
     {
         T{ ##peek f 0 D 0 }
@@ -324,13 +479,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##and-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##and f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -338,13 +493,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##and-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##and f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -352,13 +507,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##or-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##or f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -366,13 +521,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##or-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##or f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -380,13 +535,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##xor-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##xor f 2 0 1 }
     } value-numbering-step
 ] unit-test
@@ -394,13 +549,13 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##xor-imm f 2 0 100 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
+        T{ ##load-integer f 1 100 }
         T{ ##xor f 2 1 0 }
     } value-numbering-step
 ] unit-test
@@ -408,14 +563,28 @@ IN: compiler.cfg.value-numbering.tests
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-imm f 2 0 100 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-imm f 2 0 100 cc= }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare f 2 0 1 cc= }
+    } value-numbering-step trim-temps
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-imm f 2 0 100 cc<= }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare f 2 0 1 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer f 2 0 1 cc<= }
     } value-numbering-step trim-temps
 ] unit-test
 
@@ -423,13 +592,13 @@ cpu x86.32? [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-constant f 1 + }
+            T{ ##load-reference f 1 + }
             T{ ##compare-imm f 2 0 + cc= }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-constant f 1 + }
+            T{ ##load-reference f 1 + }
             T{ ##compare f 2 0 1 cc= }
         } value-numbering-step trim-temps
     ] unit-test
@@ -437,443 +606,1016 @@ cpu x86.32? [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-constant f 1 + }
+            T{ ##load-reference f 1 + }
             T{ ##compare-imm-branch f 0 + cc= }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-constant f 1 + }
+            T{ ##load-reference f 1 + }
             T{ ##compare-branch f 0 1 cc= }
         } value-numbering-step trim-temps
     ] unit-test
 ] when
 
+cpu x86.32? [
+    [
+        {
+            T{ ##peek f 0 D 0 }
+            T{ ##load-reference f 1 3.5 }
+            T{ ##compare f 2 0 1 cc= }
+        }
+    ] [
+        {
+            T{ ##peek f 0 D 0 }
+            T{ ##load-reference f 1 3.5 }
+            T{ ##compare f 2 0 1 cc= }
+        } value-numbering-step trim-temps
+    ] unit-test
+
+    [
+        {
+            T{ ##peek f 0 D 0 }
+            T{ ##load-reference f 1 3.5 }
+            T{ ##compare-branch f 0 1 cc= }
+        }
+    ] [
+        {
+            T{ ##peek f 0 D 0 }
+            T{ ##load-reference f 1 3.5 }
+            T{ ##compare-branch f 0 1 cc= }
+        } value-numbering-step trim-temps
+    ] unit-test
+] unless
+
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 3.5 }
-        T{ ##compare f 2 0 1 cc= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-imm f 2 0 100 cc>= }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 3.5 }
-        T{ ##compare f 2 0 1 cc= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer f 2 1 0 cc<= }
     } value-numbering-step trim-temps
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 3.5 }
-        T{ ##compare-branch f 0 1 cc= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-imm-branch f 0 100 cc<= }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 3.5 }
-        T{ ##compare-branch f 0 1 cc= }
-    } value-numbering-step trim-temps
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-branch f 0 1 cc<= }
+    } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-imm f 2 0 100 cc>= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-imm-branch f 0 100 cc>= }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare f 2 1 0 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-branch f 1 0 cc<= }
     } value-numbering-step trim-temps
 ] unit-test
 
+! Compare folding
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-imm-branch f 0 100 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##load-integer f 2 200 }
+        T{ ##load-reference f 3 t }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-branch f 0 1 cc<= }
-    } value-numbering-step
+        T{ ##load-integer f 1 100 }
+        T{ ##load-integer f 2 200 }
+        T{ ##compare-integer f 3 1 2 cc<= }
+    } value-numbering-step trim-temps
 ] unit-test
 
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-imm-branch f 0 100 cc>= }
+        T{ ##load-integer f 1 100 }
+        T{ ##load-integer f 2 200 }
+        T{ ##load-reference f 3 f }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-branch f 1 0 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##load-integer f 2 200 }
+        T{ ##compare-integer f 3 1 2 cc= }
     } value-numbering-step trim-temps
 ] unit-test
 
-! Branch folding
 [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##load-immediate f 2 200 }
-        T{ ##load-constant f 3 t }
+        T{ ##load-integer f 1 100 }
+        T{ ##load-reference f 2 f }
     }
 ] [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##load-immediate f 2 200 }
-        T{ ##compare f 3 1 2 cc<= }
+        T{ ##load-integer f 1 100 }
+        T{ ##compare-integer-imm f 2 1 123 cc= }
     } value-numbering-step trim-temps
 ] unit-test
 
 [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##load-immediate f 2 200 }
-        T{ ##load-constant f 3 f }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-integer f 2 20 }
+        T{ ##load-reference f 3 f }
     }
 ] [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##load-immediate f 2 200 }
-        T{ ##compare f 3 1 2 cc= }
-    } value-numbering-step trim-temps
+        T{ ##load-integer f 1 10 }
+        T{ ##load-integer f 2 20 }
+        T{ ##compare-integer f 3 1 2 cc= }
+    } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##load-constant f 2 f }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##load-reference f 3 t }
     }
 ] [
     {
-        T{ ##load-immediate f 1 100 }
-        T{ ##compare-imm f 2 1 f cc= }
-    } value-numbering-step trim-temps
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##compare-integer f 3 1 2 cc/= }
+    } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##load-constant f 1 f }
-        T{ ##load-constant f 2 t }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##load-reference f 3 t }
     }
 ] [
     {
-        T{ ##load-constant f 1 f }
-        T{ ##compare-imm f 2 1 f cc= }
-    } value-numbering-step trim-temps
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##compare-integer f 3 1 2 cc< }
+    } value-numbering-step
 ] unit-test
 
-! Reassociation
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add-imm f 4 0 150 }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-integer f 2 20 }
+        T{ ##load-reference f 3 f }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add f 4 2 3 }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-integer f 2 20 }
+        T{ ##compare-integer f 3 2 1 cc< }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add-imm f 4 0 150 }
+        T{ ##load-reference f 1 f }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add f 2 1 0 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add f 4 3 2 }
+        T{ ##compare-integer f 1 0 0 cc< }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add-imm f 4 0 50 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##load-reference f 2 f }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##sub f 4 2 3 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##compare-integer f 2 0 1 cc< }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##add-imm f 2 0 -100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##add-imm f 4 0 -150 }
+        T{ ##load-reference f 1 t }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##sub f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##sub f 4 2 3 }
+        T{ ##compare-integer f 1 0 0 cc<= }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##mul-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##mul-imm f 4 0 5000 }
+        T{ ##load-reference f 1 f }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##mul f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##mul f 4 2 3 }
+        T{ ##compare-integer f 1 0 0 cc> }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##mul-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##mul-imm f 4 0 5000 }
+        T{ ##load-reference f 1 t }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##mul f 2 1 0 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##mul f 4 3 2 }
+        T{ ##compare-integer f 1 0 0 cc>= }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##and-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##and-imm f 4 0 32 }
+        T{ ##load-reference f 1 f }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##and f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##and f 4 2 3 }
+        T{ ##compare-integer f 1 0 0 cc/= }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##and-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##and-imm f 4 0 32 }
+        T{ ##load-reference f 1 t }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##and f 2 1 0 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##and f 4 3 2 }
+        T{ ##compare-integer f 1 0 0 cc= }
     } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##or-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##or-imm f 4 0 118 }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-reference f 2 t }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##or f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##or f 4 2 3 }
+        T{ ##load-integer f 1 10 }
+        T{ ##compare-imm f 2 1 10 cc= }
     } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##or-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##or-imm f 4 0 118 }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-reference f 2 f }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##or f 2 1 0 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##or f 4 3 2 }
+        T{ ##load-integer f 1 10 }
+        T{ ##compare-imm f 2 1 20 cc= }
     } value-numbering-step
 ] unit-test
 
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##xor-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##xor-imm f 4 0 86 }
+        T{ ##load-integer f 1 10 }
+        T{ ##load-reference f 2 t }
+    }
+] [
+    {
+        T{ ##load-integer f 1 10 }
+        T{ ##compare-imm f 2 1 100 cc/= }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##load-integer f 1 10 }
+        T{ ##load-reference f 2 f }
+    }
+] [
+    {
+        T{ ##load-integer f 1 10 }
+        T{ ##compare-imm f 2 1 10 cc/= }
+    } value-numbering-step
+] unit-test
+
+cpu x86.32? [
+    [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##load-reference f 2 f }
+        }
+    ] [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##compare-imm f 2 1 + cc/= }
+        } value-numbering-step
+    ] unit-test
+
+    [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##load-reference f 2 t }
+        }
+    ] [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##compare-imm f 2 1 * cc/= }
+        } value-numbering-step
+    ] unit-test
+
+    [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##load-reference f 2 t }
+        }
+    ] [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##compare-imm f 2 1 + cc= }
+        } value-numbering-step
+    ] unit-test
+
+    [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##load-reference f 2 f }
+        }
+    ] [
+        {
+            T{ ##load-reference f 1 + }
+            T{ ##compare-imm f 2 1 * cc= }
+        } value-numbering-step
+    ] unit-test
+] when
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-reference f 1 t }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##compare f 1 0 0 cc= }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-reference f 1 f }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##compare f 1 0 0 cc/= }
+    } value-numbering-step
+] unit-test
+
+! Reassociation
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add-imm f 4 0 150 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add-imm f 4 0 150 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add f 2 1 0 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add f 4 3 2 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add-imm f 4 0 50 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##sub f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##add-imm f 2 0 -100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##add-imm f 4 0 -150 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##sub f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##sub f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##mul-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##mul-imm f 4 0 5000 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##mul f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##mul f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##mul-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##mul-imm f 4 0 5000 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##mul f 2 1 0 }
+        T{ ##load-integer f 3 50 }
+        T{ ##mul f 4 3 2 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##and-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##and-imm f 4 0 32 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##and f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##and f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##and-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##and-imm f 4 0 32 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##and f 2 1 0 }
+        T{ ##load-integer f 3 50 }
+        T{ ##and f 4 3 2 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##or-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##or-imm f 4 0 118 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##or f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##or f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##or-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##or-imm f 4 0 118 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##or f 2 1 0 }
+        T{ ##load-integer f 3 50 }
+        T{ ##or f 4 3 2 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##xor-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##xor-imm f 4 0 86 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##xor f 2 0 1 }
+        T{ ##load-integer f 3 50 }
+        T{ ##xor f 4 2 3 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##xor-imm f 2 0 100 }
+        T{ ##load-integer f 3 50 }
+        T{ ##xor-imm f 4 0 86 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 100 }
+        T{ ##xor f 2 1 0 }
+        T{ ##load-integer f 3 50 }
+        T{ ##xor f 4 3 2 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 10 }
+        T{ ##shl-imm f 2 0 21 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 10 }
+        T{ ##shl-imm f 2 1 11 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 10 }
+        T{ ##shl-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shl-imm f 1 0 10 }
+        T{ ##shl-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sar-imm f 1 0 10 }
+        T{ ##sar-imm f 2 0 21 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sar-imm f 1 0 10 }
+        T{ ##sar-imm f 2 1 11 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sar-imm f 1 0 10 }
+        T{ ##sar-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sar-imm f 1 0 10 }
+        T{ ##sar-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##shr-imm f 2 0 21 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##shr-imm f 2 1 11 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##shr-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##shr-imm f 2 1 $[ cell-bits 1 - ] }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##sar-imm f 2 1 11 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##shr-imm f 1 0 10 }
+        T{ ##sar-imm f 2 1 11 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+! Distributive law
+2 \ vreg-counter set-global
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 10 }
+        T{ ##shl-imm f 3 0 2 }
+        T{ ##add-imm f 2 3 40 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 10 }
+        T{ ##shl-imm f 2 1 2 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 10 }
+        T{ ##mul-imm f 4 0 3 }
+        T{ ##add-imm f 2 4 30 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 10 }
+        T{ ##mul-imm f 2 1 3 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 -10 }
+        T{ ##shl-imm f 5 0 2 }
+        T{ ##add-imm f 2 5 -40 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sub-imm f 1 0 10 }
+        T{ ##shl-imm f 2 1 2 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##add-imm f 1 0 -10 }
+        T{ ##mul-imm f 6 0 3 }
+        T{ ##add-imm f 2 6 -30 }
+        T{ ##replace f 2 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##sub-imm f 1 0 10 }
+        T{ ##mul-imm f 2 1 3 }
+        T{ ##replace f 2 D 0 }
+    } value-numbering-step
+] unit-test
+
+! Simplification
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##copy f 3 0 any-rep }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##add-imm f 3 0 0 }
+        T{ ##replace f 3 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##copy f 3 0 any-rep }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##or-imm f 3 0 0 }
+        T{ ##replace f 3 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##copy f 3 0 any-rep }
+        T{ ##replace f 3 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##xor-imm f 3 0 0 }
+        T{ ##replace f 3 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##and-imm f 1 0 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##and-imm f 1 0 -1 }
+        T{ ##replace f 1 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##and f 1 0 0 }
+        T{ ##replace f 1 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##or-imm f 1 0 0 }
+        T{ ##replace f 1 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##load-integer f 1 -1 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##or-imm f 1 0 -1 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
+    }
+] [
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##or f 1 0 0 }
+        T{ ##replace f 1 D 0 }
+    } value-numbering-step
+] unit-test
+
+[
+    {
+        T{ ##peek f 0 D 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##xor f 2 0 1 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##xor f 4 2 3 }
+        T{ ##xor-imm f 1 0 0 }
+        T{ ##replace f 1 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##xor-imm f 2 0 100 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##xor-imm f 4 0 86 }
+        T{ ##not f 1 0 }
+        T{ ##replace f 1 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 100 }
-        T{ ##xor f 2 1 0 }
-        T{ ##load-immediate f 3 50 }
-        T{ ##xor f 4 3 2 }
+        T{ ##xor-imm f 1 0 -1 }
+        T{ ##replace f 1 D 0 }
     } value-numbering-step
 ] unit-test
 
-! Simplification
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##copy f 3 0 any-rep }
-        T{ ##replace f 3 D 0 }
+        T{ ##load-integer f 1 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##sub f 2 1 1 }
-        T{ ##add f 3 0 2 }
-        T{ ##replace f 3 D 0 }
+        T{ ##xor f 1 0 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##copy f 3 0 any-rep }
-        T{ ##replace f 3 D 0 }
+        T{ ##copy f 2 0 any-rep }
+        T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##sub f 2 1 1 }
-        T{ ##sub f 3 0 2 }
-        T{ ##replace f 3 D 0 }
+        T{ ##mul-imm f 2 0 1 }
+        T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##copy f 3 0 any-rep }
-        T{ ##replace f 3 D 0 }
+        T{ ##copy f 2 0 any-rep }
+        T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##sub f 2 1 1 }
-        T{ ##or f 3 0 2 }
-        T{ ##replace f 3 D 0 }
+        T{ ##shl-imm f 2 0 0 }
+        T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##copy f 3 0 any-rep }
-        T{ ##replace f 3 D 0 }
+        T{ ##copy f 2 0 any-rep }
+        T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##peek f 1 D 1 }
-        T{ ##sub f 2 1 1 }
-        T{ ##xor f 3 0 2 }
-        T{ ##replace f 3 D 0 }
+        T{ ##shr-imm f 2 0 0 }
+        T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
         T{ ##copy f 2 0 any-rep }
         T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##mul f 2 0 1 }
+        T{ ##sar-imm f 2 0 0 }
         T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
@@ -882,15 +1624,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 3 }
-        T{ ##load-immediate f 3 4 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 3 }
+        T{ ##load-integer f 3 4 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 3 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 3 }
         T{ ##add f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -898,15 +1640,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 3 }
-        T{ ##load-immediate f 3 -2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 3 }
+        T{ ##load-integer f 3 -2 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 3 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 3 }
         T{ ##sub f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -914,15 +1656,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 3 }
-        T{ ##load-immediate f 3 6 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 3 }
+        T{ ##load-integer f 3 6 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 3 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 3 }
         T{ ##mul f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -930,15 +1672,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 1 }
-        T{ ##load-immediate f 3 0 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 1 }
+        T{ ##load-integer f 3 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 1 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 1 }
         T{ ##and f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -946,15 +1688,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 1 }
-        T{ ##load-immediate f 3 3 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 1 }
+        T{ ##load-integer f 3 3 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 1 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 1 }
         T{ ##or f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -962,15 +1704,15 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 3 }
-        T{ ##load-immediate f 3 1 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 3 }
+        T{ ##load-integer f 3 1 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 2 }
-        T{ ##load-immediate f 2 3 }
+        T{ ##load-integer f 1 2 }
+        T{ ##load-integer f 2 3 }
         T{ ##xor f 3 1 2 }
     } value-numbering-step
 ] unit-test
@@ -978,13 +1720,13 @@ cpu x86.32? [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 3 8 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 3 8 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
+        T{ ##load-integer f 1 1 }
         T{ ##shl-imm f 3 1 3 }
     } value-numbering-step
 ] unit-test
@@ -993,13 +1735,13 @@ cell 8 = [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 1 -1 }
-            T{ ##load-immediate f 3 HEX: ffffffffffff }
+            T{ ##load-integer f 1 -1 }
+            T{ ##load-integer f 3 HEX: ffffffffffff }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 1 -1 }
+            T{ ##load-integer f 1 -1 }
             T{ ##shr-imm f 3 1 16 }
         } value-numbering-step
     ] unit-test
@@ -1008,13 +1750,13 @@ cell 8 = [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -8 }
-        T{ ##load-immediate f 3 -4 }
+        T{ ##load-integer f 1 -8 }
+        T{ ##load-integer f 3 -4 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 -8 }
+        T{ ##load-integer f 1 -8 }
         T{ ##sar-imm f 3 1 1 }
     } value-numbering-step
 ] unit-test
@@ -1023,14 +1765,14 @@ cell 8 = [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 1 65536 }
-            T{ ##load-immediate f 2 140737488355328 }
+            T{ ##load-integer f 1 65536 }
+            T{ ##load-integer f 2 140737488355328 }
             T{ ##add f 3 0 2 }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 1 65536 }
+            T{ ##load-integer f 1 65536 }
             T{ ##shl-imm f 2 1 31 }
             T{ ##add f 3 0 2 }
         } value-numbering-step
@@ -1039,13 +1781,13 @@ cell 8 = [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 2 140737488355328 }
+            T{ ##load-integer f 2 140737488355328 }
             T{ ##add f 3 0 2 }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 2 140737488355328 }
+            T{ ##load-integer f 2 140737488355328 }
             T{ ##add f 3 0 2 }
         } value-numbering-step
     ] unit-test
@@ -1053,14 +1795,14 @@ cell 8 = [
     [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 2 2147483647 }
+            T{ ##load-integer f 2 2147483647 }
             T{ ##add-imm f 3 0 2147483647 }
             T{ ##add-imm f 4 3 2147483647 }
         }
     ] [
         {
             T{ ##peek f 0 D 0 }
-            T{ ##load-immediate f 2 2147483647 }
+            T{ ##load-integer f 2 2147483647 }
             T{ ##add f 3 0 2 }
             T{ ##add f 4 3 2 }
         } value-numbering-step
@@ -1070,13 +1812,13 @@ cell 8 = [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 -1 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 -1 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
+        T{ ##load-integer f 1 1 }
         T{ ##neg f 2 1 }
     } value-numbering-step
 ] unit-test
@@ -1084,216 +1826,152 @@ cell 8 = [
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 -2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 -2 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 1 1 }
+        T{ ##load-integer f 1 1 }
         T{ ##not f 2 1 }
     } value-numbering-step
 ] unit-test
 
-! Stupid constant folding corner case
-[
-    {
-        T{ ##load-constant f 1 f }
-        T{ ##load-immediate f 2 $[ \ f type-number ] }
-    }
-] [
-    {
-        T{ ##load-constant f 1 f }
-        T{ ##and-imm f 2 1 15 }
-    } value-numbering-step
-] unit-test
-
-! Displaced alien optimizations
-3 vreg-counter set-global
-
+! ##tagged>integer constant folding
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 2 16 }
-        T{ ##box-displaced-alien f 1 2 0 c-ptr }
-        T{ ##unbox-any-c-ptr f 4 0 }
-        T{ ##add-imm f 3 4 16 }
+        T{ ##load-reference f 1 f }
+        T{ ##load-integer f 2 $[ \ f type-number ] }
+        T{ ##copy f 3 2 any-rep }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 2 16 }
-        T{ ##box-displaced-alien f 1 2 0 c-ptr }
-        T{ ##unbox-any-c-ptr f 3 1 }
+        T{ ##load-reference f 1 f }
+        T{ ##tagged>integer f 2 1 }
+        T{ ##and-imm f 3 2 15 }
     } value-numbering-step
 ] unit-test
 
-4 vreg-counter set-global
-
 [
     {
-        T{ ##box-alien f 0 1 }
-        T{ ##load-immediate f 2 16 }
-        T{ ##box-displaced-alien f 3 2 0 c-ptr }
-        T{ ##copy f 5 1 any-rep }
-        T{ ##add-imm f 4 5 16 }
+        T{ ##load-integer f 1 100 }
+        T{ ##load-integer f 2 $[ 100 tag-fixnum ] }
+        T{ ##load-integer f 3 $[ 100 tag-fixnum 1 + ] }
     }
 ] [
     {
-        T{ ##box-alien f 0 1 }
-        T{ ##load-immediate f 2 16 }
-        T{ ##box-displaced-alien f 3 2 0 c-ptr }
-        T{ ##unbox-any-c-ptr f 4 3 }
+        T{ ##load-integer f 1 100 }
+        T{ ##tagged>integer f 2 1 }
+        T{ ##add-imm f 3 2 1 }
     } value-numbering-step
 ] unit-test
 
-3 vreg-counter set-global
-
+! Alien boxing and unboxing
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##copy f 3 0 any-rep }
-        T{ ##replace f 3 D 1 }
+        T{ ##box-alien f 1 0 }
+        T{ ##copy f 2 0 any-rep }
+        T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-immediate f 2 0 }
-        T{ ##box-displaced-alien f 3 2 0 c-ptr }
-        T{ ##replace f 3 D 1 }
-    } value-numbering-step
-] unit-test
-
-! Branch folding
-[
-    {
-        T{ ##load-immediate f 1 10 }
-        T{ ##load-immediate f 2 20 }
-        T{ ##load-constant f 3 f }
-    }
-] [
-    {
-        T{ ##load-immediate f 1 10 }
-        T{ ##load-immediate f 2 20 }
-        T{ ##compare f 3 1 2 cc= }
-    } value-numbering-step
-] unit-test
-
-[
-    {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##load-constant f 3 t }
-    }
-] [
-    {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##compare f 3 1 2 cc/= }
-    } value-numbering-step
-] unit-test
-
-[
-    {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##load-constant f 3 t }
-    }
-] [
-    {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##compare f 3 1 2 cc< }
-    } value-numbering-step
-] unit-test
-
-[
-    {
-        T{ ##load-immediate f 1 10 }
-        T{ ##load-immediate f 2 20 }
-        T{ ##load-constant f 3 f }
-    }
-] [
-    {
-        T{ ##load-immediate f 1 10 }
-        T{ ##load-immediate f 2 20 }
-        T{ ##compare f 3 2 1 cc< }
+        T{ ##box-alien f 1 0 }
+        T{ ##unbox-alien f 2 1 }
+        T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 f }
+        T{ ##box-alien f 1 0 }
+        T{ ##copy f 2 0 any-rep }
+        T{ ##replace f 2 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc< }
+        T{ ##box-alien f 1 0 }
+        T{ ##unbox-any-c-ptr f 2 1 }
+        T{ ##replace f 2 D 0 }
     } value-numbering-step
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 t }
+        T{ ##load-integer f 2 0 }
+        T{ ##copy f 1 0 any-rep }
+        T{ ##replace f 1 D 0 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc<= }
+        T{ ##load-integer f 2 0 }
+        T{ ##box-displaced-alien f 1 2 0 c-ptr }
+        T{ ##replace f 1 D 0 }
     } value-numbering-step
 ] unit-test
 
-[
-    {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 f }
-    }
-] [
-    {
-        T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc> }
-    } value-numbering-step
-] unit-test
+3 vreg-counter set-global
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 t }
+        T{ ##load-integer f 2 16 }
+        T{ ##box-displaced-alien f 1 2 0 c-ptr }
+        T{ ##unbox-any-c-ptr f 4 0 }
+        T{ ##add-imm f 3 4 16 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc>= }
+        T{ ##load-integer f 2 16 }
+        T{ ##box-displaced-alien f 1 2 0 c-ptr }
+        T{ ##unbox-any-c-ptr f 3 1 }
     } value-numbering-step
 ] unit-test
 
+4 vreg-counter set-global
+
 [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 f }
+        T{ ##box-alien f 0 1 }
+        T{ ##load-integer f 2 16 }
+        T{ ##box-displaced-alien f 3 2 0 c-ptr }
+        T{ ##copy f 5 1 any-rep }
+        T{ ##add-imm f 4 5 16 }
     }
 ] [
     {
-        T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc/= }
+        T{ ##box-alien f 0 1 }
+        T{ ##load-integer f 2 16 }
+        T{ ##box-displaced-alien f 3 2 0 c-ptr }
+        T{ ##unbox-any-c-ptr f 4 3 }
     } value-numbering-step
 ] unit-test
 
+3 vreg-counter set-global
+
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 t }
+        T{ ##load-integer f 2 0 }
+        T{ ##copy f 3 0 any-rep }
+        T{ ##replace f 3 D 1 }
     }
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare f 1 0 0 cc= }
+        T{ ##load-integer f 2 0 }
+        T{ ##box-displaced-alien f 3 2 0 c-ptr }
+        T{ ##replace f 3 D 1 }
     } value-numbering-step
 ] unit-test
 
+! Various SIMD simplifications
 [
     {
         T{ ##vector>scalar f 1 0 float-4-rep }
@@ -1342,13 +2020,13 @@ cell 8 = [
 
 [
     {
-        T{ ##load-constant f 0 $[ 55 tag-fixnum ] }
-        T{ ##load-constant f 1 B{ 55 0 0 0  55 0 0 0  55 0 0 0  55 0 0 0 } }
-        T{ ##copy f 2 1 any-rep }
+        T{ ##load-reference f 0 $[ 55 tag-fixnum ] }
+        T{ ##load-reference f 1 B{ 55 0 0 0  55 0 0 0  55 0 0 0  55 0 0 0 } }
+        T{ ##load-reference f 2 B{ 55 0 0 0  55 0 0 0  55 0 0 0  55 0 0 0 } }
     }
 ] [
     {
-        T{ ##load-constant f 0 $[ 55 tag-fixnum ] }
+        T{ ##load-reference f 0 $[ 55 tag-fixnum ] }
         T{ ##scalar>vector f 1 0 int-4-rep }
         T{ ##shuffle-vector-imm f 2 1 { 0 0 0 0 } float-4-rep }
     } value-numbering-step
@@ -1356,13 +2034,13 @@ cell 8 = [
 
 [
     {
-        T{ ##load-constant f 0 1.25 }
-        T{ ##load-constant f 1 B{ 0 0 160 63 0 0 160 63 0 0 160 63 0 0 160 63 } }
-        T{ ##copy f 2 1 any-rep }
+        T{ ##load-reference f 0 1.25 }
+        T{ ##load-reference f 1 B{ 0 0 160 63 0 0 160 63 0 0 160 63 0 0 160 63 } }
+        T{ ##load-reference f 2 B{ 0 0 160 63 0 0 160 63 0 0 160 63 0 0 160 63 } }
     }
 ] [
     {
-        T{ ##load-constant f 0 1.25 }
+        T{ ##load-reference f 0 1.25 }
         T{ ##scalar>vector f 1 0 float-4-rep }
         T{ ##shuffle-vector-imm f 2 1 { 0 0 0 0 } float-4-rep }
     } value-numbering-step
@@ -1498,8 +2176,7 @@ cell 8 = [
     } value-numbering-step
 ] unit-test
 
-! branch folding
-
+! Branch folding
 : test-branch-folding ( insns -- insns' n )
     <basic-block>
     [ V{ 0 1 } clone >>successors basic-block set value-numbering-step ] keep
@@ -1507,61 +2184,61 @@ cell 8 = [
 
 [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##branch }
     }
     1
 ] [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##compare-branch f 1 2 cc= }
     } test-branch-folding
 ] unit-test
 
 [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##branch }
     }
     0
 ] [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##compare-branch f 1 2 cc/= }
     } test-branch-folding
 ] unit-test
 
 [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##branch }
     }
     0
 ] [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##compare-branch f 1 2 cc< }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##compare-integer-branch f 1 2 cc< }
     } test-branch-folding
 ] unit-test
 
 [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
         T{ ##branch }
     }
     1
 ] [
     {
-        T{ ##load-immediate f 1 1 }
-        T{ ##load-immediate f 2 2 }
-        T{ ##compare-branch f 2 1 cc< }
+        T{ ##load-integer f 1 1 }
+        T{ ##load-integer f 2 2 }
+        T{ ##compare-integer-branch f 2 1 cc< }
     } test-branch-folding
 ] unit-test
 
@@ -1574,7 +2251,7 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc< }
+        T{ ##compare-integer-branch f 0 0 cc< }
     } test-branch-folding
 ] unit-test
 
@@ -1587,7 +2264,7 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc<= }
+        T{ ##compare-integer-branch f 0 0 cc<= }
     } test-branch-folding
 ] unit-test
 
@@ -1600,7 +2277,7 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc> }
+        T{ ##compare-integer-branch f 0 0 cc> }
     } test-branch-folding
 ] unit-test
 
@@ -1613,7 +2290,7 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc>= }
+        T{ ##compare-integer-branch f 0 0 cc>= }
     } test-branch-folding
 ] unit-test
 
@@ -1626,7 +2303,7 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc= }
+        T{ ##compare-integer-branch f 0 0 cc= }
     } test-branch-folding
 ] unit-test
 
@@ -1639,14 +2316,14 @@ cell 8 = [
 ] [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##compare-branch f 0 0 cc/= }
+        T{ ##compare-integer-branch f 0 0 cc/= }
     } test-branch-folding
 ] unit-test
 
 [
     {
         T{ ##peek f 0 D 0 }
-        T{ ##load-constant f 1 t }
+        T{ ##load-reference f 1 t }
         T{ ##branch }
     }
     0
@@ -1663,16 +2340,16 @@ V{ T{ ##branch } } 0 test-bb
 
 V{
     T{ ##peek f 0 D 0 }
-    T{ ##compare-branch f 0 0 cc< }
+    T{ ##compare-integer-branch f 0 0 cc< }
 } 1 test-bb
 
 V{
-    T{ ##load-immediate f 1 1 }
+    T{ ##load-integer f 1 1 }
     T{ ##branch }
 } 2 test-bb
 
 V{
-    T{ ##load-immediate f 2 2 }
+    T{ ##load-integer f 2 2 }
     T{ ##branch }
 } 3 test-bb
 
@@ -1704,7 +2381,7 @@ V{
 
 V{
     T{ ##peek f 1 D 1 }
-    T{ ##compare-branch f 1 1 cc< }
+    T{ ##compare-integer-branch f 1 1 cc< }
 } 1 test-bb
 
 V{
@@ -1713,7 +2390,7 @@ V{
 } 2 test-bb
 
 V{
-    T{ ##phi f 3 V{ } }
+    T{ ##phi f 3 H{ { 1 1 } { 2 0 } } }
     T{ ##branch }
 } 3 test-bb
 
@@ -1722,9 +2399,6 @@ V{
     T{ ##return }
 } 4 test-bb
 
-1 get 1 2array
-2 get 0 2array 2array 3 get instructions>> first (>>inputs)
-
 test-diamond
 
 [ ] [
@@ -1803,3 +2477,239 @@ V{
 
 [ f ] [ 1 get instructions>> [ ##peek? ] any? ] unit-test
 
+! Slot addressing optimization
+cpu x86? [
+    [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##peek f 1 D 1 }
+            T{ ##add-imm f 2 1 2 }
+            T{ ##slot f 3 0 1 $[ cell log2 ] $[ 7 2 cells - ] }
+        }
+    ] [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##peek f 1 D 1 }
+            T{ ##add-imm f 2 1 2 }
+            T{ ##slot f 3 0 2 $[ cell log2 ] 7 }
+        } value-numbering-step
+    ] unit-test
+] when
+
+! Alien addressing optimization
+
+! Base offset fusion on ##load/store-memory-imm
+[
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##tagged>integer f 2 1 }
+        T{ ##add-imm f 3 2 10 }
+        T{ ##load-memory-imm f 4 2 10 int-rep c:uchar }
+    }
+] [
+    V{
+        T{ ##peek f 1 D 0 }
+        T{ ##tagged>integer f 2 1 }
+        T{ ##add-imm f 3 2 10 }
+        T{ ##load-memory-imm f 4 3 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 10 }
+        T{ ##store-memory-imm f 2 3 10 int-rep c:uchar }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 10 }
+        T{ ##store-memory-imm f 2 4 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+! Displacement fusion on ##load/store-memory-imm
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add f 4 2 3 }
+        T{ ##load-memory f 5 2 3 0 0 int-rep c:uchar }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add f 4 2 3 }
+        T{ ##load-memory-imm f 5 4 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add f 4 2 3 }
+        T{ ##store-memory f 5 2 3 0 0 int-rep c:uchar }
+    }
+] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add f 4 2 3 }
+        T{ ##store-memory-imm f 5 4 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+! Base offset fusion on ##load/store-memory -- only on x86
+cpu x86?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 2 31337 }
+        T{ ##load-memory f 5 2 3 0 31337 int-rep c:uchar }
+    }
+]
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 2 31337 }
+        T{ ##load-memory f 5 4 3 0 0 int-rep c:uchar }
+    }
+] ?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 2 31337 }
+        T{ ##load-memory f 5 4 3 0 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+! Displacement offset fusion on ##load/store-memory -- only on x86
+cpu x86?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 31337 }
+        T{ ##load-memory f 5 2 3 0 31338 int-rep c:uchar }
+    }
+]
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 31337 }
+        T{ ##load-memory f 5 2 4 0 1 int-rep c:uchar }
+    }
+] ?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 31337 }
+        T{ ##load-memory f 5 2 4 0 1 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+! Displacement offset fusion should not occur on
+! ##load/store-memory with non-zero scale
+[ ] [
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##add-imm f 4 3 10 }
+        T{ ##load-memory f 5 2 4 1 1 int-rep c:uchar }
+    } dup value-numbering-step assert=
+] unit-test
+
+! Scale fusion on ##load/store-memory
+cpu x86?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##shl-imm f 4 3 2 }
+        T{ ##load-memory f 5 2 3 2 0 int-rep c:uchar }
+    }
+]
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##shl-imm f 4 3 2 }
+        T{ ##load-memory f 5 2 4 0 0 int-rep c:uchar }
+    }
+] ?
+[
+    V{
+        T{ ##peek f 0 D 0 }
+        T{ ##peek f 1 D 1 }
+        T{ ##tagged>integer f 2 0 }
+        T{ ##tagged>integer f 3 1 }
+        T{ ##shl-imm f 4 3 2 }
+        T{ ##load-memory f 5 2 4 0 0 int-rep c:uchar }
+    } value-numbering-step
+] unit-test
+
+cpu x86? [
+    ! Don't do scale fusion if there's already a scale
+    [ ] [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##peek f 1 D 1 }
+            T{ ##tagged>integer f 2 0 }
+            T{ ##tagged>integer f 3 1 }
+            T{ ##shl-imm f 4 3 2 }
+            T{ ##load-memory f 5 2 4 1 0 int-rep c:uchar }
+        } dup value-numbering-step assert=
+    ] unit-test
+
+    ! Don't do scale fusion if the scale factor is out of range
+    [ ] [
+        V{
+            T{ ##peek f 0 D 0 }
+            T{ ##peek f 1 D 1 }
+            T{ ##tagged>integer f 2 0 }
+            T{ ##tagged>integer f 3 1 }
+            T{ ##shl-imm f 4 3 4 }
+            T{ ##load-memory f 5 2 4 0 0 int-rep c:uchar }
+        } dup value-numbering-step assert=
+    ] unit-test
+] when
index 96ca3efcf243ecd5d61265dce57f5d2bf3c1a00d..23fae4932e2b9d2e9c3c354ab0bdc077f4813c5e 100644 (file)
@@ -1,31 +1,47 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces assocs kernel accessors
-sorting sets sequences arrays
+USING: namespaces arrays assocs kernel accessors
+sorting sets sequences locals
 cpu.architecture
 sequences.deep
 compiler.cfg
 compiler.cfg.rpo
 compiler.cfg.def-use
+compiler.cfg.utilities
 compiler.cfg.instructions
+compiler.cfg.value-numbering.alien
+compiler.cfg.value-numbering.comparisons
 compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.expressions
-compiler.cfg.value-numbering.simplify
-compiler.cfg.value-numbering.rewrite ;
+compiler.cfg.value-numbering.math
+compiler.cfg.value-numbering.rewrite
+compiler.cfg.value-numbering.slots
+compiler.cfg.value-numbering.misc
+compiler.cfg.value-numbering.expressions ;
 IN: compiler.cfg.value-numbering
 
-! Local value numbering.
+GENERIC: process-instruction ( insn -- insn' )
 
-: >copy ( insn -- insn/##copy )
-    dup defs-vreg dup vreg>vn vn>vreg
-    2dup eq? [ 2drop ] [ any-rep \ ##copy new-insn nip ] if ;
+: redundant-instruction ( insn vn -- insn' )
+    [ dst>> ] dip [ swap set-vn ] [ <copy> ] 2bi ;
 
-GENERIC: process-instruction ( insn -- insn' )
+:: useful-instruction ( insn expr -- insn' )
+    insn dst>> :> vn
+    vn vn vregs>vns get set-at
+    vn expr exprs>vns get set-at
+    insn vn vns>insns get set-at
+    insn ;
+
+: check-redundancy ( insn -- insn' )
+    dup >expr dup exprs>vns get at
+    [ redundant-instruction ] [ useful-instruction ] ?if ;
 
 M: insn process-instruction
     dup rewrite
     [ process-instruction ]
-    [ dup defs-vreg [ dup number-values >copy ] when ] ?if ;
+    [ dup defs-vreg [ check-redundancy ] when ] ?if ;
+
+M: ##copy process-instruction
+    dup [ src>> vreg>vn ] [ dst>> ] bi set-vn ;
 
 M: array process-instruction
     [ process-instruction ] map ;
@@ -34,7 +50,7 @@ M: array process-instruction
     init-value-graph
     [ process-instruction ] map flatten ;
 
-: value-numbering ( cfg -- cfg' )
-    [ value-numbering-step ] local-optimization
+: value-numbering ( cfg -- cfg )
+    dup [ value-numbering-step ] simple-optimization
 
     cfg-changed predecessors-changed ;
index cecf5f7251fc87e72d37660405519c6e1060d9d2..a34bf6c07f4e0477664add53265d2c284e67a507 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
+! Copyright (C) 2008, 2010 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs combinators.short-circuit
 compiler.cfg.instructions compiler.cfg.rpo kernel namespaces
@@ -35,10 +35,10 @@ M: ##copy eliminate-write-barrier
 
 M: insn eliminate-write-barrier drop t ;
 
-: write-barriers-step ( bb -- )
+: write-barriers-step ( insns -- insns' )
     H{ } clone fresh-allocations set
     H{ } clone mutated-objects set
-    instructions>> [ eliminate-write-barrier ] filter! drop ;
+    [ eliminate-write-barrier ] filter! ;
 
-: eliminate-write-barriers ( cfg -- cfg' )
-    dup [ write-barriers-step ] each-basic-block ;
+: eliminate-write-barriers ( cfg -- cfg )
+    dup [ write-barriers-step ] simple-optimization ;
diff --git a/basis/compiler/codegen/alien/alien.factor b/basis/compiler/codegen/alien/alien.factor
new file mode 100644 (file)
index 0000000..5123b1c
--- /dev/null
@@ -0,0 +1,231 @@
+! Copyright (C) 2008, 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien alien.complex alien.c-types
+alien.libraries alien.private alien.strings arrays
+classes.struct combinators compiler.alien
+compiler.cfg.instructions compiler.codegen
+compiler.codegen.fixup compiler.errors compiler.utilities
+cpu.architecture fry kernel layouts libc locals make math
+math.order math.parser namespaces quotations sequences strings ;
+FROM: compiler.errors => no-such-symbol ;
+IN: compiler.codegen.alien
+
+! ##alien-invoke
+GENERIC: next-fastcall-param ( rep -- )
+
+: ?dummy-stack-params ( rep -- )
+    dummy-stack-params? [ rep-size cell align stack-params +@ ] [ drop ] if ;
+
+: ?dummy-int-params ( rep -- )
+    dummy-int-params? [ rep-size cell /i 1 max int-regs +@ ] [ drop ] if ;
+
+: ?dummy-fp-params ( rep -- )
+    drop dummy-fp-params? [ float-regs inc ] when ;
+
+M: int-rep next-fastcall-param
+    int-regs inc [ ?dummy-stack-params ] [ ?dummy-fp-params ] bi ;
+
+M: float-rep next-fastcall-param
+    float-regs inc [ ?dummy-stack-params ] [ ?dummy-int-params ] bi ;
+
+M: double-rep next-fastcall-param
+    float-regs inc [ ?dummy-stack-params ] [ ?dummy-int-params ] bi ;
+
+GENERIC# reg-class-full? 1 ( reg-class abi -- ? )
+
+M: stack-params reg-class-full? 2drop t ;
+
+M: reg-class reg-class-full?
+    [ get ] swap '[ _ param-regs length ] bi >= ;
+
+: alloc-stack-param ( rep -- n reg-class rep )
+    stack-params get
+    [ rep-size cell align stack-params +@ ] dip
+    stack-params dup ;
+
+: alloc-fastcall-param ( rep -- n reg-class rep )
+    [ [ reg-class-of get ] [ reg-class-of ] [ next-fastcall-param ] tri ] keep ;
+
+:: alloc-parameter ( parameter abi -- reg rep )
+    parameter c-type-rep dup reg-class-of abi reg-class-full?
+    [ alloc-stack-param ] [ alloc-fastcall-param ] if
+    [ abi param-reg ] dip ;
+
+SYMBOL: (stack-value)
+<< void* c-type clone \ (stack-value) define-primitive-type
+stack-params \ (stack-value) c-type (>>rep) >>
+
+: ((flatten-type)) ( type to-type -- seq )
+    [ stack-size cell align cell /i ] dip c-type <repetition> ; inline
+
+: (flatten-int-type) ( type -- seq )
+    void* ((flatten-type)) ;
+: (flatten-stack-type) ( type -- seq )
+    (stack-value) ((flatten-type)) ;
+
+GENERIC: flatten-value-type ( type -- types )
+
+M: object flatten-value-type 1array ;
+M: struct-c-type flatten-value-type (flatten-int-type) ;
+M: long-long-type flatten-value-type (flatten-int-type) ;
+M: c-type-name flatten-value-type c-type flatten-value-type ;
+
+: flatten-value-types ( params -- params )
+    #! Convert value type structs to consecutive void*s.
+    [
+        0 [
+            c-type
+            [ parameter-align cell /i void* c-type <repetition> % ] keep
+            [ stack-size cell align + ] keep
+            flatten-value-type %
+        ] reduce drop
+    ] { } make ;
+
+: each-parameter ( parameters quot -- )
+    [ [ parameter-offsets nip ] keep ] dip 2each ; inline
+
+: reset-fastcall-counts ( -- )
+    { int-regs float-regs stack-params } [ 0 swap set ] each ;
+
+: with-param-regs ( quot -- )
+    #! In quot you can call alloc-parameter
+    [ reset-fastcall-counts call ] with-scope ; inline
+
+: move-parameters ( node word -- )
+    #! Moves values from C stack to registers (if word is
+    #! %load-param-reg) and registers to C stack (if word is
+    #! %save-param-reg).
+    [ [ alien-parameters flatten-value-types ] [ abi>> ] bi ]
+    [ '[ _ alloc-parameter _ execute ] ]
+    bi* each-parameter ; inline
+
+: reverse-each-parameter ( parameters quot -- )
+    [ [ parameter-offsets nip ] keep ] dip 2reverse-each ; inline
+
+: prepare-unbox-parameters ( parameters -- offsets types indices )
+    [ parameter-offsets nip ] [ ] [ length iota <reversed> ] tri ;
+
+: unbox-parameters ( offset node -- )
+    parameters>> swap
+    '[ prepare-unbox-parameters [ %pop-stack [ _ + ] dip unbox-parameter ] 3each ]
+    [ length neg %inc-d ]
+    bi ;
+
+: prepare-box-struct ( node -- offset )
+    #! Return offset on C stack where to store unboxed
+    #! parameters. If the C function is returning a structure,
+    #! the first parameter is an implicit target area pointer,
+    #! so we need to use a different offset.
+    return>> large-struct?
+    [ %prepare-box-struct cell ] [ 0 ] if ;
+
+: objects>registers ( params -- )
+    #! Generate code for unboxing a list of C types, then
+    #! generate code for moving these parameters to registers on
+    #! architectures where parameters are passed in registers.
+    [
+        [ prepare-box-struct ] keep
+        [ unbox-parameters ] keep
+        \ %load-param-reg move-parameters
+    ] with-param-regs ;
+
+: box-return* ( node -- )
+    return>> [ ] [ box-return %push-stack ] if-void ;
+
+GENERIC# dlsym-valid? 1 ( symbols dll -- ? )
+
+M: string dlsym-valid? dlsym ;
+
+M: array dlsym-valid? '[ _ dlsym ] any? ;
+
+: check-dlsym ( symbols dll -- )
+    dup dll-valid? [
+        dupd dlsym-valid?
+        [ drop ] [ compiling-word get no-such-symbol ] if
+    ] [
+        dll-path compiling-word get no-such-library drop
+    ] if ;
+
+: decorated-symbol ( params -- symbols )
+    [ function>> ] [ parameters>> parameter-offsets drop number>string ] bi
+    {
+        [ drop ]
+        [ "@" glue ]
+        [ "@" glue "_" prepend ]
+        [ "@" glue "@" prepend ]
+    } 2cleave
+    4array ;
+
+: alien-invoke-dlsym ( params -- symbols dll )
+    [ dup abi>> callee-cleanup? [ decorated-symbol ] [ function>> ] if ]
+    [ library>> load-library ]
+    bi 2dup check-dlsym ;
+
+M: ##alien-invoke generate-insn
+    params>>
+    ! Unbox parameters
+    dup objects>registers
+    %prepare-var-args
+    ! Call function
+    dup alien-invoke-dlsym %alien-invoke
+    ! Box return value
+    dup %cleanup
+    box-return* ;
+
+M: ##alien-assembly generate-insn
+    params>>
+    ! Unbox parameters
+    dup objects>registers
+    %prepare-var-args
+    ! Generate assembly
+    dup quot>> call( -- )
+    ! Box return value
+    box-return* ;
+
+! ##alien-indirect
+M: ##alien-indirect generate-insn
+    params>>
+    ! Save alien at top of stack to temporary storage
+    %prepare-alien-indirect
+    ! Unbox parameters
+    dup objects>registers
+    %prepare-var-args
+    ! Call alien in temporary storage
+    %alien-indirect
+    ! Box return value
+    dup %cleanup
+    box-return* ;
+
+! ##alien-callback
+: box-parameters ( params -- )
+    alien-parameters [ box-parameter %push-context-stack ] each-parameter ;
+
+: registers>objects ( node -- )
+    ! Generate code for boxing input parameters in a callback.
+    [
+        dup \ %save-param-reg move-parameters
+        %begin-callback
+        box-parameters
+    ] with-param-regs ;
+
+: callback-return-quot ( ctype -- quot )
+    return>> {
+        { [ dup void? ] [ drop [ ] ] }
+        { [ dup large-struct? ] [ heap-size '[ _ memcpy ] ] }
+        [ c-type c-type-unboxer-quot ]
+    } cond ;
+
+: callback-prep-quot ( params -- quot )
+    parameters>> [ c-type c-type-boxer-quot ] map spread>quot ;
+
+: wrap-callback-quot ( params -- quot )
+    [ callback-prep-quot ] [ quot>> ] [ callback-return-quot ] tri 3append
+     yield-hook get
+     '[ _ _ do-callback ]
+     >quotation ;
+
+M: ##alien-callback generate-insn
+    params>>
+    [ registers>objects ]
+    [ wrap-callback-quot %alien-callback ]
+    [ alien-return [ %end-callback ] [ %end-callback-value ] if-void ] tri ;
diff --git a/basis/compiler/codegen/alien/authors.txt b/basis/compiler/codegen/alien/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
index 99564b7e0e2b243a7b20235a474d3f9fb400e7a0..604fb2570e5fca937b29ef3b7a85c51e11052845 100755 (executable)
@@ -2,23 +2,20 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces make math math.order math.parser sequences
 accessors kernel layouts assocs words summary arrays combinators
-classes.algebra alien alien.private alien.c-types alien.strings
-alien.arrays alien.complex alien.libraries sets libc
-continuations.private fry cpu.architecture classes
-classes.struct locals source-files.errors slots parser
-generic.parser strings quotations
-compiler.errors
-compiler.alien
+classes.algebra sets continuations.private fry cpu.architecture
+classes classes.struct locals slots parser generic.parser
+strings quotations hashtables
 compiler.constants
 compiler.cfg
+compiler.cfg.linearization
 compiler.cfg.instructions
+compiler.cfg.comparisons
 compiler.cfg.stack-frame
 compiler.cfg.registers
 compiler.cfg.builder
 compiler.codegen.fixup
 compiler.utilities ;
 FROM: namespaces => set ;
-FROM: compiler.errors => no-such-symbol ;
 IN: compiler.codegen
 
 SYMBOL: insn-counts
@@ -27,45 +24,88 @@ H{ } clone insn-counts set-global
 
 GENERIC: generate-insn ( insn -- )
 
-! Mapping _label IDs to label instances
+! Control flow
 SYMBOL: labels
 
-: generate ( mr -- code )
-    dup label>> [
-        H{ } clone labels set
+: lookup-label ( bb -- label )
+    labels get [ drop <label> ] cache ;
+
+: useless-branch? ( bb successor -- ? )
+    ! If our successor immediately follows us in linearization
+    ! order then we don't need to branch.
+    [ block-number ] bi@ 1 - = ; inline
+
+: emit-branch ( bb successor -- )
+    2dup useless-branch?
+    [ 2drop ] [ nip lookup-label %jump-label ] if ;
+
+M: ##branch generate-insn
+    drop basic-block get dup successors>> first emit-branch ;
+
+GENERIC: generate-conditional-insn ( label insn -- )
+
+GENERIC: negate-insn-cc ( insn -- )
+
+M: conditional-branch-insn negate-insn-cc
+    [ negate-cc ] change-cc drop ;
+
+M: ##test-vector-branch negate-insn-cc
+    [ negate-vcc ] change-vcc drop ;
+
+M:: conditional-branch-insn generate-insn ( insn -- )
+    basic-block get :> bb
+    bb successors>> first2 :> ( first second )
+    bb second useless-branch?
+    [ bb second first ]
+    [ bb first second insn negate-insn-cc ] if
+    lookup-label insn generate-conditional-insn
+    emit-branch ;
+
+: %dispatch-label ( label -- )
+    cell 0 <repetition> %
+    rc-absolute-cell label-fixup ;
+
+M: ##dispatch generate-insn
+    [ src>> ] [ temp>> ] bi %dispatch
+    basic-block get successors>>
+    [ lookup-label %dispatch-label ] each ;
+
+: generate-block ( bb -- )
+    [ basic-block set ]
+    [ lookup-label resolve-label ]
+    [
         instructions>> [
             [ class insn-counts get inc-at ]
             [ generate-insn ]
             bi
         ] each
-    ] with-fixup ;
+    ] tri ;
 
-: lookup-label ( id -- label )
-    labels get [ drop <label> ] cache ;
+: generate ( cfg -- code )
+    dup label>> [
+        H{ } clone labels set
+        linearization-order
+        [ number-blocks ] [ [ generate-block ] each ] bi
+    ] with-fixup ;
 
 ! Special cases
 M: ##no-tco generate-insn drop ;
 
-M: _dispatch-label generate-insn
-    label>> lookup-label
-    cell 0 <repetition> %
-    rc-absolute-cell label-fixup ;
-
-M: _prologue generate-insn
-    stack-frame>> [ stack-frame set ] [ total-size>> %prologue ] bi ;
+M: ##prologue generate-insn
+    drop
+    cfg get stack-frame>>
+    [ [ stack-frame set ] [ total-size>> %prologue ] bi ] when* ;
 
-M: _epilogue generate-insn
-    stack-frame>> total-size>> %epilogue ;
-
-M: _spill-area-size generate-insn drop ;
+M: ##epilogue generate-insn
+    drop
+    cfg get stack-frame>> [ total-size>> %epilogue ] when* ;
 
 ! Some meta-programming to generate simple code generators, where
 ! the instruction is unpacked and then a %word is called
 <<
 
 : insn-slot-quot ( spec -- quot )
-    name>> [ reader-word ] [ "label" = ] bi
-    [ \ lookup-label [ ] 2sequence ] [ [ ] 1sequence ] if ;
+    name>> reader-word 1quotation ;
 
 : codegen-method-body ( class word -- quot )
     [
@@ -76,14 +116,17 @@ M: _spill-area-size generate-insn drop ;
 SYNTAX: CODEGEN:
     scan-word [ \ generate-insn create-method-in ] keep scan-word
     codegen-method-body define ;
+
 >>
 
-CODEGEN: ##load-immediate %load-immediate
+CODEGEN: ##load-integer %load-immediate
+CODEGEN: ##load-tagged %load-immediate
 CODEGEN: ##load-reference %load-reference
-CODEGEN: ##load-constant %load-reference
 CODEGEN: ##load-double %load-double
+CODEGEN: ##load-vector %load-vector
 CODEGEN: ##peek %peek
 CODEGEN: ##replace %replace
+CODEGEN: ##replace-imm %replace-imm
 CODEGEN: ##inc-d %inc-d
 CODEGEN: ##inc-r %inc-r
 CODEGEN: ##call %call
@@ -93,8 +136,6 @@ CODEGEN: ##slot %slot
 CODEGEN: ##slot-imm %slot-imm
 CODEGEN: ##set-slot %set-slot
 CODEGEN: ##set-slot-imm %set-slot-imm
-CODEGEN: ##string-nth %string-nth
-CODEGEN: ##set-string-nth-fast %set-string-nth-fast
 CODEGEN: ##add %add
 CODEGEN: ##add-imm %add-imm
 CODEGEN: ##sub %sub
@@ -119,6 +160,7 @@ CODEGEN: ##not %not
 CODEGEN: ##neg %neg
 CODEGEN: ##log2 %log2
 CODEGEN: ##copy %copy
+CODEGEN: ##tagged>integer %tagged>integer
 CODEGEN: ##add-float %add-float
 CODEGEN: ##sub-float %sub-float
 CODEGEN: ##mul-float %mul-float
@@ -187,316 +229,43 @@ CODEGEN: ##box-alien %box-alien
 CODEGEN: ##box-displaced-alien %box-displaced-alien
 CODEGEN: ##unbox-alien %unbox-alien
 CODEGEN: ##unbox-any-c-ptr %unbox-any-c-ptr
-CODEGEN: ##alien-unsigned-1 %alien-unsigned-1
-CODEGEN: ##alien-unsigned-2 %alien-unsigned-2
-CODEGEN: ##alien-unsigned-4 %alien-unsigned-4
-CODEGEN: ##alien-signed-1 %alien-signed-1
-CODEGEN: ##alien-signed-2 %alien-signed-2
-CODEGEN: ##alien-signed-4 %alien-signed-4
-CODEGEN: ##alien-cell %alien-cell
-CODEGEN: ##alien-float %alien-float
-CODEGEN: ##alien-double %alien-double
-CODEGEN: ##alien-vector %alien-vector
-CODEGEN: ##set-alien-integer-1 %set-alien-integer-1
-CODEGEN: ##set-alien-integer-2 %set-alien-integer-2
-CODEGEN: ##set-alien-integer-4 %set-alien-integer-4
-CODEGEN: ##set-alien-cell %set-alien-cell
-CODEGEN: ##set-alien-float %set-alien-float
-CODEGEN: ##set-alien-double %set-alien-double
-CODEGEN: ##set-alien-vector %set-alien-vector
+CODEGEN: ##load-memory %load-memory
+CODEGEN: ##load-memory-imm %load-memory-imm
+CODEGEN: ##store-memory %store-memory
+CODEGEN: ##store-memory-imm %store-memory-imm
 CODEGEN: ##allot %allot
 CODEGEN: ##write-barrier %write-barrier
 CODEGEN: ##write-barrier-imm %write-barrier-imm
 CODEGEN: ##compare %compare
 CODEGEN: ##compare-imm %compare-imm
+CODEGEN: ##compare-integer %compare
+CODEGEN: ##compare-integer-imm %compare-integer-imm
 CODEGEN: ##compare-float-ordered %compare-float-ordered
 CODEGEN: ##compare-float-unordered %compare-float-unordered
 CODEGEN: ##save-context %save-context
 CODEGEN: ##vm-field %vm-field
 CODEGEN: ##set-vm-field %set-vm-field
+CODEGEN: ##alien-global %alien-global
+CODEGEN: ##call-gc %call-gc
+CODEGEN: ##spill %spill
+CODEGEN: ##reload %reload
 
-CODEGEN: _fixnum-add %fixnum-add
-CODEGEN: _fixnum-sub %fixnum-sub
-CODEGEN: _fixnum-mul %fixnum-mul
-CODEGEN: _label resolve-label
-CODEGEN: _branch %jump-label
-CODEGEN: _compare-branch %compare-branch
-CODEGEN: _compare-imm-branch %compare-imm-branch
-CODEGEN: _compare-float-ordered-branch %compare-float-ordered-branch
-CODEGEN: _compare-float-unordered-branch %compare-float-unordered-branch
-CODEGEN: _test-vector-branch %test-vector-branch
-CODEGEN: _dispatch %dispatch
-CODEGEN: _spill %spill
-CODEGEN: _reload %reload
-
-! ##gc
-: wipe-locs ( locs temp -- )
-    '[
-        _
-        [ 0 %load-immediate ]
-        [ swap [ %replace ] with each ] bi
-    ] unless-empty ;
-
-GENERIC# save-gc-root 1 ( gc-root operand temp -- )
-
-M:: spill-slot save-gc-root ( gc-root operand temp -- )
-    temp int-rep operand %reload
-    gc-root temp %save-gc-root ;
-
-M: object save-gc-root drop %save-gc-root ;
-
-: save-gc-roots ( gc-roots temp -- ) '[ _ save-gc-root ] assoc-each ;
-
-: save-data-regs ( data-regs -- ) [ first3 %spill ] each ;
-
-GENERIC# load-gc-root 1 ( gc-root operand temp -- )
-
-M:: spill-slot load-gc-root ( gc-root operand temp -- )
-    gc-root temp %load-gc-root
-    temp int-rep operand %spill ;
-
-M: object load-gc-root drop %load-gc-root ;
-
-: load-gc-roots ( gc-roots temp -- ) '[ _ load-gc-root ] assoc-each ;
-
-: load-data-regs ( data-regs -- ) [ first3 %reload ] each ;
-
-M: ##gc generate-insn
-    "no-gc" define-label
-    {
-        [ [ "no-gc" get ] dip [ size>> ] [ temp1>> ] [ temp2>> ] tri %check-nursery ]
-        [ [ uninitialized-locs>> ] [ temp1>> ] bi wipe-locs ]
-        [ data-values>> save-data-regs ]
-        [ [ tagged-values>> ] [ temp1>> ] bi save-gc-roots ]
-        [ [ temp1>> ] [ temp2>> ] bi %save-context ]
-        [ [ tagged-values>> length ] [ temp1>> ] bi %call-gc ]
-        [ [ tagged-values>> ] [ temp1>> ] bi load-gc-roots ]
-        [ data-values>> load-data-regs ]
-    } cleave
-    "no-gc" resolve-label ;
-
-M: _loop-entry generate-insn drop %loop-entry ;
-
-M: ##alien-global generate-insn
-    [ dst>> ] [ symbol>> ] [ library>> ] tri
-    %alien-global ;
-
-! ##alien-invoke
-GENERIC: next-fastcall-param ( rep -- )
-
-: ?dummy-stack-params ( rep -- )
-    dummy-stack-params? [ rep-size cell align stack-params +@ ] [ drop ] if ;
-
-: ?dummy-int-params ( rep -- )
-    dummy-int-params? [ rep-size cell /i 1 max int-regs +@ ] [ drop ] if ;
-
-: ?dummy-fp-params ( rep -- )
-    drop dummy-fp-params? [ float-regs inc ] when ;
-
-M: int-rep next-fastcall-param
-    int-regs inc [ ?dummy-stack-params ] [ ?dummy-fp-params ] bi ;
-
-M: float-rep next-fastcall-param
-    float-regs inc [ ?dummy-stack-params ] [ ?dummy-int-params ] bi ;
-
-M: double-rep next-fastcall-param
-    float-regs inc [ ?dummy-stack-params ] [ ?dummy-int-params ] bi ;
-
-GENERIC# reg-class-full? 1 ( reg-class abi -- ? )
-
-M: stack-params reg-class-full? 2drop t ;
-
-M: reg-class reg-class-full?
-    [ get ] swap '[ _ param-regs length ] bi >= ;
-
-: alloc-stack-param ( rep -- n reg-class rep )
-    stack-params get
-    [ rep-size cell align stack-params +@ ] dip
-    stack-params dup ;
-
-: alloc-fastcall-param ( rep -- n reg-class rep )
-    [ [ reg-class-of get ] [ reg-class-of ] [ next-fastcall-param ] tri ] keep ;
-
-:: alloc-parameter ( parameter abi -- reg rep )
-    parameter c-type-rep dup reg-class-of abi reg-class-full?
-    [ alloc-stack-param ] [ alloc-fastcall-param ] if
-    [ abi param-reg ] dip ;
-
-SYMBOL: (stack-value)
-<< void* c-type clone \ (stack-value) define-primitive-type
-stack-params \ (stack-value) c-type (>>rep) >>
-
-: ((flatten-type)) ( type to-type -- seq )
-    [ stack-size cell align cell /i ] dip c-type <repetition> ; inline
-
-: (flatten-int-type) ( type -- seq )
-    void* ((flatten-type)) ;
-: (flatten-stack-type) ( type -- seq )
-    (stack-value) ((flatten-type)) ;
-
-GENERIC: flatten-value-type ( type -- types )
-
-M: object flatten-value-type 1array ;
-M: struct-c-type flatten-value-type (flatten-int-type) ;
-M: long-long-type flatten-value-type (flatten-int-type) ;
-M: c-type-name flatten-value-type c-type flatten-value-type ;
-
-: flatten-value-types ( params -- params )
-    #! Convert value type structs to consecutive void*s.
-    [
-        0 [
-            c-type
-            [ parameter-align cell /i void* c-type <repetition> % ] keep
-            [ stack-size cell align + ] keep
-            flatten-value-type %
-        ] reduce drop
-    ] { } make ;
-
-: each-parameter ( parameters quot -- )
-    [ [ parameter-offsets nip ] keep ] dip 2each ; inline
-
-: reset-fastcall-counts ( -- )
-    { int-regs float-regs stack-params } [ 0 swap set ] each ;
-
-: with-param-regs ( quot -- )
-    #! In quot you can call alloc-parameter
-    [ reset-fastcall-counts call ] with-scope ; inline
-
-: move-parameters ( node word -- )
-    #! Moves values from C stack to registers (if word is
-    #! %load-param-reg) and registers to C stack (if word is
-    #! %save-param-reg).
-    [ [ alien-parameters flatten-value-types ] [ abi>> ] bi ]
-    [ '[ _ alloc-parameter _ execute ] ]
-    bi* each-parameter ; inline
-
-: reverse-each-parameter ( parameters quot -- )
-    [ [ parameter-offsets nip ] keep ] dip 2reverse-each ; inline
-
-: prepare-unbox-parameters ( parameters -- offsets types indices )
-    [ parameter-offsets nip ] [ ] [ length iota <reversed> ] tri ;
-
-: unbox-parameters ( offset node -- )
-    parameters>> swap
-    '[ prepare-unbox-parameters [ %pop-stack [ _ + ] dip unbox-parameter ] 3each ]
-    [ length neg %inc-d ]
-    bi ;
-
-: prepare-box-struct ( node -- offset )
-    #! Return offset on C stack where to store unboxed
-    #! parameters. If the C function is returning a structure,
-    #! the first parameter is an implicit target area pointer,
-    #! so we need to use a different offset.
-    return>> large-struct?
-    [ %prepare-box-struct cell ] [ 0 ] if ;
-
-: objects>registers ( params -- )
-    #! Generate code for unboxing a list of C types, then
-    #! generate code for moving these parameters to registers on
-    #! architectures where parameters are passed in registers.
-    [
-        [ prepare-box-struct ] keep
-        [ unbox-parameters ] keep
-        \ %load-param-reg move-parameters
-    ] with-param-regs ;
-
-: box-return* ( node -- )
-    return>> [ ] [ box-return %push-stack ] if-void ;
-
-GENERIC# dlsym-valid? 1 ( symbols dll -- ? )
-
-M: string dlsym-valid? dlsym ;
-
-M: array dlsym-valid? '[ _ dlsym ] any? ;
-
-: check-dlsym ( symbols dll -- )
-    dup dll-valid? [
-        dupd dlsym-valid?
-        [ drop ] [ compiling-word get no-such-symbol ] if
-    ] [
-        dll-path compiling-word get no-such-library drop
-    ] if ;
-
-: decorated-symbol ( params -- symbols )
-    [ function>> ] [ parameters>> parameter-offsets drop number>string ] bi
-    {
-        [ drop ]
-        [ "@" glue ]
-        [ "@" glue "_" prepend ]
-        [ "@" glue "@" prepend ]
-    } 2cleave
-    4array ;
-
-: alien-invoke-dlsym ( params -- symbols dll )
-    [ dup abi>> callee-cleanup? [ decorated-symbol ] [ function>> ] if ]
-    [ library>> load-library ]
-    bi 2dup check-dlsym ;
-
-M: ##alien-invoke generate-insn
-    params>>
-    ! Unbox parameters
-    dup objects>registers
-    %prepare-var-args
-    ! Call function
-    dup alien-invoke-dlsym %alien-invoke
-    ! Box return value
-    dup %cleanup
-    box-return* ;
-
-M: ##alien-assembly generate-insn
-    params>>
-    ! Unbox parameters
-    dup objects>registers
-    %prepare-var-args
-    ! Generate assembly
-    dup quot>> call( -- )
-    ! Box return value
-    box-return* ;
-
-! ##alien-indirect
-M: ##alien-indirect generate-insn
-    params>>
-    ! Save alien at top of stack to temporary storage
-    %prepare-alien-indirect
-    ! Unbox parameters
-    dup objects>registers
-    %prepare-var-args
-    ! Call alien in temporary storage
-    %alien-indirect
-    ! Box return value
-    dup %cleanup
-    box-return* ;
-
-! ##alien-callback
-: box-parameters ( params -- )
-    alien-parameters [ box-parameter %push-context-stack ] each-parameter ;
-
-: registers>objects ( node -- )
-    ! Generate code for boxing input parameters in a callback.
-    [
-        dup \ %save-param-reg move-parameters
-        %begin-callback
-        box-parameters
-    ] with-param-regs ;
-
-: callback-return-quot ( ctype -- quot )
-    return>> {
-        { [ dup void? ] [ drop [ ] ] }
-        { [ dup large-struct? ] [ heap-size '[ _ memcpy ] ] }
-        [ c-type c-type-unboxer-quot ]
-    } cond ;
+<<
 
-: callback-prep-quot ( params -- quot )
-    parameters>> [ c-type c-type-boxer-quot ] map spread>quot ;
+SYNTAX: CONDITIONAL:
+    scan-word [ \ generate-conditional-insn create-method-in ] keep scan-word
+    codegen-method-body define ;
 
-: wrap-callback-quot ( params -- quot )
-    [ callback-prep-quot ] [ quot>> ] [ callback-return-quot ] tri 3append
-     yield-hook get
-     '[ _ _ do-callback ]
-     >quotation ;
+>>
 
-M: ##alien-callback generate-insn
-    params>>
-    [ registers>objects ]
-    [ wrap-callback-quot %alien-callback ]
-    [ alien-return [ %end-callback ] [ %end-callback-value ] if-void ] tri ;
+CONDITIONAL: ##compare-branch %compare-branch
+CONDITIONAL: ##compare-imm-branch %compare-imm-branch
+CONDITIONAL: ##compare-integer-branch %compare-branch
+CONDITIONAL: ##compare-integer-imm-branch %compare-integer-imm-branch
+CONDITIONAL: ##compare-float-ordered-branch %compare-float-ordered-branch
+CONDITIONAL: ##compare-float-unordered-branch %compare-float-unordered-branch
+CONDITIONAL: ##test-vector-branch %test-vector-branch
+CONDITIONAL: ##check-nursery-branch %check-nursery-branch
+CONDITIONAL: ##fixnum-add %fixnum-add
+CONDITIONAL: ##fixnum-sub %fixnum-sub
+CONDITIONAL: ##fixnum-mul %fixnum-mul
index fa8dfc21492a496ff151cdf614f69e54ed8a36f9..427c7ff94c15f8ea27f84495359d88d378039d41 100644 (file)
@@ -7,6 +7,15 @@ system combinators math.bitwise math.order generalizations
 accessors growable fry compiler.constants memoize ;
 IN: compiler.codegen.fixup
 
+! Utilities
+: push-uint ( value vector -- )
+    [ length ] [ B{ 0 0 0 0 } swap push-all ] [ underlying>> ] tri
+    swap set-alien-unsigned-4 ;
+
+: push-double ( value vector -- )
+    [ length ] [ B{ 0 0 0 0 0 0 0 0 } swap push-all ] [ underlying>> ] tri
+    swap set-alien-double ;
+
 ! Owner
 SYMBOL: compiling-word
 
@@ -42,16 +51,18 @@ TUPLE: label-fixup { label label } { class integer } { offset integer } ;
 ! Relocation table
 SYMBOL: relocation-table
 
-: push-4 ( value vector -- )
-    [ length ] [ B{ 0 0 0 0 } swap push-all ] [ underlying>> ] tri
-    swap set-alien-unsigned-4 ;
-
 : add-relocation-entry ( type class offset -- )
-    { 0 24 28 } bitfield relocation-table get push-4 ;
+    { 0 24 28 } bitfield relocation-table get push-uint ;
 
 : rel-fixup ( class type -- )
     swap compiled-offset add-relocation-entry ;
 
+! Binary literal table
+SYMBOL: binary-literal-table
+
+: add-binary-literal ( obj -- label )
+    <label> [ 2array binary-literal-table get push ] keep ;
+
 ! Caching common symbol names reduces image size a bit
 MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
 
@@ -73,8 +84,8 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
 : rel-literal ( literal class -- )
     [ add-literal ] dip rt-literal rel-fixup ;
 
-: rel-float ( literal class -- )
-    [ add-literal ] dip rt-float rel-fixup ;
+: rel-binary-literal ( literal class -- )
+    [ add-binary-literal ] dip label-fixup ;
 
 : rel-this ( class -- )
     rt-this rel-fixup ;
@@ -92,20 +103,20 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
     rt-decks-offset rel-fixup ;
 
 ! And the rest
-: resolve-offset ( label-fixup -- offset )
+: compute-target ( label-fixup -- offset )
     label>> offset>> [ "Unresolved label" throw ] unless* ;
 
-: resolve-absolute-label ( label-fixup -- )
-    dup resolve-offset neg add-literal
-    [ rt-here ] dip [ class>> ] [ offset>> ] bi add-relocation-entry ;
+: compute-relative-label ( label-fixup -- label )
+    [ class>> ] [ offset>> ] [ compute-target ] tri 3array ;
 
-: resolve-relative-label ( label-fixup -- label )
-    [ class>> ] [ offset>> ] [ resolve-offset ] tri 3array ;
+: compute-absolute-label ( label-fixup -- )
+    [ compute-target neg add-literal ]
+    [ [ rt-here ] dip [ class>> ] [ offset>> ] bi add-relocation-entry ] bi ;
 
-: resolve-labels ( label-fixups -- labels' )
+: compute-labels ( label-fixups -- labels' )
     [ class>> rc-absolute? ] partition
-    [ [ resolve-absolute-label ] each ]
-    [ [ resolve-relative-label ] map concat ]
+    [ [ compute-absolute-label ] each ]
+    [ [ compute-relative-label ] map concat ]
     bi* ;
 
 : init-fixup ( word -- )
@@ -113,13 +124,39 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
     V{ } clone parameter-table set
     V{ } clone literal-table set
     V{ } clone label-table set
-    BV{ } clone relocation-table set ;
+    BV{ } clone relocation-table set
+    V{ } clone binary-literal-table set ;
+
+: alignment ( align -- n )
+    [ compiled-offset dup ] dip align swap - ;
+
+: (align-code) ( n -- )
+    0 <repetition> % ;
+
+: align-code ( n -- )
+    alignment (align-code) ;
+
+GENERIC# emit-data 1 ( obj label -- )
+
+M: float emit-data
+    8 align-code
+    resolve-label
+    building get push-double ;
+
+M: byte-array emit-data
+    16 align-code
+    resolve-label
+    building get push-all ;
+
+: emit-binary-literals ( -- )
+    binary-literal-table get [ emit-data ] assoc-each ;
 
 : with-fixup ( word quot -- code )
     '[
         init-fixup
         @
-        label-table [ resolve-labels ] change
+        emit-binary-literals
+        label-table [ compute-labels ] change
         parameter-table get >array
         literal-table get >array
         relocation-table get >byte-array
index 71fdd6cbaf7aff1adba54e13c8283d3566ee3707..4c8a9ca61d0e652390e4724d03ba17204a4b4004 100644 (file)
@@ -16,9 +16,10 @@ compiler.tree.optimizer
 compiler.cfg
 compiler.cfg.builder
 compiler.cfg.optimizer
-compiler.cfg.mr
+compiler.cfg.finalization
 
-compiler.codegen ;
+compiler.codegen
+compiler.codegen.alien ;
 IN: compiler
 
 SYMBOL: compiled
@@ -125,8 +126,10 @@ M: word combinator? inline? ;
 
 : backend ( tree word -- )
     build-cfg [
-        [ optimize-cfg build-mr ] with-cfg
-        [ generate ] [ label>> ] bi compiled get set-at
+        [
+            optimize-cfg finalize-cfg
+            [ generate ] [ label>> ] bi compiled get set-at
+        ] with-cfg
     ] each ;
 
 : compile-word ( word -- )
index 2fdf81452102efadde11ccef11bdf8f1883f3b02..f72a2c4ec57cd2749fecf5fe0f013cf190f33d69 100644 (file)
@@ -67,7 +67,6 @@ CONSTANT: rt-vm 9
 CONSTANT: rt-cards-offset 10
 CONSTANT: rt-decks-offset 11
 CONSTANT: rt-exception-handler 12
-CONSTANT: rt-float 13
 
 : rc-absolute? ( n -- ? )
     ${
index 288940e660e82a747dfaf32fee49a88de95d207e..2edb0167342d3755708e170646c80ab00cfe88f3 100644 (file)
@@ -462,3 +462,13 @@ TUPLE: myseq { underlying1 byte-array read-only } { underlying2 byte-array read-
     1 1
     [ [ HEX: f bitand ] bi@ [ shift ] [ drop -3 shift ] 2bi ] compile-call
 ] unit-test
+
+! GC root offsets were computed wrong on x86
+: gc-root-messup ( a -- b )
+    dup [
+        1024 (byte-array) 2array
+        10 void* "libc" "malloc" { ulong } alien-invoke
+        void "libc" "free" { void* } alien-invoke
+    ] when ;
+
+[ ] [ 2000 [ "hello" clone dup gc-root-messup first eq? t assert= ] times ] unit-test
index 0d4e30279e3d65fe656c58d8045e79794bea5e94..968587093696d1e19ad3c5ef96e16bf4751fccea 100644 (file)
@@ -1,6 +1,8 @@
 USING: compiler.units compiler.test kernel kernel.private memory
 math math.private tools.test math.floats.private math.order fry
-;
+specialized-arrays sequences ;
+QUALIFIED-WITH: alien.c-types c
+SPECIALIZED-ARRAY: c:float
 IN: compiler.tests.float
 
 [ 5.0 ] [ [ 5.0 ] compile-call gc gc gc ] unit-test
@@ -97,9 +99,6 @@ IN: compiler.tests.float
 [ 2 ] [ 3.0 1.0 [ float-unordered? [ 1 ] [ 2 ] if ] compile-call ] unit-test
 [ 2 ] [ 1.0 3.0 [ float-unordered? [ 1 ] [ 2 ] if ] compile-call ] unit-test
 
-! Ensure that float-min and min, and float-max and max, have
-! consistent behavior with respect to NaNs
-
 : two-floats ( a b -- a b ) { float float } declare ; inline
 
 [ -11.3 ] [ -11.3 17.5 [ two-floats min ] compile-call ] unit-test
@@ -107,12 +106,28 @@ IN: compiler.tests.float
 [ 17.5 ] [ -11.3 17.5 [ two-floats max ] compile-call ] unit-test
 [ 17.5 ] [ 17.5 -11.3 [ two-floats max ] compile-call ] unit-test
 
-: check-compiled-binary-op ( a b word -- )
-    [ '[ [ [ two-floats _ execute ] compile-call ] call( a b -- c ) ] ]
-    [ '[ _ execute ] ]
-    bi 2bi fp-bitwise= ; inline
-
-[ t ] [ 0/0. 3.0 \ min check-compiled-binary-op ] unit-test
-[ t ] [ 3.0 0/0. \ min check-compiled-binary-op ] unit-test
-[ t ] [ 0/0. 3.0 \ max check-compiled-binary-op ] unit-test
-[ t ] [ 3.0 0/0. \ max check-compiled-binary-op ] unit-test
+! Test loops
+[ 30.0 ] [
+    float-array{ 1 2 3 4 } float-array{ 1 2 3 4 }
+    [ { float-array float-array } declare [ * ] [ + ] 2map-reduce ] compile-call
+] unit-test
+
+[ 30.0 ] [
+    float-array{ 1 2 3 4 }
+    [ { float-array } declare dup [ * ] [ + ] 2map-reduce ] compile-call
+] unit-test
+
+[ 30.0 ] [
+    float-array{ 1 2 3 4 }
+    [ { float-array } declare [ dup * ] [ + ] map-reduce ] compile-call
+] unit-test
+
+[ 4.5 ] [
+    float-array{ 1.0 3.5 }
+    [ { float-array } declare 0.0 [ + ] reduce ] compile-call
+] unit-test
+
+[ float-array{ 2.0 4.5 } ] [
+    float-array{ 1.0 3.5 }
+    [ { float-array } declare [ 1 + ] map ] compile-call
+] unit-test
index 5f00d251cf8712ad927ef24b3b888f1737551c7d..4d0ae081271596689f3e326169fbab55cdb22227 100644 (file)
@@ -1,20 +1,22 @@
 USING: accessors assocs compiler compiler.cfg
-compiler.cfg.debugger compiler.cfg.instructions compiler.cfg.mr
-compiler.cfg.registers compiler.codegen compiler.units
-cpu.architecture hashtables kernel namespaces sequences
-tools.test vectors words layouts literals math arrays
-alien.syntax math.private ;
+compiler.cfg.debugger compiler.cfg.instructions
+compiler.cfg.registers compiler.cfg.linear-scan
+compiler.cfg.ssa.destruction compiler.cfg.build-stack-frame
+compiler.codegen compiler.units cpu.architecture hashtables
+kernel namespaces sequences tools.test vectors words layouts
+literals math arrays alien.c-types alien.syntax math.private ;
 IN: compiler.tests.low-level-ir
 
 : compile-cfg ( cfg -- word )
     gensym
-    [ build-mr generate ] dip
+    [ linear-scan build-stack-frame generate ] dip
     [ associate >alist t t modify-code-heap ] keep ;
 
 : compile-test-cfg ( -- word )
     cfg new 0 get >>entry
     dup cfg set
-    dup fake-representations representations get >>reps
+    dup fake-representations
+    destruct-ssa
     compile-cfg ;
 
 : compile-test-bb ( insns -- result )
@@ -34,12 +36,6 @@ IN: compiler.tests.low-level-ir
     execute( -- result ) ;
 
 ! loading constants
-[ f ] [
-    V{
-        T{ ##load-constant f 0 f }
-    } compile-test-bb
-] unit-test
-
 [ "hello" ] [
     V{
         T{ ##load-reference f 0 "hello" }
@@ -50,9 +46,9 @@ IN: compiler.tests.low-level-ir
 ! one of the sources
 [ t ] [
     V{
-        T{ ##load-immediate f 1 $[ 2 cell log2 shift array type-number - ] }
+        T{ ##load-tagged f 1 $[ 2 cell log2 shift array type-number - ] }
         T{ ##load-reference f 0 { t f t } }
-        T{ ##slot f 0 0 1 }
+        T{ ##slot f 0 0 1 0 0 }
     } compile-test-bb
 ] unit-test
 
@@ -65,9 +61,9 @@ IN: compiler.tests.low-level-ir
 
 [ t ] [
     V{
-        T{ ##load-immediate f 1 $[ 2 cell log2 shift array type-number - ] }
+        T{ ##load-tagged f 1 $[ 2 cell log2 shift array type-number - ] }
         T{ ##load-reference f 0 { t f t } }
-        T{ ##set-slot f 0 0 1 }
+        T{ ##set-slot f 0 0 1 0 0 }
     } compile-test-bb
     dup first eq?
 ] unit-test
@@ -82,14 +78,14 @@ IN: compiler.tests.low-level-ir
 
 [ 4 ] [
     V{
-        T{ ##load-immediate f 0 4 }
+        T{ ##load-tagged f 0 4 }
         T{ ##shl f 0 0 0 }
     } compile-test-bb
 ] unit-test
 
 [ 4 ] [
     V{
-        T{ ##load-immediate f 0 4 }
+        T{ ##load-tagged f 0 4 }
         T{ ##shl-imm f 0 0 4 }
     } compile-test-bb
 ] unit-test
@@ -98,23 +94,14 @@ IN: compiler.tests.low-level-ir
     V{
         T{ ##load-reference f 1 B{ 31 67 52 } }
         T{ ##unbox-any-c-ptr f 0 1 }
-        T{ ##alien-unsigned-1 f 0 0 0 }
-        T{ ##shl-imm f 0 0 4 }
-    } compile-test-bb
-] unit-test
-
-[ CHAR: l ] [
-    V{
-        T{ ##load-reference f 0 "hello world" }
-        T{ ##load-immediate f 1 3 }
-        T{ ##string-nth f 0 0 1 2 }
+        T{ ##load-memory-imm f 0 0 0 int-rep uchar }
         T{ ##shl-imm f 0 0 4 }
     } compile-test-bb
 ] unit-test
 
 [ 1 ] [
     V{
-        T{ ##load-immediate f 0 32 }
+        T{ ##load-tagged f 0 32 }
         T{ ##add-imm f 0 0 -16 }
     } compile-test-bb
 ] unit-test
index 55629507ab6f48ea3414d641fc55bb245dffc11e..7fb36c96fd76d9bdb732403d05605d7a12661500 100644 (file)
@@ -220,14 +220,6 @@ generic-comparison-ops [
     2bi and maybe-or-never
 ] "outputs" set-word-prop
 
-\ both-fixnums? [
-    [ class>> ] bi@ {
-        { [ 2dup [ fixnum classes-intersect? not ] either? ] [ f <literal-info> ] }
-        { [ 2dup [ fixnum class<= ] both? ] [ t <literal-info> ] }
-        [ object-info ]
-    } cond 2nip
-] "outputs" set-word-prop
-
 {
     { >fixnum fixnum }
     { bignum>fixnum fixnum }
@@ -254,8 +246,8 @@ generic-comparison-ops [
     ] "outputs" set-word-prop
 ] each
 
-\ string-nth [
-    2drop fixnum 0 23 2^ [a,b] <class/interval-info>
+\ string-nth-fast [
+    2drop fixnum 0 255 [a,b] <class/interval-info>
 ] "outputs" set-word-prop
 
 {
index ad8a75ecddcbc0785991efc969d3499fae938558..17701e94c1a8cd604ca3852711cc1faa2824c988 100644 (file)
@@ -8,7 +8,8 @@ layouts compiler.tree.propagation.info compiler.tree.def-use
 compiler.tree.debugger compiler.tree.checker slots.private words
 hashtables classes assocs locals specialized-arrays system
 sorting math.libm math.floats.private math.integers.private
-math.intervals quotations effects alien alien.data sets ;
+math.intervals quotations effects alien alien.data sets
+strings.private ;
 FROM: math => float ;
 SPECIALIZED-ARRAY: double
 SPECIALIZED-ARRAY: void*
@@ -968,3 +969,10 @@ M: tuple-with-read-only-slot clone
 
 [ t ] [ [ { 1 } diff ] { diff } inlined? ] unit-test
 [ f ] [ [ { 1 } swap diff ] { diff } inlined? ] unit-test ! We could do this
+
+! Output range for string-nth now that string-nth is a library word and
+! not a primitive
+[ t ] [
+    ! Should actually be 0 23 2^ 1 - [a,b]
+    [ string-nth ] final-info first interval>> 0 23 2^ [a,b] =
+] unit-test
index f8d43e37c414dc4038b66e585522873cb224b540..3d2d7ac298c17d42ed59abac16b300aec34b15c7 100644 (file)
@@ -313,3 +313,14 @@ M\ set intersect [ intersect-quot ] 1 define-partial-eval
         [ depends-on-definition ] [ heap-size '[ _ ] ] bi
     ] [ drop f ] if
 ] 1 define-partial-eval
+
+! Eliminates a few redundant checks here and there
+\ both-fixnums? [
+    in-d>> first2 [ value-info class>> ] bi@ {
+        { [ 2dup [ fixnum classes-intersect? not ] either? ] [ [ 2drop f ] ] }
+        { [ 2dup [ fixnum class<= ] both? ] [ [ 2drop t ] ] }
+        { [ dup fixnum class<= ] [ [ drop fixnum? ] ] }
+        { [ over fixnum class<= ] [ [ nip fixnum? ] ] }
+        [ f ]
+    } cond 2nip
+] "custom-inlining" set-word-prop
old mode 100644 (file)
new mode 100755 (executable)
index 340e455..f61a02c
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors combinators io kernel math namespaces
-prettyprint sequences vectors ;
+sequences vectors ;
 QUALIFIED-WITH: bitstreams bs
 IN: compression.lzw
 
index a98b5cbafb7e183496005c7e5b75dcb0a40c5055..8f69b247292a2a2f5a12538676cd450b7d965159 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2006, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs generic kernel kernel.private
-math memory namespaces make sequences layouts system hashtables
-classes alien byte-arrays combinators words sets fry ;
+math math.order memory namespaces make sequences layouts system
+hashtables classes alien byte-arrays combinators words sets fry
+;
 IN: cpu.architecture
 
 ! Representations -- these are like low-level types
@@ -86,6 +87,20 @@ UNION: vector-rep
 int-vector-rep
 float-vector-rep ;
 
+CONSTANT: vector-reps
+    {
+        char-16-rep
+        uchar-16-rep
+        short-8-rep
+        ushort-8-rep
+        int-4-rep
+        uint-4-rep
+        longlong-2-rep
+        ulonglong-2-rep
+        float-4-rep
+        double-2-rep
+    }
+
 UNION: representation
 any-rep
 tagged-rep
@@ -202,12 +217,19 @@ M: ulonglong-2-rep scalar-rep-of drop ulonglong-scalar-rep ;
 ! Mapping from register class to machine registers
 HOOK: machine-registers cpu ( -- assoc )
 
+! Specifies if %slot, %set-slot and %write-barrier accept the
+! 'scale' and 'tag' parameters, and if %load-memory and
+! %store-memory work
+HOOK: complex-addressing? cpu ( -- ? )
+
 HOOK: %load-immediate cpu ( reg val -- )
 HOOK: %load-reference cpu ( reg obj -- )
 HOOK: %load-double cpu ( reg val -- )
+HOOK: %load-vector cpu ( reg val rep -- )
 
 HOOK: %peek cpu ( vreg loc -- )
 HOOK: %replace cpu ( vreg loc -- )
+HOOK: %replace-imm cpu ( src loc -- )
 HOOK: %inc-d cpu ( n -- )
 HOOK: %inc-r cpu ( n -- )
 
@@ -219,14 +241,11 @@ HOOK: %return cpu ( -- )
 
 HOOK: %dispatch cpu ( src temp -- )
 
-HOOK: %slot cpu ( dst obj slot -- )
+HOOK: %slot cpu ( dst obj slot scale tag -- )
 HOOK: %slot-imm cpu ( dst obj slot tag -- )
-HOOK: %set-slot cpu ( src obj slot -- )
+HOOK: %set-slot cpu ( src obj slot scale tag -- )
 HOOK: %set-slot-imm cpu ( src obj slot tag -- )
 
-HOOK: %string-nth cpu ( dst obj index temp -- )
-HOOK: %set-string-nth-fast cpu ( ch obj index temp -- )
-
 HOOK: %add     cpu ( dst src1 src2 -- )
 HOOK: %add-imm cpu ( dst src1 src2 -- )
 HOOK: %sub     cpu ( dst src1 src2 -- )
@@ -253,9 +272,11 @@ HOOK: %log2    cpu ( dst src -- )
 
 HOOK: %copy cpu ( dst src rep -- )
 
-HOOK: %fixnum-add cpu ( label dst src1 src2 -- )
-HOOK: %fixnum-sub cpu ( label dst src1 src2 -- )
-HOOK: %fixnum-mul cpu ( label dst src1 src2 -- )
+: %tagged>integer ( dst src -- ) int-rep %copy ;
+
+HOOK: %fixnum-add cpu ( label dst src1 src2 cc -- )
+HOOK: %fixnum-sub cpu ( label dst src1 src2 cc -- )
+HOOK: %fixnum-mul cpu ( label dst src1 src2 cc -- )
 
 HOOK: %add-float cpu ( dst src1 src2 -- )
 HOOK: %sub-float cpu ( dst src1 src2 -- )
@@ -428,24 +449,10 @@ HOOK: %unbox-any-c-ptr cpu ( dst src -- )
 HOOK: %box-alien cpu ( dst src temp -- )
 HOOK: %box-displaced-alien cpu ( dst displacement base temp base-class -- )
 
-HOOK: %alien-unsigned-1 cpu ( dst src offset -- )
-HOOK: %alien-unsigned-2 cpu ( dst src offset -- )
-HOOK: %alien-unsigned-4 cpu ( dst src offset -- )
-HOOK: %alien-signed-1   cpu ( dst src offset -- )
-HOOK: %alien-signed-2   cpu ( dst src offset -- )
-HOOK: %alien-signed-4   cpu ( dst src offset -- )
-HOOK: %alien-cell       cpu ( dst src offset -- )
-HOOK: %alien-float      cpu ( dst src offset -- )
-HOOK: %alien-double     cpu ( dst src offset -- )
-HOOK: %alien-vector     cpu ( dst src offset rep -- )
-
-HOOK: %set-alien-integer-1 cpu ( ptr offset value -- )
-HOOK: %set-alien-integer-2 cpu ( ptr offset value -- )
-HOOK: %set-alien-integer-4 cpu ( ptr offset value -- )
-HOOK: %set-alien-cell      cpu ( ptr offset value -- )
-HOOK: %set-alien-float     cpu ( ptr offset value -- )
-HOOK: %set-alien-double    cpu ( ptr offset value -- )
-HOOK: %set-alien-vector    cpu ( ptr offset value rep -- )
+HOOK: %load-memory cpu ( dst base displacement scale offset rep c-type -- )
+HOOK: %load-memory-imm cpu ( dst base offset rep c-type -- )
+HOOK: %store-memory cpu ( value base displacement scale offset rep c-type -- )
+HOOK: %store-memory-imm cpu ( value base offset rep c-type -- )
 
 HOOK: %alien-global cpu ( dst symbol library -- )
 HOOK: %vm-field cpu ( dst offset -- )
@@ -454,25 +461,25 @@ HOOK: %set-vm-field cpu ( src offset -- )
 : %context ( dst -- ) 0 %vm-field ;
 
 HOOK: %allot cpu ( dst size class temp -- )
-HOOK: %write-barrier cpu ( src slot temp1 temp2 -- )
-HOOK: %write-barrier-imm cpu ( src slot temp1 temp2 -- )
+HOOK: %write-barrier cpu ( src slot scale tag temp1 temp2 -- )
+HOOK: %write-barrier-imm cpu ( src slot tag temp1 temp2 -- )
 
 ! GC checks
-HOOK: %check-nursery cpu ( label size temp1 temp2 -- )
-HOOK: %save-gc-root cpu ( gc-root register -- )
-HOOK: %load-gc-root cpu ( gc-root register -- )
-HOOK: %call-gc cpu ( gc-root-count temp1 -- )
+HOOK: %check-nursery-branch cpu ( label size cc temp1 temp2 -- )
+HOOK: %call-gc cpu ( gc-roots -- )
 
 HOOK: %prologue cpu ( n -- )
 HOOK: %epilogue cpu ( n -- )
 
 HOOK: %compare cpu ( dst temp cc src1 src2 -- )
 HOOK: %compare-imm cpu ( dst temp cc src1 src2 -- )
+HOOK: %compare-integer-imm cpu ( dst temp cc src1 src2 -- )
 HOOK: %compare-float-ordered cpu ( dst temp cc src1 src2 -- )
 HOOK: %compare-float-unordered cpu ( dst temp cc src1 src2 -- )
 
 HOOK: %compare-branch cpu ( label cc src1 src2 -- )
 HOOK: %compare-imm-branch cpu ( label cc src1 src2 -- )
+HOOK: %compare-integer-imm-branch cpu ( label cc src1 src2 -- )
 HOOK: %compare-float-ordered-branch cpu ( label cc src1 src2 -- )
 HOOK: %compare-float-unordered-branch cpu ( label cc src1 src2 -- )
 
@@ -497,10 +504,9 @@ M: reg-class param-reg param-regs nth ;
 
 M: stack-params param-reg 2drop ;
 
-! Does this architecture support %load-double?
-HOOK: load-double? cpu ( -- ? )
-
-M: object load-double? f ;
+! Does this architecture support %load-double, %load-vector and
+! objects in %compare-imm?
+HOOK: fused-unboxing? cpu ( -- ? )
 
 ! Can this value be an immediate operand for %add-imm, %sub-imm,
 ! or %mul-imm?
@@ -514,13 +520,19 @@ HOOK: immediate-bitwise? cpu ( n -- ? )
 ! %compare-imm-branch?
 HOOK: immediate-comparand? cpu ( n -- ? )
 
+! Can this value be an immediate operand for %replace-imm?
+HOOK: immediate-store? cpu ( obj -- ? )
+
 M: object immediate-comparand? ( n -- ? )
     {
-        { [ dup integer? ] [ immediate-arithmetic? ] }
+        { [ dup fixnum? ] [ tag-fixnum immediate-arithmetic? ] }
         { [ dup not ] [ drop t ] }
         [ drop f ]
     } cond ;
 
+: immediate-shift-count? ( n -- ? )
+    0 cell-bits 1 - between? ;
+
 ! What c-type describes the implicit struct return pointer for
 ! large structs?
 HOOK: struct-return-pointer-type cpu ( -- c-type )
index 8e412c4c832cbeeedf74392ee0c39de1fda89ff9..a30556444e80e473fafbbed4b8150f82ab3649ff 100644 (file)
@@ -72,6 +72,14 @@ HEX{ 7c 41 1a 2e } [ 1 2 3 LHZX ] test-assembler
 HEX{ 7c 41 1a 6e } [ 1 2 3 LHZUX ] test-assembler
 HEX{ 7c 41 18 2e } [ 1 2 3 LWZX ] test-assembler
 HEX{ 7c 41 18 6e } [ 1 2 3 LWZUX ] test-assembler
+HEX{ 7c 41 1c 2e } [ 1 2 3 LFSX ] test-assembler
+HEX{ 7c 41 1c 6e } [ 1 2 3 LFSUX ] test-assembler
+HEX{ 7c 41 1c ae } [ 1 2 3 LFDX ] test-assembler
+HEX{ 7c 41 1c ee } [ 1 2 3 LFDUX ] test-assembler
+HEX{ 7c 41 1d 2e } [ 1 2 3 STFSX ] test-assembler
+HEX{ 7c 41 1d 6e } [ 1 2 3 STFSUX ] test-assembler
+HEX{ 7c 41 1d ae } [ 1 2 3 STFDX ] test-assembler
+HEX{ 7c 41 1d ee } [ 1 2 3 STFDUX ] test-assembler
 HEX{ 48 00 00 01 } [ 1 B ] test-assembler
 HEX{ 48 00 00 01 } [ 1 BL ] test-assembler
 HEX{ 41 80 00 04 } [ 1 BLT ] test-assembler
index ca626a638eec8041590dacb4612a9f5b40646edc..30beabc09c30c31de1944bec4050f3847c0eaf4c 100644 (file)
@@ -66,6 +66,10 @@ X: FCMPO 0 32 63
 X: FCMPU 0 0 63
 X: LBZUX 0 119 31
 X: LBZX 0 87 31
+X: LFDUX 0 631 31
+X: LFDX 0 599 31
+X: LFSUX 0 567 31
+X: LFSX 0 535 31
 X: LHAUX 0 375 31
 X: LHAX 0 343 31
 X: LHZUX 0 311 31
@@ -89,6 +93,10 @@ X: SRW 0 536 31
 X: SRW. 1 536 31
 X: STBUX 0 247 31
 X: STBX 0 215 31
+X: STFDUX 0 759 31
+X: STFDX 0 727 31
+X: STFSUX 0 695 31
+X: STFSX 0 663 31
 X: STHUX 0 439 31
 X: STHX 0 407 31
 X: STWUX 0 183 31
index 4df7a487d4bafd08be38c8d4a1bcdb90273695b6..68ebbf9f4f6d5e1dce357a15528dcb98a0227f38 100644 (file)
@@ -4,7 +4,7 @@ USING: bootstrap.image.private kernel kernel.private namespaces
 system cpu.ppc.assembler compiler.units compiler.constants math\r
 math.private math.ranges layouts words vocabs slots.private\r
 locals locals.backend generic.single.private fry sequences\r
-threads.private ;\r
+threads.private strings.private ;\r
 FROM: cpu.ppc.assembler => B ;\r
 IN: bootstrap.ppc\r
 \r
@@ -491,6 +491,21 @@ CONSTANT: nv-reg 17
     3 ds-reg 0 STW\r
 ] \ slot define-sub-primitive\r
 \r
+[\r
+    ! load string index from stack\r
+    3 ds-reg -4 LWZ\r
+    3 3 tag-bits get SRAWI\r
+    ! load string from stack\r
+    4 ds-reg 0 LWZ\r
+    ! load character\r
+    4 4 string-offset ADDI\r
+    3 3 4 LBZX\r
+    3 3 tag-bits get SLWI\r
+    ! store character to stack\r
+    ds-reg ds-reg 4 SUBI\r
+    3 ds-reg 0 STW\r
+] \ string-nth-fast define-sub-primitive\r
+\r
 ! Shufflers\r
 [\r
     ds-reg dup 4 SUBI\r
index 8adae2ae998234b468f2d514d641d71b5865ac7f..d0571337c2ae969ed522f6ac8c0e865058d7e826 100644 (file)
@@ -1,14 +1,16 @@
 ! Copyright (C) 2005, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs sequences kernel combinators make math
-math.order math.ranges system namespaces locals layouts words
-alien alien.accessors alien.c-types alien.complex alien.data
-literals cpu.architecture cpu.ppc.assembler
-cpu.ppc.assembler.backend compiler.cfg.registers
-compiler.cfg.instructions compiler.cfg.comparisons
-compiler.codegen.fixup compiler.cfg.intrinsics
-compiler.cfg.stack-frame compiler.cfg.build-stack-frame
-compiler.units compiler.constants compiler.codegen vm ;
+USING: accessors assocs sequences kernel combinators
+classes.algebra byte-arrays make math math.order math.ranges
+system namespaces locals layouts words alien alien.accessors
+alien.c-types alien.complex alien.data literals cpu.architecture
+cpu.ppc.assembler cpu.ppc.assembler.backend
+compiler.cfg.registers compiler.cfg.instructions
+compiler.cfg.comparisons compiler.codegen.fixup
+compiler.cfg.intrinsics compiler.cfg.stack-frame
+compiler.cfg.build-stack-frame compiler.units compiler.constants
+compiler.codegen vm ;
+QUALIFIED-WITH: alien.c-types c
 FROM: cpu.ppc.assembler => B ;
 FROM: layouts => cell ;
 FROM: math => float ;
@@ -31,8 +33,8 @@ M: label BC [ 0 BC ] dip rc-relative-ppc-2 label-fixup ;
 enable-float-intrinsics
 
 <<
-\ ##integer>float t frame-required? set-word-prop
-\ ##float>integer t frame-required? set-word-prop
+\ ##integer>float t "frame-required?" set-word-prop
+\ ##float>integer t "frame-required?" set-word-prop
 >>
 
 M: ppc machine-registers
@@ -44,10 +46,16 @@ M: ppc machine-registers
 CONSTANT: scratch-reg 30
 CONSTANT: fp-scratch-reg 30
 
+M: ppc complex-addressing? f ;
+
+M: ppc fused-unboxing? f ;
+
 M: ppc %load-immediate ( reg n -- ) swap LOAD ;
 
 M: ppc %load-reference ( reg obj -- )
-    [ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-literal ] bi* ;
+    [ [ 0 swap LOAD32 ] [ rc-absolute-ppc-2/2 rel-literal ] bi* ]
+    [ \ f type-number swap LI ]
+    if* ;
 
 M: ppc %alien-global ( register symbol dll -- )
     [ 0 swap LOAD32 ] 2dip rc-absolute-ppc-2/2 rel-dlsym ;
@@ -109,10 +117,6 @@ HOOK: reserved-area-size os ( -- n )
 : scratch@ ( n -- offset )
     factor-area-size + ;
 
-! GC root area
-: gc-root@ ( n -- offset )
-    gc-root-offset local@ ;
-
 ! Finally we have the linkage area
 HOOK: lr-save os ( -- n )
 
@@ -139,31 +143,14 @@ M:: ppc %dispatch ( src temp -- )
     temp MTCTR
     BCTR ;
 
-M: ppc %slot ( dst obj slot -- ) swapd LWZX ;
+: (%slot) ( dst obj slot scale tag -- obj dst slot )
+    [ 0 assert= ] bi@ swapd ;
+
+M: ppc %slot ( dst obj slot scale tag -- ) (%slot) LWZX ;
 M: ppc %slot-imm ( dst obj slot tag -- ) slot-offset LWZ ;
-M: ppc %set-slot ( src obj slot -- ) swapd STWX ;
+M: ppc %set-slot ( src obj slot scale tag -- ) (%slot) STWX ;
 M: ppc %set-slot-imm ( src obj slot tag -- ) slot-offset STW ;
 
-M:: ppc %string-nth ( dst src index temp -- )
-    [
-        "end" define-label
-        temp src index ADD
-        dst temp string-offset LBZ
-        0 dst HEX: 80 CMPI
-        "end" get BLT
-        temp src string-aux-offset LWZ
-        temp temp index ADD
-        temp temp index ADD
-        temp temp byte-array-offset LHZ
-        temp temp 7 SLWI
-        dst dst temp XOR
-        "end" resolve-label
-    ] with-scope ;
-
-M:: ppc %set-string-nth-fast ( ch obj index temp -- )
-    temp obj index ADD
-    ch temp string-offset STB ;
-
 M: ppc %add     ADD ;
 M: ppc %add-imm ADDI ;
 M: ppc %sub     swap SUBF ;
@@ -185,19 +172,22 @@ M: ppc %sar-imm SRAWI ;
 M: ppc %not     NOT ;
 M: ppc %neg     NEG ;
 
-:: overflow-template ( label dst src1 src2 insn -- )
+:: overflow-template ( label dst src1 src2 cc insn -- )
     0 0 LI
     0 MTXER
     dst src2 src1 insn call
-    label BO ; inline
+    cc {
+        { cc-o [ label BO ] }
+        { cc/o [ label BNO ] }
+    } case ; inline
 
-M: ppc %fixnum-add ( label dst src1 src2 -- )
+M: ppc %fixnum-add ( label dst src1 src2 cc -- )
     [ ADDO. ] overflow-template ;
 
-M: ppc %fixnum-sub ( label dst src1 src2 -- )
+M: ppc %fixnum-sub ( label dst src1 src2 cc -- )
     [ SUBFO. ] overflow-template ;
 
-M: ppc %fixnum-mul ( label dst src1 src2 -- )
+M: ppc %fixnum-mul ( label dst src1 src2 cc -- )
     [ MULLWO. ] overflow-template ;
 
 M: ppc %add-float FADD ;
@@ -224,6 +214,7 @@ M:: ppc %float>integer ( dst src -- )
 M: ppc %copy ( dst src rep -- )
     2over eq? [ 3drop ] [
         {
+            { tagged-rep [ MR ] }
             { int-rep [ MR ] }
             { double-rep [ FMR ] }
         } case
@@ -294,12 +285,69 @@ M:: ppc %box-alien ( dst src temp -- )
         "f" resolve-label
     ] with-scope ;
 
+:: %box-displaced-alien/f ( dst displacement base -- )
+    base dst 1 alien@ STW
+    displacement dst 3 alien@ STW
+    displacement dst 4 alien@ STW ;
+
+:: %box-displaced-alien/alien ( dst displacement base temp -- )
+    ! Set new alien's base to base.base
+    temp base 1 alien@ LWZ
+    temp dst 1 alien@ STW
+
+    ! Compute displacement
+    temp base 3 alien@ LWZ
+    temp temp displacement ADD
+    temp dst 3 alien@ STW
+
+    ! Compute address
+    temp base 4 alien@ LWZ
+    temp temp displacement ADD
+    temp dst 4 alien@ STW ;
+
+:: %box-displaced-alien/byte-array ( dst displacement base temp -- )
+    base dst 1 alien@ STW
+    displacement dst 3 alien@ STW
+    temp base byte-array-offset ADDI
+    temp temp displacement ADD
+    temp dst 4 alien@ STW ;
+
+:: %box-displaced-alien/dynamic ( dst displacement base temp -- )
+    "not-f" define-label
+    "not-alien" define-label
+
+    ! Is base f?
+    0 base \ f type-number CMPI
+    "not-f" get BNE
+
+    ! Yes, it is f. Fill in new object
+    dst displacement base %box-displaced-alien/f
+
+    "end" get B
+
+    "not-f" resolve-label
+
+    ! Check base type
+    temp base tag-mask get ANDI
+
+    ! Is base an alien?
+    0 temp alien type-number CMPI
+    "not-alien" get BNE
+
+    dst displacement base temp %box-displaced-alien/alien
+
+    ! We are done
+    "end" get B
+
+    ! Is base a byte array? It has to be, by now...
+    "not-alien" resolve-label
+
+    dst displacement base temp %box-displaced-alien/byte-array ;
+
 M:: ppc %box-displaced-alien ( dst displacement base temp base-class -- )
     ! This is ridiculous
     [
         "end" define-label
-        "not-f" define-label
-        "not-alien" define-label
 
         ! If displacement is zero, return the base
         dst base MR
@@ -314,73 +362,83 @@ M:: ppc %box-displaced-alien ( dst displacement base temp base-class -- )
         temp \ f type-number %load-immediate
         temp dst 2 alien@ STW
 
-        ! Is base f?
-        0 base \ f type-number CMPI
-        "not-f" get BNE
-
-        ! Yes, it is f. Fill in new object
-        base dst 1 alien@ STW
-        displacement dst 3 alien@ STW
-        displacement dst 4 alien@ STW
-
-        "end" get B
-
-        "not-f" resolve-label
-
-        ! Check base type
-        temp base tag-mask get ANDI
-
-        ! Is base an alien?
-        0 temp alien type-number CMPI
-        "not-alien" get BNE
-
-        ! Yes, it is an alien. Set new alien's base to base.base
-        temp base 1 alien@ LWZ
-        temp dst 1 alien@ STW
-
-        ! Compute displacement
-        temp base 3 alien@ LWZ
-        temp temp displacement ADD
-        temp dst 3 alien@ STW
-
-        ! Compute address
-        temp base 4 alien@ LWZ
-        temp temp displacement ADD
-        temp dst 4 alien@ STW
-
-        ! We are done
-        "end" get B
-
-        ! Is base a byte array? It has to be, by now...
-        "not-alien" resolve-label
-
-        base dst 1 alien@ STW
-        displacement dst 3 alien@ STW
-        temp base byte-array-offset ADDI
-        temp temp displacement ADD
-        temp dst 4 alien@ STW
+        dst displacement base temp
+        {
+            { [ base-class \ f class<= ] [ drop %box-displaced-alien/f ] }
+            { [ base-class \ alien class<= ] [ %box-displaced-alien/alien ] }
+            { [ base-class \ byte-array class<= ] [ %box-displaced-alien/byte-array ] }
+            [ %box-displaced-alien/dynamic ]
+        } cond
 
         "end" resolve-label
     ] with-scope ;
 
-M: ppc %alien-unsigned-1 LBZ ;
-M: ppc %alien-unsigned-2 LHZ ;
-
-M: ppc %alien-signed-1 [ dup ] 2dip LBZ dup EXTSB ;
-M: ppc %alien-signed-2 LHA ;
-
-M: ppc %alien-cell LWZ ;
+M: ppc %load-memory-imm ( dst base offset rep c-type -- )
+    [
+        {
+            { c:char   [ [ dup ] 2dip LBZ dup EXTSB ] }
+            { c:uchar  [ LBZ ] }
+            { c:short  [ LHA ] }
+            { c:ushort [ LHZ ] }
+        } case
+    ] [
+        {
+            { int-rep [ LWZ ] }
+            { float-rep [ LFS ] }
+            { double-rep [ LFD ] }
+        } case
+    ] ?if ;
 
-M: ppc %alien-float LFS ;
-M: ppc %alien-double LFD ;
+: (%memory) ( val base displacement scale offset rep c-type -- base val displacement rep c-type )
+    [ [ 0 assert= ] bi@ swapd ] 2dip ; inline
 
-M: ppc %set-alien-integer-1 -rot STB ;
-M: ppc %set-alien-integer-2 -rot STH ;
+M: ppc %load-memory ( dst base displacement scale offset rep c-type -- )
+    (%memory) [
+        {
+            { c:char   [ [ LBZX ] [ drop dup EXTSB ] 2bi ] }
+            { c:uchar  [ LBZX ] }
+            { c:short  [ LHAX ] }
+            { c:ushort [ LHZX ] }
+        } case
+    ] [
+        {
+            { int-rep [ LWZX ] }
+            { float-rep [ LFSX ] }
+            { double-rep [ LFDX ] }
+        } case
+    ] ?if ;
 
-M: ppc %set-alien-cell -rot STW ;
+M: ppc %store-memory-imm ( src base offset rep c-type -- )
+    [
+        {
+            { c:char   [ STB ] }
+            { c:uchar  [ STB ] }
+            { c:short  [ STH ] }
+            { c:ushort [ STH ] }
+        } case
+    ] [
+        {
+            { int-rep [ STW ] }
+            { float-rep [ STFS ] }
+            { double-rep [ STFD ] }
+        } case
+    ] ?if ;
 
-M: ppc %set-alien-float -rot STFS ;
-M: ppc %set-alien-double -rot STFD ;
+M: ppc %store-memory ( src base displacement scale offset rep c-type -- )
+    (%memory) [
+        {
+            { c:char   [ STBX ] }
+            { c:uchar  [ STBX ] }
+            { c:short  [ STHX ] }
+            { c:ushort [ STHX ] }
+        } case
+    ] [
+        {
+            { int-rep [ STWX ] }
+            { float-rep [ STFSX ] }
+            { double-rep [ STFDX ] }
+        } case
+    ] ?if ;
 
 : load-zone-ptr ( reg -- )
     vm-reg "nursery" vm-field-offset ADDI ;
@@ -424,33 +482,32 @@ M:: ppc %allot ( dst size class nursery-ptr -- )
     temp2 load-decks-offset
     temp1 scratch-reg temp2 STBX ;
 
-M:: ppc %write-barrier ( src slot temp1 temp2 -- )
+M:: ppc %write-barrier ( src slot scale tag temp1 temp2 -- )
+    scale 0 assert= tag 0 assert=
     temp1 src slot ADD
     temp1 temp2 (%write-barrier) ;
 
-M:: ppc %write-barrier-imm ( src slot temp1 temp2 -- )
-    temp1 src slot ADDI
+M:: ppc %write-barrier-imm ( src slot tag temp1 temp2 -- )
+    temp1 src slot tag slot-offset ADDI
     temp1 temp2 (%write-barrier) ;
 
-M:: ppc %check-nursery ( label size temp1 temp2 -- )
-    temp2 load-zone-ptr
-    temp1 temp2 0 LWZ
-    temp2 temp2 2 cells LWZ
+M:: ppc %check-nursery-branch ( label size cc temp1 temp2 -- )
+    temp1 vm-reg "nursery" vm-field-offset LWZ
+    temp2 vm-reg "nursery" vm-field-offset 2 cells + LWZ
     temp1 temp1 size ADDI
     ! is here >= end?
     temp1 0 temp2 CMP
-    label BLE ;
-
-M:: ppc %save-gc-root ( gc-root register -- )
-    register 1 gc-root gc-root@ STW ;
+    cc {
+        { cc<= [ label BLE ] }
+        { cc/<= [ label BGT ] }
+    } case ;
 
-M:: ppc %load-gc-root ( gc-root register -- )
-    register 1 gc-root gc-root@ LWZ ;
+: gc-root-offsets ( seq -- seq' )
+    [ n>> spill@ ] map f like ;
 
-M:: ppc %call-gc ( gc-root-count temp -- )
-    3 1 gc-root-base local@ ADDI
-    gc-root-count 4 LI
-    5 %load-vm-addr
+M: ppc %call-gc ( gc-roots -- )
+    3 swap gc-root-offsets %load-reference
+    4 %load-vm-addr
     "inline_gc" f %alien-invoke ;
 
 M: ppc %prologue ( n -- )
@@ -492,9 +549,18 @@ M: ppc %epilogue ( n -- )
     } case ;
 
 : (%compare) ( src1 src2 -- ) [ 0 ] dip CMP ; inline
-: (%compare-imm) ( src1 src2 -- ) [ 0 ] [ ] [ \ f type-number or ] tri* CMPI ; inline
-: (%compare-float-unordered) ( src1 src2 -- ) [ 0 ] dip FCMPU ; inline
-: (%compare-float-ordered) ( src1 src2 -- ) [ 0 ] dip FCMPO ; inline
+
+: (%compare-integer-imm) ( src1 src2 -- )
+    [ 0 ] 2dip CMPI ; inline
+
+: (%compare-imm) ( src1 src2 -- )
+    [ tag-fixnum ] [ \ f type-number ] if* (%compare-integer-imm) ; inline
+
+: (%compare-float-unordered) ( src1 src2 -- )
+    [ 0 ] dip FCMPU ; inline
+
+: (%compare-float-ordered) ( src1 src2 -- )
+    [ 0 ] dip FCMPO ; inline
 
 :: (%compare-float) ( src1 src2 cc compare -- branch1 branch2 )
     cc {
@@ -518,6 +584,8 @@ M: ppc %compare [ (%compare) ] 2dip %boolean ;
 
 M: ppc %compare-imm [ (%compare-imm) ] 2dip %boolean ;
 
+M: ppc %compare-integer-imm [ (%compare-integer-imm) ] 2dip %boolean ;
+
 M:: ppc %compare-float-ordered ( dst src1 src2 cc temp -- )
     src1 src2 cc negate-cc \ (%compare-float-ordered) (%compare-float) :> ( branch1 branch2 )
     dst temp branch1 branch2 (%boolean) ;
@@ -544,6 +612,10 @@ M:: ppc %compare-imm-branch ( label src1 src2 cc -- )
     src1 src2 (%compare-imm)
     label cc %branch ;
 
+M:: ppc %compare-integer-imm-branch ( label src1 src2 cc -- )
+    src1 src2 (%compare-integer-imm)
+    label cc %branch ;
+
 :: (%branch) ( label branch1 branch2 -- )
     label branch1 execute( label -- )
     branch2 [ label branch2 execute( label -- ) ] when ; inline
@@ -559,6 +631,7 @@ M:: ppc %compare-float-unordered-branch ( label src1 src2 cc -- )
 : load-from-frame ( dst n rep -- )
     {
         { int-rep [ [ 1 ] dip LWZ ] }
+        { tagged-rep [ [ 1 ] dip LWZ ] }
         { float-rep [ [ 1 ] dip LFS ] }
         { double-rep [ [ 1 ] dip LFD ] }
         { stack-params [ [ 0 1 ] dip LWZ [ 0 1 ] dip param@ STW ] }
@@ -570,6 +643,7 @@ M:: ppc %compare-float-unordered-branch ( label src1 src2 cc -- )
 : store-to-frame ( src n rep -- )
     {
         { int-rep [ [ 1 ] dip STW ] }
+        { tagged-rep [ [ 1 ] dip STW ] }
         { float-rep [ [ 1 ] dip STFS ] }
         { double-rep [ [ 1 ] dip STFD ] }
         { stack-params [ [ [ 0 ] dip next-param@ LWZ 0 1 ] dip STW ] }
@@ -584,7 +658,9 @@ M: ppc %reload ( dst rep src -- )
 M: ppc %loop-entry ;
 
 M: int-regs return-reg drop 3 ;
+
 M: int-regs param-regs 2drop { 3 4 5 6 7 8 9 10 } ;
+
 M: float-regs return-reg drop 1 ;
 
 M:: ppc %save-param-reg ( stack reg rep -- )
@@ -701,6 +777,8 @@ M: ppc immediate-arithmetic? ( n -- ? ) -32768 32767 between? ;
 
 M: ppc immediate-bitwise? ( n -- ? ) 0 65535 between? ;
 
+M: ppc immediate-store? drop f ;
+
 M: ppc struct-return-pointer-type void* ;
 
 M: ppc return-struct-in-registers? ( c-type -- ? )
index c567c1e1f091591b10efd492672b16e31fec62d8..cd0fa4faff1ae96ef0c3223c26af3f016080bce9 100755 (executable)
@@ -5,10 +5,11 @@ arrays kernel fry math namespaces sequences system layouts io
 vocabs.loader accessors init classes.struct combinators
 command-line make words compiler compiler.units
 compiler.constants compiler.alien compiler.codegen
-compiler.codegen.fixup compiler.cfg.instructions
-compiler.cfg.builder compiler.cfg.intrinsics
-compiler.cfg.stack-frame cpu.x86.assembler
-cpu.x86.assembler.operands cpu.x86 cpu.architecture vm ;
+compiler.codegen.alien compiler.codegen.fixup
+compiler.cfg.instructions compiler.cfg.builder
+compiler.cfg.intrinsics compiler.cfg.stack-frame
+cpu.x86.assembler cpu.x86.assembler.operands cpu.x86
+cpu.architecture vm ;
 FROM: layouts => cell ;
 IN: cpu.x86.32
 
@@ -24,13 +25,13 @@ M: x86.32 stack-reg ESP ;
 M: x86.32 frame-reg EBP ;
 M: x86.32 temp-reg ECX ;
 
-M: x86.32 immediate-comparand? ( n -- ? )
-    [ call-next-method ] [ word? ] bi or ;
-
-M: x86.32 load-double? ( -- ? ) t ;
+M: x86.32 immediate-comparand? ( obj -- ? ) drop t ;
 
 M: x86.32 %load-double ( dst val -- )
-    [ 0 [] MOVSD ] dip rc-absolute rel-float ;
+    [ 0 [] MOVSD ] dip rc-absolute rel-binary-literal ;
+
+M:: x86.32 %load-vector ( dst val rep -- )
+    dst 0 [] rep copy-memory* val rc-absolute rel-binary-literal ;
 
 M: x86.32 %mov-vm-ptr ( reg -- )
     0 MOV 0 rc-absolute-cell rel-vm ;
@@ -70,9 +71,9 @@ M:: x86.32 %dispatch ( src temp -- )
     temp HEX: 7f [+] JMP
     building get length :> end
     ! Fix up the displacement above
-    cell code-alignment
+    cell alignment
     [ end start - + building get dup pop* push ]
-    [ align-code ]
+    [ (align-code) ]
     bi ;
 
 M: x86.32 pic-tail-reg EDX ;
@@ -344,11 +345,9 @@ M: x86.32 stack-cleanup ( params -- n )
 M: x86.32 %cleanup ( params -- )
     stack-cleanup [ ESP swap SUB ] unless-zero ;
 
-M:: x86.32 %call-gc ( gc-root-count temp -- )
-    temp gc-root-base special@ LEA
-    8 save-vm-ptr
-    4 stack@ gc-root-count MOV
-    0 stack@ temp MOV
+M:: x86.32 %call-gc ( gc-roots -- )
+    4 save-vm-ptr
+    0 stack@ gc-roots gc-root-offsets %load-reference
     "inline_gc" f %alien-invoke ;
 
 M: x86.32 dummy-stack-params? f ;
index 432d210bec63eef45ab7e0b86ef77daf5b37a40f..93f7c6d22fffd6a6e8608568a78c0a5acd6da1b7 100644 (file)
@@ -3,7 +3,7 @@
 USING: accessors arrays kernel math namespaces make sequences
 system layouts alien alien.c-types alien.accessors alien.libraries
 slots splitting assocs combinators locals compiler.constants
-compiler.codegen compiler.codegen.fixup
+compiler.codegen compiler.codegen.alien compiler.codegen.fixup
 compiler.cfg.instructions compiler.cfg.builder
 compiler.cfg.intrinsics compiler.cfg.stack-frame
 cpu.x86.assembler cpu.x86.assembler.operands cpu.x86
@@ -46,6 +46,12 @@ M: x86.64 %mov-vm-ptr ( reg -- )
 M: x86.64 %vm-field ( dst offset -- )
     [ vm-reg ] dip [+] MOV ;
 
+M: x86.64 %load-double ( dst val -- )
+    [ 0 [RIP+] MOVSD ] dip rc-relative rel-binary-literal ;
+
+M:: x86.64 %load-vector ( dst val rep -- )
+    dst 0 [RIP+] rep copy-memory* val rc-relative rel-binary-literal ;
+
 M: x86.64 %set-vm-field ( src offset -- )
     [ vm-reg ] dip [+] swap MOV ;
 
@@ -85,9 +91,9 @@ M:: x86.64 %dispatch ( src temp -- )
     temp HEX: 7f [+] JMP
     building get length :> end
     ! Fix up the displacement above
-    cell code-alignment
+    cell alignment
     [ end start - + building get dup pop* push ]
-    [ align-code ]
+    [ (align-code) ]
     bi ;
 
 M: stack-params copy-register*
@@ -168,9 +174,7 @@ M:: x86.64 %box ( n rep func -- )
     ] [
         rep load-return-value
     ] if
-    rep int-rep?
-    cpu x86.64? os windows? and or
-    param-reg-1 param-reg-0 ? %mov-vm-ptr
+    rep int-rep? os windows? or param-reg-1 param-reg-0 ? %mov-vm-ptr
     func f %alien-invoke ;
 
 : box-struct-field@ ( i -- operand ) 1 + cells param@ ;
@@ -269,14 +273,9 @@ M:: x86.64 %binary-float-function ( dst src1 src2 func -- )
     func "libm" load-library %alien-invoke
     dst float-function-return ;
 
-M:: x86.64 %call-gc ( gc-root-count temp -- )
-    ! Pass pointer to start of GC roots as first parameter
-    param-reg-0 gc-root-base param@ LEA
-    ! Pass number of roots as second parameter
-    param-reg-1 gc-root-count MOV
-    ! Pass VM ptr as third parameter
-    param-reg-2 %mov-vm-ptr
-    ! Call GC
+M:: x86.64 %call-gc ( gc-roots -- )
+    param-reg-0 gc-roots gc-root-offsets %load-reference
+    param-reg-1 %mov-vm-ptr
     "inline_gc" f %alien-invoke ;
 
 M: x86.64 struct-return-pointer-type void* ;
index a1868a3bc89ca60d666395bf50ad429b59067df1..fd696b7fda706ed63c2f70dc016fe9fbf2d19ef6 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays sequences math splitting make assocs kernel
-layouts system alien.c-types classes.struct cpu.architecture 
-cpu.x86.assembler cpu.x86.assembler.operands cpu.x86 compiler.codegen
-compiler.cfg.registers ;
+USING: accessors arrays sequences math splitting make assocs
+kernel layouts system alien.c-types classes.struct
+cpu.architecture cpu.x86.assembler cpu.x86.assembler.operands
+cpu.x86 compiler.codegen.alien compiler.cfg.registers ;
 IN: cpu.x86.64.unix
 
 M: int-regs param-regs
index 8ed789f392e317d269aae787c903a075a9093f9f..2959910f0e62af5fe109cc1eaf09d242dacb1619 100644 (file)
@@ -2,6 +2,18 @@ USING: cpu.x86.assembler cpu.x86.assembler.operands
 kernel tools.test namespaces make layouts ;
 IN: cpu.x86.assembler.tests
 
+! immediate operands
+cell 4 = [
+    [ { HEX: b9 HEX: 01 HEX: 00 HEX: 00 HEX: 00 } ] [ [ ECX 1 MOV ] { } make ] unit-test
+] [
+    [ { HEX: b9 HEX: 01 HEX: 00 HEX: 00 HEX: 00 HEX: 00 HEX: 00 HEX: 00 HEX: 00 } ] [ [ ECX 1 MOV ] { } make ] unit-test
+] if
+
+[ { HEX: 83 HEX: c1 HEX: 01 } ] [ [ ECX 1 ADD ] { } make ] unit-test
+[ { HEX: 81 HEX: c1 HEX: 96 HEX: 00 HEX: 00 HEX: 00 } ] [ [ ECX 150 ADD ] { } make ] unit-test
+[ { HEX: f7 HEX: c1 HEX: d2 HEX: 04 HEX: 00 HEX: 00 } ] [ [ ECX 1234 TEST ] { } make ] unit-test
+
+! 64-bit registers
 [ { HEX: 40 HEX: 8a HEX: 2a } ] [ [ BPL RDX [] MOV ] { } make ] unit-test
 
 [ { HEX: 49 HEX: 89 HEX: 04 HEX: 24 } ] [ [ R12 [] RAX MOV ] { } make ] unit-test
@@ -11,6 +23,58 @@ IN: cpu.x86.assembler.tests
 [ { HEX: 4c HEX: 89 HEX: e2 } ] [ [ RDX R12 MOV ] { } make ] unit-test
 [ { HEX: 49 HEX: 89 HEX: d4 } ] [ [ R12 RDX MOV ] { } make ] unit-test
 
+! memory address modes
+[ { HEX: 8a HEX: 18         } ] [ [ BL RAX [] MOV ] { } make ] unit-test
+[ { HEX: 66 HEX: 8b HEX: 18 } ] [ [ BX RAX [] MOV ] { } make ] unit-test
+[ { HEX: 8b HEX: 18         } ] [ [ EBX RAX [] MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 8b HEX: 18 } ] [ [ RBX RAX [] MOV ] { } make ] unit-test
+[ { HEX: 88 HEX: 18         } ] [ [ RAX [] BL MOV ] { } make ] unit-test
+[ { HEX: 66 HEX: 89 HEX: 18 } ] [ [ RAX [] BX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 18         } ] [ [ RAX [] EBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 18 } ] [ [ RAX [] RBX MOV ] { } make ] unit-test
+
+[ { HEX: 0f HEX: be HEX: c3 } ] [ [ EAX BL MOVSX ] { } make ] unit-test
+[ { HEX: 0f HEX: bf HEX: c3 } ] [ [ EAX BX MOVSX ] { } make ] unit-test
+
+[ { HEX: 80 HEX: 08 HEX: 05 } ] [ [ EAX [] 5 <byte> OR ] { } make ] unit-test
+[ { HEX: c6 HEX: 00 HEX: 05 } ] [ [ EAX [] 5 <byte> MOV ] { } make ] unit-test
+
+[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1a } ] [ [ R10 RBX [+] RAX MOV ] { } make ] unit-test
+[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1b } ] [ [ R11 RBX [+] RAX MOV ] { } make ] unit-test
+
+[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1c } ] [ [ R12 RBX [+] RAX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 04 HEX: 1c } ] [ [ RSP RBX [+] RAX MOV ] { } make ] unit-test
+
+[ { HEX: 49 HEX: 89 HEX: 44 HEX: 1d HEX: 00 } ] [ [ R13 RBX [+] RAX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 44 HEX: 1d HEX: 00 } ] [ [ RBP RBX [+] RAX MOV ] { } make ] unit-test
+
+[ { HEX: 4a HEX: 89 HEX: 04 HEX: 23 } ] [ [ RBX R12 [+] RAX MOV ] { } make ] unit-test
+[ { HEX: 4a HEX: 89 HEX: 04 HEX: 2b } ] [ [ RBX R13 [+] RAX MOV ] { } make ] unit-test
+
+[ { HEX: 4b HEX: 89 HEX: 44 HEX: 25 HEX: 00 } ] [ [ R13 R12 [+] RAX MOV ] { } make ] unit-test
+[ { HEX: 4b HEX: 89 HEX: 04 HEX: 2c } ] [ [ R12 R13 [+] RAX MOV ] { } make ] unit-test
+
+[ { HEX: 49 HEX: 89 HEX: 04 HEX: 2c } ] [ [ R12 RBP [+] RAX MOV ] { } make ] unit-test
+[ [ R12 RSP [+] RAX MOV ] { } make ] must-fail
+
+[ { HEX: 89 HEX: 1c HEX: 11 } ] [ [ ECX EDX [+] EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 1c HEX: 51 } ] [ [ ECX EDX 1 0 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 1c HEX: 91 } ] [ [ ECX EDX 2 0 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 1c HEX: d1 } ] [ [ ECX EDX 3 0 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 5c HEX: 11 HEX: 64 } ] [ [ ECX EDX 0 100 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 5c HEX: 51 HEX: 64 } ] [ [ ECX EDX 1 100 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 5c HEX: 91 HEX: 64 } ] [ [ ECX EDX 2 100 <indirect> EBX MOV ] { } make ] unit-test
+[ { HEX: 89 HEX: 5c HEX: d1 HEX: 64 } ] [ [ ECX EDX 3 100 <indirect> EBX MOV ] { } make ] unit-test
+
+[ { HEX: 48 HEX: 89 HEX: 1c HEX: 11 } ] [ [ RCX RDX [+] RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 1c HEX: 51 } ] [ [ RCX RDX 1 0 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 1c HEX: 91 } ] [ [ RCX RDX 2 0 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 1c HEX: d1 } ] [ [ RCX RDX 3 0 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 5c HEX: 11 HEX: 64 } ] [ [ RCX RDX 0 100 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 5c HEX: 51 HEX: 64 } ] [ [ RCX RDX 1 100 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 5c HEX: 91 HEX: 64 } ] [ [ RCX RDX 2 100 <indirect> RBX MOV ] { } make ] unit-test
+[ { HEX: 48 HEX: 89 HEX: 5c HEX: d1 HEX: 64 } ] [ [ RCX RDX 3 100 <indirect> RBX MOV ] { } make ] unit-test
+
 ! r-rm / m-r sse instruction
 [ { HEX: 0f HEX: 10 HEX: c1 } ] [ [ XMM0 XMM1 MOVUPS ] { } make ] unit-test
 [ { HEX: 0f HEX: 10 HEX: 01 } ] [ [ XMM0 ECX [] MOVUPS ] { } make ] unit-test
@@ -48,13 +112,6 @@ IN: cpu.x86.assembler.tests
 [ { HEX: f2 HEX: 48 HEX: 0f HEX: 2a HEX: c0 } ] [ [ XMM0 RAX CVTSI2SD ] { } make ] unit-test
 [ { HEX: f2 HEX: 49 HEX: 0f HEX: 2a HEX: c4 } ] [ [ XMM0 R12 CVTSI2SD ] { } make ] unit-test
 
-! [ { HEX: f2 HEX: 49 HEX: 0f HEX: 2c HEX: c1 } ] [ [ XMM9 RAX CVTSI2SD ] { } make ] unit-test
-
-! [ { HEX: f2 HEX: 0f HEX: 10 HEX: 00 } ] [ [ XMM0 RAX [] MOVSD ] { } make ] unit-test
-! [ { HEX: f2 HEX: 41 HEX: 0f HEX: 10 HEX: 04 HEX: 24 } ] [ [ XMM0 R12 [] MOVSD ] { } make ] unit-test
-! [ { HEX: f2 HEX: 0f HEX: 11 HEX: 00 } ] [ [ RAX [] XMM0 MOVSD ] { } make ] unit-test
-! [ { HEX: f2 HEX: 41 HEX: 0f HEX: 11 HEX: 04 HEX: 24 } ] [ [ R12 [] XMM0 MOVSD ] { } make ] unit-test
-
 ! 3-operand r-rm-imm sse instructions
 [ { HEX: 66 HEX: 0f HEX: 70 HEX: c1 HEX: 02 } ]
 [ [ XMM0 XMM1 2 PSHUFD ] { } make ] unit-test
@@ -115,47 +172,18 @@ IN: cpu.x86.assembler.tests
 [ { HEX: f2 HEX: 0f HEX: 38 HEX: f1 HEX: c1 } ] [ [ EAX ECX CRC32 ] { } make ] unit-test
 [ { HEX: f2 HEX: 0f HEX: 38 HEX: f1 HEX: 01 } ] [ [ EAX ECX [] CRC32 ] { } make ] unit-test
 
-! memory address modes
-[ { HEX: 8a HEX: 18         } ] [ [ BL RAX [] MOV ] { } make ] unit-test
-[ { HEX: 66 HEX: 8b HEX: 18 } ] [ [ BX RAX [] MOV ] { } make ] unit-test
-[ { HEX: 8b HEX: 18         } ] [ [ EBX RAX [] MOV ] { } make ] unit-test
-[ { HEX: 48 HEX: 8b HEX: 18 } ] [ [ RBX RAX [] MOV ] { } make ] unit-test
-[ { HEX: 88 HEX: 18         } ] [ [ RAX [] BL MOV ] { } make ] unit-test
-[ { HEX: 66 HEX: 89 HEX: 18 } ] [ [ RAX [] BX MOV ] { } make ] unit-test
-[ { HEX: 89 HEX: 18         } ] [ [ RAX [] EBX MOV ] { } make ] unit-test
-[ { HEX: 48 HEX: 89 HEX: 18 } ] [ [ RAX [] RBX MOV ] { } make ] unit-test
-
-[ { HEX: 0f HEX: be HEX: c3 } ] [ [ EAX BL MOVSX ] { } make ] unit-test
-[ { HEX: 0f HEX: bf HEX: c3 } ] [ [ EAX BX MOVSX ] { } make ] unit-test
-
-[ { HEX: 80 HEX: 08 HEX: 05 } ] [ [ EAX [] 5 <byte> OR ] { } make ] unit-test
-[ { HEX: c6 HEX: 00 HEX: 05 } ] [ [ EAX [] 5 <byte> MOV ] { } make ] unit-test
-
-[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1a } ] [ [ R10 RBX [+] RAX MOV ] { } make ] unit-test
-[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1b } ] [ [ R11 RBX [+] RAX MOV ] { } make ] unit-test
-
-[ { HEX: 49 HEX: 89 HEX: 04 HEX: 1c } ] [ [ R12 RBX [+] RAX MOV ] { } make ] unit-test
-[ { HEX: 48 HEX: 89 HEX: 04 HEX: 1c } ] [ [ RSP RBX [+] RAX MOV ] { } make ] unit-test
-
-[ { HEX: 49 HEX: 89 HEX: 44 HEX: 1d HEX: 00 } ] [ [ R13 RBX [+] RAX MOV ] { } make ] unit-test
-[ { HEX: 48 HEX: 89 HEX: 44 HEX: 1d HEX: 00 } ] [ [ RBP RBX [+] RAX MOV ] { } make ] unit-test
-
-[ { HEX: 4a HEX: 89 HEX: 04 HEX: 23 } ] [ [ RBX R12 [+] RAX MOV ] { } make ] unit-test
-[ { HEX: 4a HEX: 89 HEX: 04 HEX: 2b } ] [ [ RBX R13 [+] RAX MOV ] { } make ] unit-test
-
-[ { HEX: 4b HEX: 89 HEX: 44 HEX: 25 HEX: 00 } ] [ [ R13 R12 [+] RAX MOV ] { } make ] unit-test
-[ { HEX: 4b HEX: 89 HEX: 04 HEX: 2c } ] [ [ R12 R13 [+] RAX MOV ] { } make ] unit-test
-
-[ { HEX: 49 HEX: 89 HEX: 04 HEX: 2c } ] [ [ R12 RBP [+] RAX MOV ] { } make ] unit-test
-[ [ R12 RSP [+] RAX MOV ] { } make ] must-fail
-
+! shifts
 [ { HEX: 48 HEX: d3 HEX: e0 } ] [ [ RAX CL SHL ] { } make ] unit-test
 [ { HEX: 48 HEX: d3 HEX: e1 } ] [ [ RCX CL SHL ] { } make ] unit-test
 [ { HEX: 48 HEX: d3 HEX: e8 } ] [ [ RAX CL SHR ] { } make ] unit-test
 [ { HEX: 48 HEX: d3 HEX: e9 } ] [ [ RCX CL SHR ] { } make ] unit-test
 
-[ { HEX: f7 HEX: c1 HEX: d2 HEX: 04 HEX: 00 HEX: 00 } ] [ [ ECX 1234 TEST ] { } make ] unit-test
+[ { HEX: c1 HEX: e0 HEX: 05 } ] [ [ EAX 5 SHL ] { } make ] unit-test
+[ { HEX: c1 HEX: e1 HEX: 05 } ] [ [ ECX 5 SHL ] { } make ] unit-test
+[ { HEX: c1 HEX: e8 HEX: 05 } ] [ [ EAX 5 SHR ] { } make ] unit-test
+[ { HEX: c1 HEX: e9 HEX: 05 } ] [ [ ECX 5 SHR ] { } make ] unit-test
 
+! multiplication
 [ { HEX: 4d HEX: 6b HEX: c0 HEX: 03 } ] [ [ R8 R8 3 IMUL3 ] { } make ] unit-test
 [ { HEX: 49 HEX: 6b HEX: c0 HEX: 03 } ] [ [ RAX R8 3 IMUL3 ] { } make ] unit-test
 [ { HEX: 4c HEX: 6b HEX: c0 HEX: 03 } ] [ [ R8 RAX 3 IMUL3 ] { } make ] unit-test
index b91083dad1f64345b727ecc2330d403c61e63a4c..76157bd7cc9b53067099f876d4837a1d209c4181 100644 (file)
@@ -4,7 +4,6 @@ USING: arrays io.binary kernel combinators
 combinators.short-circuit math math.bitwise locals namespaces
 make sequences words system layouts math.order accessors
 cpu.x86.assembler.operands cpu.x86.assembler.operands.private ;
-QUALIFIED: sequences
 IN: cpu.x86.assembler
 
 ! A postfix assembler for x86-32 and x86-64.
@@ -71,10 +70,10 @@ M: byte n, [ value>> ] dip n, ;
 : 2, ( n -- ) 2 n, ; inline
 : cell, ( n -- ) bootstrap-cell n, ; inline
 
-: mod-r/m, ( reg# indirect -- )
+: mod-r/m, ( reg operand -- )
     [ 3 shift ] [ [ modifier 6 shift ] [ r/m ] bi ] bi* bitor bitor , ;
 
-: sib, ( indirect -- )
+: sib, ( operand -- )
     dup sib-present? [
         [ indirect-base* ]
         [ indirect-index* 3 shift ]
@@ -93,14 +92,14 @@ M: indirect displacement,
 
 M: register displacement, drop ;
 
-: addressing ( reg# indirect -- )
+: addressing ( reg operand -- )
     [ mod-r/m, ] [ sib, ] [ displacement, ] tri ;
 
 : rex.w? ( rex.w reg r/m -- ? )
     {
-        { [ dup register-128? ] [ drop operand-64? ] }
-        { [ dup not ] [ drop operand-64? ] }
-        [ nip operand-64? ]
+        { [ over register-128? ] [ nip operand-64? ] }
+        { [ over not ] [ nip operand-64? ] }
+        [ drop operand-64? ]
     } cond and ;
 
 : rex.r ( m op -- n )
@@ -119,16 +118,15 @@ M: register displacement, drop ;
 :: rex-prefix ( reg r/m rex.w -- )
     #! Compile an AMD64 REX prefix.
     rex.w reg r/m rex.w? BIN: 01001000 BIN: 01000000 ?
-    r/m rex.r
-    reg rex.b
+    reg rex.r
+    r/m rex.b
     dup reg r/m no-prefix? [ drop ] [ , ] if ;
 
-: 16-prefix ( reg r/m -- )
-    [ register-16? ] either? [ HEX: 66 , ] when ;
+: 16-prefix ( reg -- )
+    register-16? [ HEX: 66 , ] when ;
 
-: prefix ( reg r/m rex.w -- ) [ drop 16-prefix ] [ rex-prefix ] 3bi ;
-
-: prefix-1 ( reg rex.w -- ) f swap prefix ;
+: prefix-1 ( reg rex.w -- )
+    [ drop 16-prefix ] [ [ f ] 2dip rex-prefix ] 2bi ;
 
 : short-operand ( reg rex.w n -- )
     #! Some instructions encode their single operand as part of
@@ -138,57 +136,57 @@ M: register displacement, drop ;
 : opcode, ( opcode -- ) dup array? [ % ] [ , ] if ;
 
 : extended-opcode ( opcode -- opcode' )
-    dup array? [ OCT: 17 sequences:prefix ] [ OCT: 17 swap 2array ] if ;
+    dup array? [ OCT: 17 prefix ] [ OCT: 17 swap 2array ] if ;
 
 : extended-opcode, ( opcode -- ) extended-opcode opcode, ;
 
 : opcode-or ( opcode mask -- opcode' )
-    swap dup array?
-    [ unclip-last rot bitor suffix ] [ bitor ] if ;
+    over array?
+    [ [ unclip-last ] dip bitor suffix ] [ bitor ] if ;
 
-: 1-operand ( op reg,rex.w,opcode -- )
+: 1-operand ( operand reg,rex.w,opcode -- )
     #! The 'reg' is not really a register, but a value for the
     #! 'reg' field of the mod-r/m byte.
     first3 [ [ over ] dip prefix-1 ] dip opcode, swap addressing ;
 
-: immediate-operand-size-bit ( imm dst reg,rex.w,opcode -- imm dst reg,rex.w,opcode )
-    pick integer? [ first3 BIN: 1 opcode-or 3array ] when ;
+: immediate-operand-size-bit ( dst imm reg,rex.w,opcode -- imm dst reg,rex.w,opcode )
+    over integer? [ first3 BIN: 1 opcode-or 3array ] when ;
 
-: immediate-1 ( imm dst reg,rex.w,opcode -- )
-    immediate-operand-size-bit 1-operand 1, ;
+: immediate-1 ( dst imm reg,rex.w,opcode -- )
+    immediate-operand-size-bit swap [ 1-operand ] dip 1, ;
 
-: immediate-4 ( imm dst reg,rex.w,opcode -- )
-    immediate-operand-size-bit 1-operand 4, ;
+: immediate-4 ( dst imm reg,rex.w,opcode -- )
+    immediate-operand-size-bit swap [ 1-operand ] dip 4, ;
 
-: immediate-fits-in-size-bit ( imm dst reg,rex.w,opcode -- imm dst reg,rex.w,opcode )
-    pick integer? [ first3 BIN: 10 opcode-or 3array ] when ;
+: immediate-fits-in-size-bit ( dst imm reg,rex.w,opcode -- imm dst reg,rex.w,opcode )
+    over integer? [ first3 BIN: 10 opcode-or 3array ] when ;
 
-: immediate-1/4 ( imm dst reg,rex.w,opcode -- )
+: immediate-1/4 ( dst imm reg,rex.w,opcode -- )
     #! If imm is a byte, compile the opcode and the byte.
     #! Otherwise, set the 8-bit operand flag in the opcode, and
     #! compile the cell. The 'reg' is not really a register, but
     #! a value for the 'reg' field of the mod-r/m byte.
-    pick fits-in-byte? [
+    over fits-in-byte? [
         immediate-fits-in-size-bit immediate-1
     ] [
         immediate-4
     ] if ;
 
-: (2-operand) ( dst src op -- )
+: (2-operand) ( reg operand op -- )
     [ 2dup t rex-prefix ] dip opcode,
-    reg-code swap addressing ;
+    [ reg-code ] dip addressing ;
 
-: direction-bit ( dst src op -- dst' src' op' )
+: direction-bit ( dst src op -- reg operand op' )
     pick register? pick register? not and
-    [ BIN: 10 opcode-or swapd ] when ;
+    [ BIN: 10 opcode-or ] [ swapd ] if ;
 
-: operand-size-bit ( dst src op -- dst' src' op' )
-    over register-8? [ BIN: 1 opcode-or ] unless ;
+: operand-size-bit ( reg operand op -- reg operand op' )
+    pick register-8? [ BIN: 1 opcode-or ] unless ;
 
 : 2-operand ( dst src op -- )
-    #! Sets the opcode's direction bit. It is set if the
-    #! destination is a direct register operand.
-    [ drop 16-prefix ] [ direction-bit operand-size-bit (2-operand) ] 3bi ;
+    direction-bit operand-size-bit
+    pick 16-prefix
+    (2-operand) ;
 
 PRIVATE>
 
@@ -212,16 +210,16 @@ M: operand POP { BIN: 000 f HEX: 8f } 1-operand ;
 ! MOV where the src is immediate.
 <PRIVATE
 
-GENERIC: (MOV-I) ( src dst -- )
-M: register (MOV-I) t HEX: b8 short-operand cell, ;
+GENERIC# (MOV-I) 1 ( dst src -- )
+M: register (MOV-I) [ t HEX: b8 short-operand ] [ cell, ] bi* ;
 M: operand (MOV-I)
     { BIN: 000 t HEX: c6 }
-    pick byte? [ immediate-1 ] [ immediate-4 ] if ;
+    over byte? [ immediate-1 ] [ immediate-4 ] if ;
 
 PRIVATE>
 
 GENERIC: MOV ( dst src -- )
-M: immediate MOV swap (MOV-I) ;
+M: immediate MOV (MOV-I) ;
 M: operand MOV HEX: 88 2-operand ;
 
 : LEA ( dst src -- ) swap HEX: 8d 2-operand ;
@@ -267,44 +265,44 @@ PRIVATE>
 ! Arithmetic
 
 GENERIC: ADD ( dst src -- )
-M: immediate ADD swap { BIN: 000 t HEX: 80 } immediate-1/4 ;
+M: immediate ADD { BIN: 000 t HEX: 80 } immediate-1/4 ;
 M: operand ADD OCT: 000 2-operand ;
 
 GENERIC: OR ( dst src -- )
-M: immediate OR swap { BIN: 001 t HEX: 80 } immediate-1/4 ;
+M: immediate OR { BIN: 001 t HEX: 80 } immediate-1/4 ;
 M: operand OR OCT: 010 2-operand ;
 
 GENERIC: ADC ( dst src -- )
-M: immediate ADC swap { BIN: 010 t HEX: 80 } immediate-1/4 ;
+M: immediate ADC { BIN: 010 t HEX: 80 } immediate-1/4 ;
 M: operand ADC OCT: 020 2-operand ;
 
 GENERIC: SBB ( dst src -- )
-M: immediate SBB swap { BIN: 011 t HEX: 80 } immediate-1/4 ;
+M: immediate SBB { BIN: 011 t HEX: 80 } immediate-1/4 ;
 M: operand SBB OCT: 030 2-operand ;
 
 GENERIC: AND ( dst src -- )
-M: immediate AND swap { BIN: 100 t HEX: 80 } immediate-1/4 ;
+M: immediate AND { BIN: 100 t HEX: 80 } immediate-1/4 ;
 M: operand AND OCT: 040 2-operand ;
 
 GENERIC: SUB ( dst src -- )
-M: immediate SUB swap { BIN: 101 t HEX: 80 } immediate-1/4 ;
+M: immediate SUB { BIN: 101 t HEX: 80 } immediate-1/4 ;
 M: operand SUB OCT: 050 2-operand ;
 
 GENERIC: XOR ( dst src -- )
-M: immediate XOR swap { BIN: 110 t HEX: 80 } immediate-1/4 ;
+M: immediate XOR { BIN: 110 t HEX: 80 } immediate-1/4 ;
 M: operand XOR OCT: 060 2-operand ;
 
 GENERIC: CMP ( dst src -- )
-M: immediate CMP swap { BIN: 111 t HEX: 80 } immediate-1/4 ;
+M: immediate CMP { BIN: 111 t HEX: 80 } immediate-1/4 ;
 M: operand CMP OCT: 070 2-operand ;
 
 GENERIC: TEST ( dst src -- )
-M: immediate TEST swap { BIN: 0 t HEX: f7 } immediate-4 ;
+M: immediate TEST { BIN: 0 t HEX: f7 } immediate-4 ;
 M: operand TEST OCT: 204 2-operand ;
 
 : XCHG ( dst src -- ) OCT: 207 2-operand ;
 
-: BSR ( dst src -- ) swap { HEX: 0f HEX: bd } (2-operand) ;
+: BSR ( dst src -- ) { HEX: 0f HEX: bd } (2-operand) ;
 
 : NOT  ( dst -- ) { BIN: 010 t HEX: f7 } 1-operand ;
 : NEG  ( dst -- ) { BIN: 011 t HEX: f7 } 1-operand ;
@@ -318,11 +316,11 @@ M: operand TEST OCT: 204 2-operand ;
 
 <PRIVATE
 
-: (SHIFT) ( dst src op -- )
-    over CL eq? [
-        nip t HEX: d3 3array 1-operand
+:: (SHIFT) ( dst src op -- )
+    src CL eq? [
+        dst { op t HEX: d3 } 1-operand
     ] [
-        swapd t HEX: c0 3array immediate-1
+        dst src { op t HEX: c0 } immediate-1
     ] if ; inline
 
 PRIVATE>
@@ -346,19 +344,17 @@ PRIVATE>
     ] if ;
 
 : MOVSX ( dst src -- )
-    swap
-    over register-32? OCT: 143 OCT: 276 extended-opcode ?
-    pick register-16? [ BIN: 1 opcode-or ] when
+    dup register-32? OCT: 143 OCT: 276 extended-opcode ?
+    over register-16? [ BIN: 1 opcode-or ] when
     (2-operand) ;
 
 : MOVZX ( dst src -- )
-    swap
     OCT: 266 extended-opcode
-    pick register-16? [ BIN: 1 opcode-or ] when
+    over register-16? [ BIN: 1 opcode-or ] when
     (2-operand) ;
 
 ! Conditional move
-: MOVcc ( dst src cc -- ) extended-opcode swapd (2-operand) ;
+: MOVcc ( dst src cc -- ) extended-opcode (2-operand) ;
 
 : CMOVO  ( dst src -- ) HEX: 40 MOVcc ;
 : CMOVNO ( dst src -- ) HEX: 41 MOVcc ;
@@ -409,34 +405,34 @@ PRIVATE>
 <PRIVATE
 
 : direction-bit-sse ( dst src op1 -- dst' src' op1' )
-    pick register-128? [ swapd ] [ BIN: 1 bitor ] if ;
+    pick register-128? [ swapd BIN: 1 bitor ] unless ;
 
 : 2-operand-sse ( dst src op1 op2 -- )
     [ , ] when* direction-bit-sse extended-opcode (2-operand) ;
 
 : direction-op-sse ( dst src op1s -- dst' src' op1' )
-    pick register-128? [ swapd first ] [ second ] if ;
+    pick register-128? [ first ] [ swapd second ] if ;
 
 : 2-operand-rm-mr-sse ( dst src op1{rm,mr} op2 -- )
     [ , ] when* direction-op-sse extended-opcode (2-operand) ;
 
 : 2-operand-rm-sse ( dst src op1 op2 -- )
-    [ , ] when* swapd extended-opcode (2-operand) ;
+    [ , ] when* extended-opcode (2-operand) ;
 
 : 2-operand-mr-sse ( dst src op1 op2 -- )
-    [ , ] when* extended-opcode (2-operand) ;
+    [ , ] when* extended-opcode swapd (2-operand) ;
 
 : 2-operand-int/sse ( dst src op1 op2 -- )
-    [ , ] when* swapd extended-opcode (2-operand) ;
+    [ , ] when* extended-opcode (2-operand) ;
 
-: 3-operand-rm-sse ( dst src imm op1 op2 -- )
-    rot [ 2-operand-rm-sse ] dip , ;
+:: 3-operand-rm-sse ( dst src imm op1 op2 -- )
+    dst src op1 op2 2-operand-rm-sse imm , ;
 
-: 3-operand-mr-sse ( dst src imm op1 op2 -- )
-    rot [ 2-operand-mr-sse ] dip , ;
+:: 3-operand-mr-sse ( dst src imm op1 op2 -- )
+    dst src op1 op2 2-operand-mr-sse imm , ;
 
-: 3-operand-rm-mr-sse ( dst src imm op1 op2 -- )
-    rot [ 2-operand-rm-mr-sse ] dip , ;
+:: 3-operand-rm-mr-sse ( dst src imm op1 op2 -- )
+    dst src op1 op2 2-operand-rm-mr-sse imm , ;
 
 : 2-operand-sse-cmp ( dst src cmp op1 op2 -- )
     3-operand-rm-sse ; inline
@@ -739,7 +735,7 @@ PRIVATE>
 : CMPNLESS   ( dest src -- ) 6 HEX: c2 HEX: f3 2-operand-sse-cmp ;
 : CMPORDSS   ( dest src -- ) 7 HEX: c2 HEX: f3 2-operand-sse-cmp ;
 
-: MOVNTI     ( dest src -- ) { HEX: 0f HEX: c3 } (2-operand) ;
+: MOVNTI     ( dest src -- ) swap { HEX: 0f HEX: c3 } (2-operand) ;
 
 : PINSRW     ( dest src imm -- ) HEX: c4 HEX: 66 3-operand-rm-sse ;
 : SHUFPS     ( dest src imm -- ) 4shuffler HEX: c6 f       3-operand-rm-sse ;
@@ -793,4 +789,3 @@ PRIVATE>
 
 : HWNT ( -- ) HEX: 2e , ; ! Hint branch Weakly Not Taken
 : HST  ( -- ) HEX: 3e , ; ! Hint branch Strongly Taken
-
index e8d98cde1730e240779d9d350d8e9a2c05cef439..0ef2b030d127f7cc7e8f28cd6779d0e58a7f65df 100644 (file)
@@ -53,6 +53,10 @@ TUPLE: indirect base index scale displacement ;
 
 M: indirect extended? base>> extended? ;
 
+: canonicalize-displacement ( indirect -- indirect )
+    dup [ base>> ] [ displacement>> 0 = ] bi and
+    [ f >>displacement ] when ;
+
 : canonicalize-EBP ( indirect -- indirect )
     #! { EBP } ==> { EBP 0 }
     dup [ base>> { EBP RBP R13 } member? ] [ displacement>> not ] bi and
@@ -66,10 +70,7 @@ ERROR: bad-index indirect ;
 : canonicalize ( indirect -- indirect )
     #! Modify the indirect to work around certain addressing mode
     #! quirks.
-    canonicalize-EBP check-ESP ;
-
-: <indirect> ( base index scale displacement -- indirect )
-    indirect boa canonicalize ;
+    canonicalize-displacement canonicalize-EBP check-ESP ;
 
 ! Utilities
 UNION: operand register indirect ;
@@ -85,7 +86,10 @@ M: object operand-64? drop f ;
 
 PRIVATE>
 
-: [] ( reg/displacement -- indirect )
+: <indirect> ( base index scale displacement -- indirect )
+    indirect boa canonicalize ;
+
+: [] ( base/displacement -- indirect )
     dup integer?
     [ [ f f bootstrap-cell 8 = 0 f ? ] dip <indirect> ]
     [ f f f <indirect> ]
@@ -94,12 +98,24 @@ PRIVATE>
 : [RIP+] ( displacement -- indirect )
     [ f f f ] dip <indirect> ;
 
-: [+] ( reg displacement -- indirect )
+: [+] ( base index/displacement -- indirect )
     dup integer?
-    [ dup zero? [ drop f ] when [ f f ] dip ]
+    [ [ f f ] dip ]
     [ f f ] if
     <indirect> ;
 
+: [++] ( base index displacement -- indirect )
+    [ f ] dip <indirect> ;
+
+: [+*2+] ( base index displacement -- indirect )
+    [ 1 ] dip <indirect> ;
+
+: [+*4+] ( base index displacement -- indirect )
+    [ 2 ] dip <indirect> ;
+
+: [+*8+] ( base index displacement -- indirect )
+    [ 3 ] dip <indirect> ;
+
 TUPLE: byte value ;
 
 C: <byte> byte
index 969c02c91040fe989da4af31f8aaa0791bc8ff75..7669b17f20b8c4bbdee7c3d3b2a7884507ae2118 100644 (file)
@@ -3,7 +3,8 @@
 USING: bootstrap.image.private compiler.constants
 compiler.units cpu.x86.assembler cpu.x86.assembler.operands
 kernel kernel.private layouts locals.backend make math
-math.private namespaces sequences slots.private vocabs ;
+math.private namespaces sequences slots.private strings.private
+vocabs ;
 IN: bootstrap.x86
 
 big-endian off
@@ -294,6 +295,21 @@ big-endian off
     ds-reg [] temp0 MOV
 ] \ slot define-sub-primitive
 
+[
+    ! load string index from stack
+    temp0 ds-reg bootstrap-cell neg [+] MOV
+    temp0 tag-bits get SHR
+    ! load string from stack
+    temp1 ds-reg [] MOV
+    ! load character
+    temp0 8-bit-version-of temp0 temp1 string-offset [++] MOV
+    temp0 temp0 8-bit-version-of MOVZX
+    temp0 tag-bits get SHL
+    ! store character to stack
+    ds-reg bootstrap-cell SUB
+    ds-reg [] temp0 MOV
+] \ string-nth-fast define-sub-primitive
+
 ! Shufflers
 [
     ds-reg bootstrap-cell SUB
@@ -449,7 +465,7 @@ big-endian off
     ! multiply
     temp0 temp1 IMUL2
     ! push result
-    ds-reg [] temp1 MOV
+    ds-reg [] temp0 MOV
 ] \ fixnum*fast define-sub-primitive
 
 [ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
index 7bb33dec9ad3d9de81989955fdad517ff8d2b163..aa802c76fc5e3fd0be41d46f897c22d501d06ba4 100644 (file)
@@ -5,13 +5,15 @@ cpu.x86.assembler cpu.x86.assembler.private cpu.x86.assembler.operands
 cpu.x86.features cpu.x86.features.private cpu.architecture kernel
 kernel.private math memory namespaces make sequences words system
 layouts combinators math.order math.vectors fry locals compiler.constants
-byte-arrays io macros quotations compiler compiler.units init vm
+byte-arrays io macros quotations classes.algebra compiler
+compiler.units init vm
 compiler.cfg.registers
 compiler.cfg.instructions
 compiler.cfg.intrinsics
 compiler.cfg.comparisons
 compiler.cfg.stack-frame
 compiler.codegen.fixup ;
+QUALIFIED-WITH: alien.c-types c
 FROM: layouts => cell ;
 FROM: math => float ;
 IN: cpu.x86
@@ -32,17 +34,19 @@ HOOK: extra-stack-space cpu ( stack-frame -- n )
 
 : stack@ ( n -- op ) stack-reg swap [+] ;
 
-: special@ ( n -- op )
+: special-offset ( m -- n )
     stack-frame get extra-stack-space +
-    reserved-stack-space +
-    stack@ ;
+    reserved-stack-space + ;
 
-: spill@ ( n -- op ) spill-offset special@ ;
+: special@ ( n -- op ) special-offset stack@ ;
 
-: gc-root@ ( n -- op ) gc-root-offset special@ ;
+: spill@ ( n -- op ) spill-offset special@ ;
 
 : param@ ( n -- op ) reserved-stack-space + stack@ ;
 
+: gc-root-offsets ( seq -- seq' )
+    [ n>> spill-offset special-offset cell + ] map f like ;
+
 : decr-stack-reg ( n -- )
     dup 0 = [ drop ] [ stack-reg swap SUB ] if ;
 
@@ -64,9 +68,18 @@ HOOK: temp-reg cpu ( -- reg )
 
 HOOK: pic-tail-reg cpu ( -- reg )
 
+M: x86 complex-addressing? t ;
+
+M: x86 fused-unboxing? t ;
+
+M: x86 immediate-store? immediate-comparand? ;
+
 M: x86 %load-immediate dup 0 = [ drop dup XOR ] [ MOV ] if ;
 
-M: x86 %load-reference swap 0 MOV rc-absolute-cell rel-literal ;
+M: x86 %load-reference
+    [ swap 0 MOV rc-absolute-cell rel-literal ]
+    [ \ f type-number MOV ]
+    if* ;
 
 HOOK: ds-reg cpu ( -- reg )
 HOOK: rs-reg cpu ( -- reg )
@@ -79,7 +92,17 @@ M: ds-loc loc>operand n>> ds-reg reg-stack ;
 M: rs-loc loc>operand n>> rs-reg reg-stack ;
 
 M: x86 %peek loc>operand MOV ;
+
 M: x86 %replace loc>operand swap MOV ;
+
+M: x86 %replace-imm
+    loc>operand swap
+    {
+        { [ dup not ] [ drop \ f type-number MOV ] }
+        { [ dup fixnum? ] [ tag-fixnum MOV ] }
+        [ [ HEX: ffffffff MOV ] dip rc-absolute rel-literal ]
+    } cond ;
+
 : (%inc) ( n reg -- ) swap cells dup 0 > [ ADD ] [ neg SUB ] if ; inline
 M: x86 %inc-d ( n -- ) ds-reg (%inc) ;
 M: x86 %inc-r ( n -- ) rs-reg (%inc) ;
@@ -100,18 +123,12 @@ M: x86 %jump-label ( label -- ) 0 JMP rc-relative label-fixup ;
 
 M: x86 %return ( -- ) 0 RET ;
 
-: code-alignment ( align -- n )
-    [ building get length dup ] dip align swap - ;
-
-: align-code ( n -- )
-    0 <repetition> % ;
+: (%slot) ( obj slot scale tag -- op ) neg <indirect> ; inline
+: (%slot-imm) ( obj slot tag -- op ) slot-offset [+] ; inline
 
-:: (%slot-imm) ( obj slot tag -- op )
-    obj slot tag slot-offset [+] ; inline
-
-M: x86 %slot ( dst obj slot -- ) [+] MOV ;
+M: x86 %slot ( dst obj slot scale tag -- ) (%slot) MOV ;
 M: x86 %slot-imm ( dst obj slot tag -- ) (%slot-imm) MOV ;
-M: x86 %set-slot ( src obj slot -- ) [+] swap MOV ;
+M: x86 %set-slot ( src obj slot scale tag -- ) (%slot) swap MOV ;
 M: x86 %set-slot-imm ( src obj slot tag -- ) (%slot-imm) swap MOV ;
 
 :: two-operand ( dst src1 src2 rep -- dst src )
@@ -127,7 +144,7 @@ M: x86 %add     2over eq? [ nip ADD ] [ [+] LEA ] if ;
 M: x86 %add-imm 2over eq? [ nip ADD ] [ [+] LEA ] if ;
 M: x86 %sub     int-rep two-operand SUB ;
 M: x86 %sub-imm 2over eq? [ nip SUB ] [ neg [+] LEA ] if ;
-M: x86 %mul     int-rep two-operand swap IMUL2 ;
+M: x86 %mul     int-rep two-operand IMUL2 ;
 M: x86 %mul-imm IMUL3 ;
 M: x86 %and     int-rep two-operand AND ;
 M: x86 %and-imm int-rep two-operand AND ;
@@ -169,14 +186,21 @@ M: x86 %copy ( dst src rep -- )
         2over [ register? ] both? [ copy-register* ] [ copy-memory* ] if
     ] if ;
 
-M: x86 %fixnum-add ( label dst src1 src2 -- )
-    int-rep two-operand ADD JO ;
+: fixnum-overflow ( label dst src1 src2 cc quot -- )
+    swap [ [ int-rep two-operand ] dip call ] dip
+    {
+        { cc-o [ JO ] }
+        { cc/o [ JNO ] }
+    } case ; inline
+
+M: x86 %fixnum-add ( label dst src1 src2 cc -- )
+    [ ADD ] fixnum-overflow ;
 
-M: x86 %fixnum-sub ( label dst src1 src2 -- )
-    int-rep two-operand SUB JO ;
+M: x86 %fixnum-sub ( label dst src1 src2 cc -- )
+    [ SUB ] fixnum-overflow ;
 
-M: x86 %fixnum-mul ( label dst src1 src2 -- )
-    int-rep two-operand swap IMUL2 JO ;
+M: x86 %fixnum-mul ( label dst src1 src2 cc -- )
+    [ IMUL2 ] fixnum-overflow ;
 
 M: x86 %unbox-alien ( dst src -- )
     alien-offset [+] MOV ;
@@ -217,12 +241,68 @@ M:: x86 %box-alien ( dst src temp -- )
         "end" resolve-label
     ] with-scope ;
 
+:: %box-displaced-alien/f ( dst displacement -- )
+    dst 1 alien@ \ f type-number MOV
+    dst 3 alien@ displacement MOV
+    dst 4 alien@ displacement MOV ;
+
+:: %box-displaced-alien/alien ( dst displacement base temp -- )
+    ! Set new alien's base to base.base
+    temp base 1 alien@ MOV
+    dst 1 alien@ temp MOV
+
+    ! Compute displacement
+    temp base 3 alien@ MOV
+    temp displacement ADD
+    dst 3 alien@ temp MOV
+
+    ! Compute address
+    temp base 4 alien@ MOV
+    temp displacement ADD
+    dst 4 alien@ temp MOV ;
+
+:: %box-displaced-alien/byte-array ( dst displacement base temp -- )
+    dst 1 alien@ base MOV
+    dst 3 alien@ displacement MOV
+    temp base displacement byte-array-offset [++] LEA
+    dst 4 alien@ temp MOV ;
+
+:: %box-displaced-alien/dynamic ( dst displacement base temp -- )
+    "not-f" define-label
+    "not-alien" define-label
+
+    ! Check base type
+    temp base MOV
+    temp tag-mask get AND
+
+    ! Is base f?
+    temp \ f type-number CMP
+    "not-f" get JNE
+
+    ! Yes, it is f. Fill in new object
+    dst displacement %box-displaced-alien/f
+
+    "end" get JMP
+
+    "not-f" resolve-label
+
+    ! Is base an alien?
+    temp alien type-number CMP
+    "not-alien" get JNE
+
+    dst displacement base temp %box-displaced-alien/alien
+
+    ! We are done
+    "end" get JMP
+
+    ! Is base a byte array? It has to be, by now...
+    "not-alien" resolve-label
+
+    dst displacement base temp %box-displaced-alien/byte-array ;
+
 M:: x86 %box-displaced-alien ( dst displacement base temp base-class -- )
-    ! This is ridiculous
     [
         "end" define-label
-        "not-f" define-label
-        "not-alien" define-label
 
         ! If displacement is zero, return the base
         dst base MOV
@@ -236,53 +316,13 @@ M:: x86 %box-displaced-alien ( dst displacement base temp base-class -- )
         ! Set expired to f
         dst 2 alien@ \ f type-number MOV
 
-        ! Is base f?
-        base \ f type-number CMP
-        "not-f" get JNE
-
-        ! Yes, it is f. Fill in new object
-        dst 1 alien@ base MOV
-        dst 3 alien@ displacement MOV
-        dst 4 alien@ displacement MOV
-
-        "end" get JMP
-
-        "not-f" resolve-label
-
-        ! Check base type
-        temp base MOV
-        temp tag-mask get AND
-
-        ! Is base an alien?
-        temp alien type-number CMP
-        "not-alien" get JNE
-
-        ! Yes, it is an alien. Set new alien's base to base.base
-        temp base 1 alien@ MOV
-        dst 1 alien@ temp MOV
-
-        ! Compute displacement
-        temp base 3 alien@ MOV
-        temp displacement ADD
-        dst 3 alien@ temp MOV
-
-        ! Compute address
-        temp base 4 alien@ MOV
-        temp displacement ADD
-        dst 4 alien@ temp MOV
-
-        ! We are done
-        "end" get JMP
-
-        ! Is base a byte array? It has to be, by now...
-        "not-alien" resolve-label
-
-        dst 1 alien@ base MOV
-        dst 3 alien@ displacement MOV
-        temp base MOV
-        temp byte-array-offset ADD
-        temp displacement ADD
-        dst 4 alien@ temp MOV
+        dst displacement base temp
+        {
+            { [ base-class \ f class<= ] [ 2drop %box-displaced-alien/f ] }
+            { [ base-class \ alien class<= ] [ %box-displaced-alien/alien ] }
+            { [ base-class \ byte-array class<= ] [ %box-displaced-alien/byte-array ] }
+            [ %box-displaced-alien/dynamic ]
+        } cond
 
         "end" resolve-label
     ] with-scope ;
@@ -324,82 +364,66 @@ M: x86.64 has-small-reg? 2drop t ;
         [ quot call ] with-save/restore
     ] if ; inline
 
-M:: x86 %string-nth ( dst src index temp -- )
-    ! We request a small-reg of size 8 since those of size 16 are
-    ! a superset.
-    "end" define-label
-    dst { src index temp } 8 [| new-dst |
-        ! Load the least significant 7 bits into new-dst.
-        ! 8th bit indicates whether we have to load from
-        ! the aux vector or not.
-        temp src index [+] LEA
-        new-dst 8-bit-version-of temp string-offset [+] MOV
-        new-dst new-dst 8-bit-version-of MOVZX
-        ! Do we have to look at the aux vector?
-        new-dst HEX: 80 CMP
-        "end" get JL
-        ! Yes, this is a non-ASCII character. Load aux vector
-        temp src string-aux-offset [+] MOV
-        new-dst temp XCHG
-        ! Compute index
-        new-dst index ADD
-        new-dst index ADD
-        ! Load high 16 bits
-        new-dst 16-bit-version-of new-dst byte-array-offset [+] MOV
-        new-dst new-dst 16-bit-version-of MOVZX
-        new-dst 7 SHL
-        ! Compute code point
-        new-dst temp XOR
-        "end" resolve-label
-        dst new-dst int-rep %copy
-    ] with-small-register ;
-
-M:: x86 %set-string-nth-fast ( ch str index temp -- )
-    ch { index str temp } 8 [| new-ch |
-        new-ch ch int-rep %copy
-        temp str index [+] LEA
-        temp string-offset [+] new-ch 8-bit-version-of MOV
-    ] with-small-register ;
-
-:: %alien-integer-getter ( dst src offset size quot -- )
-    dst { src } size [| new-dst |
-        new-dst dup size n-bit-version-of dup src offset [+] MOV
+:: %alien-integer-getter ( dst exclude address bits quot -- )
+    dst exclude bits [| new-dst |
+        new-dst dup bits n-bit-version-of dup address MOV
         quot call
         dst new-dst int-rep %copy
     ] with-small-register ; inline
 
-: %alien-unsigned-getter ( dst src offset size -- )
+: %alien-unsigned-getter ( dst exclude address bits -- )
     [ MOVZX ] %alien-integer-getter ; inline
 
-: %alien-signed-getter ( dst src offset size -- )
+: %alien-signed-getter ( dst exclude address bits -- )
     [ MOVSX ] %alien-integer-getter ; inline
 
-:: %alien-integer-setter ( ptr offset value size -- )
-    value { ptr } size [| new-value |
+:: %alien-integer-setter ( value exclude address bits -- )
+    value exclude bits [| new-value |
         new-value value int-rep %copy
-        ptr offset [+] new-value size n-bit-version-of MOV
+        address new-value bits n-bit-version-of MOV
     ] with-small-register ; inline
 
-M: x86 %alien-unsigned-1 8 %alien-unsigned-getter ;
-M: x86 %alien-unsigned-2 16 %alien-unsigned-getter ;
-M: x86 %alien-unsigned-4 32 [ 2drop ] %alien-integer-getter ;
+: (%memory) ( base displacement scale offset rep c-type -- exclude address rep c-type )
+    [ [ [ 2array ] 2keep ] 2dip <indirect> ] 2dip ;
 
-M: x86 %alien-signed-1 8 %alien-signed-getter ;
-M: x86 %alien-signed-2 16 %alien-signed-getter ;
-M: x86 %alien-signed-4 32 %alien-signed-getter ;
+: (%memory-imm) ( base offset rep c-type -- exclude address rep c-type )
+    [ [ drop 1array ] [ [+] ] 2bi ] 2dip ;
 
-M: x86 %alien-cell [+] MOV ;
-M: x86 %alien-float [+] MOVSS ;
-M: x86 %alien-double [+] MOVSD ;
-M: x86 %alien-vector [ [+] ] dip %copy ;
+: (%load-memory) ( dst exclude address rep c-type -- )
+    [
+        {
+            { c:char   [ 8 %alien-signed-getter ] }
+            { c:uchar  [ 8 %alien-unsigned-getter ] }
+            { c:short  [ 16 %alien-signed-getter ] }
+            { c:ushort [ 16 %alien-unsigned-getter ] }
+            { c:int    [ 32 %alien-signed-getter ] }
+            { c:uint   [ 32 [ 2drop ] %alien-integer-getter ] }
+        } case
+    ] [ [ drop ] 2dip %copy ] ?if ;
 
-M: x86 %set-alien-integer-1 8 %alien-integer-setter ;
-M: x86 %set-alien-integer-2 16 %alien-integer-setter ;
-M: x86 %set-alien-integer-4 32 %alien-integer-setter ;
-M: x86 %set-alien-cell [ [+] ] dip MOV ;
-M: x86 %set-alien-float [ [+] ] dip MOVSS ;
-M: x86 %set-alien-double [ [+] ] dip MOVSD ;
-M: x86 %set-alien-vector [ [+] ] 2dip %copy ;
+M: x86 %load-memory ( dst base displacement scale offset rep c-type -- )
+    (%memory) (%load-memory) ;
+
+M: x86 %load-memory-imm ( dst base offset rep c-type -- )
+    (%memory-imm) (%load-memory) ;
+
+: (%store-memory) ( src exclude address rep c-type -- )
+    [
+        {
+            { c:char   [ 8 %alien-integer-setter ] }
+            { c:uchar  [ 8 %alien-integer-setter ] }
+            { c:short  [ 16 %alien-integer-setter ] }
+            { c:ushort [ 16 %alien-integer-setter ] }
+            { c:int    [ 32 %alien-integer-setter ] }
+            { c:uint   [ 32 %alien-integer-setter ] }
+        } case
+    ] [ [ nip swap ] dip %copy ] ?if ;
+
+M: x86 %store-memory ( src base displacement scale offset rep c-type -- )
+    (%memory) (%store-memory) ;
+
+M: x86 %store-memory-imm ( src base offset rep c-type -- )
+    (%memory-imm) (%store-memory) ;
 
 : shift-count? ( reg -- ? ) { ECX RCX } member-eq? ;
 
@@ -451,30 +475,29 @@ M:: x86 %allot ( dst size class nursery-ptr -- )
 HOOK: %mark-card cpu ( card temp -- )
 HOOK: %mark-deck cpu ( card temp -- )
 
-:: (%write-barrier) ( src slot temp1 temp2 -- )
-    temp1 src slot [+] LEA
+:: (%write-barrier) ( temp1 temp2 -- )
     temp1 card-bits SHR
     temp1 temp2 %mark-card
     temp1 deck-bits card-bits - SHR
     temp1 temp2 %mark-deck ;
 
-M: x86 %write-barrier ( src slot temp1 temp2 -- ) (%write-barrier) ;
+M:: x86 %write-barrier ( src slot scale tag temp1 temp2 -- )
+    temp1 src slot scale tag (%slot) LEA
+    temp1 temp2 (%write-barrier) ;
 
-M: x86 %write-barrier-imm ( src slot temp1 temp2 -- ) (%write-barrier) ;
+M:: x86 %write-barrier-imm ( src slot tag temp1 temp2 -- )
+    temp1 src slot tag (%slot-imm) LEA
+    temp1 temp2 (%write-barrier) ;
 
-M:: x86 %check-nursery ( label size temp1 temp2 -- )
+M:: x86 %check-nursery-branch ( label size cc temp1 temp2 -- )
     temp1 load-zone-offset
-    ! Load 'here' into temp2
     temp2 temp1 [] MOV
     temp2 size ADD
-    ! Load 'end' into temp1
-    temp1 temp1 2 cells [+] MOV
-    temp2 temp1 CMP
-    label JLE ;
-
-M: x86 %save-gc-root ( gc-root register -- ) [ gc-root@ ] dip MOV ;
-
-M: x86 %load-gc-root ( gc-root register -- ) swap gc-root@ MOV ;
+    temp2 temp1 2 cells [+] CMP
+    cc {
+        { cc<= [ label JLE ] }
+        { cc/<= [ label JG ] }
+    } case ;
 
 M: x86 %alien-global ( dst symbol library -- )
     [ 0 MOV ] 2dip rc-absolute-cell rel-dlsym ;    
@@ -516,12 +539,18 @@ M:: x86 %compare ( dst src1 src2 cc temp -- )
 : (%compare-tagged) ( src1 src2 -- )
     [ HEX: ffffffff CMP ] dip rc-absolute rel-literal ;
 
+: (%compare-integer-imm) ( src1 src2 cc -- )
+    3dup use-test? [ 2drop dup TEST ] [ drop CMP ] if ;
+
+M:: x86 %compare-integer-imm ( dst src1 src2 cc temp -- )
+    src1 src2 cc (%compare-integer-imm)
+    dst cc temp %boolean ;
+
 : (%compare-imm) ( src1 src2 cc -- )
     {
-        { [ 3dup use-test? ] [ 2drop dup TEST ] }
-        { [ over integer? ] [ drop CMP ] }
-        { [ over word? ] [ drop (%compare-tagged) ] }
+        { [ over fixnum? ] [ [ tag-fixnum ] dip (%compare-integer-imm) ] }
         { [ over not ] [ 2drop \ f type-number CMP ] }
+        [ drop (%compare-tagged) ]
     } cond ;
 
 M:: x86 %compare-imm ( dst src1 src2 cc temp -- )
@@ -542,6 +571,10 @@ M:: x86 %compare-branch ( label src1 src2 cc -- )
     src1 src2 CMP
     label cc %branch ;
 
+M:: x86 %compare-integer-imm-branch ( label src1 src2 cc -- )
+    src1 src2 cc (%compare-integer-imm)
+    label cc %branch ;
+
 M:: x86 %compare-imm-branch ( label src1 src2 cc -- )
     src1 src2 cc (%compare-imm)
     label cc %branch ;
@@ -1423,7 +1456,7 @@ M: x86 %scalar>vector %copy ;
 M:: x86 %spill ( src rep dst -- ) dst src rep %copy ;
 M:: x86 %reload ( dst rep src -- ) dst src rep %copy ;
 
-M: x86 %loop-entry 16 code-alignment [ NOP ] times ;
+M: x86 %loop-entry 16 alignment [ NOP ] times ;
 
 M:: x86 %restore-context ( temp1 temp2 -- )
     #! Load Factor stack pointers on entry from C to Factor.
@@ -1457,7 +1490,7 @@ M: x86 immediate-bitwise? ( n -- ? )
     frame-reg swap 2 cells + [+] ;
 
 enable-min/max
-enable-fixnum-log2
+enable-log2
 
 :: install-sse2-check ( -- )
     [
index 05df13f07347d20ef427e2a876d8463f0502a83a..a158302ecc02117523861f40ab5fc38dfc06c7b7 100644 (file)
@@ -74,6 +74,10 @@ GENERIC: disjoint-set-member? ( a disjoint-set -- ? )
 
 M: disjoint-set disjoint-set-member? parents>> key? ;
 
+GENERIC: disjoint-set-members ( disjoint-set -- seq )
+
+M: disjoint-set disjoint-set-members parents>> keys ;
+
 GENERIC: equiv-set-size ( a disjoint-set -- n )
 
 M: disjoint-set equiv-set-size [ representative ] keep count ;
index 568deb3750ff669d8c86170c14caa946f193afa7..32c2cd47bfb7339e11c68310902c91e6f2319218 100644 (file)
@@ -30,7 +30,7 @@ MACRO: map-index-compose ( seq quot -- seq )
       XINPUT_GAMEPAD_B
       XINPUT_GAMEPAD_X
       XINPUT_GAMEPAD_Y }
-      [ [ bitand ] dip swap 0 = [ 2drop ] [ 1.0 -rot swap set-nth ] if ]
+      [ [ bitand ] dip swap 0 = [ 2drop ] [ [ 1.0 ] 2dip swap set-nth ] if ]
       map-index-compose 2cleave ;
 
  : >pov ( byte -- symbol )
old mode 100644 (file)
new mode 100755 (executable)
index d50d517..9610189
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors ascii combinators images images.loader io
 io.encodings.ascii io.encodings.string kernel locals make math
-math.parser prettyprint sequences ;
+math.parser sequences ;
 IN: images.ppm
 
 SINGLETON: ppm-image
old mode 100644 (file)
new mode 100755 (executable)
index 4a82545..a1880a3
@@ -4,7 +4,7 @@ USING: accessors arrays assocs byte-arrays classes combinators
 compression.lzw endian fry grouping images io
 io.binary io.encodings.ascii io.encodings.binary
 io.encodings.string io.encodings.utf8 io.files kernel math
-math.bitwise math.order math.parser pack prettyprint sequences
+math.bitwise math.order math.parser pack sequences
 strings math.vectors specialized-arrays locals
 images.loader ;
 FROM: alien.c-types => float ;
index 53a67bbeab4f36fcd503242e08abba5c81a95557..6c63d3eda0a234f5deeac8aaf536b6549caa9d7a 100644 (file)
@@ -1,8 +1,10 @@
-USING: alien alien.c-types alien.data alien.syntax arrays continuations
-destructors generic io.mmap io.ports io.backend.windows io.files.windows
-kernel libc locals math math.bitwise namespaces quotations sequences windows
-windows.advapi32 windows.kernel32 windows.types io.backend system accessors
-io.backend.windows.privileges classes.struct windows.errors literals ;
+USING: alien alien.c-types alien.data alien.syntax arrays
+continuations destructors generic io.mmap io.ports
+io.backend.windows io.files.windows kernel libc fry locals math
+math.bitwise namespaces quotations sequences windows
+windows.advapi32 windows.kernel32 windows.types io.backend
+system accessors io.backend.windows.privileges classes.struct
+windows.errors literals ;
 IN: io.backend.windows.nt.privileges
 
 TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
@@ -37,7 +39,11 @@ TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
         >>Privileges ;
 
 M: winnt set-privilege ( name ? -- )
-    [
-        -rot 0 -rot make-token-privileges
-        dup byte-length f f AdjustTokenPrivileges win32-error=0/f
+    '[
+        0
+        _ _ make-token-privileges
+        dup byte-length
+        f
+        f
+        AdjustTokenPrivileges win32-error=0/f
     ] with-process-token ;
index bb7569516a329033b65dbc8064d942682f19a0b5..fef6b076ba2f9890a739ec403df326a6709575fc 100644 (file)
@@ -135,6 +135,6 @@ concurrency.promises threads unix.process calendar unix ;
         ] in-thread
 
         p 1 seconds ?promise-timeout handle>> kill-process*
-        s ?promise 0 =
+        s 3 seconds ?promise-timeout 0 =
     ]
 ] unit-test
index 22c649c54422cf68eb436f42ee9392ea46ee9541..a551190dbdcc35e8080f5bd343a50bc633a54b3c 100644 (file)
@@ -137,7 +137,7 @@ M: blas-matrix-base clone
 : <empty-matrix> ( rows cols exemplar -- matrix )
     [ element-type heap-size * * <byte-array> ]
     [ 2drop ]
-    [ f swap (blas-matrix-like) ] 3tri ;
+    [ [ f ] dip (blas-matrix-like) ] 3tri ;
 
 : n*M.V+n*V ( alpha A x beta y -- alpha*A.x+b*y )
     clone n*M.V+n*V! ;
@@ -153,7 +153,7 @@ M: blas-matrix-base clone
     n*M.V+n*V! ; inline
 
 : M.V ( A x -- A.x )
-    1.0 -rot n*M.V ; inline
+    [ 1.0 ] 2dip n*M.V ; inline
 
 : n*V(*)V ( alpha x y -- alpha*x(*)y )
     2dup [ length>> ] bi@ pick <empty-matrix>
@@ -163,16 +163,16 @@ M: blas-matrix-base clone
     n*V(*)Vconj+M! ;
 
 : V(*) ( x y -- x(*)y )
-    1.0 -rot n*V(*)V ; inline
+    [ 1.0 ] 2dip n*V(*)V ; inline
 : V(*)conj ( x y -- x(*)yconj )
-    1.0 -rot n*V(*)Vconj ; inline
+    [ 1.0 ] 2dip n*V(*)Vconj ; inline
 
 : n*M.M ( alpha A B -- alpha*A.B )
     2dup [ Mheight ] [ Mwidth ] bi* pick <empty-matrix> 
-    1.0 swap n*M.M+n*M! ;
+    [ 1.0 ] dip n*M.M+n*M! ;
 
 : M. ( A B -- A.B )
-    1.0 -rot n*M.M ; inline
+    [ 1.0 ] 2dip n*M.M ; inline
 
 :: (Msub) ( matrix row col height width -- data ld rows cols )
     matrix ld>> col * row + matrix element-type heap-size *
index 1d19c76dc1ac871e2d64a90d9fff72a12dd5cc9a..f3d56ba8687ab7237e0f74319876a06fd36264b2 100644 (file)
@@ -128,7 +128,7 @@ CONSTANT: vector-words
         @
         [ dup [ class ] { } map-as ] dip '[ _ declare @ ]
         {
-            [ "print-mr" get [ nip test-mr mr. ] [ 2drop ] if ]
+            [ "print-mr" get [ nip regs. ] [ 2drop ] if ]
             [ "print-checks" get [ [ . ] bi@ ] [ 2drop ] if ]
             [ [ [ call ] dip call ] call( quot quot -- result ) ]
             [ [ [ call ] dip compile-call ] call( quot quot -- result ) ]
index aba92899da7f8a4c178b5b56cf672a588bf5ee59..897746a9c963d7c8c66d9753100345cdf273e231 100644 (file)
@@ -528,3 +528,17 @@ Tok                = Spaces (Number | Special )
 ] [
     error>> [ redefined-rule? ] [ name>> "lol" = ] bi and
 ] must-fail-with
+
+[
+    { "a" "a" }
+] [
+    EBNF: foo   Bar = "a":a1 "a":a2 => [[ a1 a2 2array ]] ;EBNF
+    "aa" foo
+] unit-test
+
+[
+    { "a" "a" }
+] [
+    EBNF: foo2   Bar = "a":a-1 "a":a-2 => [[ a-1 a-2 2array ]] ;EBNF
+    "aa" foo2
+] unit-test
index ffc4cb91ad78aa462b4abbf529ac615225179e80..b682f582add9e8420bd959a2a7b72a23aea1b913 100644 (file)
@@ -230,7 +230,11 @@ DEFER: 'action'
 \r
 : 'element' ( -- parser )\r
   [\r
-    [ ('element') , ":" syntax , "a-zA-Z" range-pattern repeat1 [ >string ] action , ] seq* [ first2 <ebnf-var> ] action ,\r
+    [\r
+      ('element') , ":" syntax ,\r
+      "a-zA-Z_" range-pattern\r
+      "a-zA-Z0-9_-" range-pattern repeat1 2seq [ first2 swap prefix >string ] action ,\r
+    ] seq* [ first2 <ebnf-var> ] action ,\r
     ('element') ,\r
   ] choice* ;\r
 \r
index 2dee88df8842514ca01d9b70553499d2b9c02bc3..ad1b4ad2b713ece63d6bc44a03b351ca1d22a3d9 100644 (file)
@@ -188,5 +188,6 @@ SPECIALIZED-ARRAY: struct-resize-test
 [ ] [
     [
         struct-resize-test specialized-array-vocab forget-vocab
+        \ struct-resize-test-usage forget
     ] with-compilation-unit
 ] unit-test
index c0d4b6c543f639cf47cfa798873e136fba345a35..a652c500bac5ff180c03e3d415900abba46f61fd 100644 (file)
@@ -454,11 +454,10 @@ M: bad-executable summary
 \ set-slot { object object fixnum } { } define-primitive
 \ set-special-object { object fixnum } { } define-primitive
 \ set-string-nth-fast { fixnum fixnum string } { } define-primitive
-\ set-string-nth-slow { fixnum fixnum string } { } define-primitive
 \ size { object } { fixnum } define-primitive \ size make-flushable
 \ slot { object fixnum } { object } define-primitive \ slot make-flushable
 \ special-object { fixnum } { object } define-primitive \ special-object make-flushable
-\ string-nth { fixnum string } { fixnum } define-primitive \ string-nth make-flushable
+\ string-nth-fast { fixnum string } { fixnum } define-primitive \ string-nth-fast make-flushable
 \ strip-stack-traces { } { } define-primitive
 \ system-micros { } { integer } define-primitive \ system-micros make-flushable
 \ tag { object } { fixnum } define-primitive \ tag make-foldable
index 485f0f5fa7f2144ed5da1118edb112c0d47f41c3..44291a96cc5b5193bce15435631fad31f58b39d1 100755 (executable)
@@ -1,13 +1,15 @@
 ! Copyright (C) 2007, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays alien.libraries accessors io.backend io.encodings.utf8 io.files
-io.streams.c init fry namespaces math make assocs kernel parser
-parser.notes lexer strings.parser vocabs sequences sequences.deep
-sequences.private words memory kernel.private continuations io
-vocabs.loader system strings sets vectors quotations byte-arrays
-sorting compiler.units definitions generic generic.standard
-generic.single tools.deploy.config combinators classes vocabs.loader.private
-classes.builtin slots.private grouping command-line io.pathnames ;
+USING: arrays alien.libraries accessors io.backend
+io.encodings.utf8 io.files io.streams.c init fry namespaces math
+make assocs kernel parser parser.notes lexer strings.parser
+vocabs sequences sequences.deep sequences.private words memory
+kernel.private continuations io vocabs.loader system strings
+sets vectors quotations byte-arrays sorting compiler.units
+definitions generic generic.standard generic.single
+tools.deploy.config combinators combinators.private classes
+vocabs.loader.private classes.builtin slots.private grouping
+command-line io.pathnames ;
 QUALIFIED: bootstrap.stage2
 QUALIFIED: classes.private
 QUALIFIED: compiler.crossref
@@ -548,10 +550,18 @@ SYMBOL: deploy-vocab
     strip-words
     clear-megamorphic-caches ;
 
+: die-with ( error original-error -- * )
+    #! We don't want DCE to drop the error before the die call!
+    [ die 1 exit ] (( a -- * )) call-effect-unsafe ;
+
+: die-with2 ( error original-error -- * )
+    #! We don't want DCE to drop the error before the die call!
+    [ die 1 exit ] (( a b -- * )) call-effect-unsafe ;
+
 : deploy-error-handler ( quot -- )
     [
         strip-debugger?
-        [ error-continuation get call>> callstack>array die 1 exit ]
+        [ original-error get die-with2 ]
         ! Don't reference these words literally, if we're stripping the
         ! debugger out we don't want to load the prettyprinter at all
         [ [:c] execute( -- ) nl [print-error] execute( error -- ) flush ] if
index b7565e7d9e7407985e2eeb5c45413bc545f4de5d..121891b5636b450a37756a6b74ff0b1a4a284a01 100644 (file)
@@ -1,17 +1,14 @@
-USING: compiler.units words vocabs kernel threads.private ;
+USING: compiler.units continuations kernel namespaces
+threads.private words vocabs tools.deploy.shaker ;
 IN: debugger
 
-: consume ( error -- )
-    #! We don't want DCE to drop the error before the die call!
-    drop ;
+: error. ( error -- ) original-error get die-with2 ;
 
-: print-error ( error -- ) die consume ;
-
-: error. ( error -- ) die consume ;
+: print-error ( error -- ) error. ;
 
 "threads" vocab [
     [
         "error-in-thread" "threads" lookup
-        [ [ die 2drop ] define ] [ f "combination" set-word-prop ] bi
+        [ [ drop error. ] define ] [ f "combination" set-word-prop ] bi
     ] with-compilation-unit
 ] when
index dae30fa9d80d7cafec5e0d89e4e7fd0e83ff452e..98a083a2babb32d878583b304676638859ec2fdd 100644 (file)
@@ -3,12 +3,11 @@ USING: typed compiler.cfg.debugger compiler.tree.debugger
 tools.disassembler words ;
 IN: typed.debugger
 
-: typed-test-mr ( word -- mrs )
-    "typed-word" word-prop test-mr ; inline
-: typed-test-mr. ( word -- )
-    "typed-word" word-prop test-mr mr. ; inline
+M: typed-word test-builder
+    "typed-word" word-prop test-builder ;
+
 : typed-optimized. ( word -- )
-    "typed-word" word-prop optimized. ; inline
+    "typed-word" word-prop optimized. ;
 
-: typed-disassemble ( word -- )
-    "typed-word" word-prop disassemble ; inline
+M: typed-word disassemble ( word -- )
+    "typed-word" word-prop disassemble ;
index 65b21fcc38236e7b32a6acfc2450a48c97b31a7f..50da7b1bad5e1386c45c563058ad97cb44837662 100644 (file)
@@ -167,3 +167,4 @@ SYNTAX: TYPED::
 USE: vocabs.loader
 
 { "typed" "prettyprint" } "typed.prettyprint" require-when
+{ "typed" "compiler.cfg.debugger" } "typed.debugger" require-when
index 057c8320acad497d758e3b095b5eb84c3a203352..45f948e14ada974c687836e23dd3c8bed7951a7a 100644 (file)
@@ -25,13 +25,11 @@ ARTICLE: "ui.gadgets.tables.selection" "Table row selection"
   { { $slot "selection" } { " - if set to a model, the values of the currently selected row or rows, as determined by a " { $link row-value } " call to the renderer, is stored in this model. See " { $link "models" } "." } }
   { { $slot "selection-index" } { " - if set to a model, the indices of the currently selected rows." } }
   { { $slot "selection-required?" } { " - if set to a true value, the table ensures that some row is always selected, if the model is non-empty. If set to " { $link f } ", a state where nothing is selected is permitted to occur. The default is " { $link f } "." } }
-  { { $slot "multiple-selection?" } { " - if set to a true value, users are allowed to select more than one value." } }
 }
 "Some words for row selection:"
 { $subsections
-    selected-rows
-    (selected-rows)
-    selected
+    selected-row
+    (selected-row)
 } ;
 
 ARTICLE: "ui.gadgets.tables.actions" "Table row actions"
index c907e90673fa58af3e6c44035a64e38baea1eae7..77b9ec99edb76bb365d420002cacf86dbe493b50 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs hashtables arrays colors colors.constants fry
 kernel math math.functions math.ranges math.rectangles math.order
@@ -18,6 +18,7 @@ GENERIC: column-titles ( renderer -- strings )
 GENERIC: row-columns ( row renderer -- columns )
 GENERIC: row-value ( row renderer -- object )
 GENERIC: row-color ( row renderer -- color )
+GENERIC: row-value? ( value row renderer -- ? )
 
 SINGLETON: trivial-renderer
 
@@ -29,6 +30,7 @@ M: object column-titles drop f ;
 M: trivial-renderer row-columns drop ;
 M: object row-value drop ;
 M: object row-color 2drop f ;
+M: object row-value? drop eq? ;
 
 TUPLE: table < line-gadget
 { renderer initial: trivial-renderer }
@@ -41,33 +43,11 @@ focus-border-color
 { mouse-color initial: COLOR: black }
 column-line-color
 selection-required?
-selection
 selection-index
-selected-indices
+selection
 mouse-index
 { takes-focus? initial: t }
-focused?
-multiple-selection? ;
-
-<PRIVATE
-
-: add-selected-index ( table n -- table )
-    over selected-indices>> conjoin ;
-
-: multiple>single ( values -- value/f ? )
-    dup assoc-empty? [ drop f f ] [ values first t ] if ;
-
-: selected-index ( table -- n )
-    selected-indices>> multiple>single drop ;
-
-: set-selected-index ( table n -- table )
-    dup associate >>selected-indices ;
-
-PRIVATE>
-
-: selected ( table -- index/indices )
-    [ selected-indices>> ] [ multiple-selection?>> ] bi
-    [ multiple>single drop ] unless ;
+focused? ;
 
 : new-table ( rows renderer class -- table )
     new-line-gadget
@@ -77,8 +57,7 @@ PRIVATE>
         focus-border-color >>focus-border-color
         transparent >>column-line-color
         f <model> >>selection-index
-        f <model> >>selection
-        H{ } clone >>selected-indices ;
+        f <model> >>selection ;
 
 : <table> ( rows renderer -- table ) table new-table ;
 
@@ -156,30 +135,23 @@ M: table layout*
 : row-bounds ( table row -- loc dim )
     row-rect rect-bounds ; inline
 
-: draw-selected-rows ( table -- )
-    {
-        { [ dup selected-indices>> assoc-empty? ] [ drop ] }
-        [
-            [ selected-indices>> keys ] [ selection-color>> gl-color ] [ ] tri
-            [ swap row-bounds gl-fill-rect ] curry each
-        ]
-    } cond ;
+: draw-selected-row ( table -- )
+    dup selection-index>> value>> [
+        dup selection-color>> gl-color
+        dup selection-index>> value>> row-bounds gl-fill-rect
+    ] [ drop ] if ;
 
 : draw-focused-row ( table -- )
-    {
-        { [ dup focused?>> not ] [ drop ] }
-        { [ dup selected-index not ] [ drop ] }
-        [
-            [ ] [ selected-index ] [ focus-border-color>> gl-color ] tri
-            row-bounds gl-rect
-        ]
-    } cond ;
+    dup { [ focused?>> ] [ selection-index>> value>> ] } 1&& [
+        dup focus-border-color>> gl-color
+        dup selection-index>> value>> row-bounds gl-rect
+    ] [ drop ] if ;
 
 : draw-moused-row ( table -- )
-    dup mouse-index>> dup [
-        over mouse-color>> gl-color
-        row-bounds gl-rect
-    ] [ 2drop ] if ;
+    dup mouse-index>> [
+        dup mouse-color>> gl-color
+        dup mouse-index>> row-bounds gl-rect
+    ] [ drop ] if ;
 
 : column-line-offsets ( table -- xs )
     [ column-widths>> ] [ gap>> ] bi
@@ -217,7 +189,7 @@ M: table layout*
 :: row-font ( row ind table -- font )
     table font>> clone
     row table renderer>> row-color [ >>foreground ] when*
-    ind table selected-indices>> key?
+    ind table selection-index>> value>> =
     [ table selection-color>> >>background ] when ;
 
 : draw-columns ( columns widths alignment font gap -- )
@@ -239,7 +211,7 @@ M: table draw-gadget*
     dup control-value empty? [ drop ] [
         dup line-height \ line-height [
             {
-                [ draw-selected-rows ]
+                [ draw-selected-row ]
                 [ draw-lines ]
                 [ draw-column-lines ]
                 [ draw-focused-row ]
@@ -262,37 +234,15 @@ M: table pref-dim*
 
 PRIVATE>
 
-: (selected-rows) ( table -- assoc )
-    [ selected-indices>> ] keep
-    '[ _ nth-row drop ] assoc-map ;
-
-: selected-rows ( table -- assoc )
-    [ selected-indices>> ] [ ] [ renderer>> ] tri
-    '[ _ nth-row drop _ row-value ] assoc-map ;
-
-: (selected-row) ( table -- value/f ? ) (selected-rows) multiple>single ;
+: (selected-row) ( table -- value/f ? )
+    [ selection-index>> value>> ] keep nth-row ;
 
-: selected-row ( table -- value/f ? ) selected-rows multiple>single ;
+: selected-row ( table -- value/f ? )
+    [ (selected-row) ] [ renderer>> ] bi
+    swap [ row-value t ] [ 2drop f f ] if ;
 
 <PRIVATE
 
-: set-table-model ( model value multiple? -- )
-    [ values ] [ multiple>single drop ] if swap set-model ;
-
-: update-selected ( table -- )
-    [
-        [ selection>> ]
-        [ selected-rows ]
-        [ multiple-selection?>> ] tri
-        set-table-model
-    ]
-    [
-        [ selection-index>> ]
-        [ selected-indices>> ]
-        [ multiple-selection?>> ] tri
-        set-table-model
-    ] bi ;
-
 : show-row-summary ( table n -- )
     over nth-row
     [ swap [ renderer>> row-value ] keep show-summary ]
@@ -302,34 +252,45 @@ PRIVATE>
 : hide-mouse-help ( table -- )
     f >>mouse-index [ hide-status ] [ relayout-1 ] bi ;
 
-: find-row-index ( value table -- n/f )
-    [ model>> value>> ] [ renderer>> ] bi
-    '[ _ row-value eq? ] with find drop ;
+: ((select-row)) ( n table -- )
+    [ selection-index>> set-model ]
+    [ [ selected-row drop ] keep selection>> set-model ]
+    bi ;
 
-: (update-selected-indices) ( table -- set )
-    [ selection>> value>> dup { [ array? not ] [ ] } 1&& [ 1array ] when ] keep
-    '[ _ find-row-index ] map sift unique f assoc-like ;
+: update-mouse-index ( table -- )
+    dup [ model>> value>> ] [ mouse-index>> ] bi
+    dup [ swap length [ drop f ] [ 1 - min ] if-zero ] [ 2drop f ] if
+    >>mouse-index drop ;
 
-: initial-selected-indices ( table -- set )
+: initial-selection-index ( table -- n/f )
     {
         [ model>> value>> empty? not ]
         [ selection-required?>> ]
-        [ drop { 0 } unique ]
+        [ drop 0 ]
     } 1&& ;
 
-: update-selected-indices ( table -- set )
-    {
-        [ (update-selected-indices) ]
-        [ initial-selected-indices ]
-    } 1|| ;
+: find-row-index ( value table -- n/f )
+    [ model>> value>> ] [ renderer>> ] bi
+    '[ _ row-value? ] with find drop ;
+
+: update-selection ( table -- )
+    [
+        {
+            [ [ selection>> value>> ] keep find-row-index ]
+            [ initial-selection-index ]
+        } 1||
+    ] keep
+    over [ ((select-row)) ] [
+        [ selection-index>> set-model ]
+        [ selection>> set-model ]
+        2bi
+    ] if ;
 
 M: table model-changed
-    nip dup update-selected-indices {
-        [ >>selected-indices f >>mouse-index drop ]
-        [ multiple>single drop show-row-summary ]
-        [ drop update-selected ]
-        [ drop relayout ]
-    } 2cleave ;
+    nip
+        dup update-selection
+        dup update-mouse-index
+    [ dup mouse-index>> show-row-summary ] [ relayout ] bi ;
 
 : thin-row-rect ( table row -- rect )
     row-rect [ { 0 1 } v* ] change-dim ;
@@ -337,14 +298,11 @@ M: table model-changed
 : scroll-to-row ( table n -- )
     dup [ [ thin-row-rect ] [ drop ] 2bi scroll>rect ] [ 2drop ] if ;
 
-: add-selected-row ( table n -- )
-    [ scroll-to-row ]
-    [ add-selected-index relayout-1 ] 2bi ;
-
 : (select-row) ( table n -- )
     [ scroll-to-row ]
-    [ set-selected-index relayout-1 ]
-    2bi ;
+    [ swap ((select-row)) ]
+    [ drop relayout-1 ]
+    2tri ;
 
 : mouse-row ( table -- n )
     [ hand-rel second ] keep y>line ;
@@ -353,23 +311,9 @@ M: table model-changed
     [ [ mouse-row ] keep 2dup valid-line? ]
     [ ] [ '[ nip @ ] ] tri* if ; inline
 
-: (table-button-down) ( quot table -- )
-    dup takes-focus?>> [ dup request-focus ] when swap
-   '[ swap [ >>mouse-index ] _ bi ] [ drop ] if-mouse-row ; inline
-
 : table-button-down ( table -- )
-    [ (select-row) ] swap (table-button-down) ;
-
-: continued-button-down ( table -- )
-    dup multiple-selection?>>
-    [ [ add-selected-row ] swap (table-button-down) ] [ table-button-down ] if ;
-
-: thru-button-down ( table -- )
-    dup multiple-selection?>> [
-      [ 2dup over selected-index (a,b) swap
-      [ swap add-selected-index drop ] curry each add-selected-row ]
-      swap (table-button-down)
-    ] [ table-button-down ] if ;
+    dup takes-focus?>> [ dup request-focus ] when
+    [ swap [ >>mouse-index ] [ (select-row) ] bi ] [ drop ] if-mouse-row ; inline
 
 PRIVATE>
 
@@ -386,22 +330,20 @@ PRIVATE>
 
 : table-button-up ( table -- )
     dup [ mouse-row ] keep valid-line? [
-        dup row-action? [ row-action ] [ update-selected ] if
+        dup row-action? [ row-action ] [ drop ] if
     ] [ drop ] if ;
 
 PRIVATE>
 
 : select-row ( table n -- )
     over validate-line
-    [ (select-row) ]
-    [ drop update-selected ]
-    [ show-row-summary ]
-    2tri ;
+    [ (select-row) ] [ show-row-summary ] 2bi ;
 
 <PRIVATE
 
 : prev/next-row ( table n -- )
-    [ dup selected-index ] dip '[ _ + ] [ 0 ] if* select-row ;
+    [ dup selection-index>> value>> ] dip
+    '[ _ + ] [ 0 ] if* select-row ;
     
 : previous-row ( table -- )
     -1 prev/next-row ;
@@ -453,8 +395,6 @@ table "sundry" f {
     { mouse-enter show-mouse-help }
     { mouse-leave hide-mouse-help }
     { motion show-mouse-help }
-    { T{ button-down f { S+ } 1 } thru-button-down }
-    { T{ button-down f { A+ } 1 } continued-button-down }
     { T{ button-up } table-button-up }
     { T{ button-up f { S+ } } table-button-up }
     { T{ button-down } table-button-down }
index eaa947b2d6f31299d54c5c146edabe327b5218b4..8cc8781b192247a0936776f1b92c42fce29934af 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays sequences sorting assocs colors.constants fry
 combinators combinators.smart combinators.short-circuit editors make
@@ -49,6 +49,8 @@ M: source-file-renderer prototype-row
 M: source-file-renderer row-value
     drop dup [ first [ <pathname> ] [ f ] if* ] when ;
 
+M: source-file-renderer row-value? row-value = ;
+
 M: source-file-renderer column-titles
     drop { "" "File" "Errors" } ;
 
@@ -152,7 +154,7 @@ error-display "toolbar" f {
     [ swap '[ error-type _ at ] filter ] <smart-arrow> ;
 
 :: <error-list-gadget> ( model -- gadget )
-    vertical error-list-gadget new-track
+    vertical error-list-gadget new-track
         <error-toggle> [ >>error-toggle ] [ >>visible-errors ] bi*
         dup visible-errors>> model <error-model> >>model 
         f <model> >>source-file
@@ -176,16 +178,16 @@ M: error-list-gadget focusable-child*
 
 \ error-list-help H{ { +nullary+ t } } define-command
 
-error-list-gadget "toolbar" f {
+error-list-gadget "toolbar" f {
     { T{ key-down f f "F1" } error-list-help }
 } define-command-map
 
-: error-list-window ( -- )
-    error-list-model get [ drop all-errors ] <arrow>
-    <error-list-gadget> "Errors" open-status-window ;
+MEMO: error-list-gadget ( -- gadget )
+    error-list-model get-global [ drop all-errors ] <arrow>
+    <error-list-gadget> ;
 
 : show-error-list ( -- )
-    [ error-list-gadget? ] find-window
-    [ raise-window ] [ error-list-window ] if* ;
+    [ error-list-gadget eq? ] find-window
+    [ raise-window ] [ error-list-gadget "Errors" open-status-window ] if* ;
 
 \ show-error-list H{ { +nullary+ t } } define-command
old mode 100644 (file)
new mode 100755 (executable)
index 6a2d9b1..c77364c
@@ -1,8 +1,8 @@
-USING: windows.directx.dinput windows.kernel32 windows.ole32 windows.com
-windows.com.syntax alien alien.c-types alien.data alien.syntax
-kernel system namespaces combinators sequences fry math accessors
-macros words quotations libc continuations generalizations
-splitting locals assocs init specialized-arrays memoize
+USING: windows.directx.dinput windows.kernel32 windows.ole32
+windows.com windows.com.syntax alien alien.c-types alien.data
+alien.syntax kernel system namespaces combinators sequences fry
+math accessors macros words quotations libc continuations
+generalizations splitting locals assocs init specialized-arrays
 classes.struct strings arrays literals ;
 SPECIALIZED-ARRAY: DIOBJECTDATAFORMAT
 IN: windows.directx.dinput.constants
@@ -20,21 +20,21 @@ SYMBOLS:
 
 <PRIVATE
 
-<<
+: initialize ( variable quot -- )
+    call swap set-global ; inline
 
-MEMO: c-type* ( name -- c-type ) c-type ;
-MEMO: heap-size* ( c-type -- n ) heap-size ;
+<<
 
 GENERIC: array-base-type ( c-type -- c-type' )
 M: object array-base-type ;
 M: array array-base-type first ;
 
 : (field-spec-of) ( field struct -- field-spec )
-    c-type* fields>> [ name>> = ] with find nip ;
+    c-type fields>> [ name>> = ] with find nip ;
 : (offsetof) ( field struct -- offset )
     [ (field-spec-of) offset>> ] [ drop 0 ] if* ;
 : (sizeof) ( field struct -- size )
-    [ (field-spec-of) type>> array-base-type heap-size* ] [ drop 1 ] if* ;
+    [ (field-spec-of) type>> array-base-type heap-size ] [ drop 1 ] if* ;
 
 : (flag) ( thing -- integer )
     {
@@ -56,14 +56,17 @@ M: array array-base-type first ;
         [ first dup word? [ '[ _ get ] ] [ drop [ f ] ] if ]
     } cleave
     [ DIOBJECTDATAFORMAT <struct-boa> ] dip
-    '[ _ clone @ >>pguid ] ;
+    curry ;
+
+: set-DIOBJECTDATAFORMAT ( array struct pguid n -- array )
+    [ [ clone ] dip >>pguid ] dip pick set-nth ;
 
 :: make-DIOBJECTDATAFORMAT-array-quot ( struct array -- quot )
     array length '[ _ malloc-DIOBJECTDATAFORMAT-array ]
     array [| args i |
         struct args <DIOBJECTDATAFORMAT>-quot
-        i '[ _ pick set-nth ] compose compose
-    ] each-index ;
+        i '[ @ _ set-DIOBJECTDATAFORMAT ]
+    ] map-index [ ] join compose ;
 
 >>
 
@@ -832,8 +835,7 @@ MACRO: <DIDATAFORMAT> ( dwFlags dwDataSize struct rgodf-array -- alien )
 [ define-constants ] "windows.directx.dinput.constants" add-startup-hook
 
 : uninitialize ( variable quot -- )
-    [ '[ _ when* f ] change-global ]
-    [ drop global delete-at ] 2bi ; inline
+    [ [ get-global ] dip when* ] [ drop global delete-at ] 2bi ; inline
 
 : free-dinput-constants ( -- )
     {
index 06cb09a4ddf8b645f7f304ffc0f327e5174d2b07..b52a942eb109f9cf4b1d95132048a36f76bb91f7 100644 (file)
@@ -8,3 +8,9 @@ Nmakefile
 unmaintained
 build-support
 images
+factor.dll.exp
+factor.dll.lib
+factor.exp
+factor.lib
+libfactor-ffi-test.exp
+libfactor-ffi-test.lib
index 3321dbe2edc196ea2c2bb4d08ddc46b99d68b4f5..100908123663db93121ac9227a5759dca61bae57 100644 (file)
@@ -64,13 +64,13 @@ cell 8 = [
 
 [ 1 1 <displaced-alien> ] must-fail
 
-[ f ] [ 0 B{ 1 2 3 } <displaced-alien> pinned-c-ptr? ] unit-test
+[ f ] [ 1 B{ 1 2 3 } <displaced-alien> pinned-c-ptr? ] unit-test
 
-[ f ] [ 0 B{ 1 2 3 } <displaced-alien> 1 swap <displaced-alien> pinned-c-ptr? ] unit-test
+[ f ] [ 2 B{ 1 2 3 } <displaced-alien> 1 swap <displaced-alien> pinned-c-ptr? ] unit-test
 
 [ t ] [ 0 B{ 1 2 3 } <displaced-alien> 1 swap <displaced-alien> underlying>> byte-array? ] unit-test
 
-[ "( displaced alien )" ] [ 0 B{ 1 2 3 } <displaced-alien> unparse ] unit-test
+[ "( displaced alien )" ] [ 1 B{ 1 2 3 } <displaced-alien> unparse ] unit-test
 
 SYMBOL: initialize-test
 
index 27699725f1438f6e07fd97e590b4cd3334586be2..c00199e9b3dbecc4da406fc929db39a00704cb33 100644 (file)
@@ -370,6 +370,7 @@ tuple
     { "fixnum<=" "math.private" (( x y -- z )) }
     { "fixnum>" "math.private" (( x y -- ? )) }
     { "fixnum>=" "math.private" (( x y -- ? )) }
+    { "string-nth-fast" "strings.private" (( n string -- ch )) }
     { "(set-context)" "threads.private" (( obj context -- obj' )) }
     { "(set-context-and-delete)" "threads.private" (( obj context -- * )) }
     { "(start-context)" "threads.private" (( obj quot -- obj' )) }
@@ -533,8 +534,6 @@ tuple
     { "<string>" "strings" "primitive_string" (( n ch -- string )) }
     { "resize-string" "strings" "primitive_resize_string" (( n str -- newstr )) }
     { "set-string-nth-fast" "strings.private" "primitive_set_string_nth_fast" (( ch n string -- )) }
-    { "set-string-nth-slow" "strings.private" "primitive_set_string_nth_slow" (( ch n string -- )) }
-    { "string-nth" "strings.private" "primitive_string_nth" (( n string -- ch )) }
     { "(exit)" "system" "primitive_exit" (( n -- * )) }
     { "nano-count" "system" "primitive_nano_count" (( -- ns )) }
     { "system-micros" "system" "primitive_system_micros" (( -- us )) }
index 196a12d0d2765fce3f71222683dd72a2bef0382c..896a4b982d3934ac5b0aab3f394fb2e79e03cade 100644 (file)
@@ -12,6 +12,7 @@ IN: continuations
         swap [ set-datastack ] dip
     ] (( stack quot -- new-stack )) call-effect-unsafe ;
 
+SYMBOL: original-error
 SYMBOL: error
 SYMBOL: error-continuation
 SYMBOL: error-thread
@@ -102,8 +103,8 @@ GENERIC: compute-restarts ( error -- seq )
 <PRIVATE
 
 : save-error ( error -- )
-    dup error set-global
-    compute-restarts restarts set-global ;
+    [ error set-global ]
+    [ compute-restarts restarts set-global ] bi ;
 
 PRIVATE>
 
@@ -113,7 +114,8 @@ SYMBOL: thread-error-hook
     dup save-error
     catchstack* empty? [
         thread-error-hook get-global
-        [ (( error -- * )) call-effect-unsafe ] [ die ] if*
+        [ original-error get-global die ] or
+        (( error -- * )) call-effect-unsafe
     ] when
     c> continue-with ;
 
@@ -176,7 +178,7 @@ M: condition compute-restarts
         ! 63 = self
         63 special-object error-thread set-global
         continuation error-continuation set-global
-        rethrow
+        [ original-error set-global ] [ rethrow ] bi
     ] 5 set-special-object
     ! VM adds this to kernel errors, so that user-space
     ! can identify them
index b90d96a356e0809616fa2d87c698139d8c747307..247bd8d00766910a353c5ab1b3d108147e1a1519 100644 (file)
@@ -85,6 +85,9 @@ unit-test
     "s" get >array
 ] unit-test
 
+! Make sure string initialization works
+[ HEX: 123456 ] [ 100 HEX: 123456 <string> first ] unit-test
+
 ! Make sure we clear aux vector when storing octets
 [ "\u123456hi" ] [ "ih\u123456" clone reverse! ] unit-test
 
index 50d79a4d8ab015c5e979af6219cb4493a3822724..f356d2a87772edffdda015503286b38eb6d1ced3 100644 (file)
@@ -1,7 +1,7 @@
-! Copyright (C) 2003, 2008 Slava Pestov.
+! Copyright (C) 2003, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel math.private sequences kernel.private
-math sequences.private slots.private alien.accessors ;
+USING: accessors alien.accessors byte-arrays kernel math.private
+sequences kernel.private math sequences.private slots.private ;
 IN: strings
 
 <PRIVATE
@@ -16,8 +16,31 @@ IN: strings
 : rehash-string ( str -- )
     1 over sequence-hashcode swap set-string-hashcode ; inline
 
+: (aux) ( n string -- byte-array m )
+    aux>> { byte-array } declare swap 1 fixnum-shift-fast ; inline
+
+: small-char? ( ch -- ? ) HEX: 7f fixnum<= ; inline
+
+: string-nth ( n string -- ch )
+    2dup string-nth-fast dup small-char?
+    [ 2nip ] [
+        [ (aux) alien-unsigned-2 7 fixnum-shift-fast ] dip
+        fixnum-bitxor
+    ] if ; inline
+
+: ensure-aux ( string -- string )
+    dup aux>> [ dup length 2 * (byte-array) >>aux ] unless ; inline
+
+: set-string-nth-slow ( ch n string -- )
+    [ [ HEX: 80 fixnum-bitor ] 2dip set-string-nth-fast ]
+    [
+        ensure-aux
+        [ -7 fixnum-shift-fast 1 fixnum-bitxor ] 2dip
+        (aux) set-alien-unsigned-2
+    ] 3bi ;
+
 : set-string-nth ( ch n string -- )
-    pick HEX: 7f fixnum<=
+    pick small-char?
     [ set-string-nth-fast ] [ set-string-nth-slow ] if ; inline
 
 PRIVATE>
index b182b4f832ee703b18df1f437498400e3393ded7..4a5a0285fcf912baa4321cc8335f8aa3fc50b803 100644 (file)
@@ -1,11 +1,12 @@
 ! Copyright (C) Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien.accessors alien.c-types alien.syntax byte-arrays
-destructors generalizations hints kernel libc locals math math.order
-sequences sequences.private classes.struct accessors alien.data ;
+destructors generalizations kernel libc locals math math.order
+sequences sequences.private classes.struct accessors alien.data
+typed ;
 IN: benchmark.yuv-to-rgb
 
-STRUCT: yuv_buffer
+STRUCT: yuv-buffer
     { y_width int }
     { y_height int }
     { y_stride int }
@@ -19,7 +20,7 @@ STRUCT: yuv_buffer
 :: fake-data ( -- rgb yuv )
     1600 :> w
     1200 :> h
-    yuv_buffer <struct> :> buffer
+    yuv-buffer <struct> :> buffer
     w h * 3 * <byte-array> :> rgb
     rgb buffer
         w >>y_width
@@ -79,14 +80,12 @@ STRUCT: yuv_buffer
     pick y_width>> iota
     [ yuv>rgb-pixel ] with with with with each ; inline
 
-: yuv>rgb ( rgb yuv -- )
+TYPED: yuv>rgb ( rgb: byte-array yuv: yuv-buffer -- )
     [ 0 ] 2dip
     dup y_height>> iota
     [ yuv>rgb-row ] with with each
     drop ;
 
-HINTS: yuv>rgb byte-array yuv_buffer ;
-
 : yuv>rgb-benchmark ( -- )
     [ fake-data yuv>rgb ] with-destructors ;
 
index 7378d3284c36eb0a7243ec2965ed5d1a38a681fe..79a72b33eabbd8a357c4288f92f30f693c04f0bb 100644 (file)
@@ -78,8 +78,8 @@ IN: compiler.graphviz
 : optimized-cfg ( quot -- cfgs )
     {
         { [ dup cfg? ] [ 1array ] }
-        { [ dup quotation? ] [ test-cfg [ dup cfg set optimize-cfg ] map ] }
-        { [ dup word? ] [ test-cfg [ dup cfg set optimize-cfg ] map ] }
+        { [ dup quotation? ] [ test-optimizer ] }
+        { [ dup word? ] [ test-optimizer ] }
         [ ]
     } cond ;
 
index da70fa134ea984ee1a92a53f51684dea436b0467..5354c959aedce6d61545c6445429cea2eeb21ec6 100755 (executable)
@@ -35,8 +35,8 @@ VM_C_API char *pinned_alien_offset(cell obj, factor_vm *parent)
 /* make an alien */
 cell factor_vm::allot_alien(cell delegate_, cell displacement)
 {
-       if(delegate_ == false_object && displacement == 0)
-               return false_object;
+       if(displacement == 0)
+               return delegate_;
 
        data_root<object> delegate(delegate_,this);
        data_root<alien> new_alien(allot<alien>(sizeof(alien)),this);
index 2e7b8d4f0970fddf003590005e8c761524bda3e9..e8c6216d8d958cdbc40f002396c5cec799347409 100755 (executable)
@@ -231,7 +231,7 @@ void factor_vm::store_external_address(instruction_operand op)
                break;
 #endif
        default:
-               critical_error("Bad rel type",op.rel_type());
+               critical_error("Bad rel type in store_external_address()",op.rel_type());
                break;
        }
 }
@@ -265,9 +265,6 @@ struct initial_code_block_visitor {
                case RT_LITERAL:
                        op.store_value(next_literal());
                        break;
-               case RT_FLOAT:
-                       op.store_float(next_literal());
-                       break;
                case RT_ENTRY_POINT:
                        op.store_value(parent->compute_entry_point_address(next_literal()));
                        break;
index 34398e3d88ccfbefd786d8a4f8c9acb9c7987872..5e52c70b0c852cd1385b9865e7e2d2d99da02873 100644 (file)
@@ -111,9 +111,6 @@ struct code_block_compaction_relocation_visitor {
                case RT_LITERAL:
                        op.store_value(slot_forwarder.visit_pointer(op.load_value(old_offset)));
                        break;
-               case RT_FLOAT:
-                       op.store_float(slot_forwarder.visit_pointer(op.load_float(old_offset)));
-                       break;
                case RT_ENTRY_POINT:
                case RT_ENTRY_POINT_PIC:
                case RT_ENTRY_POINT_PIC_TAIL:
index 85335d49ae7f344fbb491ab1aa23b69d0954ff9b..bb3a8b0ce51df052c92403b660b521340d4fdc82 100755 (executable)
@@ -6,7 +6,7 @@ namespace factor
 std::ostream &operator<<(std::ostream &out, const string *str)
 {
        for(cell i = 0; i < string_capacity(str); i++)
-               out << (char)str->nth(i);
+               out << (char)str->data()[i];
        return out;
 }
 
index e01a05aa5ba8e4f5eee3dba8ca8b912c9813c3ab..ed36aff563d727c33e84669d1dc98f79722d5f09 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -215,16 +215,34 @@ void factor_vm::primitive_compact_gc()
                true /* trace contexts? */);
 }
 
-void factor_vm::inline_gc(cell *data_roots_base, cell data_roots_size)
+void factor_vm::inline_gc(cell gc_roots_)
 {
-       data_roots.push_back(data_root_range(data_roots_base,data_roots_size));
-       primitive_minor_gc();
-       data_roots.pop_back();
+       cell stack_pointer = (cell)ctx->callstack_top;
+
+       if(to_boolean(gc_roots_))
+       {
+               tagged<array> gc_roots(gc_roots_);
+
+               cell capacity = array_capacity(gc_roots.untagged());
+               for(cell i = 0; i < capacity; i++)
+               {
+                       cell spill_slot = untag_fixnum(array_nth(gc_roots.untagged(),i));
+                       cell *address = (cell *)(spill_slot + stack_pointer);
+                       data_roots.push_back(data_root_range(address,1));
+               }
+
+               primitive_minor_gc();
+
+               for(cell i = 0; i < capacity; i++)
+                       data_roots.pop_back();
+       }
+       else
+               primitive_minor_gc();
 }
 
-VM_C_API void inline_gc(cell *data_roots_base, cell data_roots_size, factor_vm *parent)
+VM_C_API void inline_gc(cell gc_roots, factor_vm *parent)
 {
-       parent->inline_gc(data_roots_base,data_roots_size);
+       parent->inline_gc(gc_roots);
 }
 
 /*
index 5129ced909179996cb829f3850520ed0a7bf5c96..39a69e34f4c0678ee93ffd964fcc74a5754df26a 100755 (executable)
--- a/vm/gc.hpp
+++ b/vm/gc.hpp
@@ -52,6 +52,6 @@ struct gc_state {
        void start_again(gc_op op_, factor_vm *parent);
 };
 
-VM_C_API void inline_gc(cell *data_roots_base, cell data_roots_size, factor_vm *parent);
+VM_C_API void inline_gc(cell gc_roots, factor_vm *parent);
 
 }
index 4dfdc4242eac3957ed85ef0ebd1b0f1e40bf642e..ccce96a952c56970c8b728293989347173338bc6 100755 (executable)
@@ -185,9 +185,6 @@ struct code_block_fixup_relocation_visitor {
                case RT_LITERAL:
                        op.store_value(data_visitor.visit_pointer(op.load_value(old_offset)));
                        break;
-               case RT_FLOAT:
-                       op.store_float(data_visitor.visit_pointer(op.load_float(old_offset)));
-                       break;
                case RT_ENTRY_POINT:
                case RT_ENTRY_POINT_PIC:
                case RT_ENTRY_POINT_PIC_TAIL:
index af7d363aefa82f5beeb9db1cf3035a22dfa762d9..b11db279a5bfc536e62df76e0ddbeaed0b460e53 100644 (file)
@@ -62,16 +62,6 @@ fixnum instruction_operand::load_value()
        return load_value(pointer);
 }
 
-cell instruction_operand::load_float()
-{
-       return (cell)load_value() - boxed_float_offset;
-}
-
-cell instruction_operand::load_float(cell pointer)
-{
-       return (cell)load_value(pointer) - boxed_float_offset;
-}
-
 code_block *instruction_operand::load_code_block(cell relative_to)
 {
        return ((code_block *)load_value(relative_to) - 1);
@@ -145,11 +135,6 @@ void instruction_operand::store_value(fixnum absolute_value)
        }
 }
 
-void instruction_operand::store_float(cell value)
-{
-       store_value((fixnum)value + boxed_float_offset);
-}
-
 void instruction_operand::store_code_block(code_block *compiled)
 {
        store_value((cell)compiled->entry_point());
index 5c120c2ec770934e617aabfa78c5291a89a593dd..475e48d20673cd55ca67e4623cb3dc9499ab7c20 100644 (file)
@@ -30,8 +30,6 @@ enum relocation_type {
        type since its used in a situation where relocation arguments cannot
        be passed in, and so RT_DLSYM is inappropriate (Windows only) */
        RT_EXCEPTION_HANDLER,
-       /* pointer to a float's payload */
-       RT_FLOAT,
 
 };
 
@@ -115,10 +113,9 @@ struct relocation_entry {
                case RT_CARDS_OFFSET:
                case RT_DECKS_OFFSET:
                case RT_EXCEPTION_HANDLER:
-               case RT_FLOAT:
                        return 0;
                default:
-                       critical_error("Bad rel type",rel_type());
+                       critical_error("Bad rel type in number_of_parameters()",rel_type());
                        return -1; /* Can't happen */
                }
        }
@@ -156,15 +153,12 @@ struct instruction_operand {
        fixnum load_value_masked(cell mask, cell bits, cell shift);
        fixnum load_value(cell relative_to);
        fixnum load_value();
-       cell load_float(cell relative_to);
-       cell load_float();
        code_block *load_code_block(cell relative_to);
        code_block *load_code_block();
 
        void store_value_2_2(fixnum value);
        void store_value_masked(fixnum value, cell mask, cell shift);
        void store_value(fixnum value);
-       void store_float(cell value);
        void store_code_block(code_block *compiled);
 };
 
index 3e51d1fa4de17d780723f266eac78f89be0bc2dd..5e7ca0279f73582e1476c895ff4e8dc4939169c7 100644 (file)
@@ -91,8 +91,6 @@ inline static cell tag_fixnum(fixnum untagged)
        return RETAG(untagged << TAG_BITS,FIXNUM_TYPE);
 }
 
-struct object;
-
 #define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
 
 struct object {
@@ -205,8 +203,6 @@ struct string : public object {
        cell hashcode;
 
        u8 *data() const { return (u8 *)(this + 1); }
-
-       cell nth(cell i) const;
 };
 
 struct code_block;
@@ -246,8 +242,6 @@ struct wrapper : public object {
        cell object;
 };
 
-const fixnum boxed_float_offset = 8 - FLOAT_TYPE;
-
 /* Assembly code makes assumptions about the layout of this struct */
 struct boxed_float : object {
        static const cell type_number = FLOAT_TYPE;
index a2bf912749fa6520fe07f4f738b76b3630f0853b..cf52168231f24afafe07876b2c897218e36ad4a9 100644 (file)
@@ -120,12 +120,10 @@ namespace factor
        _(set_slot) \
        _(set_special_object) \
        _(set_string_nth_fast) \
-       _(set_string_nth_slow) \
        _(size) \
        _(sleep) \
        _(special_object) \
        _(string) \
-       _(string_nth) \
        _(strip_stack_traces) \
        _(system_micros) \
        _(tuple) \
index cb2db1c7050b96356ece36f154189dab00144763..d4dd44bed1a59b81cc78b5bdc50b04dedfb8ed75 100644 (file)
@@ -192,17 +192,8 @@ struct literal_references_visitor {
 
        void operator()(instruction_operand op)
        {
-               switch(op.rel_type())
-               {
-               case RT_LITERAL:
+               if(op.rel_type() == RT_LITERAL)
                        op.store_value(visitor->visit_pointer(op.load_value()));
-                       break;
-               case RT_FLOAT:
-                       op.store_float(visitor->visit_pointer(op.load_float()));
-                       break;
-               default:
-                       break;
-               }
        }
 };
 
index 5aad936a9eb3e378efad85517bb6ab314a16c7a1..aea4641905a85725bb7ea225842e4a12df7a21e7 100644 (file)
@@ -3,66 +3,6 @@
 namespace factor
 {
 
-cell string::nth(cell index) const
-{
-       /* If high bit is set, the most significant 16 bits of the char
-       come from the aux vector. The least significant bit of the
-       corresponding aux vector entry is negated, so that we can
-       XOR the two components together and get the original code point
-       back. */
-       cell lo_bits = data()[index];
-
-       if((lo_bits & 0x80) == 0)
-               return lo_bits;
-       else
-       {
-               byte_array *aux = untag<byte_array>(this->aux);
-               cell hi_bits = aux->data<u16>()[index];
-               return (hi_bits << 7) ^ lo_bits;
-       }
-}
-
-void factor_vm::set_string_nth_fast(string *str, cell index, cell ch)
-{
-       str->data()[index] = (u8)ch;
-}
-
-void factor_vm::set_string_nth_slow(string *str_, cell index, cell ch)
-{
-       data_root<string> str(str_,this);
-
-       byte_array *aux;
-
-       str->data()[index] = ((ch & 0x7f) | 0x80);
-
-       if(to_boolean(str->aux))
-               aux = untag<byte_array>(str->aux);
-       else
-       {
-               /* We don't need to pre-initialize the
-               byte array with any data, since we
-               only ever read from the aux vector
-               if the most significant bit of a
-               character is set. Initially all of
-               the bits are clear. */
-               aux = allot_uninitialized_array<byte_array>(untag_fixnum(str->length) * sizeof(u16));
-
-               str->aux = tag<byte_array>(aux);
-               write_barrier(&str->aux);
-       }
-
-       aux->data<u16>()[index] = (u16)((ch >> 7) ^ 1);
-}
-
-/* allocates memory */
-void factor_vm::set_string_nth(string *str, cell index, cell ch)
-{
-       if(ch <= 0x7f)
-               set_string_nth_fast(str,index,ch);
-       else
-               set_string_nth_slow(str,index,ch);
-}
-
 /* Allocates memory */
 string *factor_vm::allot_string_internal(cell capacity)
 {
@@ -81,13 +21,23 @@ void factor_vm::fill_string(string *str_, cell start, cell capacity, cell fill)
        data_root<string> str(str_,this);
 
        if(fill <= 0x7f)
-               memset(&str->data()[start],(int)fill,capacity - start);
+               memset(&str->data()[start],(u8)fill,capacity - start);
        else
        {
-               cell i;
+               byte_array *aux;
+               if(to_boolean(str->aux))
+                       aux = untag<byte_array>(str->aux);
+               else
+               {
+                       aux = allot_uninitialized_array<byte_array>(untag_fixnum(str->length) * 2);
+                       str->aux = tag<byte_array>(aux);
+                       write_barrier(&str->aux);
+               }
 
-               for(i = start; i < capacity; i++)
-                       set_string_nth(str.untagged(),i,fill);
+               u8 lo_fill = (u8)((fill & 0x7f) | 0x80);
+               u16 hi_fill = (u16)((fill >> 7) ^ 0x1);
+               memset(&str->data()[start],lo_fill,capacity - start);
+               memset_2(&aux->data<u16>()[start],hi_fill,(capacity - start) * sizeof(u16));
        }
 }
 
@@ -141,8 +91,7 @@ string* factor_vm::reallot_string(string *str_, cell capacity)
 
                if(to_boolean(str->aux))
                {
-                       byte_array *new_aux = allot_byte_array(capacity * sizeof(u16));
-
+                       byte_array *new_aux = allot_uninitialized_array<byte_array>(capacity * 2);
                        new_str->aux = tag<byte_array>(new_aux);
                        write_barrier(&new_str->aux);
 
@@ -163,27 +112,12 @@ void factor_vm::primitive_resize_string()
        ctx->push(tag<string>(reallot_string(str.untagged(),capacity)));
 }
 
-void factor_vm::primitive_string_nth()
-{
-       string *str = untag<string>(ctx->pop());
-       cell index = untag_fixnum(ctx->pop());
-       ctx->push(tag_fixnum(str->nth(index)));
-}
-
 void factor_vm::primitive_set_string_nth_fast()
 {
        string *str = untag<string>(ctx->pop());
        cell index = untag_fixnum(ctx->pop());
        cell value = untag_fixnum(ctx->pop());
-       set_string_nth_fast(str,index,value);
-}
-
-void factor_vm::primitive_set_string_nth_slow()
-{
-       string *str = untag<string>(ctx->pop());
-       cell index = untag_fixnum(ctx->pop());
-       cell value = untag_fixnum(ctx->pop());
-       set_string_nth_slow(str,index,value);
+       str->data()[index] = (u8)value;
 }
 
 }
index cea70c0c372e755468ae2a5095b75a55ffa7bdb3..e75d3ece123f7423946953eb506cc2dbd14280eb 100755 (executable)
@@ -1,6 +1,27 @@
 namespace factor
 {
 
+inline static void memset_2(void *dst, u16 pattern, size_t size)
+{
+#ifdef __APPLE__
+       cell cell_pattern = (pattern | (pattern << 16));
+       memset_pattern4(dst,&cell_pattern,size);
+#else
+       if(pattern == 0)
+               memset(dst,0,size);
+       else
+       {
+               u16 *start = (u16 *)dst;
+               u16 *end = (u16 *)((cell)dst + size);
+               while(start < end)
+               {
+                       *start = pattern;
+                       start++;
+               }
+       }
+#endif
+}
+
 inline static void memset_cell(void *dst, cell pattern, size_t size)
 {
 #ifdef __APPLE__
index d9bd17fa51de90f91ef3cfac838307e72bf7a59e..bfe105e67d958d58df980d51fd612f258da8b3f4 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -320,7 +320,7 @@ struct factor_vm
        void primitive_minor_gc();
        void primitive_full_gc();
        void primitive_compact_gc();
-       void inline_gc(cell *data_roots_base, cell data_roots_size);
+       void inline_gc(cell gc_roots);
        void primitive_enable_gc_events();
        void primitive_disable_gc_events();
        object *allot_object(cell type, cell size);
@@ -381,10 +381,6 @@ struct factor_vm
        cell std_vector_to_array(std::vector<cell> &elements);
 
        // strings
-       cell string_nth(const string *str, cell index);
-       void set_string_nth_fast(string *str, cell index, cell ch);
-       void set_string_nth_slow(string *str_, cell index, cell ch);
-       void set_string_nth(string *str, cell index, cell ch);
        string *allot_string_internal(cell capacity);
        void fill_string(string *str_, cell start, cell capacity, cell fill);
        string *allot_string(cell capacity, cell fill);
@@ -392,9 +388,7 @@ struct factor_vm
        bool reallot_string_in_place_p(string *str, cell capacity);
        string* reallot_string(string *str_, cell capacity);
        void primitive_resize_string();
-       void primitive_string_nth();
        void primitive_set_string_nth_fast();
-       void primitive_set_string_nth_slow();
 
        // booleans
        cell tag_boolean(cell untagged)