Merge branch 'master' into marshall

* master: (96 commits)
  compiler.cfg.dataflow-analysis: iterative dataflow analysis framework
  functors: add MIXIN:, SINGLETON:
  Add assoc-refine, which takes the intersection of a sequence of assocs
  compiler.cfg: Fix unit tests
  compiler.cfg.registers: minor optimization
  compiler.cfg.ssa: Cytron's SSA construction algorithm
  compiler.cfg.dominance: fix idom computation, compute dominator tree, compute dominance frontiers, add some tests
  Move conjoin-at from compiler.cfg.liveness to sets
  sequences.abbrev: add docs - not much, but a start
  sequences.abbrev: keep insertion order
  sequences.abbrev: more small refactoring
  sequences.abbrev: small refactoring
  sequences.abbrev: Initial commit
  opengl is for chumps
  alien.inline.compiler: help-lint fix
  parser: remove outdated unit tests that were superseded by tests in vocabs.parser
  vocabs.parser: add tests to assert that the correct errors get thrown
  ui.tools.listener: selecting a word from a completion popup now behaves like a USE: followed by a FROM:
  FROM: and RENAME: give a more meaningful error if the vocabulary does not exist
  compiler.cfg.stack-analysis: fix outdated tests
  ...
db4
Jeremy Hughes 2009-07-22 19:45:48 +12:00
commit 2c40a6667c
195 changed files with 9216 additions and 1616 deletions

View File

@ -42,9 +42,13 @@ M: bit-array set-nth-unsafe
[ byte/bit set-bit ] 2keep [ byte/bit set-bit ] 2keep
swap n>byte set-alien-unsigned-1 ; swap n>byte set-alien-unsigned-1 ;
: clear-bits ( bit-array -- ) 0 (set-bits) ; GENERIC: clear-bits ( bit-array -- )
: set-bits ( bit-array -- ) -1 (set-bits) ; M: bit-array clear-bits 0 (set-bits) ;
GENERIC: set-bits ( bit-array -- )
M: bit-array set-bits -1 (set-bits) ;
M: bit-array clone M: bit-array clone
[ length>> ] [ underlying>> clone ] bi bit-array boa ; [ length>> ] [ underlying>> clone ] bi bit-array boa ;

View File

@ -1,62 +1,46 @@
! Copyright (C) 2008 Doug Coleman. ! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax io.streams.string quotations USING: help.markup help.syntax io.streams.string quotations
math ; math kernel ;
IN: combinators.short-circuit IN: combinators.short-circuit
HELP: 0&& HELP: 0&&
{ $values { $values { "quots" "a sequence of quotations with stack effect " { $snippet "( -- )" } } { "?" "the result of the last quotation, or " { $link f } } }
{ "quots" "a sequence of quotations" } { $description "If every quotation in the sequence outputs a true value, outputs the result of the last quotation, otherwise outputs " { $link f } "." } ;
{ "quot" quotation } }
{ $description "Returns true if every quotation in the sequence of quotations returns true." } ;
HELP: 0|| HELP: 0||
{ $values { $values { "quots" "a sequence of quotations with stack effect " { $snippet "( -- )" } } { "?" "the first true result, or " { $link f } } }
{ "quots" "a sequence of quotations" } { $description "If every quotation in the sequence outputs " { $link f } ", outputs " { $link f } ", otherwise outputs the result of the first quotation that did not yield " { $link f } "." } ;
{ "quot" quotation } }
{ $description "Returns true if any quotation in the sequence returns true." } ;
HELP: 1&& HELP: 1&&
{ $values { $values { "obj" object } { "quots" "a sequence of quotations with stack effect " { $snippet "( -- )" } } { "?" "the result of the last quotation, or " { $link f } } }
{ "quots" "a sequence of quotations" } { $description "If every quotation in the sequence outputs a true value, outputs the result of the last quotation, otherwise outputs " { $link f } "." } ;
{ "quot" quotation } }
{ $description "Returns true if every quotation in the sequence of quotations returns true. Each quotation gets the same element from the datastack and must output a boolean." } ;
HELP: 1|| HELP: 1||
{ $values { $values { "obj" object } { "quots" "a sequence of quotations" } { "?" "the first true result, or " { $link f } } }
{ "quots" "a sequence of quotations" }
{ "quot" quotation } }
{ $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same element from the datastack and must return a boolean." } ; { $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same element from the datastack and must return a boolean." } ;
HELP: 2&& HELP: 2&&
{ $values { $values { "obj1" object } { "obj2" object } { "quots" "a sequence of quotations with stack effect " { $snippet "( -- )" } } { "?" "the result of the last quotation, or " { $link f } } }
{ "quots" "a sequence of quotations" } { $description "If every quotation in the sequence outputs a true value, outputs the result of the last quotation, otherwise outputs " { $link f } "." } ;
{ "quot" quotation } }
{ $description "Returns true if every quotation in the sequence of quotations returns true. Each quotation gets the same two elements from the datastack and must output a boolean." } ;
HELP: 2|| HELP: 2||
{ $values { $values { "obj1" object } { "obj2" object } { "quots" "a sequence of quotations" } { "?" "the first true result, or " { $link f } } }
{ "quots" "a sequence of quotations" }
{ "quot" quotation } }
{ $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same two elements from the datastack and must return a boolean." } ; { $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same two elements from the datastack and must return a boolean." } ;
HELP: 3&& HELP: 3&&
{ $values { $values { "obj1" object } { "obj2" object } { "obj3" object } { "quots" "a sequence of quotations with stack effect " { $snippet "( -- )" } } { "?" "the result of the last quotation, or " { $link f } } }
{ "quots" "a sequence of quotations" } { $description "If every quotation in the sequence outputs a true value, outputs the result of the last quotation, otherwise outputs " { $link f } "." } ;
{ "quot" quotation } }
{ $description "Returns true if every quotation in the sequence of quotations returns true. Each quotation gets the same three elements from the datastack and must output a boolean." } ;
HELP: 3|| HELP: 3||
{ $values { $values { "obj1" object } { "obj2" object } { "obj3" object } { "quots" "a sequence of quotations" } { "?" "the first true result, or " { $link f } } }
{ "quots" "a sequence of quotations" }
{ "quot" quotation } }
{ $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same three elements from the datastack and must return a boolean." } ; { $description "Returns true if any quotation in the sequence returns true. Each quotation takes the same three elements from the datastack and must return a boolean." } ;
HELP: n&& HELP: n&&
{ $values { $values
{ "quots" "a sequence of quotations" } { "N" integer } { "quots" "a sequence of quotations" } { "n" integer }
{ "quot" quotation } } { "quot" quotation } }
{ $description "A macro that rewrites the code to pass " { $snippet "n" } " parameters from the stack to each AND quotation." } ; { $description "A macro that rewrites the code to pass " { $snippet "n" } " parameters from the stack to each quotation, evaluating the result in the same manner as " { $link 0&& } "." } ;
HELP: n|| HELP: n||
{ $values { $values

View File

@ -1,32 +1,25 @@
USING: kernel math tools.test combinators.short-circuit ; USING: kernel math tools.test combinators.short-circuit ;
IN: combinators.short-circuit.tests IN: combinators.short-circuit.tests
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [ 3 ] [ { [ 1 ] [ 2 ] [ 3 ] } 0&& ] unit-test
[ 5 ] [ 3 { [ 0 > ] [ odd? ] [ 2 + ] } 1&& ] unit-test
[ 30 ] [ 10 20 { [ + 0 > ] [ - even? ] [ + ] } 2&& ] unit-test
: must-be-t ( in -- ) [ t ] swap unit-test ; [ f ] [ { [ 1 ] [ f ] [ 3 ] } 0&& ] unit-test
: must-be-f ( in -- ) [ f ] swap unit-test ; [ f ] [ 3 { [ 0 > ] [ even? ] [ 2 + ] } 1&& ] unit-test
[ f ] [ 10 20 { [ + 0 > ] [ - odd? ] [ + ] } 2&& ] unit-test
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! [ "factor" ] [ { [ 10 0 < ] [ f ] [ "factor" ] } 0|| ] unit-test
[ 11 ] [ 10 { [ odd? ] [ 100 > ] [ 1 + ] } 1|| ] unit-test
[ 30 ] [ 10 20 { [ + odd? ] [ + 100 > ] [ + ] } 2|| ] unit-test
[ f ] [ { [ 10 0 < ] [ f ] [ 0 1 = ] } 0|| ] unit-test
[ { [ 1 ] [ 2 ] [ 3 ] } 0&& 3 = ] must-be-t : compiled-&& ( a -- ? ) { [ 0 > ] [ even? ] [ 2 + ] } 1&& ;
[ 3 { [ 0 > ] [ odd? ] [ 2 + ] } 1&& 5 = ] must-be-t
[ 10 20 { [ + 0 > ] [ - even? ] [ + ] } 2&& 30 = ] must-be-t
[ { [ 1 ] [ f ] [ 3 ] } 0&& 3 = ] must-be-f [ f ] [ 3 compiled-&& ] unit-test
[ 3 { [ 0 > ] [ even? ] [ 2 + ] } 1&& ] must-be-f [ 4 ] [ 2 compiled-&& ] unit-test
[ 10 20 { [ + 0 > ] [ - odd? ] [ + ] } 2&& 30 = ] must-be-f
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : compiled-|| ( a b -- ? ) { [ + odd? ] [ + 100 > ] [ + ] } 2|| ;
[ { [ 10 0 < ] [ f ] [ "factor" ] } 0|| "factor" = ] must-be-t
[ 10 { [ odd? ] [ 100 > ] [ 1 + ] } 1|| 11 = ] must-be-t
[ 10 20 { [ + odd? ] [ + 100 > ] [ + ] } 2|| 30 = ] must-be-t
[ { [ 10 0 < ] [ f ] [ 0 1 = ] } 0|| ] must-be-f
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[ 30 ] [ 10 20 compiled-|| ] unit-test
[ 2 ] [ 1 1 compiled-|| ] unit-test

View File

@ -12,10 +12,17 @@ MACRO:: n&& ( quots n -- quot )
n '[ _ nnip ] suffix 1array n '[ _ nnip ] suffix 1array
[ cond ] 3append ; [ cond ] 3append ;
MACRO: 0&& ( quots -- quot ) '[ _ 0 n&& ] ; <PRIVATE
MACRO: 1&& ( quots -- quot ) '[ _ 1 n&& ] ;
MACRO: 2&& ( quots -- quot ) '[ _ 2 n&& ] ; : unoptimized-&& ( quots quot -- ? )
MACRO: 3&& ( quots -- quot ) '[ _ 3 n&& ] ; [ [ call dup ] ] dip call [ nip ] prepose [ f ] 2dip all? swap and ; inline
PRIVATE>
: 0&& ( quots -- ? ) [ ] unoptimized-&& ;
: 1&& ( obj quots -- ? ) [ with ] unoptimized-&& ;
: 2&& ( obj1 obj2 quots -- ? ) [ with with ] unoptimized-&& ;
: 3&& ( obj1 obj2 obj3 quots -- ? ) [ with with with ] unoptimized-&& ;
MACRO:: n|| ( quots n -- quot ) MACRO:: n|| ( quots n -- quot )
[ f ] quots [| q | [ f ] quots [| q |
@ -27,7 +34,14 @@ MACRO:: n|| ( quots n -- quot )
n '[ drop _ ndrop t ] [ f ] 2array suffix 1array n '[ drop _ ndrop t ] [ f ] 2array suffix 1array
[ cond ] 3append ; [ cond ] 3append ;
MACRO: 0|| ( quots -- quot ) '[ _ 0 n|| ] ; <PRIVATE
MACRO: 1|| ( quots -- quot ) '[ _ 1 n|| ] ;
MACRO: 2|| ( quots -- quot ) '[ _ 2 n|| ] ; : unoptimized-|| ( quots quot -- ? )
MACRO: 3|| ( quots -- quot ) '[ _ 3 n|| ] ; [ [ call ] ] dip call map-find drop ; inline
PRIVATE>
: 0|| ( quots -- ? ) [ ] unoptimized-|| ;
: 1|| ( obj quots -- ? ) [ with ] unoptimized-|| ;
: 2|| ( obj1 obj2 quots -- ? ) [ with with ] unoptimized-|| ;
: 3|| ( obj1 obj2 obj3 quots -- ? ) [ with with with ] unoptimized-|| ;

View File

@ -0,0 +1,43 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators.short-circuit kernel sequences math
compiler.utilities compiler.cfg compiler.cfg.instructions compiler.cfg.rpo
compiler.cfg.utilities ;
IN: compiler.cfg.block-joining
! Joining blocks that are not calls and are connected by a single CFG edge.
! Predecessors must be recomputed after this. Also this pass does not
! update ##phi nodes and should therefore only run before stack analysis.
: kill-vreg-block? ( bb -- ? )
instructions>> {
[ length 2 >= ]
[ penultimate kill-vreg-insn? ]
} 1&& ;
: predecessor ( bb -- pred )
predecessors>> first ; inline
: join-block? ( bb -- ? )
{
[ predecessors>> length 1 = ]
[ predecessor kill-vreg-block? not ]
[ predecessor successors>> length 1 = ]
[ [ predecessor ] keep back-edge? not ]
} 1&& ;
: join-instructions ( bb pred -- )
[ instructions>> ] bi@ dup pop* push-all ;
: update-successors ( bb pred -- )
[ successors>> ] dip (>>successors) ;
: join-block ( bb pred -- )
[ join-instructions ] [ update-successors ] 2bi ;
: join-blocks ( cfg -- cfg' )
dup post-order [
dup join-block?
[ dup predecessor join-block ] [ drop ] if
] each
cfg-changed ;

View File

@ -1,85 +0,0 @@
IN: compiler.cfg.branch-folding.tests
USING: compiler.cfg.branch-folding compiler.cfg.instructions
compiler.cfg compiler.cfg.registers compiler.cfg.debugger
arrays compiler.cfg.phi-elimination compiler.cfg.dce
compiler.cfg.predecessors kernel accessors assocs
sequences classes namespaces tools.test cpu.architecture ;
V{ T{ ##branch } } 0 test-bb
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< }
} 1 test-bb
V{
T{ ##load-immediate f V int-regs 1 1 }
T{ ##branch }
} 2 test-bb
V{
T{ ##load-immediate f V int-regs 2 2 }
T{ ##branch }
} 3 test-bb
V{
T{ ##phi f V int-regs 3 { } }
T{ ##replace f V int-regs 3 D 0 }
T{ ##return }
} 4 test-bb
4 get instructions>> first
2 get V int-regs 1 2array
3 get V int-regs 2 2array 2array
>>inputs drop
test-diamond
[ ] [ cfg new 0 get >>entry fold-branches compute-predecessors eliminate-phis drop ] unit-test
[ 1 ] [ 1 get successors>> length ] unit-test
[ t ] [ 1 get successors>> first 3 get eq? ] unit-test
[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test
[ 2 ] [ 4 get instructions>> length ] unit-test
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##branch }
} 0 test-bb
V{
T{ ##peek f V int-regs 1 D 1 }
T{ ##compare-branch f V int-regs 1 V int-regs 1 cc< }
} 1 test-bb
V{
T{ ##copy f V int-regs 2 V int-regs 0 }
T{ ##branch }
} 2 test-bb
V{
T{ ##phi f V int-regs 3 V{ } }
T{ ##branch }
} 3 test-bb
V{
T{ ##replace f V int-regs 3 D 0 }
T{ ##return }
} 4 test-bb
1 get V int-regs 1 2array
2 get V int-regs 0 2array 2array 3 get instructions>> first (>>inputs)
test-diamond
[ ] [
cfg new 0 get >>entry
compute-predecessors
fold-branches
compute-predecessors
eliminate-dead-code
drop
] unit-test
[ 1 ] [ 3 get instructions>> first inputs>> assoc-size ] unit-test

View File

@ -1,30 +0,0 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators.short-circuit kernel sequences vectors
compiler.cfg.instructions compiler.cfg.rpo ;
IN: compiler.cfg.branch-folding
! Fold comparisons where both inputs are the same. Predecessors must be
! recomputed after this
: fold-branch? ( bb -- ? )
instructions>> last {
[ ##compare-branch? ]
[ [ src1>> ] [ src2>> ] bi = ]
} 1&& ;
: chosen-successor ( bb -- succ )
[ instructions>> last cc>> { cc= cc<= cc>= } memq? 0 1 ? ]
[ successors>> ]
bi nth ;
: fold-branch ( bb -- )
dup chosen-successor 1vector >>successors
instructions>> [ pop* ] [ [ \ ##branch new-insn ] dip push ] bi ;
: fold-branches ( cfg -- cfg' )
dup [
dup fold-branch?
[ fold-branch ] [ drop ] if
] each-basic-block
f >>post-order ;

View File

@ -0,0 +1,85 @@
USING: accessors assocs compiler.cfg
compiler.cfg.branch-splitting compiler.cfg.debugger
compiler.cfg.predecessors compiler.cfg.rpo compiler.cfg.instructions fry kernel
tools.test namespaces sequences vectors ;
IN: compiler.cfg.branch-splitting.tests
: get-predecessors ( cfg -- assoc )
H{ } clone [ '[ [ predecessors>> ] keep _ set-at ] each-basic-block ] keep ;
: check-predecessors ( cfg -- )
[ get-predecessors ]
[ compute-predecessors drop ]
[ get-predecessors ] tri assert= ;
: check-branch-splitting ( cfg -- )
compute-predecessors
split-branches
check-predecessors ;
: test-branch-splitting ( -- )
cfg new 0 get >>entry check-branch-splitting ;
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
test-diamond
[ ] [ test-branch-splitting ] unit-test
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
V{ T{ ##branch } } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 3 get 4 get V{ } 2sequence >>successors drop
2 get 3 get 4 get V{ } 2sequence >>successors drop
[ ] [ test-branch-splitting ] unit-test
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 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 3 get 4 get V{ } 2sequence >>successors drop
2 get 4 get 1vector >>successors drop
[ ] [ test-branch-splitting ] unit-test
V{ T{ ##branch } } 0 test-bb
V{ T{ ##branch } } 1 test-bb
V{ T{ ##branch } } 2 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 2 get 1vector >>successors drop
[ ] [ test-branch-splitting ] unit-test

View File

@ -1,37 +1,81 @@
! Copyright (C) 2009 Doug Coleman, Slava Pestov. ! Copyright (C) 2009 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators.short-circuit kernel math sequences USING: accessors combinators.short-circuit kernel math math.order
compiler.cfg.def-use compiler.cfg compiler.cfg.rpo ; sequences assocs namespaces vectors fry arrays splitting
compiler.cfg.def-use compiler.cfg compiler.cfg.rpo
compiler.cfg.renaming compiler.cfg.instructions compiler.cfg.utilities ;
IN: compiler.cfg.branch-splitting IN: compiler.cfg.branch-splitting
! Predecessors must be recomputed after this : clone-renamings ( insns -- assoc )
[ defs-vregs ] map concat [ dup fresh-vreg ] H{ } map>assoc ;
: split-branch-for ( bb predecessor -- ) : clone-instructions ( insns -- insns' )
[ dup clone-renamings renamings [
[ [
<basic-block> clone
swap dup rename-insn-defs
[ instructions>> [ clone ] map >>instructions ] dup rename-insn-uses
[ successors>> clone >>successors ] dup fresh-insn-temps
bi ] map
] keep ] with-variable ;
] dip
[ [ 2dup eq? [ 2drop ] [ 2nip ] if ] with with map ] change-successors : clone-basic-block ( bb -- bb' )
drop ; ! The new block gets the same RPO number as the old one.
! This is just to make 'back-edge?' work.
<basic-block>
swap
[ instructions>> clone-instructions >>instructions ]
[ successors>> clone >>successors ]
[ number>> >>number ]
tri ;
: new-blocks ( bb -- copies )
dup predecessors>> [
[ clone-basic-block ] dip
1vector >>predecessors
] with map ;
: update-predecessor-successor ( pred copy old-bb -- )
'[
[ _ _ 3dup nip eq? [ drop nip ] [ 2drop ] if ] map
] change-successors drop ;
: update-predecessor-successors ( copies old-bb -- )
[ predecessors>> swap ] keep
'[ _ update-predecessor-successor ] 2each ;
: update-successor-predecessor ( copies old-bb succ -- )
[
swap 1array split swap join V{ } like
] change-predecessors drop ;
: update-successor-predecessors ( copies old-bb -- )
dup successors>> [
update-successor-predecessor
] with with each ;
: split-branch ( bb -- ) : split-branch ( bb -- )
dup predecessors>> [ split-branch-for ] with each ; [ new-blocks ] keep
[ update-predecessor-successors ]
[ update-successor-predecessors ]
2bi ;
: split-branches? ( bb -- ? ) UNION: irrelevant ##peek ##replace ##inc-d ##inc-r ;
: split-instructions? ( insns -- ? )
[ [ irrelevant? not ] count 5 <= ]
[ last ##fixnum-overflow? not ]
bi and ;
: split-branch? ( bb -- ? )
{ {
[ successors>> empty? ] [ dup successors>> [ back-edge? ] with any? not ]
[ predecessors>> length 1 > ] [ predecessors>> length 2 4 between? ]
[ instructions>> [ defs-vregs ] any? not ] [ instructions>> split-instructions? ]
[ instructions>> [ temp-vregs ] any? not ]
} 1&& ; } 1&& ;
: split-branches ( cfg -- cfg' ) : split-branches ( cfg -- cfg' )
dup [ dup [
dup split-branches? [ split-branch ] [ drop ] if dup split-branch? [ split-branch ] [ drop ] if
] each-basic-block ] each-basic-block
f >>post-order ; cfg-changed ;

View File

@ -1,4 +1,4 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces accessors math.order assocs kernel sequences USING: namespaces accessors math.order assocs kernel sequences
combinators make classes words cpu.architecture combinators make classes words cpu.architecture
@ -36,12 +36,6 @@ M: insn compute-stack-frame*
] when ; ] when ;
\ _spill t frame-required? set-word-prop \ _spill t frame-required? set-word-prop
\ ##fixnum-add t frame-required? set-word-prop
\ ##fixnum-sub t frame-required? set-word-prop
\ ##fixnum-mul t frame-required? set-word-prop
\ ##fixnum-add-tail f frame-required? set-word-prop
\ ##fixnum-sub-tail f frame-required? set-word-prop
\ ##fixnum-mul-tail f frame-required? set-word-prop
: compute-stack-frame ( insns -- ) : compute-stack-frame ( insns -- )
frame-required? off frame-required? off

View File

@ -14,6 +14,7 @@ compiler.cfg.stacks
compiler.cfg.utilities compiler.cfg.utilities
compiler.cfg.registers compiler.cfg.registers
compiler.cfg.intrinsics compiler.cfg.intrinsics
compiler.cfg.comparisons
compiler.cfg.stack-frame compiler.cfg.stack-frame
compiler.cfg.instructions compiler.cfg.instructions
compiler.alien ; compiler.alien ;
@ -22,30 +23,20 @@ IN: compiler.cfg.builder
! Convert tree SSA IR to CFG SSA IR. ! Convert tree SSA IR to CFG SSA IR.
SYMBOL: procedures SYMBOL: procedures
SYMBOL: current-word
SYMBOL: current-label
SYMBOL: loops SYMBOL: loops
: add-procedure ( -- )
basic-block get current-word get current-label get
<cfg> procedures get push ;
: begin-procedure ( word label -- ) : begin-procedure ( word label -- )
end-basic-block end-basic-block
begin-basic-block begin-basic-block
H{ } clone loops set H{ } clone loops set
current-label set [ basic-block get ] 2dip
current-word set <cfg> procedures get push ;
add-procedure ;
: with-cfg-builder ( nodes word label quot -- ) : with-cfg-builder ( nodes word label quot -- )
'[ begin-procedure @ ] with-scope ; inline '[ begin-procedure @ ] with-scope ; inline
GENERIC: emit-node ( node -- ) GENERIC: emit-node ( node -- )
: check-basic-block ( node -- node' )
basic-block get [ drop f ] unless ; inline
: emit-nodes ( nodes -- ) : emit-nodes ( nodes -- )
[ basic-block get [ emit-node ] [ drop ] if ] each ; [ basic-block get [ emit-node ] [ drop ] if ] each ;
@ -97,17 +88,10 @@ M: #recursive emit-node
! #if ! #if
: emit-branch ( obj -- final-bb ) : emit-branch ( obj -- final-bb )
[ [ emit-nodes ] with-branch ;
begin-basic-block
emit-nodes
basic-block get dup [ ##branch ] when
] with-scope ;
: emit-if ( node -- ) : emit-if ( node -- )
children>> [ emit-branch ] map children>> [ emit-branch ] map emit-conditional ;
end-basic-block
begin-basic-block
basic-block get '[ [ _ swap successors>> push ] when* ] each ;
: ##branch-t ( vreg -- ) : ##branch-t ( vreg -- )
\ f tag-number cc/= ##compare-imm-branch ; \ f tag-number cc/= ##compare-imm-branch ;

View File

@ -1,9 +1,6 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel arrays vectors accessors assocs sets USING: kernel math vectors arrays accessors namespaces ;
namespaces math make fry sequences
combinators.short-circuit
compiler.cfg.instructions ;
IN: compiler.cfg IN: compiler.cfg
TUPLE: basic-block < identity-tuple TUPLE: basic-block < identity-tuple
@ -22,36 +19,12 @@ M: basic-block hashcode* nip id>> ;
V{ } clone >>predecessors V{ } clone >>predecessors
\ basic-block counter >>id ; \ basic-block counter >>id ;
: empty-block? ( bb -- ? )
instructions>> {
[ length 1 = ]
[ first ##branch? ]
} 1&& ;
SYMBOL: visited
: (skip-empty-blocks) ( bb -- bb' )
dup visited get key? [
dup empty-block? [
dup visited get conjoin
successors>> first (skip-empty-blocks)
] when
] unless ;
: skip-empty-blocks ( bb -- bb' )
H{ } clone visited [ (skip-empty-blocks) ] with-variable ;
: add-instructions ( bb quot -- )
[ instructions>> building ] dip '[
building get pop
_ dip
building get push
] with-variable ; inline
TUPLE: cfg { entry basic-block } word label spill-counts post-order ; TUPLE: cfg { entry basic-block } word label spill-counts post-order ;
: <cfg> ( entry word label -- cfg ) f f cfg boa ; : <cfg> ( entry word label -- cfg ) f f cfg boa ;
: cfg-changed ( cfg -- cfg ) f >>post-order ; inline
TUPLE: mr { instructions array } word label ; TUPLE: mr { instructions array } word label ;
: <mr> ( instructions word label -- mr ) : <mr> ( instructions word label -- mr )

View File

@ -16,9 +16,9 @@ ERROR: last-insn-not-a-jump insn ;
[ ##return? ] [ ##return? ]
[ ##callback-return? ] [ ##callback-return? ]
[ ##jump? ] [ ##jump? ]
[ ##fixnum-add-tail? ] [ ##fixnum-add? ]
[ ##fixnum-sub-tail? ] [ ##fixnum-sub? ]
[ ##fixnum-mul-tail? ] [ ##fixnum-mul? ]
[ ##no-tco? ] [ ##no-tco? ]
} 1|| [ drop ] [ last-insn-not-a-jump ] if ; } 1|| [ drop ] [ last-insn-not-a-jump ] if ;

View File

@ -0,0 +1,36 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: assocs math.order sequences ;
IN: compiler.cfg.comparisons
SYMBOLS: cc< cc<= cc= cc> cc>= cc/= ;
: negate-cc ( cc -- cc' )
H{
{ cc< cc>= }
{ cc<= cc> }
{ cc> cc<= }
{ cc>= cc< }
{ cc= cc/= }
{ cc/= cc= }
} at ;
: swap-cc ( cc -- cc' )
H{
{ cc< cc> }
{ cc<= cc>= }
{ cc> cc< }
{ cc>= cc<= }
{ cc= cc= }
{ cc/= cc/= }
} at ;
: evaluate-cc ( result cc -- ? )
H{
{ cc< { +lt+ } }
{ cc<= { +lt+ +eq+ } }
{ cc= { +eq+ } }
{ cc>= { +eq+ +gt+ } }
{ cc> { +gt+ } }
{ cc/= { +lt+ +gt+ } }
} at memq? ;

View File

@ -0,0 +1,140 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs deques dlists kernel locals sequences lexer
namespaces functors compiler.cfg.rpo compiler.cfg.utilities
compiler.cfg ;
IN: compiler.cfg.dataflow-analysis
GENERIC: join-sets ( sets dfa -- set )
GENERIC: transfer-set ( in-set bb dfa -- out-set )
GENERIC: block-order ( cfg dfa -- bbs )
GENERIC: successors ( bb dfa -- seq )
GENERIC: predecessors ( bb dfa -- seq )
<PRIVATE
MIXIN: dataflow-analysis
: <dfa-worklist> ( cfg dfa -- queue )
block-order <hashed-dlist> [ push-all-front ] keep ;
GENERIC# compute-in-set 2 ( bb out-sets dfa -- set )
M: kill-block compute-in-set 3drop f ;
M:: basic-block compute-in-set ( bb out-sets dfa -- set )
bb dfa predecessors [ out-sets at ] map dfa join-sets ;
:: update-in-set ( bb in-sets out-sets dfa -- ? )
bb out-sets dfa compute-in-set
bb in-sets maybe-set-at ; inline
GENERIC# compute-out-set 2 ( bb out-sets dfa -- set )
M: kill-block compute-out-set 3drop f ;
M:: basic-block compute-out-set ( bb in-sets dfa -- set )
bb in-sets at bb dfa transfer-set ;
:: update-out-set ( bb in-sets out-sets dfa -- ? )
bb in-sets dfa compute-out-set
bb out-sets maybe-set-at ; inline
:: dfa-step ( bb in-sets out-sets dfa work-list -- )
bb in-sets out-sets dfa update-in-set [
bb in-sets out-sets dfa update-out-set [
bb dfa successors work-list push-all-front
] when
] when ; inline
:: run-dataflow-analysis ( cfg dfa -- in-sets out-sets )
H{ } clone :> in-sets
H{ } clone :> out-sets
cfg dfa <dfa-worklist> :> work-list
work-list [ in-sets out-sets dfa work-list dfa-step ] slurp-deque
in-sets
out-sets ; inline
M: dataflow-analysis join-sets drop assoc-refine ;
FUNCTOR: define-analysis ( name -- )
name-analysis DEFINES-CLASS ${name}-analysis
name-ins DEFINES ${name}-ins
name-outs DEFINES ${name}-outs
name-in DEFINES ${name}-in
name-out DEFINES ${name}-out
WHERE
SINGLETON: name-analysis
SYMBOL: name-ins
: name-in ( bb -- set ) name-ins get at ;
SYMBOL: name-outs
: name-out ( bb -- set ) name-outs get at ;
;FUNCTOR
! ! ! Forward dataflow analysis
MIXIN: forward-analysis
INSTANCE: forward-analysis dataflow-analysis
M: forward-analysis block-order drop reverse-post-order ;
M: forward-analysis successors drop successors>> ;
M: forward-analysis predecessors drop predecessors>> ;
FUNCTOR: define-forward-analysis ( name -- )
name-analysis IS ${name}-analysis
name-ins IS ${name}-ins
name-outs IS ${name}-outs
compute-name-sets DEFINES compute-${name}-sets
WHERE
INSTANCE: name-analysis forward-analysis
: compute-name-sets ( cfg -- )
name-analysis run-dataflow-analysis
[ name-ins set ] [ name-outs set ] bi* ;
;FUNCTOR
! ! ! Backward dataflow analysis
MIXIN: backward-analysis
INSTANCE: backward-analysis dataflow-analysis
M: backward-analysis block-order drop post-order ;
M: backward-analysis successors drop predecessors>> ;
M: backward-analysis predecessors drop successors>> ;
FUNCTOR: define-backward-analysis ( name -- )
name-analysis IS ${name}-analysis
name-ins IS ${name}-ins
name-outs IS ${name}-outs
compute-name-sets DEFINES compute-${name}-sets
WHERE
INSTANCE: name-analysis backward-analysis
: compute-name-sets ( cfg -- )
\ name-analysis run-dataflow-analysis
[ name-outs set ] [ name-ins set ] bi* ;
;FUNCTOR
PRIVATE>
SYNTAX: FORWARD-ANALYSIS:
scan [ define-analysis ] [ define-forward-analysis ] bi ;
SYNTAX: BACKWARD-ANALYSIS:
scan [ define-analysis ] [ define-backward-analysis ] bi ;

View File

@ -26,7 +26,7 @@ M: word test-cfg
] map ; ] map ;
: insn. ( insn -- ) : insn. ( insn -- )
tuple>array [ pprint bl ] each nl ; tuple>array but-last [ pprint bl ] each nl ;
: mr. ( mrs -- ) : mr. ( mrs -- )
[ [

View File

@ -8,6 +8,7 @@ GENERIC: temp-vregs ( insn -- seq )
GENERIC: uses-vregs ( insn -- seq ) GENERIC: uses-vregs ( insn -- seq )
M: ##flushable defs-vregs dst>> 1array ; M: ##flushable defs-vregs dst>> 1array ;
M: ##fixnum-overflow defs-vregs dst>> 1array ;
M: insn defs-vregs drop f ; M: insn defs-vregs drop f ;
M: ##write-barrier temp-vregs [ card#>> ] [ table>> ] bi 2array ; M: ##write-barrier temp-vregs [ card#>> ] [ table>> ] bi 2array ;
@ -21,8 +22,6 @@ M: ##set-string-nth-fast temp-vregs temp>> 1array ;
M: ##compare temp-vregs temp>> 1array ; M: ##compare temp-vregs temp>> 1array ;
M: ##compare-imm temp-vregs temp>> 1array ; M: ##compare-imm temp-vregs temp>> 1array ;
M: ##compare-float temp-vregs temp>> 1array ; M: ##compare-float temp-vregs temp>> 1array ;
M: ##fixnum-mul temp-vregs [ temp1>> ] [ temp2>> ] bi 2array ;
M: ##fixnum-mul-tail temp-vregs [ temp1>> ] [ temp2>> ] bi 2array ;
M: ##gc temp-vregs [ temp1>> ] [ temp2>> ] bi 2array ; M: ##gc temp-vregs [ temp1>> ] [ temp2>> ] bi 2array ;
M: _dispatch temp-vregs temp>> 1array ; M: _dispatch temp-vregs temp>> 1array ;
M: insn temp-vregs drop f ; M: insn temp-vregs drop f ;

View File

@ -0,0 +1,76 @@
IN: compiler.cfg.dominance.tests
USING: tools.test sequences vectors namespaces kernel accessors assocs sets
math.ranges arrays compiler.cfg compiler.cfg.dominance compiler.cfg.debugger
compiler.cfg.predecessors ;
: test-dominance ( -- )
cfg new 0 get >>entry
compute-predecessors
compute-dominance
drop ;
! Example with no back edges
V{ } 0 test-bb
V{ } 1 test-bb
V{ } 2 test-bb
V{ } 3 test-bb
V{ } 4 test-bb
V{ } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 3 get 1vector >>successors drop
2 get 4 get 1vector >>successors drop
3 get 4 get 1vector >>successors drop
4 get 5 get 1vector >>successors drop
[ ] [ test-dominance ] unit-test
[ t ] [ 0 get dom-parent 0 get eq? ] unit-test
[ t ] [ 1 get dom-parent 0 get eq? ] unit-test
[ t ] [ 2 get dom-parent 0 get eq? ] unit-test
[ t ] [ 4 get dom-parent 0 get eq? ] unit-test
[ t ] [ 3 get dom-parent 1 get eq? ] unit-test
[ t ] [ 5 get dom-parent 4 get eq? ] unit-test
[ t ] [ 0 get dom-children 1 get 2 get 4 get 3array set= ] unit-test
[ { 4 } ] [ 1 get dom-frontier [ number>> ] map ] unit-test
[ { 4 } ] [ 2 get dom-frontier [ number>> ] map ] unit-test
[ { } ] [ 0 get dom-frontier ] unit-test
[ { } ] [ 4 get dom-frontier ] unit-test
! Example from the paper
V{ } 0 test-bb
V{ } 1 test-bb
V{ } 2 test-bb
V{ } 3 test-bb
V{ } 4 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 3 get 1vector >>successors drop
2 get 4 get 1vector >>successors drop
3 get 4 get 1vector >>successors drop
4 get 3 get 1vector >>successors drop
[ ] [ test-dominance ] unit-test
[ t ] [ 0 4 [a,b] [ get dom-parent 0 get eq? ] all? ] unit-test
! The other example from the paper
V{ } 0 test-bb
V{ } 1 test-bb
V{ } 2 test-bb
V{ } 3 test-bb
V{ } 4 test-bb
V{ } 5 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 5 get 1vector >>successors drop
2 get 4 get 3 get V{ } 2sequence >>successors drop
5 get 4 get 1vector >>successors drop
4 get 5 get 3 get V{ } 2sequence >>successors drop
3 get 4 get 1vector >>successors drop
[ ] [ test-dominance ] unit-test
[ t ] [ 0 5 [a,b] [ get dom-parent 0 get eq? ] all? ] unit-test

View File

@ -1,8 +1,7 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs combinators compiler.cfg.rpo USING: accessors assocs combinators sets math fry kernel math.order
compiler.cfg.stack-analysis fry kernel math.order namespaces namespaces sequences sorting compiler.cfg.rpo ;
sequences ;
IN: compiler.cfg.dominance IN: compiler.cfg.dominance
! Reference: ! Reference:
@ -11,31 +10,83 @@ IN: compiler.cfg.dominance
! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy ! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
! http://www.cs.rice.edu/~keith/EMBED/dom.pdf ! http://www.cs.rice.edu/~keith/EMBED/dom.pdf
SYMBOL: idoms ! Also, a nice overview is given in these lecture notes:
! http://llvm.cs.uiuc.edu/~vadve/CS526/public_html/Notes/4ssa.4up.pdf
: idom ( bb -- bb' ) idoms get at ;
<PRIVATE <PRIVATE
: set-idom ( idom bb -- changed? ) idoms get maybe-set-at ; ! Maps bb -> idom(bb)
SYMBOL: dom-parents
PRIVATE>
: dom-parent ( bb -- bb' ) dom-parents get at ;
<PRIVATE
: set-idom ( idom bb -- changed? )
dom-parents get maybe-set-at ;
: intersect ( finger1 finger2 -- bb ) : intersect ( finger1 finger2 -- bb )
2dup [ number>> ] compare { 2dup [ number>> ] compare {
{ +lt+ [ [ idom ] dip intersect ] } { +gt+ [ [ dom-parent ] dip intersect ] }
{ +gt+ [ idom intersect ] } { +lt+ [ dom-parent intersect ] }
[ 2drop ] [ 2drop ]
} case ; } case ;
: compute-idom ( bb -- idom ) : compute-idom ( bb -- idom )
predecessors>> [ idom ] map sift predecessors>> [ dom-parent ] filter
[ ] [ intersect ] map-reduce ; [ ] [ intersect ] map-reduce ;
: iterate ( rpo -- changed? ) : iterate ( rpo -- changed? )
[ [ compute-idom ] keep set-idom ] map [ ] any? ; [ [ compute-idom ] keep set-idom ] map [ ] any? ;
: compute-dom-parents ( cfg -- )
H{ } clone dom-parents set
reverse-post-order
unclip dup set-idom drop '[ _ iterate ] loop ;
! Maps bb -> {bb' | idom(bb') = bb}
SYMBOL: dom-childrens
PRIVATE> PRIVATE>
: compute-dominance ( cfg -- cfg ) : dom-children ( bb -- seq ) dom-childrens get at ;
H{ } clone idoms set
dup reverse-post-order <PRIVATE
unclip dup set-idom drop '[ _ iterate ] loop ;
: compute-dom-children ( -- )
dom-parents get H{ } clone
[ '[ 2dup eq? [ 2drop ] [ _ push-at ] if ] assoc-each ] keep
dom-childrens set ;
! Maps bb -> DF(bb)
SYMBOL: dom-frontiers
PRIVATE>
: dom-frontier ( bb -- set ) dom-frontiers get at keys ;
<PRIVATE
: compute-dom-frontier ( bb pred -- )
2dup [ dom-parent ] dip eq? [ 2drop ] [
[ dom-frontiers get conjoin-at ]
[ dom-parent compute-dom-frontier ] 2bi
] if ;
: compute-dom-frontiers ( cfg -- )
H{ } clone dom-frontiers set
[
dup predecessors>> dup length 2 >= [
[ compute-dom-frontier ] with each
] [ 2drop ] if
] each-basic-block ;
PRIVATE>
: compute-dominance ( cfg -- cfg' )
[ compute-dom-parents compute-dom-children ]
[ compute-dom-frontiers ]
[ ]
tri ;

View File

@ -27,6 +27,7 @@ IN: compiler.cfg.hats
: ^^add-imm ( src1 src2 -- dst ) ^^i2 ##add-imm ; inline : ^^add-imm ( src1 src2 -- dst ) ^^i2 ##add-imm ; inline
: ^^sub ( src1 src2 -- dst ) ^^i2 ##sub ; inline : ^^sub ( src1 src2 -- dst ) ^^i2 ##sub ; inline
: ^^sub-imm ( src1 src2 -- dst ) ^^i2 ##sub-imm ; inline : ^^sub-imm ( src1 src2 -- dst ) ^^i2 ##sub-imm ; inline
: ^^neg ( src -- dst ) [ 0 ^^load-literal ] dip ^^sub ; inline
: ^^mul ( src1 src2 -- dst ) ^^i2 ##mul ; inline : ^^mul ( src1 src2 -- dst ) ^^i2 ##mul ; inline
: ^^mul-imm ( src1 src2 -- dst ) ^^i2 ##mul-imm ; inline : ^^mul-imm ( src1 src2 -- dst ) ^^i2 ##mul-imm ; inline
: ^^and ( input mask -- output ) ^^i2 ##and ; inline : ^^and ( input mask -- output ) ^^i2 ##and ; inline
@ -35,8 +36,11 @@ IN: compiler.cfg.hats
: ^^or-imm ( src1 src2 -- dst ) ^^i2 ##or-imm ; inline : ^^or-imm ( src1 src2 -- dst ) ^^i2 ##or-imm ; inline
: ^^xor ( src1 src2 -- dst ) ^^i2 ##xor ; inline : ^^xor ( src1 src2 -- dst ) ^^i2 ##xor ; inline
: ^^xor-imm ( src1 src2 -- dst ) ^^i2 ##xor-imm ; inline : ^^xor-imm ( src1 src2 -- dst ) ^^i2 ##xor-imm ; inline
: ^^shl ( src1 src2 -- dst ) ^^i2 ##shl ; inline
: ^^shl-imm ( src1 src2 -- dst ) ^^i2 ##shl-imm ; inline : ^^shl-imm ( src1 src2 -- dst ) ^^i2 ##shl-imm ; inline
: ^^shr ( src1 src2 -- dst ) ^^i2 ##shr ; inline
: ^^shr-imm ( src1 src2 -- dst ) ^^i2 ##shr-imm ; inline : ^^shr-imm ( src1 src2 -- dst ) ^^i2 ##shr-imm ; inline
: ^^sar ( src1 src2 -- dst ) ^^i2 ##sar ; inline
: ^^sar-imm ( src1 src2 -- dst ) ^^i2 ##sar-imm ; inline : ^^sar-imm ( src1 src2 -- dst ) ^^i2 ##sar-imm ; inline
: ^^not ( src -- dst ) ^^i1 ##not ; inline : ^^not ( src -- dst ) ^^i1 ##not ; inline
: ^^log2 ( src -- dst ) ^^i1 ##log2 ; inline : ^^log2 ( src -- dst ) ^^i1 ##log2 ; inline
@ -73,5 +77,7 @@ IN: compiler.cfg.hats
: ^^offset>slot ( vreg -- vreg' ) cell 4 = [ 1 ^^shr-imm ] when ; inline : ^^offset>slot ( vreg -- vreg' ) cell 4 = [ 1 ^^shr-imm ] when ; inline
: ^^tag-fixnum ( src -- dst ) ^^i1 ##tag-fixnum ; inline : ^^tag-fixnum ( src -- dst ) ^^i1 ##tag-fixnum ; inline
: ^^untag-fixnum ( src -- dst ) ^^i1 ##untag-fixnum ; inline : ^^untag-fixnum ( src -- dst ) ^^i1 ##untag-fixnum ; inline
: ^^fixnum-add ( src1 src2 -- dst ) ^^i2 ##fixnum-add ; inline
: ^^fixnum-sub ( src1 src2 -- dst ) ^^i2 ##fixnum-sub ; inline
: ^^fixnum-mul ( src1 src2 -- dst ) ^^i2 ##fixnum-mul ; inline
: ^^phi ( inputs -- dst ) ^^i1 ##phi ; inline : ^^phi ( inputs -- dst ) ^^i1 ##phi ; inline

View File

@ -86,21 +86,15 @@ INSN: ##or < ##commutative ;
INSN: ##or-imm < ##commutative-imm ; INSN: ##or-imm < ##commutative-imm ;
INSN: ##xor < ##commutative ; INSN: ##xor < ##commutative ;
INSN: ##xor-imm < ##commutative-imm ; INSN: ##xor-imm < ##commutative-imm ;
INSN: ##shl < ##binary ;
INSN: ##shl-imm < ##binary-imm ; INSN: ##shl-imm < ##binary-imm ;
INSN: ##shr < ##binary ;
INSN: ##shr-imm < ##binary-imm ; INSN: ##shr-imm < ##binary-imm ;
INSN: ##sar < ##binary ;
INSN: ##sar-imm < ##binary-imm ; INSN: ##sar-imm < ##binary-imm ;
INSN: ##not < ##unary ; INSN: ##not < ##unary ;
INSN: ##log2 < ##unary ; INSN: ##log2 < ##unary ;
! Overflowing arithmetic
TUPLE: ##fixnum-overflow < insn src1 src2 ;
INSN: ##fixnum-add < ##fixnum-overflow ;
INSN: ##fixnum-add-tail < ##fixnum-overflow ;
INSN: ##fixnum-sub < ##fixnum-overflow ;
INSN: ##fixnum-sub-tail < ##fixnum-overflow ;
INSN: ##fixnum-mul < ##fixnum-overflow temp1 temp2 ;
INSN: ##fixnum-mul-tail < ##fixnum-overflow temp1 temp2 ;
: ##tag-fixnum ( dst src -- ) tag-bits get ##shl-imm ; inline : ##tag-fixnum ( dst src -- ) tag-bits get ##shl-imm ; inline
: ##untag-fixnum ( dst src -- ) tag-bits get ##sar-imm ; inline : ##untag-fixnum ( dst src -- ) tag-bits get ##sar-imm ; inline
@ -181,44 +175,7 @@ INSN: ##loop-entry ;
INSN: ##phi < ##pure inputs ; INSN: ##phi < ##pure inputs ;
! Condition codes ! Conditionals
SYMBOL: cc<
SYMBOL: cc<=
SYMBOL: cc=
SYMBOL: cc>
SYMBOL: cc>=
SYMBOL: cc/=
: negate-cc ( cc -- cc' )
H{
{ cc< cc>= }
{ cc<= cc> }
{ cc> cc<= }
{ cc>= cc< }
{ cc= cc/= }
{ cc/= cc= }
} at ;
: swap-cc ( cc -- cc' )
H{
{ cc< cc> }
{ cc<= cc>= }
{ cc> cc< }
{ cc>= cc<= }
{ cc= cc= }
{ cc/= cc/= }
} at ;
: evaluate-cc ( result cc -- ? )
H{
{ cc< { +lt+ } }
{ cc<= { +lt+ +eq+ } }
{ cc= { +eq+ } }
{ cc>= { +eq+ +gt+ } }
{ cc> { +gt+ } }
{ cc/= { +lt+ +gt+ } }
} at memq? ;
TUPLE: ##conditional-branch < insn { src1 vreg } { src2 vreg } cc ; TUPLE: ##conditional-branch < insn { src1 vreg } { src2 vreg } cc ;
INSN: ##compare-branch < ##conditional-branch ; INSN: ##compare-branch < ##conditional-branch ;
@ -230,6 +187,12 @@ INSN: ##compare-imm < ##binary-imm cc temp ;
INSN: ##compare-float-branch < ##conditional-branch ; INSN: ##compare-float-branch < ##conditional-branch ;
INSN: ##compare-float < ##binary cc temp ; INSN: ##compare-float < ##binary cc temp ;
! Overflowing arithmetic
TUPLE: ##fixnum-overflow < insn { dst vreg } { src1 vreg } { src2 vreg } ;
INSN: ##fixnum-add < ##fixnum-overflow ;
INSN: ##fixnum-sub < ##fixnum-overflow ;
INSN: ##fixnum-mul < ##fixnum-overflow ;
INSN: ##gc { temp1 vreg } { temp2 vreg } live-values ; INSN: ##gc { temp1 vreg } { temp2 vreg } live-values ;
! Instructions used by machine IR only. ! Instructions used by machine IR only.
@ -250,6 +213,12 @@ INSN: _compare-imm-branch label { src1 vreg } { src2 integer } cc ;
INSN: _compare-float-branch < _conditional-branch ; INSN: _compare-float-branch < _conditional-branch ;
! Overflowing arithmetic
TUPLE: _fixnum-overflow < insn label { dst vreg } { src1 vreg } { src2 vreg } ;
INSN: _fixnum-add < _fixnum-overflow ;
INSN: _fixnum-sub < _fixnum-overflow ;
INSN: _fixnum-mul < _fixnum-overflow ;
TUPLE: spill-slot n ; C: <spill-slot> spill-slot TUPLE: spill-slot n ; C: <spill-slot> spill-slot
INSN: _gc { temp1 vreg } { temp2 vreg } gc-roots gc-root-count gc-root-size ; INSN: _gc { temp1 vreg } { temp2 vreg } gc-roots gc-root-count gc-root-size ;
@ -261,3 +230,19 @@ INSN: _reload dst class n ;
INSN: _copy dst src class ; INSN: _copy dst src class ;
INSN: _spill-counts counts ; INSN: _spill-counts counts ;
! Instructions that poison the stack state
UNION: poison-insn
##jump
##return
##callback-return ;
! Instructions that kill all live vregs
UNION: kill-vreg-insn
poison-insn
##stack-frame
##call
##prologue
##epilogue
##alien-invoke
##alien-indirect
##alien-callback ;

View File

@ -1,13 +1,14 @@
! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman. ! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: sequences accessors layouts kernel math namespaces USING: sequences accessors layouts kernel math math.intervals
combinators fry locals namespaces combinators fry arrays
compiler.tree.propagation.info compiler.tree.propagation.info
compiler.cfg.hats compiler.cfg.hats
compiler.cfg.stacks compiler.cfg.stacks
compiler.cfg.instructions compiler.cfg.instructions
compiler.cfg.utilities compiler.cfg.utilities
compiler.cfg.registers ; compiler.cfg.registers
compiler.cfg.comparisons ;
IN: compiler.cfg.intrinsics.fixnum IN: compiler.cfg.intrinsics.fixnum
: emit-both-fixnums? ( -- ) : emit-both-fixnums? ( -- )
@ -20,44 +21,27 @@ IN: compiler.cfg.intrinsics.fixnum
: tag-literal ( n -- tagged ) : tag-literal ( n -- tagged )
literal>> [ tag-fixnum ] [ \ f tag-number ] if* ; literal>> [ tag-fixnum ] [ \ f tag-number ] if* ;
: emit-fixnum-imm-op1 ( infos insn -- dst ) : emit-fixnum-op ( insn -- )
[ ds-pop ds-drop ] [ first tag-literal ] [ ] tri* call ; inline [ 2inputs ] dip call ds-push ; inline
: emit-fixnum-imm-op2 ( infos insn -- dst ) : emit-fixnum-left-shift ( -- )
[ ds-drop ds-pop ] [ second tag-literal ] [ ] tri* call ; inline [ ^^untag-fixnum ^^shl ] emit-fixnum-op ;
: (emit-fixnum-op) ( insn -- dst ) : emit-fixnum-right-shift ( -- )
[ 2inputs ] dip call ; inline [ ^^untag-fixnum ^^neg ^^sar dup tag-mask get ^^and-imm ^^xor ] emit-fixnum-op ;
:: emit-fixnum-op ( node insn imm-insn -- ) : emit-fixnum-shift-general ( -- )
[let | infos [ node node-input-infos ] | D 0 ^^peek 0 cc> ##compare-imm-branch
infos second value-info-small-tagged? [ emit-fixnum-left-shift ] with-branch
[ infos imm-insn emit-fixnum-imm-op2 ] [ emit-fixnum-right-shift ] with-branch
[ insn (emit-fixnum-op) ] if 2array emit-conditional ;
ds-push
] ; inline
:: emit-commutative-fixnum-op ( node insn imm-insn -- )
[let | infos [ node node-input-infos ] |
{
{ [ infos first value-info-small-tagged? ] [ infos imm-insn emit-fixnum-imm-op1 ] }
{ [ infos second value-info-small-tagged? ] [ infos imm-insn emit-fixnum-imm-op2 ] }
[ insn (emit-fixnum-op) ]
} cond
ds-push
] ; inline
: emit-fixnum-shift-fast ( node -- ) : emit-fixnum-shift-fast ( node -- )
dup node-input-infos dup second value-info-small-fixnum? [ node-input-infos second interval>> {
nip { [ dup 0 [a,inf] interval-subset? ] [ drop emit-fixnum-left-shift ] }
[ ds-drop ds-pop ] dip { [ dup 0 [-inf,a] interval-subset? ] [ drop emit-fixnum-right-shift ] }
second literal>> dup sgn { [ drop emit-fixnum-shift-general ]
{ -1 [ neg tag-bits get + ^^sar-imm ^^tag-fixnum ] } } cond ;
{ 0 [ drop ] }
{ 1 [ ^^shl-imm ] }
} case
ds-push
] [ drop emit-primitive ] if ;
: emit-fixnum-bitnot ( -- ) : emit-fixnum-bitnot ( -- )
ds-pop ^^not tag-mask get ^^xor-imm ds-push ; ds-pop ^^not tag-mask get ^^xor-imm ds-push ;
@ -65,34 +49,11 @@ IN: compiler.cfg.intrinsics.fixnum
: emit-fixnum-log2 ( -- ) : emit-fixnum-log2 ( -- )
ds-pop ^^log2 tag-bits get ^^sub-imm ^^tag-fixnum ds-push ; ds-pop ^^log2 tag-bits get ^^sub-imm ^^tag-fixnum ds-push ;
: (emit-fixnum*fast) ( -- dst ) : emit-fixnum*fast ( -- )
2inputs ^^untag-fixnum ^^mul ; 2inputs ^^untag-fixnum ^^mul ds-push ;
: (emit-fixnum*fast-imm1) ( infos -- dst ) : emit-fixnum-comparison ( cc -- )
[ ds-pop ds-drop ] [ first literal>> ] bi* ^^mul-imm ; '[ _ ^^compare ] emit-fixnum-op ;
: (emit-fixnum*fast-imm2) ( infos -- dst )
[ ds-drop ds-pop ] [ second literal>> ] bi* ^^mul-imm ;
: emit-fixnum*fast ( node -- )
node-input-infos
dup first value-info-small-fixnum? drop f
[
(emit-fixnum*fast-imm1)
] [
dup second value-info-small-fixnum?
[ (emit-fixnum*fast-imm2) ] [ drop (emit-fixnum*fast) ] if
] if
ds-push ;
: (emit-fixnum-comparison) ( cc -- quot1 quot2 )
[ ^^compare ] [ ^^compare-imm ] bi-curry ; inline
: emit-eq ( node -- )
cc= (emit-fixnum-comparison) emit-commutative-fixnum-op ;
: emit-fixnum-comparison ( node cc -- )
(emit-fixnum-comparison) emit-fixnum-op ;
: emit-bignum>fixnum ( -- ) : emit-bignum>fixnum ( -- )
ds-pop ^^bignum>integer ^^tag-fixnum ds-push ; ds-pop ^^bignum>integer ^^tag-fixnum ds-push ;
@ -100,6 +61,28 @@ IN: compiler.cfg.intrinsics.fixnum
: emit-fixnum>bignum ( -- ) : emit-fixnum>bignum ( -- )
ds-pop ^^untag-fixnum ^^integer>bignum ds-push ; ds-pop ^^untag-fixnum ^^integer>bignum ds-push ;
: emit-fixnum-overflow-op ( quot -- next ) : emit-no-overflow-case ( dst -- final-bb )
[ 2inputs 1 ##inc-d ] dip call ##branch [ -2 ##inc-d ds-push ] with-branch ;
begin-basic-block ; inline
: emit-overflow-case ( word -- final-bb )
[ ##call ] with-branch ;
: emit-fixnum-overflow-op ( quot word -- )
[ [ D 1 ^^peek D 0 ^^peek ] dip call ] dip
[ emit-no-overflow-case ] [ emit-overflow-case ] bi* 2array
emit-conditional ; inline
: fixnum+overflow ( x y -- z ) [ >bignum ] bi@ + ;
: fixnum-overflow ( x y -- z ) [ >bignum ] bi@ - ;
: fixnum*overflow ( x y -- z ) [ >bignum ] bi@ * ;
: emit-fixnum+ ( -- )
[ ^^fixnum-add ] \ fixnum+overflow emit-fixnum-overflow-op ;
: emit-fixnum- ( -- )
[ ^^fixnum-sub ] \ fixnum-overflow emit-fixnum-overflow-op ;
: emit-fixnum* ( -- )
[ ^^untag-fixnum ^^fixnum-mul ] \ fixnum*overflow emit-fixnum-overflow-op ;

View File

@ -8,7 +8,8 @@ compiler.cfg.intrinsics.allot
compiler.cfg.intrinsics.fixnum compiler.cfg.intrinsics.fixnum
compiler.cfg.intrinsics.float compiler.cfg.intrinsics.float
compiler.cfg.intrinsics.slots compiler.cfg.intrinsics.slots
compiler.cfg.intrinsics.misc ; compiler.cfg.intrinsics.misc
compiler.cfg.comparisons ;
QUALIFIED: kernel QUALIFIED: kernel
QUALIFIED: arrays QUALIFIED: arrays
QUALIFIED: byte-arrays QUALIFIED: byte-arrays
@ -40,8 +41,8 @@ IN: compiler.cfg.intrinsics
math.private:fixnum<= math.private:fixnum<=
math.private:fixnum>= math.private:fixnum>=
math.private:fixnum> math.private:fixnum>
math.private:bignum>fixnum ! math.private:bignum>fixnum
math.private:fixnum>bignum ! math.private:fixnum>bignum
kernel:eq? kernel:eq?
slots.private:slot slots.private:slot
slots.private:set-slot slots.private:set-slot
@ -99,23 +100,23 @@ IN: compiler.cfg.intrinsics
{ \ kernel.private:tag [ drop emit-tag ] } { \ kernel.private:tag [ drop emit-tag ] }
{ \ kernel.private:getenv [ emit-getenv ] } { \ kernel.private:getenv [ emit-getenv ] }
{ \ math.private:both-fixnums? [ drop emit-both-fixnums? ] } { \ math.private:both-fixnums? [ drop emit-both-fixnums? ] }
{ \ math.private:fixnum+ [ drop [ ##fixnum-add ] emit-fixnum-overflow-op ] } { \ math.private:fixnum+ [ drop emit-fixnum+ ] }
{ \ math.private:fixnum- [ drop [ ##fixnum-sub ] emit-fixnum-overflow-op ] } { \ math.private:fixnum- [ drop emit-fixnum- ] }
{ \ math.private:fixnum* [ drop [ i i ##fixnum-mul ] emit-fixnum-overflow-op ] } { \ math.private:fixnum* [ drop emit-fixnum* ] }
{ \ math.private:fixnum+fast [ [ ^^add ] [ ^^add-imm ] emit-commutative-fixnum-op ] } { \ math.private:fixnum+fast [ drop [ ^^add ] emit-fixnum-op ] }
{ \ math.private:fixnum-fast [ [ ^^sub ] [ ^^sub-imm ] emit-fixnum-op ] } { \ math.private:fixnum-fast [ drop [ ^^sub ] emit-fixnum-op ] }
{ \ math.private:fixnum-bitand [ [ ^^and ] [ ^^and-imm ] emit-commutative-fixnum-op ] } { \ math.private:fixnum-bitand [ drop [ ^^and ] emit-fixnum-op ] }
{ \ math.private:fixnum-bitor [ [ ^^or ] [ ^^or-imm ] emit-commutative-fixnum-op ] } { \ math.private:fixnum-bitor [ drop [ ^^or ] emit-fixnum-op ] }
{ \ math.private:fixnum-bitxor [ [ ^^xor ] [ ^^xor-imm ] emit-commutative-fixnum-op ] } { \ math.private:fixnum-bitxor [ drop [ ^^xor ] emit-fixnum-op ] }
{ \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast ] } { \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast ] }
{ \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot ] } { \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot ] }
{ \ math.integers.private:fixnum-log2 [ drop emit-fixnum-log2 ] } { \ math.integers.private:fixnum-log2 [ drop emit-fixnum-log2 ] }
{ \ math.private:fixnum*fast [ emit-fixnum*fast ] } { \ math.private:fixnum*fast [ drop emit-fixnum*fast ] }
{ \ math.private:fixnum< [ cc< emit-fixnum-comparison ] } { \ math.private:fixnum< [ drop cc< emit-fixnum-comparison ] }
{ \ math.private:fixnum<= [ cc<= emit-fixnum-comparison ] } { \ math.private:fixnum<= [ drop cc<= emit-fixnum-comparison ] }
{ \ math.private:fixnum>= [ cc>= emit-fixnum-comparison ] } { \ math.private:fixnum>= [ drop cc>= emit-fixnum-comparison ] }
{ \ math.private:fixnum> [ cc> emit-fixnum-comparison ] } { \ math.private:fixnum> [ drop cc> emit-fixnum-comparison ] }
{ \ kernel:eq? [ emit-eq ] } { \ kernel:eq? [ drop cc= emit-fixnum-comparison ] }
{ \ math.private:bignum>fixnum [ drop emit-bignum>fixnum ] } { \ math.private:bignum>fixnum [ drop emit-bignum>fixnum ] }
{ \ math.private:fixnum>bignum [ drop emit-fixnum>bignum ] } { \ math.private:fixnum>bignum [ drop emit-fixnum>bignum ] }
{ \ math.private:float+ [ drop [ ^^add-float ] emit-float-op ] } { \ math.private:float+ [ drop [ ^^add-float ] emit-float-op ] }

View File

@ -1,6 +1,6 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel sequences USING: accessors kernel sequences namespaces assocs fry
combinators.short-circuit combinators.short-circuit
compiler.cfg.linear-scan.live-intervals compiler.cfg.linear-scan.live-intervals
compiler.cfg.linear-scan.allocation.state ; compiler.cfg.linear-scan.allocation.state ;
@ -20,9 +20,16 @@ IN: compiler.cfg.linear-scan.allocation.coalescing
[ avoids-inactive-intervals? ] [ avoids-inactive-intervals? ]
} 1&& ; } 1&& ;
: reuse-spill-slot ( old new -- )
[ vreg>> spill-slots get at ] dip '[ _ vreg>> spill-slots get set-at ] when* ;
: reuse-register ( old new -- )
reg>> >>reg drop ;
: (coalesce) ( old new -- )
[ add-active ] [ [ delete-active ] [ add-handled ] bi ] bi* ;
: coalesce ( live-interval -- ) : coalesce ( live-interval -- )
dup copy-from>> active-interval dup copy-from>> active-interval
[ [ add-active ] [ [ delete-active ] [ add-handled ] bi ] bi* ] [ reuse-spill-slot ] [ reuse-register ] [ (coalesce) ] 2tri ;
[ reg>> >>reg drop ]
2bi ;

View File

@ -17,7 +17,7 @@ ERROR: bad-live-ranges interval ;
] [ drop ] if ; ] [ drop ] if ;
: trim-before-ranges ( live-interval -- ) : trim-before-ranges ( live-interval -- )
[ ranges>> ] [ uses>> last ] bi [ ranges>> ] [ uses>> last 1 + ] bi
[ '[ from>> _ <= ] filter-here ] [ '[ from>> _ <= ] filter-here ]
[ swap last (>>to) ] [ swap last (>>to) ]
2bi ; 2bi ;

View File

@ -19,7 +19,7 @@ IN: compiler.cfg.linear-scan.assignment
SYMBOL: pending-intervals SYMBOL: pending-intervals
: add-active ( live-interval -- ) : add-active ( live-interval -- )
pending-intervals get push ; dup end>> pending-intervals get heap-push ;
! Minheap of live intervals which still need a register allocation ! Minheap of live intervals which still need a register allocation
SYMBOL: unhandled-intervals SYMBOL: unhandled-intervals
@ -37,7 +37,7 @@ SYMBOL: register-live-ins
SYMBOL: register-live-outs SYMBOL: register-live-outs
: init-assignment ( live-intervals -- ) : init-assignment ( live-intervals -- )
V{ } clone pending-intervals set <min-heap> pending-intervals set
<min-heap> unhandled-intervals set <min-heap> unhandled-intervals set
H{ } clone register-live-ins set H{ } clone register-live-ins set
H{ } clone register-live-outs set H{ } clone register-live-outs set
@ -61,12 +61,17 @@ SYMBOL: register-live-outs
register->register register->register
] [ drop ] if ; ] [ drop ] if ;
: (expire-old-intervals) ( n heap -- )
dup heap-empty? [ 2drop ] [
2dup heap-peek nip <= [ 2drop ] [
dup heap-pop drop [ handle-spill ] [ handle-copy ] bi
(expire-old-intervals)
] if
] if ;
: expire-old-intervals ( n -- ) : expire-old-intervals ( n -- )
[ [
[ pending-intervals get ] dip '[ pending-intervals get (expire-old-intervals)
dup end>> _ <
[ [ handle-spill ] [ handle-copy ] bi f ] [ drop t ] if
] filter-here
] { } make mapping-instructions % ; ] { } make mapping-instructions % ;
: insert-reload ( live-interval -- ) : insert-reload ( live-interval -- )
@ -111,14 +116,12 @@ ERROR: overlapping-registers intervals ;
dup [ reg>> ] map all-unique? [ drop ] [ overlapping-registers ] if ; dup [ reg>> ] map all-unique? [ drop ] [ overlapping-registers ] if ;
: active-intervals ( n -- intervals ) : active-intervals ( n -- intervals )
pending-intervals get [ covers? ] with filter pending-intervals get heap-values [ covers? ] with filter
check-assignment? get [ dup check-assignment ] when ; check-assignment? get [ dup check-assignment ] when ;
M: vreg-insn assign-registers-in-insn M: vreg-insn assign-registers-in-insn
dup [ all-vregs ] [ insn#>> active-intervals ] bi dup [ all-vregs ] [ insn#>> active-intervals register-mapping ] bi
'[ _ [ vreg>> = ] with find nip ] map extract-keys >>regs drop ;
register-mapping
>>regs drop ;
M: ##gc assign-registers-in-insn M: ##gc assign-registers-in-insn
! This works because ##gc is always the first instruction ! This works because ##gc is always the first instruction
@ -150,7 +153,7 @@ ERROR: bad-live-values live-values ;
: begin-block ( bb -- ) : begin-block ( bb -- )
dup basic-block set dup basic-block set
dup block-from prepare-insn dup block-from activate-new-intervals
[ [ live-in ] [ block-from ] bi compute-live-values ] keep [ [ live-in ] [ block-from ] bi compute-live-values ] keep
register-live-ins get set-at ; register-live-ins get set-at ;

View File

@ -12,6 +12,7 @@ compiler.cfg.predecessors
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.linearization compiler.cfg.linearization
compiler.cfg.debugger compiler.cfg.debugger
compiler.cfg.comparisons
compiler.cfg.linear-scan compiler.cfg.linear-scan
compiler.cfg.linear-scan.numbering compiler.cfg.linear-scan.numbering
compiler.cfg.linear-scan.live-intervals compiler.cfg.linear-scan.live-intervals
@ -82,9 +83,9 @@ check-numbering? on
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
{ start 0 } { start 0 }
{ end 1 } { end 2 }
{ uses V{ 0 1 } } { uses V{ 0 1 } }
{ ranges V{ T{ live-range f 0 1 } } } { ranges V{ T{ live-range f 0 2 } } }
} }
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@ -107,9 +108,9 @@ check-numbering? on
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
{ start 0 } { start 0 }
{ end 0 } { end 1 }
{ uses V{ 0 } } { uses V{ 0 } }
{ ranges V{ T{ live-range f 0 0 } } } { ranges V{ T{ live-range f 0 1 } } }
} }
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@ -132,9 +133,9 @@ check-numbering? on
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
{ start 0 } { start 0 }
{ end 0 } { end 1 }
{ uses V{ 0 } } { uses V{ 0 } }
{ ranges V{ T{ live-range f 0 0 } } } { ranges V{ T{ live-range f 0 1 } } }
} }
T{ live-interval T{ live-interval
{ vreg T{ vreg { reg-class int-regs } { n 1 } } } { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@ -384,7 +385,7 @@ SYMBOL: max-uses
[ [
\ live-interval new \ live-interval new
swap int-regs swap vreg boa >>vreg swap int-regs swap vreg boa >>vreg
max-uses get random 2 max [ not-taken ] replicate natural-sort max-uses get random 2 max [ not-taken 2 * ] replicate natural-sort
[ >>uses ] [ first >>start ] bi [ >>uses ] [ first >>start ] bi
dup uses>> last >>end dup uses>> last >>end
dup [ start>> ] [ end>> ] bi <live-range> 1vector >>ranges dup [ start>> ] [ end>> ] bi <live-range> 1vector >>ranges
@ -1317,38 +1318,6 @@ USING: math.private ;
allocate-registers drop allocate-registers drop
] unit-test ] unit-test
! Spill slot liveness was computed incorrectly, leading to a FEP
! early in bootstrap on x86-32
[ t ] [
[
H{ } clone live-ins set
H{ } clone live-outs set
H{ } clone phi-live-ins set
T{ basic-block
{ id 12345 }
{ instructions
V{
T{ ##gc f V int-regs 6 V int-regs 7 }
T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 1 D 1 }
T{ ##peek f V int-regs 2 D 2 }
T{ ##peek f V int-regs 3 D 3 }
T{ ##peek f V int-regs 4 D 4 }
T{ ##peek f V int-regs 5 D 5 }
T{ ##replace f V int-regs 0 D 1 }
T{ ##replace f V int-regs 1 D 2 }
T{ ##replace f V int-regs 2 D 3 }
T{ ##replace f V int-regs 3 D 4 }
T{ ##replace f V int-regs 4 D 5 }
T{ ##replace f V int-regs 5 D 0 }
}
}
} dup 1array { { int-regs V{ 0 1 2 3 } } } (linear-scan)
instructions>> first
live-values>> assoc-empty?
] with-scope
] unit-test
[ f ] [ [ f ] [
T{ live-range f 0 10 } T{ live-range f 0 10 }
T{ live-range f 20 30 } T{ live-range f 20 30 }
@ -1541,6 +1510,7 @@ SYMBOL: linear-scan-result
compute-liveness compute-liveness
dup reverse-post-order dup reverse-post-order
{ { int-regs regs } } (linear-scan) { { int-regs regs } } (linear-scan)
cfg-changed
flatten-cfg 1array mr. flatten-cfg 1array mr.
] with-scope ; ] with-scope ;
@ -1802,7 +1772,8 @@ test-diamond
2 get instructions>> first regs>> V int-regs 1 swap at assert= 2 get instructions>> first regs>> V int-regs 1 swap at assert=
] unit-test ] unit-test
[ _copy ] [ 3 get instructions>> second class ] unit-test ! Not until splitting is finished
! [ _copy ] [ 3 get instructions>> second class ] unit-test
! Resolve pass; make sure the spilling is done correctly ! Resolve pass; make sure the spilling is done correctly
V{ T{ ##peek f V int-regs 3 R 1 } T{ ##branch } } 0 test-bb V{ T{ ##peek f V int-regs 3 R 1 } T{ ##branch } } 0 test-bb
@ -1834,7 +1805,7 @@ test-diamond
[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
[ _spill ] [ 2 get instructions>> first class ] unit-test [ _spill ] [ 2 get successors>> first instructions>> first class ] unit-test
[ _spill ] [ 3 get instructions>> second class ] unit-test [ _spill ] [ 3 get instructions>> second class ] unit-test
@ -1890,7 +1861,7 @@ V{
[ t ] [ 2 get instructions>> [ _spill? ] any? ] unit-test [ t ] [ 2 get instructions>> [ _spill? ] any? ] unit-test
[ t ] [ 3 get instructions>> [ _spill? ] any? ] unit-test [ t ] [ 3 get predecessors>> first instructions>> [ _spill? ] any? ] unit-test
[ t ] [ 5 get instructions>> [ _reload? ] any? ] unit-test [ t ] [ 5 get instructions>> [ _reload? ] any? ] unit-test
@ -1957,7 +1928,7 @@ V{
[ V{ 3 2 1 } ] [ 9 get instructions>> [ _reload? ] filter [ n>> ] map ] unit-test [ V{ 3 2 1 } ] [ 9 get instructions>> [ _reload? ] filter [ n>> ] map ] unit-test
! Resolve pass should insert this ! Resolve pass should insert this
[ _reload ] [ 5 get instructions>> first class ] unit-test [ _reload ] [ 5 get predecessors>> first instructions>> first class ] unit-test
! Some random bug ! Some random bug
V{ V{
@ -2188,12 +2159,7 @@ V{
T{ ##replace { src V int-regs 85 } { loc D 1 } } T{ ##replace { src V int-regs 85 } { loc D 1 } }
T{ ##replace { src V int-regs 89 } { loc D 4 } } T{ ##replace { src V int-regs 89 } { loc D 4 } }
T{ ##replace { src V int-regs 96 } { loc R 0 } } T{ ##replace { src V int-regs 96 } { loc R 0 } }
T{ ##fixnum-mul T{ ##replace { src V int-regs 129 } { loc R 0 } }
{ src1 V int-regs 128 }
{ src2 V int-regs 129 }
{ temp1 V int-regs 132 }
{ temp2 V int-regs 133 }
}
T{ ##branch } T{ ##branch }
} 2 test-bb } 2 test-bb
@ -2284,202 +2250,159 @@ V{
[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
! Another push-all reduction to demonstrate numbering anamoly ! Fencepost error in assignment pass
V{ T{ ##prologue } T{ ##branch } } V{ T{ ##branch } } 0 test-bb
0 test-bb
V{ V{
T{ ##peek { dst V int-regs 1 } { loc D 0 } } T{ ##peek f V int-regs 0 D 0 }
T{ ##slot-imm T{ ##compare-imm-branch f V int-regs 0 5 cc= }
{ dst V int-regs 5 } } 1 test-bb
{ obj V int-regs 1 }
{ slot 3 } V{ T{ ##branch } } 2 test-bb
{ tag 7 }
}
T{ ##peek { dst V int-regs 7 } { loc D 1 } }
T{ ##slot-imm
{ dst V int-regs 12 }
{ obj V int-regs 7 }
{ slot 1 }
{ tag 6 }
}
T{ ##add
{ dst V int-regs 25 }
{ src1 V int-regs 5 }
{ src2 V int-regs 12 }
}
T{ ##compare-branch
{ src1 V int-regs 25 }
{ src2 V int-regs 5 }
{ cc cc> }
}
}
1 test-bb
V{ V{
T{ ##slot-imm T{ ##peek f V int-regs 1 D 0 }
{ dst V int-regs 41 } T{ ##peek f V int-regs 2 D 0 }
{ obj V int-regs 1 } T{ ##replace f V int-regs 1 D 0 }
{ slot 2 } T{ ##replace f V int-regs 2 D 0 }
{ tag 7 }
}
T{ ##slot-imm
{ dst V int-regs 44 }
{ obj V int-regs 41 }
{ slot 1 }
{ tag 6 }
}
T{ ##compare-branch
{ src1 V int-regs 25 }
{ src2 V int-regs 44 }
{ cc cc> }
}
}
2 test-bb
V{
T{ ##add-imm
{ dst V int-regs 54 }
{ src1 V int-regs 25 }
{ src2 8 }
}
T{ ##load-immediate { dst V int-regs 55 } { val 24 } }
T{ ##inc-d { n 4 } }
T{ ##inc-r { n 1 } }
T{ ##replace { src V int-regs 25 } { loc D 2 } }
T{ ##replace { src V int-regs 1 } { loc D 3 } }
T{ ##replace { src V int-regs 5 } { loc D 4 } }
T{ ##replace { src V int-regs 1 } { loc D 1 } }
T{ ##replace { src V int-regs 54 } { loc D 0 } }
T{ ##replace { src V int-regs 12 } { loc R 0 } }
T{ ##fixnum-mul
{ src1 V int-regs 54 }
{ src2 V int-regs 55 }
{ temp1 V int-regs 58 }
{ temp2 V int-regs 59 }
}
T{ ##branch } T{ ##branch }
} } 3 test-bb
3 test-bb
V{ V{
T{ ##peek { dst V int-regs 60 } { loc D 1 } } T{ ##replace f V int-regs 0 D 0 }
T{ ##slot-imm
{ dst V int-regs 66 }
{ obj V int-regs 60 }
{ slot 2 }
{ tag 7 }
}
T{ ##inc-d { n 1 } }
T{ ##inc-r { n 1 } }
T{ ##replace { src V int-regs 66 } { loc D 0 } }
T{ ##replace { src V int-regs 60 } { loc R 0 } }
T{ ##call { word resize-string } }
T{ ##branch }
}
4 test-bb
V{
T{ ##peek { dst V int-regs 67 } { loc R 0 } }
T{ ##peek { dst V int-regs 68 } { loc D 0 } }
T{ ##set-slot-imm
{ src V int-regs 68 }
{ obj V int-regs 67 }
{ slot 2 }
{ tag 7 }
}
T{ ##write-barrier
{ src V int-regs 67 }
{ card# V int-regs 75 }
{ table V int-regs 76 }
}
T{ ##inc-d { n -1 } }
T{ ##inc-r { n -1 } }
T{ ##peek { dst V int-regs 94 } { loc D 0 } }
T{ ##peek { dst V int-regs 96 } { loc D 1 } }
T{ ##peek { dst V int-regs 98 } { loc D 2 } }
T{ ##peek { dst V int-regs 100 } { loc D 3 } }
T{ ##peek { dst V int-regs 102 } { loc D 4 } }
T{ ##peek { dst V int-regs 106 } { loc R 0 } }
T{ ##copy { dst V int-regs 95 } { src V int-regs 94 } }
T{ ##copy { dst V int-regs 97 } { src V int-regs 96 } }
T{ ##copy { dst V int-regs 99 } { src V int-regs 98 } }
T{ ##copy { dst V int-regs 101 } { src V int-regs 100 } }
T{ ##copy { dst V int-regs 103 } { src V int-regs 102 } }
T{ ##copy { dst V int-regs 107 } { src V int-regs 106 } }
T{ ##branch }
}
5 test-bb
V{
T{ ##inc-d { n 3 } }
T{ ##inc-r { n 1 } }
T{ ##copy { dst V int-regs 95 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 97 } { src V int-regs 25 } }
T{ ##copy { dst V int-regs 99 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 101 } { src V int-regs 5 } }
T{ ##copy { dst V int-regs 103 } { src V int-regs 7 } }
T{ ##copy { dst V int-regs 107 } { src V int-regs 12 } }
T{ ##branch }
}
6 test-bb
V{
T{ ##load-immediate
{ dst V int-regs 78 }
{ val 4611686018427387896 }
}
T{ ##and
{ dst V int-regs 81 }
{ src1 V int-regs 97 }
{ src2 V int-regs 78 }
}
T{ ##set-slot-imm
{ src V int-regs 81 }
{ obj V int-regs 95 }
{ slot 3 }
{ tag 7 }
}
T{ ##inc-d { n -2 } }
T{ ##copy { dst V int-regs 110 } { src V int-regs 99 } }
T{ ##copy { dst V int-regs 111 } { src V int-regs 101 } }
T{ ##copy { dst V int-regs 112 } { src V int-regs 103 } }
T{ ##copy { dst V int-regs 117 } { src V int-regs 107 } }
T{ ##branch }
}
7 test-bb
V{
T{ ##inc-d { n 1 } }
T{ ##inc-r { n 1 } }
T{ ##copy { dst V int-regs 110 } { src V int-regs 1 } }
T{ ##copy { dst V int-regs 111 } { src V int-regs 5 } }
T{ ##copy { dst V int-regs 112 } { src V int-regs 7 } }
T{ ##copy { dst V int-regs 117 } { src V int-regs 12 } }
T{ ##branch }
}
8 test-bb
V{
T{ ##inc-d { n 1 } }
T{ ##inc-r { n -1 } }
T{ ##replace { src V int-regs 117 } { loc D 0 } }
T{ ##replace { src V int-regs 110 } { loc D 1 } }
T{ ##replace { src V int-regs 111 } { loc D 2 } }
T{ ##replace { src V int-regs 112 } { loc D 3 } }
T{ ##epilogue }
T{ ##return } T{ ##return }
} } 4 test-bb
9 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 V int-regs 0 D 0 }
T{ ##compare-imm-branch f V int-regs 0 5 cc= }
} 1 test-bb
V{
T{ ##peek f V int-regs 1 D 0 }
T{ ##peek f V int-regs 2 D 0 }
T{ ##replace f V int-regs 1 D 0 }
T{ ##replace f V int-regs 2 D 0 }
T{ ##replace f V int-regs 0 D 0 }
T{ ##branch }
} 2 test-bb
V{
T{ ##branch }
} 3 test-bb
V{
T{ ##replace f V int-regs 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
! GC check tests
! Spill slot liveness was computed incorrectly, leading to a FEP
! early in bootstrap on x86-32
[ t ] [
[
H{ } clone live-ins set
H{ } clone live-outs set
H{ } clone phi-live-ins set
T{ basic-block
{ id 12345 }
{ instructions
V{
T{ ##gc f V int-regs 6 V int-regs 7 }
T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 1 D 1 }
T{ ##peek f V int-regs 2 D 2 }
T{ ##peek f V int-regs 3 D 3 }
T{ ##peek f V int-regs 4 D 4 }
T{ ##peek f V int-regs 5 D 5 }
T{ ##replace f V int-regs 0 D 1 }
T{ ##replace f V int-regs 1 D 2 }
T{ ##replace f V int-regs 2 D 3 }
T{ ##replace f V int-regs 3 D 4 }
T{ ##replace f V int-regs 4 D 5 }
T{ ##replace f V int-regs 5 D 0 }
}
}
} dup 1array { { int-regs V{ 0 1 2 3 } } } (linear-scan)
instructions>> first
live-values>> assoc-empty?
] with-scope
] unit-test
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 1 D 1 }
T{ ##replace f V int-regs 1 D 1 }
T{ ##branch }
} 0 test-bb
V{
T{ ##gc f V int-regs 2 V int-regs 3 }
T{ ##branch }
} 1 test-bb
V{
T{ ##replace f V int-regs 0 D 0 }
T{ ##return }
} 2 test-bb
0 get 1 get 1vector >>successors drop 0 get 1 get 1vector >>successors drop
1 get 2 get 8 get V{ } 2sequence >>successors drop 1 get 2 get 1vector >>successors drop
2 get 3 get 6 get V{ } 2sequence >>successors drop
3 get 4 get 1vector >>successors drop
4 get 5 get 1vector >>successors drop
5 get 7 get 1vector >>successors drop
6 get 7 get 1vector >>successors drop
7 get 9 get 1vector >>successors drop
8 get 9 get 1vector >>successors drop
[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test [ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
[ H{ { V int-regs 0 3 } } ] [ 1 get instructions>> first live-values>> ] unit-test
V{
T{ ##peek f V int-regs 0 D 0 }
T{ ##peek f V int-regs 1 D 1 }
T{ ##compare-imm-branch f V int-regs 1 5 cc= }
} 0 test-bb
V{
T{ ##gc f V int-regs 2 V int-regs 3 }
T{ ##replace f V int-regs 0 D 0 }
T{ ##return }
} 1 test-bb
V{
T{ ##return }
} 2 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
[ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
[ H{ { V int-regs 0 3 } } ] [ 1 get instructions>> first live-values>> ] unit-test

View File

@ -40,4 +40,5 @@ IN: compiler.cfg.linear-scan
init-mapping init-mapping
dup reverse-post-order machine-registers (linear-scan) dup reverse-post-order machine-registers (linear-scan)
spill-counts get >>spill-counts spill-counts get >>spill-counts
cfg-changed
] with-scope ; ] with-scope ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel assocs accessors sequences math math.order fry USING: namespaces kernel assocs accessors sequences math math.order fry
combinators compiler.cfg.instructions compiler.cfg.registers combinators binary-search compiler.cfg.instructions compiler.cfg.registers
compiler.cfg.def-use compiler.cfg.liveness compiler.cfg ; compiler.cfg.def-use compiler.cfg.liveness compiler.cfg ;
IN: compiler.cfg.linear-scan.live-intervals IN: compiler.cfg.linear-scan.live-intervals
@ -16,16 +16,21 @@ split-before split-after split-next
start end ranges uses start end ranges uses
copy-from ; copy-from ;
: covers? ( insn# live-interval -- ? ) GENERIC: covers? ( insn# obj -- ? )
ranges>> [ [ from>> ] [ to>> ] bi between? ] with any? ;
: child-interval-at ( insn# interval -- interval' ) M: f covers? 2drop f ;
dup split-after>> [
2dup split-after>> start>> <
[ split-before>> ] [ split-after>> ] if
child-interval-at
] [ nip ] if ;
M: live-range covers? [ from>> ] [ to>> ] bi between? ;
M: live-interval covers? ( insn# live-interval -- ? )
ranges>>
dup length 4 <= [
[ covers? ] with any?
] [
[ drop ] [ [ from>> <=> ] with search nip ] 2bi
covers?
] if ;
ERROR: dead-value-error vreg ; ERROR: dead-value-error vreg ;
: shorten-range ( n live-interval -- ) : shorten-range ( n live-interval -- )
@ -122,10 +127,10 @@ M: ##copy-float compute-live-intervals*
dup ranges>> [ first from>> ] [ last to>> ] bi dup ranges>> [ first from>> ] [ last to>> ] bi
[ >>start ] [ >>end ] bi* drop ; [ >>start ] [ >>end ] bi* drop ;
: check-start/end ( live-interval -- ) ERROR: bad-live-interval live-interval ;
[ [ start>> ] [ uses>> first ] bi assert= ]
[ [ end>> ] [ uses>> last ] bi assert= ] : check-start ( live-interval -- )
bi ; dup start>> -1 = [ bad-live-interval ] [ drop ] if ;
: finish-live-intervals ( live-intervals -- ) : finish-live-intervals ( live-intervals -- )
! Since live intervals are computed in a backward order, we have ! Since live intervals are computed in a backward order, we have
@ -135,7 +140,7 @@ M: ##copy-float compute-live-intervals*
[ ranges>> reverse-here ] [ ranges>> reverse-here ]
[ uses>> reverse-here ] [ uses>> reverse-here ]
[ compute-start/end ] [ compute-start/end ]
[ check-start/end ] [ check-start ]
} cleave } cleave
] each ; ] each ;

View File

@ -1,7 +0,0 @@
USING: arrays compiler.cfg.linear-scan.resolve kernel
tools.test ;
IN: compiler.cfg.linear-scan.resolve.tests
[ { 1 2 3 4 5 6 } ] [
{ 3 4 } V{ 1 2 } clone [ { 5 6 } 3append-here ] keep >array
] unit-test

View File

@ -3,6 +3,7 @@
USING: accessors arrays assocs combinators USING: accessors arrays assocs combinators
combinators.short-circuit fry kernel locals combinators.short-circuit fry kernel locals
make math sequences make math sequences
compiler.cfg.utilities
compiler.cfg.instructions compiler.cfg.instructions
compiler.cfg.linear-scan.assignment compiler.cfg.linear-scan.assignment
compiler.cfg.linear-scan.mapping compiler.cfg.liveness ; compiler.cfg.linear-scan.mapping compiler.cfg.liveness ;
@ -30,42 +31,14 @@ IN: compiler.cfg.linear-scan.resolve
[ resolve-value-data-flow ] with with each [ resolve-value-data-flow ] with with each
] { } make ; ] { } make ;
: fork? ( from to -- ? ) : perform-mappings ( bb to mappings -- )
{ dup empty? [ 3drop ] [
[ drop successors>> length 1 >= ] mapping-instructions <simple-block>
[ nip predecessors>> length 1 = ] insert-basic-block
} 2&& ; inline
: insert-position/fork ( from to -- before after )
nip instructions>> [ >array ] [ dup delete-all ] bi swap ;
: join? ( from to -- ? )
{
[ drop successors>> length 1 = ]
[ nip predecessors>> length 1 >= ]
} 2&& ; inline
: insert-position/join ( from to -- before after )
drop instructions>> dup pop 1array ;
: insert-position ( bb to -- before after )
{
{ [ 2dup fork? ] [ insert-position/fork ] }
{ [ 2dup join? ] [ insert-position/join ] }
} cond ;
: 3append-here ( seq2 seq1 seq3 -- )
#! Mutate seq1
swap '[ _ push-all ] bi@ ;
: perform-mappings ( mappings bb to -- )
pick empty? [ 3drop ] [
[ mapping-instructions ] 2dip
insert-position 3append-here
] if ; ] if ;
: resolve-edge-data-flow ( bb to -- ) : resolve-edge-data-flow ( bb to -- )
[ compute-mappings ] [ perform-mappings ] 2bi ; 2dup compute-mappings perform-mappings ;
: resolve-block-data-flow ( bb -- ) : resolve-block-data-flow ( bb -- )
dup successors>> [ resolve-edge-data-flow ] with each ; dup successors>> [ resolve-edge-data-flow ] with each ;

View File

@ -5,6 +5,7 @@ combinators assocs arrays locals cpu.architecture
compiler.cfg compiler.cfg
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.liveness compiler.cfg.liveness
compiler.cfg.comparisons
compiler.cfg.stack-frame compiler.cfg.stack-frame
compiler.cfg.instructions ; compiler.cfg.instructions ;
IN: compiler.cfg.linearization IN: compiler.cfg.linearization
@ -30,8 +31,10 @@ M: insn linearize-insn , drop ;
M: ##branch linearize-insn M: ##branch linearize-insn
drop dup successors>> first emit-branch ; drop dup successors>> first emit-branch ;
: successors ( bb -- first second ) successors>> first2 ; inline
: (binary-conditional) ( basic-block insn -- basic-block successor1 successor2 src1 src2 cc ) : (binary-conditional) ( basic-block insn -- basic-block successor1 successor2 src1 src2 cc )
[ dup successors>> first2 ] [ dup successors ]
[ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline [ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline
: binary-conditional ( basic-block insn -- basic-block successor label2 src1 src2 cc ) : binary-conditional ( basic-block insn -- basic-block successor label2 src1 src2 cc )
@ -51,6 +54,19 @@ M: ##compare-imm-branch linearize-insn
M: ##compare-float-branch linearize-insn M: ##compare-float-branch linearize-insn
[ binary-conditional _compare-float-branch ] with-regs emit-branch ; [ binary-conditional _compare-float-branch ] with-regs emit-branch ;
: overflow-conditional ( basic-block insn -- basic-block successor label2 dst src1 src2 )
[ dup successors number>> ]
[ [ dst>> ] [ src1>> ] [ src2>> ] tri ] bi* ; inline
M: ##fixnum-add linearize-insn
[ overflow-conditional _fixnum-add ] with-regs emit-branch ;
M: ##fixnum-sub linearize-insn
[ overflow-conditional _fixnum-sub ] with-regs emit-branch ;
M: ##fixnum-mul linearize-insn
[ overflow-conditional _fixnum-mul ] with-regs emit-branch ;
M: ##dispatch linearize-insn M: ##dispatch linearize-insn
swap swap
[ [ [ src>> ] [ temp>> ] bi _dispatch ] with-regs ] [ [ [ src>> ] [ temp>> ] bi _dispatch ] with-regs ]

View File

@ -43,9 +43,6 @@ SYMBOL: work-list
[ nip kill-set ] [ nip kill-set ]
2bi assoc-diff ; 2bi assoc-diff ;
: conjoin-at ( value key assoc -- )
[ dupd ?set-at ] change-at ;
: compute-phi-live-in ( basic-block -- phi-live-in ) : compute-phi-live-in ( basic-block -- phi-live-in )
instructions>> [ ##phi? ] filter [ f ] [ instructions>> [ ##phi? ] filter [ f ] [
H{ } clone [ H{ } clone [

View File

@ -1,10 +1,14 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors kernel assocs compiler.cfg.liveness compiler.cfg.rpo ; USING: locals accessors kernel assocs namespaces
compiler.cfg compiler.cfg.liveness compiler.cfg.rpo ;
IN: compiler.cfg.local IN: compiler.cfg.local
: optimize-basic-block ( bb init-quot insn-quot -- ) :: optimize-basic-block ( bb init-quot insn-quot -- )
[ '[ live-in keys @ ] ] [ '[ _ change-instructions drop ] ] bi* bi ; inline bb basic-block set
bb live-in keys init-quot call
bb insn-quot change-instructions drop ; inline
: local-optimization ( cfg init-quot: ( live-in -- ) insn-quot: ( insns -- insns' ) -- cfg' ) :: local-optimization ( cfg init-quot: ( live-in -- ) insn-quot: ( insns -- insns' ) -- cfg' )
[ dup ] 2dip '[ _ _ optimize-basic-block ] each-basic-block ; inline cfg [ init-quot insn-quot optimize-basic-block ] each-basic-block
cfg ; inline

View File

@ -1,8 +1,8 @@
USING: accessors arrays compiler.cfg.checker USING: accessors arrays compiler.cfg.checker
compiler.cfg.debugger compiler.cfg.def-use compiler.cfg.debugger compiler.cfg.def-use
compiler.cfg.instructions fry kernel kernel.private math compiler.cfg.instructions fry kernel kernel.private math
math.private sbufs sequences sequences.private sets math.partial-dispatch math.private sbufs sequences sequences.private sets
slots.private strings tools.test vectors layouts ; slots.private strings strings.private tools.test vectors layouts ;
IN: compiler.cfg.optimizer.tests IN: compiler.cfg.optimizer.tests
! Miscellaneous tests ! Miscellaneous tests
@ -31,6 +31,19 @@ IN: compiler.cfg.optimizer.tests
[ [ 2 fixnum+ ] when 3 ] [ [ 2 fixnum+ ] when 3 ]
[ [ 2 fixnum- ] when 3 ] [ [ 2 fixnum- ] when 3 ]
[ 10000 [ ] times ] [ 10000 [ ] times ]
[
over integer? [
over dup 16 <-integer-fixnum
[ 0 >=-integer-fixnum ] [ drop f ] if [
nip dup
[ ] [ ] if
] [ 2drop f ] if
] [ 2drop f ] if
]
[
pick 10 fixnum>= [ [ 123 fixnum-bitand ] 2dip ] [ ] if
set-string-nth-fast
]
} [ } [
[ [ ] ] dip '[ _ test-mr first check-mr ] unit-test [ [ ] ] dip '[ _ test-mr first check-mr ] unit-test
] each ] each

View File

@ -6,10 +6,10 @@ compiler.cfg.predecessors
compiler.cfg.useless-conditionals compiler.cfg.useless-conditionals
compiler.cfg.stack-analysis compiler.cfg.stack-analysis
compiler.cfg.branch-splitting compiler.cfg.branch-splitting
compiler.cfg.block-joining
compiler.cfg.alias-analysis compiler.cfg.alias-analysis
compiler.cfg.value-numbering compiler.cfg.value-numbering
compiler.cfg.dce compiler.cfg.dce
compiler.cfg.branch-folding
compiler.cfg.write-barrier compiler.cfg.write-barrier
compiler.cfg.liveness compiler.cfg.liveness
compiler.cfg.rpo compiler.cfg.rpo
@ -29,15 +29,15 @@ SYMBOL: check-optimizer?
! The passes that need this document it. ! The passes that need this document it.
[ [
optimize-tail-calls optimize-tail-calls
compute-predecessors
delete-useless-conditionals delete-useless-conditionals
compute-predecessors
split-branches split-branches
join-blocks
compute-predecessors compute-predecessors
stack-analysis stack-analysis
compute-liveness compute-liveness
alias-analysis alias-analysis
value-numbering value-numbering
fold-branches
compute-predecessors compute-predecessors
eliminate-dead-code eliminate-dead-code
eliminate-write-barriers eliminate-write-barriers

View File

@ -1 +1,2 @@
Slava Pestov Slava Pestov
Daniel Ehrenberg

View File

@ -1,7 +1,10 @@
IN: compiler.cfg.phi-elimination.tests ! Copyright (C) 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
USING: compiler.cfg.instructions compiler.cfg compiler.cfg.registers USING: compiler.cfg.instructions compiler.cfg compiler.cfg.registers
compiler.cfg.debugger compiler.cfg.phi-elimination kernel accessors compiler.cfg.comparisons compiler.cfg.debugger locals
sequences classes namespaces tools.test cpu.architecture arrays ; compiler.cfg.phi-elimination kernel accessors sequences classes
namespaces tools.test cpu.architecture arrays ;
IN: compiler.cfg.phi-elimination.tests
V{ T{ ##branch } } 0 test-bb V{ T{ ##branch } } 0 test-bb
@ -33,8 +36,20 @@ V{
test-diamond test-diamond
3 vreg-counter set-global
[ ] [ cfg new 0 get >>entry eliminate-phis drop ] unit-test [ ] [ cfg new 0 get >>entry eliminate-phis drop ] unit-test
[ T{ ##copy f V int-regs 3 V int-regs 1 } ] [ 2 get instructions>> second ] unit-test [ T{ ##copy f V int-regs 4 V int-regs 1 } ] [
[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test 2 get successors>> first instructions>> first
[ 2 ] [ 4 get instructions>> length ] unit-test ] unit-test
[ T{ ##copy f V int-regs 4 V int-regs 2 } ] [
3 get successors>> first instructions>> first
] unit-test
[ T{ ##copy f V int-regs 3 V int-regs 4 } ] [
4 get instructions>> first
] unit-test
[ 3 ] [ 4 get instructions>> length ] unit-test

View File

@ -1,17 +1,26 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs fry kernel sequences USING: accessors assocs fry kernel sequences namespaces
compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ; compiler.cfg compiler.cfg.instructions compiler.cfg.rpo
compiler.cfg.utilities compiler.cfg.hats make
locals ;
IN: compiler.cfg.phi-elimination IN: compiler.cfg.phi-elimination
: insert-copy ( predecessor input output -- ) : insert-copy ( predecessor input output -- )
'[ _ _ swap ##copy ] add-instructions ; '[ _ _ swap ##copy ] add-instructions ;
: eliminate-phi ( ##phi -- ) : eliminate-phi ( ##phi -- ##copy )
[ inputs>> ] [ dst>> ] bi '[ _ insert-copy ] assoc-each ; i
[ [ inputs>> ] dip '[ _ insert-copy ] assoc-each ]
[ [ dst>> ] dip \ ##copy new-insn ]
2bi ;
: eliminate-phi-step ( bb -- ) : eliminate-phi-step ( bb -- )
instructions>> [ dup ##phi? [ eliminate-phi f ] [ drop t ] if ] filter-here ; H{ } clone added-instructions set
[ instructions>> [ dup ##phi? [ eliminate-phi ] when ] change-each ]
[ insert-basic-blocks ]
bi ;
: eliminate-phis ( cfg -- cfg' ) : eliminate-phis ( cfg -- cfg' )
dup [ eliminate-phi-step ] each-basic-block ; dup [ eliminate-phi-step ] each-basic-block
cfg-changed ;

View File

@ -1,11 +1,17 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors namespaces kernel arrays parser ; USING: accessors namespaces kernel arrays parser math math.order ;
IN: compiler.cfg.registers IN: compiler.cfg.registers
! Virtual registers, used by CFG and machine IRs ! Virtual registers, used by CFG and machine IRs
TUPLE: vreg { reg-class read-only } { n read-only } ; TUPLE: vreg { reg-class read-only } { n fixnum read-only } ;
M: vreg equal? over vreg? [ [ n>> ] bi@ eq? ] [ 2drop f ] if ;
M: vreg hashcode* nip n>> ;
SYMBOL: vreg-counter SYMBOL: vreg-counter
: next-vreg ( reg-class -- vreg ) \ vreg-counter counter vreg boa ; : next-vreg ( reg-class -- vreg ) \ vreg-counter counter vreg boa ;
! Stack locations -- 'n' is an index starting from the top of the stack ! Stack locations -- 'n' is an index starting from the top of the stack

View File

@ -0,0 +1,155 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs kernel namespaces sequences
compiler.cfg.instructions compiler.cfg.registers ;
IN: compiler.cfg.renaming
SYMBOL: renamings
: rename-value ( vreg -- vreg' ) renamings get at ;
GENERIC: rename-insn-defs ( insn -- )
M: ##flushable rename-insn-defs
[ rename-value ] change-dst
drop ;
M: ##fixnum-overflow rename-insn-defs
[ rename-value ] change-dst
drop ;
M: _fixnum-overflow rename-insn-defs
[ rename-value ] change-dst
drop ;
M: insn rename-insn-defs drop ;
GENERIC: rename-insn-uses ( insn -- )
M: ##effect rename-insn-uses
[ rename-value ] change-src
drop ;
M: ##unary rename-insn-uses
[ rename-value ] change-src
drop ;
M: ##binary rename-insn-uses
[ rename-value ] change-src1
[ rename-value ] change-src2
drop ;
M: ##binary-imm rename-insn-uses
[ rename-value ] change-src1
drop ;
M: ##slot rename-insn-uses
[ rename-value ] change-obj
[ rename-value ] change-slot
drop ;
M: ##slot-imm rename-insn-uses
[ rename-value ] change-obj
drop ;
M: ##set-slot rename-insn-uses
dup call-next-method
[ rename-value ] change-obj
[ rename-value ] change-slot
drop ;
M: ##string-nth rename-insn-uses
[ rename-value ] change-obj
[ rename-value ] change-index
drop ;
M: ##set-string-nth-fast rename-insn-uses
dup call-next-method
[ rename-value ] change-obj
[ rename-value ] change-index
drop ;
M: ##set-slot-imm rename-insn-uses
dup call-next-method
[ rename-value ] change-obj
drop ;
M: ##alien-getter rename-insn-uses
dup call-next-method
[ rename-value ] change-src
drop ;
M: ##alien-setter rename-insn-uses
dup call-next-method
[ rename-value ] change-value
drop ;
M: ##conditional-branch rename-insn-uses
[ rename-value ] change-src1
[ rename-value ] change-src2
drop ;
M: ##compare-imm-branch rename-insn-uses
[ rename-value ] change-src1
drop ;
M: ##dispatch rename-insn-uses
[ rename-value ] change-src
drop ;
M: ##fixnum-overflow rename-insn-uses
[ rename-value ] change-src1
[ rename-value ] change-src2
drop ;
M: insn rename-insn-uses drop ;
: fresh-vreg ( vreg -- vreg' )
reg-class>> next-vreg ;
GENERIC: fresh-insn-temps ( insn -- )
M: ##write-barrier fresh-insn-temps
[ fresh-vreg ] change-card#
[ fresh-vreg ] change-table
drop ;
M: ##unary/temp fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##allot fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##dispatch fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##slot fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##set-slot fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##string-nth fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##set-string-nth-fast fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##compare fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##compare-imm fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##compare-float fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: ##gc fresh-insn-temps
[ fresh-vreg ] change-temp1
[ fresh-vreg ] change-temp2
drop ;
M: _dispatch fresh-insn-temps
[ fresh-vreg ] change-temp drop ;
M: insn fresh-insn-temps drop ;

View File

@ -0,0 +1,79 @@
USING: accessors compiler.cfg compiler.cfg.debugger
compiler.cfg.dominance compiler.cfg.instructions
compiler.cfg.predecessors compiler.cfg.ssa assocs
compiler.cfg.registers cpu.architecture kernel namespaces sequences
tools.test vectors ;
IN: compiler.cfg.ssa.tests
! Reset counters so that results are deterministic w.r.t. hash order
0 vreg-counter set-global
0 basic-block set-global
V{
T{ ##load-immediate f V int-regs 1 100 }
T{ ##add-imm f V int-regs 2 V int-regs 1 50 }
T{ ##add-imm f V int-regs 2 V int-regs 2 10 }
T{ ##branch }
} 0 test-bb
V{
T{ ##load-immediate f V int-regs 3 3 }
T{ ##branch }
} 1 test-bb
V{
T{ ##load-immediate f V int-regs 3 4 }
T{ ##branch }
} 2 test-bb
V{
T{ ##replace f V int-regs 3 D 0 }
T{ ##return }
} 3 test-bb
0 get 1 get 2 get V{ } 2sequence >>successors drop
1 get 3 get 1vector >>successors drop
2 get 3 get 1vector >>successors drop
: test-ssa ( -- )
cfg new 0 get >>entry
compute-predecessors
compute-dominance
construct-ssa
drop ;
[ ] [ test-ssa ] unit-test
[
V{
T{ ##load-immediate f V int-regs 1 100 }
T{ ##add-imm f V int-regs 2 V int-regs 1 50 }
T{ ##add-imm f V int-regs 3 V int-regs 2 10 }
T{ ##branch }
}
] [ 0 get instructions>> ] unit-test
[
V{
T{ ##load-immediate f V int-regs 4 3 }
T{ ##branch }
}
] [ 1 get instructions>> ] unit-test
[
V{
T{ ##load-immediate f V int-regs 5 4 }
T{ ##branch }
}
] [ 2 get instructions>> ] unit-test
[
V{
T{ ##phi f V int-regs 6 H{ { 1 V int-regs 4 } { 2 V int-regs 5 } } }
T{ ##replace f V int-regs 6 D 0 }
T{ ##return }
}
] [
3 get instructions>>
[ dup ##phi? [ [ [ [ number>> ] dip ] assoc-map ] change-inputs ] when ] map
] unit-test

View File

@ -0,0 +1,146 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces kernel accessors sequences fry dlists
deques assocs sets math combinators sorting
compiler.cfg
compiler.cfg.rpo
compiler.cfg.def-use
compiler.cfg.renaming
compiler.cfg.registers
compiler.cfg.dominance
compiler.cfg.instructions ;
IN: compiler.cfg.ssa
! SSA construction. Predecessors and dominance must be computed first.
! This is the classical algorithm based on dominance frontiers:
! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.25.8240
! Eventually might be worth trying something fancier:
! http://portal.acm.org/citation.cfm?id=1065887.1065890
<PRIVATE
! Maps vreg to sequence of basic blocks
SYMBOL: defs
! Maps basic blocks to sequences of vregs
SYMBOL: inserting-phi-nodes
: compute-defs ( cfg -- )
H{ } clone dup defs set
'[
dup instructions>> [
defs-vregs [
_ push-at
] with each
] with each
] each-basic-block ;
SYMBOLS: has-already ever-on-work-list work-list ;
: init-insert-phi-nodes ( bbs -- )
H{ } clone has-already set
[ unique ever-on-work-list set ]
[ <hashed-dlist> [ push-all-front ] keep work-list set ] bi ;
: add-to-work-list ( bb -- )
dup ever-on-work-list get key? [ drop ] [
[ ever-on-work-list get conjoin ]
[ work-list get push-front ]
bi
] if ;
: insert-phi-node-later ( vreg bb -- )
[ predecessors>> over '[ _ ] H{ } map>assoc \ ##phi new-insn ] keep
inserting-phi-nodes get push-at ;
: compute-phi-node-in ( vreg bb -- )
dup has-already get key? [ 2drop ] [
[ insert-phi-node-later ]
[ has-already get conjoin ]
[ add-to-work-list ]
tri
] if ;
: compute-phi-nodes-for ( vreg bbs -- )
dup length 2 >= [
init-insert-phi-nodes
work-list get [
dom-frontier [
compute-phi-node-in
] with each
] with slurp-deque
] [ 2drop ] if ;
: compute-phi-nodes ( -- )
H{ } clone inserting-phi-nodes set
defs get [ compute-phi-nodes-for ] assoc-each ;
: insert-phi-nodes-in ( phis bb -- )
[ append ] change-instructions drop ;
: insert-phi-nodes ( -- )
inserting-phi-nodes get [ swap insert-phi-nodes-in ] assoc-each ;
SYMBOLS: stacks originals ;
: init-renaming ( -- )
H{ } clone stacks set
H{ } clone originals set ;
: gen-name ( vreg -- vreg' )
[ reg-class>> next-vreg ] keep
[ stacks get push-at ]
[ swap originals get set-at ]
[ drop ]
2tri ;
: top-name ( vreg -- vreg' )
stacks get at last ;
GENERIC: rename-insn ( insn -- )
M: insn rename-insn
[ dup uses-vregs [ dup top-name ] { } map>assoc renamings set rename-insn-uses ]
[ dup defs-vregs [ dup gen-name ] { } map>assoc renamings set rename-insn-defs ]
bi ;
M: ##phi rename-insn
dup defs-vregs [ dup gen-name ] { } map>assoc renamings set rename-insn-defs ;
: rename-insns ( bb -- )
instructions>> [ rename-insn ] each ;
: rename-successor-phi ( phi bb -- )
swap inputs>> [ top-name ] change-at ;
: rename-successor-phis ( succ bb -- )
[ inserting-phi-nodes get at ] dip
'[ _ rename-successor-phi ] each ;
: rename-successors-phis ( bb -- )
[ successors>> ] keep '[ _ rename-successor-phis ] each ;
: pop-stacks ( bb -- )
instructions>> [
defs-vregs originals get stacks get
'[ _ at _ at pop* ] each
] each ;
: rename-in-block ( bb -- )
{
[ rename-insns ]
[ rename-successors-phis ]
[ dom-children [ rename-in-block ] each ]
[ pop-stacks ]
} cleave ;
: rename ( cfg -- )
init-renaming
entry>> rename-in-block ;
PRIVATE>
: construct-ssa ( cfg -- cfg' )
dup [ compute-defs compute-phi-nodes insert-phi-nodes ] [ rename ] bi ;

View File

@ -1,8 +1,8 @@
IN: compiler.cfg.stack-analysis.merge.tests IN: compiler.cfg.stack-analysis.merge.tests
USING: compiler.cfg.stack-analysis.merge tools.test arrays accessors USING: compiler.cfg.stack-analysis.merge tools.test arrays accessors
compiler.cfg.instructions compiler.cfg.stack-analysis.state compiler.cfg.instructions compiler.cfg.stack-analysis.state
compiler.cfg compiler.cfg.registers compiler.cfg.debugger compiler.cfg.utilities compiler.cfg compiler.cfg.registers
cpu.architecture make assocs compiler.cfg.debugger cpu.architecture make assocs namespaces
sequences kernel classes ; sequences kernel classes ;
[ [
@ -11,13 +11,15 @@ sequences kernel classes ;
] [ ] [
<state> <state>
<basic-block> V{ T{ ##branch } } >>instructions <basic-block> V{ T{ ##branch } } >>instructions dup 1 set
<basic-block> V{ T{ ##branch } } >>instructions 2array <basic-block> V{ T{ ##branch } } >>instructions dup 2 set 2array
<state> H{ { D 0 V int-regs 0 } } >>locs>vregs <state> H{ { D 0 V int-regs 0 } } >>locs>vregs
<state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array <state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array
[ merge-locs locs>vregs>> keys ] { } make first inputs>> values H{ } clone added-instructions set
V{ } clone added-phis set
merge-locs locs>vregs>> keys added-phis get values first
] unit-test ] unit-test
[ [
@ -26,15 +28,16 @@ sequences kernel classes ;
] [ ] [
<state> <state>
<basic-block> V{ T{ ##branch } } >>instructions <basic-block> V{ T{ ##branch } } >>instructions dup 1 set
<basic-block> V{ T{ ##branch } } >>instructions 2array <basic-block> V{ T{ ##branch } } >>instructions dup 2 set 2array
[ <state>
<state> <state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array
<state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array
[ merge-locs locs>vregs>> keys ] { } make drop H{ } clone added-instructions set
] keep first instructions>> first class V{ } clone added-phis set
[ merge-locs locs>vregs>> keys ] { } make drop
1 get added-instructions get at first class
] unit-test ] unit-test
[ [
@ -42,15 +45,17 @@ sequences kernel classes ;
] [ ] [
<state> <state>
<basic-block> V{ T{ ##branch } } >>instructions <basic-block> V{ T{ ##branch } } >>instructions dup 1 set
<basic-block> V{ T{ ##branch } } >>instructions 2array <basic-block> V{ T{ ##branch } } >>instructions dup 2 set 2array
[ H{ } clone added-instructions set
<state> -1 >>ds-height V{ } clone added-phis set
<state> 2array
[ merge-ds-heights ds-height>> ] { } make drop <state> -1 >>ds-height
] keep first instructions>> first class <state> 2array
[ merge-ds-heights ds-height>> ] { } make drop
1 get added-instructions get at first class
] unit-test ] unit-test
[ [
@ -63,6 +68,9 @@ sequences kernel classes ;
<basic-block> V{ T{ ##branch } } >>instructions <basic-block> V{ T{ ##branch } } >>instructions
<basic-block> V{ T{ ##branch } } >>instructions 2array <basic-block> V{ T{ ##branch } } >>instructions 2array
H{ } clone added-instructions set
V{ } clone added-phis set
[ [
<state> -1 >>ds-height H{ { D 1 V int-regs 0 } } >>locs>vregs <state> -1 >>ds-height H{ { D 1 V int-regs 0 } } >>locs>vregs
<state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array <state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array
@ -82,6 +90,9 @@ sequences kernel classes ;
<basic-block> V{ T{ ##branch } } >>instructions <basic-block> V{ T{ ##branch } } >>instructions
<basic-block> V{ T{ ##branch } } >>instructions 2array <basic-block> V{ T{ ##branch } } >>instructions 2array
H{ } clone added-instructions set
V{ } clone added-phis set
[ [
<state> -1 >>ds-height H{ { D -1 V int-regs 0 } } >>locs>vregs <state> -1 >>ds-height H{ { D -1 V int-regs 0 } } >>locs>vregs
<state> -1 >>ds-height H{ { D -1 V int-regs 1 } } >>locs>vregs 2array <state> -1 >>ds-height H{ { D -1 V int-regs 1 } } >>locs>vregs 2array

View File

@ -1,12 +1,11 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel assocs sequences accessors fry combinators grouping USING: kernel assocs sequences accessors fry combinators grouping sets
sets locals compiler.cfg compiler.cfg.hats compiler.cfg.instructions arrays vectors locals namespaces make compiler.cfg compiler.cfg.hats
compiler.cfg.stack-analysis.state ; compiler.cfg.instructions compiler.cfg.stack-analysis.state
compiler.cfg.registers compiler.cfg.utilities cpu.architecture ;
IN: compiler.cfg.stack-analysis.merge IN: compiler.cfg.stack-analysis.merge
! XXX critical edges
: initial-state ( bb states -- state ) 2drop <state> ; : initial-state ( bb states -- state ) 2drop <state> ;
: single-predecessor ( bb states -- state ) nip first clone ; : single-predecessor ( bb states -- state ) nip first clone ;
@ -27,14 +26,14 @@ IN: compiler.cfg.stack-analysis.merge
[ nip first >>rs-height ] [ nip first >>rs-height ]
[ [ '[ _ save-rs-height ] add-instructions ] 2each ] if ; [ [ '[ _ save-rs-height ] add-instructions ] 2each ] if ;
: assoc-map-values ( assoc quot -- assoc' ) : assoc-map-keys ( assoc quot -- assoc' )
'[ _ dip ] assoc-map ; inline '[ _ dip ] assoc-map ; inline
: translate-locs ( assoc state -- assoc' ) : translate-locs ( assoc state -- assoc' )
'[ _ translate-loc ] assoc-map-values ; '[ _ translate-loc ] assoc-map-keys ;
: untranslate-locs ( assoc state -- assoc' ) : untranslate-locs ( assoc state -- assoc' )
'[ _ untranslate-loc ] assoc-map-values ; '[ _ untranslate-loc ] assoc-map-keys ;
: collect-locs ( loc-maps states -- assoc ) : collect-locs ( loc-maps states -- assoc )
! assoc maps locs to sequences ! assoc maps locs to sequences
@ -45,12 +44,16 @@ IN: compiler.cfg.stack-analysis.merge
: insert-peek ( predecessor loc state -- vreg ) : insert-peek ( predecessor loc state -- vreg )
'[ _ _ translate-loc ^^peek ] add-instructions ; '[ _ _ translate-loc ^^peek ] add-instructions ;
SYMBOL: added-phis
: add-phi-later ( inputs -- vreg )
[ int-regs next-vreg dup ] dip 2array added-phis get push ;
: merge-loc ( predecessors vregs loc state -- vreg ) : merge-loc ( predecessors vregs loc state -- vreg )
! Insert a ##phi in the current block where the input ! Insert a ##phi in the current block where the input
! is the vreg storing loc from each predecessor block ! is the vreg storing loc from each predecessor block
[ dup ] 3dip
'[ [ ] [ _ _ insert-peek ] ?if ] 2map '[ [ ] [ _ _ insert-peek ] ?if ] 2map
dup all-equal? [ nip first ] [ zip ^^phi ] if ; dup all-equal? [ first ] [ add-phi-later ] if ;
:: merge-locs ( state predecessors states -- state ) :: merge-locs ( state predecessors states -- state )
states [ locs>vregs>> ] map states collect-locs states [ locs>vregs>> ] map states collect-locs
@ -77,30 +80,36 @@ IN: compiler.cfg.stack-analysis.merge
over translate-locs over translate-locs
>>changed-locs ; >>changed-locs ;
ERROR: cannot-merge-poisoned states ; :: insert-phis ( bb -- )
bb predecessors>> :> predecessors
[
added-phis get [| dst inputs |
dst predecessors inputs zip ##phi
] assoc-each
] V{ } make bb instructions>> over push-all
bb (>>instructions) ;
: multiple-predecessors ( bb states -- state ) :: multiple-predecessors ( bb states -- state )
dup [ not ] any? [ states [ not ] any? [
2drop <state> <state>
bb add-to-work-list
] [ ] [
dup [ poisoned?>> ] any? [ [
cannot-merge-poisoned H{ } clone added-instructions set
] [ V{ } clone added-phis set
[ state new ] 2dip bb predecessors>> :> predecessors
[ predecessors>> ] dip state new
{ predecessors states merge-ds-heights
[ merge-ds-heights ] predecessors states merge-rs-heights
[ merge-rs-heights ] predecessors states merge-locs
[ merge-locs ] states merge-actual-locs
[ nip merge-actual-locs ] states merge-changed-locs
[ nip merge-changed-locs ] bb insert-basic-blocks
} 2cleave bb insert-phis
] if ] with-scope
] if ; ] if ;
: merge-states ( bb states -- state ) : merge-states ( bb states -- state )
! If any states are poisoned, save all registers
! to the stack in each branch
dup length { dup length {
{ 0 [ initial-state ] } { 0 [ initial-state ] }
{ 1 [ single-predecessor ] } { 1 [ single-predecessor ] }

View File

@ -91,15 +91,15 @@ IN: compiler.cfg.stack-analysis.tests
! Sync before a back-edge, not after ! Sync before a back-edge, not after
! ##peeks should be inserted before a ##loop-entry ! ##peeks should be inserted before a ##loop-entry
! Don't optimize out the constants ! Don't optimize out the constants
[ 1 t ] [ [ t ] [
[ 1000 [ ] times ] test-stack-analysis eliminate-dead-code linearize [ 1000 [ ] times ] test-stack-analysis eliminate-dead-code linearize
[ [ ##add-imm? ] count ] [ [ ##load-immediate? ] any? ] bi [ ##load-immediate? ] any?
] unit-test ] unit-test
! Correct height tracking ! Correct height tracking
[ t ] [ [ t ] [
[ pick [ <array> ] [ drop ] if swap ] test-stack-analysis eliminate-dead-code [ pick [ <array> ] [ drop ] if swap ] test-stack-analysis eliminate-dead-code
reverse-post-order 3 swap nth reverse-post-order 4 swap nth
instructions>> [ ##peek? ] filter first2 [ loc>> ] [ loc>> ] bi* instructions>> [ ##peek? ] filter first2 [ loc>> ] [ loc>> ] bi*
2array { D 1 D 0 } set= 2array { D 1 D 0 } set=
] unit-test ] unit-test
@ -126,7 +126,7 @@ IN: compiler.cfg.stack-analysis.tests
stack-analysis stack-analysis
drop drop
3 get instructions>> second loc>> 3 get successors>> first instructions>> first loc>>
] unit-test ] unit-test
! Do inserted ##peeks reference the correct stack location if ! Do inserted ##peeks reference the correct stack location if
@ -156,7 +156,7 @@ IN: compiler.cfg.stack-analysis.tests
stack-analysis stack-analysis
drop drop
3 get instructions>> [ ##peek? ] find nip loc>> 3 get successors>> first instructions>> [ ##peek? ] find nip loc>>
] unit-test ] unit-test
! Missing ##replace ! Missing ##replace
@ -170,9 +170,9 @@ IN: compiler.cfg.stack-analysis.tests
! Inserted ##peeks reference the wrong stack location ! Inserted ##peeks reference the wrong stack location
[ t ] [ [ t ] [
[ [ "B" ] 2dip dup [ [ /mod ] dip ] when ] test-stack-analysis [ [ "B" ] 2dip dup [ [ /mod ] dip ] when ] test-stack-analysis
eliminate-dead-code reverse-post-order 3 swap nth eliminate-dead-code reverse-post-order 4 swap nth
instructions>> [ ##peek? ] filter [ loc>> ] map instructions>> [ ##peek? ] filter [ loc>> ] map
{ R 0 D 0 D 1 } set= { D 0 D 1 } set=
] unit-test ] unit-test
[ D 0 ] [ [ D 0 ] [
@ -200,5 +200,5 @@ IN: compiler.cfg.stack-analysis.tests
stack-analysis stack-analysis
drop drop
3 get instructions>> [ ##peek? ] find nip loc>> 3 get successors>> first instructions>> [ ##peek? ] find nip loc>>
] unit-test ] unit-test

View File

@ -1,7 +1,7 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs kernel namespaces math sequences fry grouping USING: accessors assocs kernel namespaces math sequences fry grouping
sets make combinators sets make combinators dlists deques
compiler.cfg compiler.cfg
compiler.cfg.copy-prop compiler.cfg.copy-prop
compiler.cfg.def-use compiler.cfg.def-use
@ -10,9 +10,12 @@ compiler.cfg.registers
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.hats compiler.cfg.hats
compiler.cfg.stack-analysis.state compiler.cfg.stack-analysis.state
compiler.cfg.stack-analysis.merge ; compiler.cfg.stack-analysis.merge
compiler.cfg.utilities ;
IN: compiler.cfg.stack-analysis IN: compiler.cfg.stack-analysis
SYMBOL: global-optimization?
: redundant-replace? ( vreg loc -- ? ) : redundant-replace? ( vreg loc -- ? )
dup state get untranslate-loc n>> 0 < dup state get untranslate-loc n>> 0 <
[ 2drop t ] [ state get actual-locs>vregs>> at = ] if ; [ 2drop t ] [ state get actual-locs>vregs>> at = ] if ;
@ -58,17 +61,16 @@ UNION: sync-if-back-edge
##conditional-branch ##conditional-branch
##compare-imm-branch ##compare-imm-branch
##dispatch ##dispatch
##loop-entry ; ##loop-entry
##fixnum-overflow ;
: back-edge? ( from to -- ? )
[ number>> ] bi@ > ;
: sync-state? ( -- ? ) : sync-state? ( -- ? )
basic-block get successors>> basic-block get successors>>
[ [ predecessors>> ] keep '[ _ back-edge? ] any? ] any? ; [ [ predecessors>> ] keep '[ _ back-edge? ] any? ] any? ;
M: sync-if-back-edge visit M: sync-if-back-edge visit
sync-state? [ sync-state ] when , ; global-optimization? get [ sync-state? [ sync-state ] when ] unless
, ;
: eliminate-peek ( dst src -- ) : eliminate-peek ( dst src -- )
! the requested stack location is already in 'src' ! the requested stack location is already in 'src'
@ -85,42 +87,16 @@ M: ##replace visit
M: ##copy visit M: ##copy visit
[ call-next-method ] [ record-copy ] bi ; [ call-next-method ] [ record-copy ] bi ;
! Instructions that poison the stack state
UNION: poison-insn
##jump
##return
##callback-return
##fixnum-mul-tail
##fixnum-add-tail
##fixnum-sub-tail ;
M: poison-insn visit call-next-method poison-state ; M: poison-insn visit call-next-method poison-state ;
! Instructions that kill all live vregs
UNION: kill-vreg-insn
poison-insn
##stack-frame
##call
##prologue
##epilogue
##fixnum-mul
##fixnum-add
##fixnum-sub
##alien-invoke
##alien-indirect
##alien-callback ;
M: kill-vreg-insn visit sync-state , ; M: kill-vreg-insn visit sync-state , ;
! Maps basic-blocks to states ! Maps basic-blocks to states
SYMBOLS: state-in state-out ; SYMBOL: state-out
: block-in-state ( bb -- states ) : block-in-state ( bb -- states )
dup predecessors>> state-out get '[ _ at ] map merge-states ; dup predecessors>> state-out get '[ _ at ] map merge-states ;
: set-block-in-state ( state bb -- )
[ clone ] dip state-in get set-at ;
: set-block-out-state ( state bb -- ) : set-block-out-state ( state bb -- )
[ clone ] dip state-out get set-at ; [ clone ] dip state-out get set-at ;
@ -130,20 +106,20 @@ SYMBOLS: state-in state-out ;
[ [
dup basic-block set dup basic-block set
dup block-in-state dup block-in-state
[ swap set-block-in-state ] [ state [
state [ [ instructions>> [ visit ] each ]
[ instructions>> [ visit ] each ] [ [ state get ] dip set-block-out-state ]
[ [ state get ] dip set-block-out-state ] [ ]
[ ] tri
tri ] with-variable
] with-variable
] 2bi
] V{ } make >>instructions drop ; ] V{ } make >>instructions drop ;
: stack-analysis ( cfg -- cfg' ) : stack-analysis ( cfg -- cfg' )
[ [
<hashed-dlist> work-list set
H{ } clone copies set H{ } clone copies set
H{ } clone state-in set
H{ } clone state-out set H{ } clone state-out set
dup [ visit-block ] each-basic-block dup [ visit-block ] each-basic-block
global-optimization? get [ work-list get [ visit-block ] slurp-deque ] when
cfg-changed
] with-scope ; ] with-scope ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors namespaces assocs sets math USING: kernel accessors namespaces assocs sets math deques
compiler.cfg.registers ; compiler.cfg.registers ;
IN: compiler.cfg.stack-analysis.state IN: compiler.cfg.stack-analysis.state
@ -47,3 +47,7 @@ M: rs-loc translate-loc [ n>> ] [ rs-height>> ] bi* - <rs-loc> ;
GENERIC# untranslate-loc 1 ( loc state -- loc' ) GENERIC# untranslate-loc 1 ( loc state -- loc' )
M: ds-loc untranslate-loc [ n>> ] [ ds-height>> ] bi* + <ds-loc> ; M: ds-loc untranslate-loc [ n>> ] [ ds-height>> ] bi* + <ds-loc> ;
M: rs-loc untranslate-loc [ n>> ] [ rs-height>> ] bi* + <rs-loc> ; M: rs-loc untranslate-loc [ n>> ] [ rs-height>> ] bi* + <rs-loc> ;
SYMBOL: work-list
: add-to-work-list ( bb -- ) work-list get push-front ;

View File

@ -2,10 +2,12 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators.short-circuit kernel math USING: accessors combinators.short-circuit kernel math
namespaces sequences fry combinators namespaces sequences fry combinators
compiler.utilities
compiler.cfg compiler.cfg
compiler.cfg.rpo compiler.cfg.rpo
compiler.cfg.hats compiler.cfg.hats
compiler.cfg.instructions ; compiler.cfg.instructions
compiler.cfg.utilities ;
IN: compiler.cfg.tco IN: compiler.cfg.tco
! Tail call optimization. You must run compute-predecessors after this ! Tail call optimization. You must run compute-predecessors after this
@ -18,8 +20,6 @@ IN: compiler.cfg.tco
[ second ##return? ] [ second ##return? ]
} 1&& ; } 1&& ;
: penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
: tail-call? ( bb -- ? ) : tail-call? ( bb -- ? )
{ {
[ instructions>> { [ length 2 >= ] [ last ##branch? ] } 1&& ] [ instructions>> { [ length 2 >= ] [ last ##branch? ] } 1&& ]
@ -53,28 +53,11 @@ IN: compiler.cfg.tco
[ [ cfg get entry>> successors>> first ] dip successors>> push ] [ [ cfg get entry>> successors>> first ] dip successors>> push ]
tri ; tri ;
: fixnum-tail-call? ( bb -- ? )
instructions>> penultimate
{ [ ##fixnum-add? ] [ ##fixnum-sub? ] [ ##fixnum-mul? ] } 1|| ;
GENERIC: convert-fixnum-tail-call* ( src1 src2 insn -- insn' )
M: ##fixnum-add convert-fixnum-tail-call* drop \ ##fixnum-add-tail new-insn ;
M: ##fixnum-sub convert-fixnum-tail-call* drop \ ##fixnum-sub-tail new-insn ;
M: ##fixnum-mul convert-fixnum-tail-call* drop i i \ ##fixnum-mul-tail new-insn ;
: convert-fixnum-tail-call ( bb -- )
[
[ src1>> ] [ src2>> ] [ ] tri
convert-fixnum-tail-call*
] convert-tail-call ;
: optimize-tail-call ( bb -- ) : optimize-tail-call ( bb -- )
dup tail-call? [ dup tail-call? [
{ {
{ [ dup loop-tail-call? ] [ convert-loop-tail-call ] } { [ dup loop-tail-call? ] [ convert-loop-tail-call ] }
{ [ dup word-tail-call? ] [ convert-word-tail-call ] } { [ dup word-tail-call? ] [ convert-word-tail-call ] }
{ [ dup fixnum-tail-call? ] [ convert-fixnum-tail-call ] }
[ drop ] [ drop ]
} cond } cond
] [ drop ] if ; ] [ drop ] if ;
@ -82,4 +65,4 @@ M: ##fixnum-mul convert-fixnum-tail-call* drop i i \ ##fixnum-mul-tail new-insn
: optimize-tail-calls ( cfg -- cfg' ) : optimize-tail-calls ( cfg -- cfg' )
dup cfg set dup cfg set
dup [ optimize-tail-call ] each-basic-block dup [ optimize-tail-call ] each-basic-block
f >>post-order ; cfg-changed ;

View File

@ -11,10 +11,6 @@ IN: compiler.cfg.two-operand
! since x86 has LEA and IMUL instructions which are effectively ! since x86 has LEA and IMUL instructions which are effectively
! three-operand addition and multiplication, respectively. ! three-operand addition and multiplication, respectively.
: make-copy ( dst src -- insn ) \ ##copy new-insn ; inline
: make-copy/float ( dst src -- insn ) \ ##copy-float new-insn ; inline
: convert-two-operand/integer ( insn -- ) : convert-two-operand/integer ( insn -- )
[ [ dst>> ] [ src1>> ] bi ##copy ] [ [ dst>> ] [ src1>> ] bi ##copy ]
[ dup dst>> >>src1 , ] [ dup dst>> >>src1 , ]
@ -40,10 +36,15 @@ M: ##or convert-two-operand* convert-two-operand/integer ;
M: ##or-imm convert-two-operand* convert-two-operand/integer ; M: ##or-imm convert-two-operand* convert-two-operand/integer ;
M: ##xor convert-two-operand* convert-two-operand/integer ; M: ##xor convert-two-operand* convert-two-operand/integer ;
M: ##xor-imm convert-two-operand* convert-two-operand/integer ; M: ##xor-imm convert-two-operand* convert-two-operand/integer ;
M: ##shl convert-two-operand* convert-two-operand/integer ;
M: ##shl-imm convert-two-operand* convert-two-operand/integer ; M: ##shl-imm convert-two-operand* convert-two-operand/integer ;
M: ##shr convert-two-operand* convert-two-operand/integer ;
M: ##shr-imm convert-two-operand* convert-two-operand/integer ; M: ##shr-imm convert-two-operand* convert-two-operand/integer ;
M: ##sar convert-two-operand* convert-two-operand/integer ;
M: ##sar-imm convert-two-operand* convert-two-operand/integer ; M: ##sar-imm convert-two-operand* convert-two-operand/integer ;
M: ##fixnum-overflow convert-two-operand* convert-two-operand/integer ;
M: ##add-float convert-two-operand* convert-two-operand/float ; M: ##add-float convert-two-operand* convert-two-operand/float ;
M: ##sub-float convert-two-operand* convert-two-operand/float ; M: ##sub-float convert-two-operand* convert-two-operand/float ;
M: ##mul-float convert-two-operand* convert-two-operand/float ; M: ##mul-float convert-two-operand* convert-two-operand/float ;

View File

@ -1,7 +1,8 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors sequences math combinators combinators.short-circuit USING: kernel accessors sequences math combinators combinators.short-circuit
classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ; classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo
compiler.cfg.utilities ;
IN: compiler.cfg.useless-conditionals IN: compiler.cfg.useless-conditionals
: delete-conditional? ( bb -- ? ) : delete-conditional? ( bb -- ? )
@ -18,4 +19,4 @@ IN: compiler.cfg.useless-conditionals
dup [ dup [
dup delete-conditional? [ delete-conditional ] [ drop ] if dup delete-conditional? [ delete-conditional ] [ drop ] if
] each-basic-block ] each-basic-block
f >>post-order ; cfg-changed ;

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel math layouts make sequences combinators USING: accessors assocs combinators combinators.short-circuit
cpu.architecture namespaces compiler.cfg compiler.cfg compiler.cfg.instructions cpu.architecture kernel
compiler.cfg.instructions ; layouts locals make math namespaces sequences sets vectors fry ;
IN: compiler.cfg.utilities IN: compiler.cfg.utilities
: value-info-small-fixnum? ( value-info -- ? ) : value-info-small-fixnum? ( value-info -- ? )
@ -33,7 +33,65 @@ IN: compiler.cfg.utilities
building off building off
basic-block off ; basic-block off ;
: stop-iterating ( -- next ) end-basic-block f ;
: emit-primitive ( node -- ) : emit-primitive ( node -- )
word>> ##call ##branch begin-basic-block ; word>> ##call ##branch begin-basic-block ;
: with-branch ( quot -- final-bb )
[
begin-basic-block
call
basic-block get dup [ ##branch ] when
] with-scope ; inline
: emit-conditional ( branches -- )
end-basic-block
begin-basic-block
basic-block get '[ [ _ swap successors>> push ] when* ] each ;
: back-edge? ( from to -- ? )
[ number>> ] bi@ >= ;
: empty-block? ( bb -- ? )
instructions>> {
[ length 1 = ]
[ first ##branch? ]
} 1&& ;
SYMBOL: visited
: (skip-empty-blocks) ( bb -- bb' )
dup visited get key? [
dup empty-block? [
dup visited get conjoin
successors>> first (skip-empty-blocks)
] when
] unless ;
: skip-empty-blocks ( bb -- bb' )
H{ } clone visited [ (skip-empty-blocks) ] with-variable ;
! assoc mapping predecessors to sequences
SYMBOL: added-instructions
: add-instructions ( predecessor quot -- )
[
added-instructions get
[ drop V{ } clone ] cache
building
] dip with-variable ; inline
:: insert-basic-block ( from to bb -- )
bb from 1vector >>predecessors drop
bb to 1vector >>successors drop
to predecessors>> [ dup from eq? [ drop bb ] when ] change-each
from successors>> [ dup to eq? [ drop bb ] when ] change-each ;
: <simple-block> ( insns -- bb )
<basic-block>
swap >vector
\ ##branch new-insn over push
>>instructions ;
: insert-basic-blocks ( bb -- )
[ added-instructions get ] dip
'[ [ _ ] dip <simple-block> insert-basic-block ] assoc-each ;

View File

@ -1,7 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors classes kernel math namespaces combinators USING: accessors classes kernel math namespaces combinators
compiler.cfg.instructions compiler.cfg.value-numbering.graph ; combinators.short-circuit compiler.cfg.instructions
compiler.cfg.value-numbering.graph ;
IN: compiler.cfg.value-numbering.expressions IN: compiler.cfg.value-numbering.expressions
! Referentially-transparent expressions ! Referentially-transparent expressions
@ -11,15 +12,29 @@ TUPLE: binary-expr < expr in1 in2 ;
TUPLE: commutative-expr < binary-expr ; TUPLE: commutative-expr < binary-expr ;
TUPLE: compare-expr < binary-expr cc ; TUPLE: compare-expr < binary-expr cc ;
TUPLE: constant-expr < expr value ; TUPLE: constant-expr < expr value ;
TUPLE: reference-expr < expr value ;
: <constant> ( constant -- expr ) : <constant> ( constant -- expr )
f swap constant-expr boa ; inline f swap constant-expr boa ; inline
M: constant-expr equal? M: constant-expr equal?
over constant-expr? [ over constant-expr? [
[ [ value>> ] bi@ = ] {
[ [ value>> class ] bi@ = ] 2bi [ [ value>> class ] bi@ = ]
and [ [ value>> ] bi@ = ]
} 2&&
] [ 2drop f ] if ;
: <reference> ( constant -- expr )
f swap reference-expr boa ; inline
M: reference-expr equal?
over reference-expr? [
[ value>> ] bi@ {
{ [ 2dup eq? ] [ 2drop t ] }
{ [ 2dup [ float? ] both? ] [ fp-bitwise= ] }
[ 2drop f ]
} cond
] [ 2drop f ] if ; ] [ 2drop f ] if ;
! Expressions whose values are inputs to the basic block. We ! Expressions whose values are inputs to the basic block. We
@ -39,6 +54,8 @@ GENERIC: >expr ( insn -- expr )
M: ##load-immediate >expr val>> <constant> ; M: ##load-immediate >expr val>> <constant> ;
M: ##load-reference >expr obj>> <reference> ;
M: ##unary >expr M: ##unary >expr
[ class ] [ src>> vreg>vn ] bi unary-expr boa ; [ class ] [ src>> vreg>vn ] bi unary-expr boa ;

View File

@ -1,69 +0,0 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs sequences kernel accessors
compiler.cfg.instructions compiler.cfg.value-numbering.graph ;
IN: compiler.cfg.value-numbering.propagate
! If two vregs compute the same value, replace references to
! the latter with the former.
: resolve ( vreg -- vreg' ) vreg>vn vn>vreg ; inline
GENERIC: propagate ( insn -- insn )
M: ##effect propagate
[ resolve ] change-src ;
M: ##unary propagate
[ resolve ] change-src ;
M: ##binary propagate
[ resolve ] change-src1
[ resolve ] change-src2 ;
M: ##binary-imm propagate
[ resolve ] change-src1 ;
M: ##slot propagate
[ resolve ] change-obj
[ resolve ] change-slot ;
M: ##slot-imm propagate
[ resolve ] change-obj ;
M: ##set-slot propagate
call-next-method
[ resolve ] change-obj
[ resolve ] change-slot ;
M: ##string-nth propagate
[ resolve ] change-obj
[ resolve ] change-index ;
M: ##set-slot-imm propagate
call-next-method
[ resolve ] change-obj ;
M: ##alien-getter propagate
call-next-method
[ resolve ] change-src ;
M: ##alien-setter propagate
call-next-method
[ resolve ] change-value ;
M: ##conditional-branch propagate
[ resolve ] change-src1
[ resolve ] change-src2 ;
M: ##compare-imm-branch propagate
[ resolve ] change-src1 ;
M: ##dispatch propagate
[ resolve ] change-src ;
M: ##fixnum-overflow propagate
[ resolve ] change-src1
[ resolve ] change-src2 ;
M: insn propagate ;

View File

@ -1 +0,0 @@
Propagation pass to update code after value numbering

View File

@ -1,16 +1,32 @@
! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman. ! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors locals combinators combinators.short-circuit arrays USING: accessors combinators combinators.short-circuit arrays
fry kernel layouts math namespaces sequences cpu.architecture fry kernel layouts math namespaces sequences cpu.architecture
math.bitwise compiler.cfg.hats compiler.cfg.instructions math.bitwise math.order classes vectors
compiler.cfg
compiler.cfg.hats
compiler.cfg.comparisons
compiler.cfg.instructions
compiler.cfg.value-numbering.expressions compiler.cfg.value-numbering.expressions
compiler.cfg.value-numbering.graph compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.simplify ; compiler.cfg.value-numbering.simplify ;
IN: compiler.cfg.value-numbering.rewrite IN: compiler.cfg.value-numbering.rewrite
GENERIC: rewrite ( insn -- insn' ) : vreg-small-constant? ( vreg -- ? )
vreg>expr {
[ constant-expr? ]
[ value>> small-enough? ]
} 1&& ;
M: insn rewrite ; ! Outputs f to mean no change
GENERIC: rewrite* ( insn -- insn/f )
: rewrite ( insn -- insn' )
dup [ number-values ] [ rewrite* ] bi
[ rewrite ] [ ] ?if ;
M: insn rewrite* drop f ;
: ##branch-t? ( insn -- ? ) : ##branch-t? ( insn -- ? )
dup ##compare-imm-branch? [ dup ##compare-imm-branch? [
@ -49,13 +65,16 @@ M: insn rewrite ;
[ src2>> tag-mask get bitand 0 = ] [ src2>> tag-mask get bitand 0 = ]
} 1&& ; inline } 1&& ; inline
: tagged>constant ( n -- n' )
tag-bits get neg shift ; inline
: (rewrite-tagged-comparison) ( insn -- src1 src2 cc ) : (rewrite-tagged-comparison) ( insn -- src1 src2 cc )
[ src1>> vreg>expr in1>> vn>vreg ] [ src1>> vreg>expr in1>> vn>vreg ]
[ src2>> tag-bits get neg shift ] [ src2>> tagged>constant ]
[ cc>> ] [ cc>> ]
tri ; inline tri ; inline
GENERIC: rewrite-tagged-comparison ( insn -- insn' ) GENERIC: rewrite-tagged-comparison ( insn -- insn/f )
M: ##compare-imm-branch rewrite-tagged-comparison M: ##compare-imm-branch rewrite-tagged-comparison
(rewrite-tagged-comparison) \ ##compare-imm-branch new-insn ; (rewrite-tagged-comparison) \ ##compare-imm-branch new-insn ;
@ -64,41 +83,6 @@ M: ##compare-imm rewrite-tagged-comparison
[ dst>> ] [ (rewrite-tagged-comparison) ] bi [ dst>> ] [ (rewrite-tagged-comparison) ] bi
i \ ##compare-imm new-insn ; i \ ##compare-imm new-insn ;
M: ##compare-imm-branch rewrite
dup rewrite-boolean-comparison? [ rewrite-boolean-comparison ] when
dup ##compare-imm-branch? [
dup rewrite-tagged-comparison? [ rewrite-tagged-comparison ] when
] when ;
:: >compare-imm ( insn swap? -- insn' )
insn dst>>
insn src1>>
insn src2>> swap? [ swap ] when vreg>constant
insn cc>> swap? [ swap-cc ] when
i \ ##compare-imm new-insn ; inline
! M: ##compare rewrite
! dup [ src1>> ] [ src2>> ] bi
! [ vreg>expr constant-expr? ] bi@ 2array {
! { { f t } [ f >compare-imm ] }
! { { t f } [ t >compare-imm ] }
! [ drop ]
! } case ;
:: >compare-imm-branch ( insn swap? -- insn' )
insn src1>>
insn src2>> swap? [ swap ] when vreg>constant
insn cc>> swap? [ swap-cc ] when
\ ##compare-imm-branch new-insn ; inline
! M: ##compare-branch rewrite
! dup [ src1>> ] [ src2>> ] bi
! [ vreg>expr constant-expr? ] bi@ 2array {
! { { f t } [ f >compare-imm-branch ] }
! { { t f } [ t >compare-imm-branch ] }
! [ drop ]
! } case ;
: rewrite-redundant-comparison? ( insn -- ? ) : rewrite-redundant-comparison? ( insn -- ? )
{ {
[ src1>> vreg>expr compare-expr? ] [ src1>> vreg>expr compare-expr? ]
@ -114,101 +98,259 @@ M: ##compare-imm-branch rewrite
} case } case
swap cc= eq? [ [ negate-cc ] change-cc ] when ; swap cc= eq? [ [ negate-cc ] change-cc ] when ;
M: ##compare-imm rewrite ERROR: bad-comparison ;
dup rewrite-redundant-comparison? [
rewrite-redundant-comparison
dup number-values rewrite
] when
dup ##compare-imm? [
dup rewrite-tagged-comparison? [
rewrite-tagged-comparison
dup number-values rewrite
] when
] when ;
: constant-fold ( insn -- insn' ) : (fold-compare-imm) ( insn -- ? )
dup dst>> vreg>expr dup constant-expr? [ [ [ src1>> vreg>constant ] [ src2>> ] bi ] [ cc>> ] bi
[ dst>> ] [ value>> ] bi* \ ##load-immediate new-insn pick integer?
dup number-values [ [ <=> ] dip evaluate-cc ]
] [ [
drop 2nip {
{ cc= [ f ] }
{ cc/= [ t ] }
[ bad-comparison ]
} case
] if ; ] if ;
: (new-imm-insn) ( insn dst src1 n op -- new-insn/insn ) : fold-compare-imm? ( insn -- ? )
[ cell-bits bits ] dip over small-enough? [ src1>> vreg>expr [ constant-expr? ] [ reference-expr? ] bi or ;
new-insn dup number-values nip
] [
2drop 2drop
] if constant-fold ; inline
: new-imm-insn ( insn dst src n op -- n' op' ) : fold-branch ( ? -- insn )
2dup [ sgn ] dip 2array 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*
{ {
{ { -1 ##add-imm } [ drop neg \ ##sub-imm (new-imm-insn) ] } { [ dup rewrite-boolean-comparison? ] [ rewrite-boolean-comparison ] }
{ { -1 ##sub-imm } [ drop neg \ ##add-imm (new-imm-insn) ] } { [ dup rewrite-tagged-comparison? ] [ rewrite-tagged-comparison ] }
[ drop (new-imm-insn) ] { [ dup fold-compare-imm? ] [ fold-compare-imm-branch ] }
} case ; inline [ drop f ]
} cond ;
: combine-imm? ( insn op -- ? ) : swap-compare ( src1 src2 cc swap? -- src1 src2 cc )
[ src1>> vreg>expr op>> ] dip = ; [ [ swap ] dip swap-cc ] when ; inline
: (combine-imm) ( insn quot op -- insn ) : >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>= } memq? ;
: rewrite-self-compare-branch ( insn -- insn' )
(rewrite-self-compare) fold-branch ;
M: ##compare-branch rewrite*
{
{ [ dup src1>> vreg-small-constant? ] [ t >compare-imm-branch ] }
{ [ dup src2>> vreg-small-constant? ] [ 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
i \ ##compare-imm new-insn ; inline
: >boolean-insn ( insn ? -- insn' )
[ dst>> ] dip
{
{ t [ t \ ##load-reference new-insn ] }
{ f [ \ f tag-number \ ##load-immediate new-insn ] }
} case ;
: rewrite-self-compare ( insn -- insn' )
dup (rewrite-self-compare) >boolean-insn ;
M: ##compare rewrite*
{
{ [ dup src1>> vreg-small-constant? ] [ t >compare-imm ] }
{ [ dup src2>> vreg-small-constant? ] [ 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 ] [ src2>> ] [ ] tri constant-fold* ] bi
\ ##load-immediate new-insn ; inline
: reassociate? ( insn -- ? )
[ src1>> vreg>expr op>> ] [ class ] bi = ; inline
: reassociate ( insn op -- insn )
[ [
{ {
[ ]
[ dst>> ] [ dst>> ]
[ src1>> vreg>expr [ in1>> vn>vreg ] [ in2>> vn>constant ] bi ] [ src1>> vreg>expr [ in1>> vn>vreg ] [ in2>> vn>constant ] bi ]
[ src2>> ] [ src2>> ]
} cleave [ ]
] [ call ] [ ] tri* new-imm-insn ; inline } cleave constant-fold*
] dip
over small-enough? [ new-insn ] [ 2drop 2drop f ] if ; inline
:: combine-imm ( insn quot op -- insn ) M: ##add-imm rewrite*
insn op combine-imm? [
insn quot op (combine-imm)
] [
insn
] if ; inline
M: ##add-imm rewrite
{ {
{ [ dup \ ##add-imm combine-imm? ] [ [ + ] \ ##add-imm (combine-imm) ] } { [ dup constant-fold? ] [ constant-fold ] }
{ [ dup \ ##sub-imm combine-imm? ] [ [ - ] \ ##sub-imm (combine-imm) ] } { [ dup reassociate? ] [ \ ##add-imm reassociate ] }
[ ] [ drop f ]
} cond ; } cond ;
M: ##sub-imm rewrite : sub-imm>add-imm ( insn -- insn' )
[ dst>> ] [ src1>> ] [ src2>> neg ] tri dup small-enough?
[ \ ##add-imm new-insn ] [ 3drop f ] if ;
M: ##sub-imm rewrite*
{ {
{ [ dup \ ##add-imm combine-imm? ] [ [ - ] \ ##add-imm (combine-imm) ] } { [ dup constant-fold? ] [ constant-fold ] }
{ [ dup \ ##sub-imm combine-imm? ] [ [ + ] \ ##sub-imm (combine-imm) ] } [ sub-imm>add-imm ]
[ ]
} cond ; } cond ;
M: ##mul-imm rewrite : strength-reduce-mul ( insn -- insn' )
dup src2>> dup power-of-2? [ [ [ dst>> ] [ src1>> ] bi ] [ src2>> log2 ] bi \ ##shl-imm new-insn ;
[ [ dst>> ] [ src1>> ] bi ] [ log2 ] bi* \ ##shl-imm new-insn
dup number-values
] [
drop [ * ] \ ##mul-imm combine-imm
] if ;
M: ##and-imm rewrite [ bitand ] \ ##and-imm combine-imm ; : strength-reduce-mul? ( insn -- ? )
src2>> power-of-2? ;
M: ##or-imm rewrite [ bitor ] \ ##or-imm combine-imm ; M: ##mul-imm rewrite*
{
{ [ dup constant-fold? ] [ constant-fold ] }
{ [ dup strength-reduce-mul? ] [ strength-reduce-mul ] }
{ [ dup reassociate? ] [ \ ##mul-imm reassociate ] }
[ drop f ]
} cond ;
M: ##xor-imm rewrite [ bitxor ] \ ##xor-imm combine-imm ; M: ##and-imm rewrite*
{
{ [ dup constant-fold? ] [ constant-fold ] }
{ [ dup reassociate? ] [ \ ##and-imm reassociate ] }
[ drop f ]
} cond ;
: rewrite-add? ( insn -- ? ) M: ##or-imm rewrite*
src2>> { {
[ vreg>expr constant-expr? ] { [ dup constant-fold? ] [ constant-fold ] }
[ vreg>constant small-enough? ] { [ dup reassociate? ] [ \ ##or-imm reassociate ] }
} 1&& ; [ drop f ]
} cond ;
M: ##add rewrite M: ##xor-imm rewrite*
dup rewrite-add? [ {
[ dst>> ] { [ dup constant-fold? ] [ constant-fold ] }
[ src1>> ] { [ dup reassociate? ] [ \ ##xor-imm reassociate ] }
[ src2>> vreg>constant ] tri \ ##add-imm new-insn [ drop f ]
dup number-values } cond ;
] when ;
M: ##sub rewrite constant-fold ; M: ##shl-imm rewrite*
{
{ [ dup constant-fold? ] [ constant-fold ] }
[ drop f ]
} cond ;
M: ##shr-imm rewrite*
{
{ [ dup constant-fold? ] [ constant-fold ] }
[ drop f ]
} cond ;
M: ##sar-imm rewrite*
{
{ [ dup constant-fold? ] [ constant-fold ] }
[ drop f ]
} cond ;
: insn>imm-insn ( insn op swap? -- )
swap [
[ [ dst>> ] [ src1>> ] [ src2>> ] tri ] dip
[ swap ] when vreg>constant
] dip new-insn ; inline
: rewrite-arithmetic ( insn op -- ? )
{
{ [ over src2>> vreg-small-constant? ] [ f insn>imm-insn ] }
[ 2drop f ]
} cond ; inline
: rewrite-arithmetic-commutative ( insn op -- ? )
{
{ [ over src2>> vreg-small-constant? ] [ f insn>imm-insn ] }
{ [ over src1>> vreg-small-constant? ] [ 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 ;
M: ##sub rewrite*
{
{ [ 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 ;

View File

@ -32,6 +32,8 @@ M: unary-expr simplify*
: expr-zero? ( expr -- ? ) T{ constant-expr f f 0 } = ; inline : expr-zero? ( expr -- ? ) T{ constant-expr f f 0 } = ; inline
: expr-one? ( expr -- ? ) T{ constant-expr f f 1 } = ; inline
: >binary-expr< ( expr -- in1 in2 ) : >binary-expr< ( expr -- in1 in2 )
[ in1>> vn>expr ] [ in2>> vn>expr ] bi ; inline [ in1>> vn>expr ] [ in2>> vn>expr ] bi ; inline
@ -44,18 +46,54 @@ M: unary-expr simplify*
: simplify-sub ( expr -- vn/expr/f ) : simplify-sub ( expr -- vn/expr/f )
>binary-expr< { >binary-expr< {
{ [ 2dup eq? ] [ 2drop T{ constant-expr f f 0 } ] }
{ [ dup expr-zero? ] [ drop ] } { [ dup expr-zero? ] [ drop ] }
[ 2drop f ] [ 2drop f ]
} cond ; inline } cond ; inline
: useless-shift? ( in1 in2 -- ? ) : simplify-mul ( expr -- vn/expr/f )
>binary-expr< {
{ [ over expr-one? ] [ drop ] }
{ [ dup expr-one? ] [ drop ] }
[ 2drop f ]
} cond ; inline
: simplify-and ( expr -- vn/expr/f )
>binary-expr< {
{ [ 2dup eq? ] [ drop ] }
[ 2drop f ]
} cond ; inline
: simplify-or ( expr -- vn/expr/f )
>binary-expr< {
{ [ 2dup eq? ] [ drop ] }
{ [ over expr-zero? ] [ nip ] }
{ [ dup expr-zero? ] [ drop ] }
[ 2drop f ]
} cond ; inline
: simplify-xor ( expr -- vn/expr/f )
>binary-expr< {
{ [ over expr-zero? ] [ nip ] }
{ [ dup expr-zero? ] [ drop ] }
[ 2drop f ]
} cond ; inline
: useless-shr? ( in1 in2 -- ? )
over op>> \ ##shl-imm eq? over op>> \ ##shl-imm eq?
[ [ in2>> ] [ expr>vn ] bi* = ] [ 2drop f ] if ; inline [ [ in2>> ] [ expr>vn ] bi* = ] [ 2drop f ] if ; inline
: simplify-shift ( expr -- vn/expr/f ) : simplify-shr ( expr -- vn/expr/f )
>binary-expr< >binary-expr< {
2dup useless-shift? [ drop in1>> ] [ 2drop f ] if ; inline { [ 2dup useless-shr? ] [ drop in1>> ] }
{ [ dup expr-zero? ] [ drop ] }
[ 2drop f ]
} cond ; inline
: simplify-shl ( expr -- vn/expr/f )
>binary-expr< {
{ [ dup expr-zero? ] [ drop ] }
[ 2drop f ]
} cond ; inline
M: binary-expr simplify* M: binary-expr simplify*
dup op>> { dup op>> {
@ -63,8 +101,20 @@ M: binary-expr simplify*
{ \ ##add-imm [ simplify-add ] } { \ ##add-imm [ simplify-add ] }
{ \ ##sub [ simplify-sub ] } { \ ##sub [ simplify-sub ] }
{ \ ##sub-imm [ simplify-sub ] } { \ ##sub-imm [ simplify-sub ] }
{ \ ##shr-imm [ simplify-shift ] } { \ ##mul [ simplify-mul ] }
{ \ ##sar-imm [ simplify-shift ] } { \ ##mul-imm [ simplify-mul ] }
{ \ ##and [ simplify-and ] }
{ \ ##and-imm [ simplify-and ] }
{ \ ##or [ simplify-or ] }
{ \ ##or-imm [ simplify-or ] }
{ \ ##xor [ simplify-xor ] }
{ \ ##xor-imm [ simplify-xor ] }
{ \ ##shr [ simplify-shr ] }
{ \ ##shr-imm [ simplify-shr ] }
{ \ ##sar [ simplify-shr ] }
{ \ ##sar-imm [ simplify-shr ] }
{ \ ##shl [ simplify-shl ] }
{ \ ##shl-imm [ simplify-shl ] }
[ 2drop f ] [ 2drop f ]
} case ; } case ;

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,19 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs biassocs classes kernel math accessors USING: namespaces assocs biassocs classes kernel math accessors
sorting sets sequences sorting sets sequences fry
compiler.cfg
compiler.cfg.local compiler.cfg.local
compiler.cfg.liveness compiler.cfg.liveness
compiler.cfg.renaming
compiler.cfg.value-numbering.graph compiler.cfg.value-numbering.graph
compiler.cfg.value-numbering.expressions compiler.cfg.value-numbering.expressions
compiler.cfg.value-numbering.propagate
compiler.cfg.value-numbering.simplify compiler.cfg.value-numbering.simplify
compiler.cfg.value-numbering.rewrite ; compiler.cfg.value-numbering.rewrite ;
IN: compiler.cfg.value-numbering IN: compiler.cfg.value-numbering
! Local value numbering. Predecessors must be recomputed after this
: number-input-values ( live-in -- ) : number-input-values ( live-in -- )
[ [ f next-input-expr simplify ] dip set-vn ] each ; [ [ f next-input-expr simplify ] dip set-vn ] each ;
@ -19,8 +22,18 @@ IN: compiler.cfg.value-numbering
init-expressions init-expressions
number-input-values ; number-input-values ;
: vreg>vreg-mapping ( -- assoc )
vregs>vns get [ keys ] keep
'[ dup _ [ at ] [ value-at ] bi ] H{ } map>assoc ;
: rename-uses ( insns -- )
vreg>vreg-mapping renamings [
[ rename-insn-uses ] each
] with-variable ;
: value-numbering-step ( insns -- insns' ) : value-numbering-step ( insns -- insns' )
[ [ number-values ] [ rewrite propagate ] bi ] map ; [ rewrite ] map dup rename-uses ;
: value-numbering ( cfg -- cfg' ) : value-numbering ( cfg -- cfg' )
[ init-value-numbering ] [ value-numbering-step ] local-optimization ; [ init-value-numbering ] [ value-numbering-step ] local-optimization
cfg-changed ;

View File

@ -165,24 +165,21 @@ M: ##or generate-insn dst/src1/src2 %or ;
M: ##or-imm generate-insn dst/src1/src2 %or-imm ; M: ##or-imm generate-insn dst/src1/src2 %or-imm ;
M: ##xor generate-insn dst/src1/src2 %xor ; M: ##xor generate-insn dst/src1/src2 %xor ;
M: ##xor-imm generate-insn dst/src1/src2 %xor-imm ; M: ##xor-imm generate-insn dst/src1/src2 %xor-imm ;
M: ##shl generate-insn dst/src1/src2 %shl ;
M: ##shl-imm generate-insn dst/src1/src2 %shl-imm ; M: ##shl-imm generate-insn dst/src1/src2 %shl-imm ;
M: ##shr generate-insn dst/src1/src2 %shr ;
M: ##shr-imm generate-insn dst/src1/src2 %shr-imm ; M: ##shr-imm generate-insn dst/src1/src2 %shr-imm ;
M: ##sar generate-insn dst/src1/src2 %sar ;
M: ##sar-imm generate-insn dst/src1/src2 %sar-imm ; M: ##sar-imm generate-insn dst/src1/src2 %sar-imm ;
M: ##not generate-insn dst/src %not ; M: ##not generate-insn dst/src %not ;
M: ##log2 generate-insn dst/src %log2 ; M: ##log2 generate-insn dst/src %log2 ;
: src1/src2 ( insn -- src1 src2 ) : label/dst/src1/src2 ( insn -- label dst src1 src2 )
[ src1>> register ] [ src2>> register ] bi ; inline [ label>> lookup-label ] [ dst/src1/src2 ] bi ; inline
: src1/src2/temp1/temp2 ( insn -- src1 src2 temp1 temp2 ) M: _fixnum-add generate-insn label/dst/src1/src2 %fixnum-add ;
[ src1/src2 ] [ temp1>> register ] [ temp2>> register ] tri ; inline M: _fixnum-sub generate-insn label/dst/src1/src2 %fixnum-sub ;
M: _fixnum-mul generate-insn label/dst/src1/src2 %fixnum-mul ;
M: ##fixnum-add generate-insn src1/src2 %fixnum-add ;
M: ##fixnum-add-tail generate-insn src1/src2 %fixnum-add-tail ;
M: ##fixnum-sub generate-insn src1/src2 %fixnum-sub ;
M: ##fixnum-sub-tail generate-insn src1/src2 %fixnum-sub-tail ;
M: ##fixnum-mul generate-insn src1/src2/temp1/temp2 %fixnum-mul ;
M: ##fixnum-mul-tail generate-insn src1/src2/temp1/temp2 %fixnum-mul-tail ;
: dst/src/temp ( insn -- dst src temp ) : dst/src/temp ( insn -- dst src temp )
[ dst/src ] [ temp>> register ] bi ; inline [ dst/src ] [ temp>> register ] bi ; inline

View File

@ -314,4 +314,11 @@ M: cucumber equal? "The cucumber has no equal" throw ;
! Regression from Doug's value numbering changes ! Regression from Doug's value numbering changes
[ t ] [ 2 [ 1 swap fixnum< ] compile-call ] unit-test [ t ] [ 2 [ 1 swap fixnum< ] compile-call ] unit-test
[ 3 ] [ 2 [ 1 swap fixnum< [ 3 ] [ 4 ] if ] compile-call ] unit-test [ 3 ] [ 2 [ 1 swap fixnum< [ 3 ] [ 4 ] if ] compile-call ] unit-test
cell 4 = [
[ 0 ] [ 101 [ dup fixnum-fast 1 fixnum+fast 20 fixnum-shift-fast 20 fixnum-shift-fast ] compile-call ] unit-test
] when
! Regression from Slava's value numbering changes
[ 1 ] [ 31337 [ dup fixnum<= [ 1 ] [ 2 ] if ] compile-call ] unit-test

View File

@ -213,12 +213,25 @@ IN: compiler.tests.intrinsics
[ -1 ] [ [ -123 -64 fixnum-shift ] compile-call ] unit-test [ -1 ] [ [ -123 -64 fixnum-shift ] compile-call ] unit-test
[ -1 ] [ -123 -64 [ fixnum-shift ] compile-call ] unit-test [ -1 ] [ -123 -64 [ fixnum-shift ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: 1000000 HEX: 10 [ fixnum* ] compile-call ] unit-test [ 4294967296 ] [ 1 32 [ fixnum-shift ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: -10000000 >fixnum [ 0 swap fixnum- ] compile-call ] unit-test [ 4294967296 ] [ 1 [ 32 fixnum-shift ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: -fffffff >fixnum [ 1 swap fixnum- ] compile-call ] unit-test [ 4294967296 ] [ 1 [ 16 fixnum-shift 16 fixnum-shift ] compile-call ] unit-test
[ -4294967296 ] [ -1 32 [ fixnum-shift ] compile-call ] unit-test
[ -4294967296 ] [ -1 [ 32 fixnum-shift ] compile-call ] unit-test
[ -4294967296 ] [ -1 [ 16 fixnum-shift 16 fixnum-shift ] compile-call ] unit-test
[ t ] [ 1 27 fixnum-shift dup [ fixnum+ ] compile-call 1 28 fixnum-shift = ] unit-test [ 8 ] [ 1 3 [ fixnum-shift-fast ] compile-call ] unit-test
[ -268435457 ] [ 1 28 shift neg >fixnum [ -1 fixnum+ ] compile-call ] unit-test [ 8 ] [ 1 3 [ 15 bitand fixnum-shift-fast ] compile-call ] unit-test
[ 8 ] [ 1 [ 3 fixnum-shift-fast ] compile-call ] unit-test
[ 8 ] [ [ 1 3 fixnum-shift-fast ] compile-call ] unit-test
[ -8 ] [ -1 3 [ fixnum-shift-fast ] compile-call ] unit-test
[ -8 ] [ -1 3 [ 15 bitand fixnum-shift-fast ] compile-call ] unit-test
[ -8 ] [ -1 [ 3 fixnum-shift-fast ] compile-call ] unit-test
[ -8 ] [ [ -1 3 fixnum-shift-fast ] compile-call ] unit-test
[ 2 ] [ 8 -2 [ fixnum-shift-fast ] compile-call ] unit-test
[ 2 ] [ 8 2 [ 15 bitand neg fixnum-shift-fast ] compile-call ] unit-test
[ 2 ] [ 8 [ -2 fixnum-shift-fast ] compile-call ] unit-test
[ 4294967296 ] [ 1 32 [ fixnum-shift ] compile-call ] unit-test [ 4294967296 ] [ 1 32 [ fixnum-shift ] compile-call ] unit-test
[ 4294967296 ] [ 1 [ 32 fixnum-shift ] compile-call ] unit-test [ 4294967296 ] [ 1 [ 32 fixnum-shift ] compile-call ] unit-test
@ -227,6 +240,13 @@ IN: compiler.tests.intrinsics
[ -4294967296 ] [ -1 [ 32 fixnum-shift ] compile-call ] unit-test [ -4294967296 ] [ -1 [ 32 fixnum-shift ] compile-call ] unit-test
[ -4294967296 ] [ -1 [ 16 fixnum-shift 16 fixnum-shift ] compile-call ] unit-test [ -4294967296 ] [ -1 [ 16 fixnum-shift 16 fixnum-shift ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: 1000000 HEX: 10 [ fixnum* ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: -10000000 >fixnum [ 0 swap fixnum- ] compile-call ] unit-test
[ HEX: 10000000 ] [ HEX: -fffffff >fixnum [ 1 swap fixnum- ] compile-call ] unit-test
[ t ] [ 1 27 fixnum-shift dup [ fixnum+ ] compile-call 1 28 fixnum-shift = ] unit-test
[ -268435457 ] [ 1 28 shift neg >fixnum [ -1 fixnum+ ] compile-call ] unit-test
[ t ] [ 1 20 shift 1 20 shift [ fixnum* ] compile-call 1 40 shift = ] unit-test [ t ] [ 1 20 shift 1 20 shift [ fixnum* ] compile-call 1 40 shift = ] unit-test
[ t ] [ 1 20 shift neg 1 20 shift [ fixnum* ] compile-call 1 40 shift neg = ] unit-test [ t ] [ 1 20 shift neg 1 20 shift [ fixnum* ] compile-call 1 40 shift neg = ] unit-test
[ t ] [ 1 20 shift neg 1 20 shift neg [ fixnum* ] compile-call 1 40 shift = ] unit-test [ t ] [ 1 20 shift neg 1 20 shift neg [ fixnum* ] compile-call 1 40 shift = ] unit-test

View File

@ -242,6 +242,11 @@ M: float detect-float ;
{ fixnum-shift-fast } inlined? { fixnum-shift-fast } inlined?
] unit-test ] unit-test
[ t ] [
[ 1 swap 7 bitand shift ]
{ shift fixnum-shift } inlined?
] unit-test
cell-bits 32 = [ cell-bits 32 = [
[ t ] [ [ t ] [
[ { fixnum fixnum } declare 1 swap 31 bitand shift ] [ { fixnum fixnum } declare 1 swap 31 bitand shift ]

View File

@ -1,4 +1,4 @@
! Copyright (C) 2006, 2008 Slava Pestov. ! Copyright (C) 2006, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel assocs match fry accessors namespaces make effects USING: kernel assocs match fry accessors namespaces make effects
sequences sequences.private quotations generic macros arrays sequences sequences.private quotations generic macros arrays
@ -15,7 +15,9 @@ compiler.tree.def-use
compiler.tree.builder compiler.tree.builder
compiler.tree.optimizer compiler.tree.optimizer
compiler.tree.combinators compiler.tree.combinators
compiler.tree.checker ; compiler.tree.checker
compiler.tree.dead-code
compiler.tree.modular-arithmetic ;
FROM: fry => _ ; FROM: fry => _ ;
RENAME: _ match => __ RENAME: _ match => __
IN: compiler.tree.debugger IN: compiler.tree.debugger
@ -201,8 +203,15 @@ SYMBOL: node-count
: cleaned-up-tree ( quot -- nodes ) : cleaned-up-tree ( quot -- nodes )
[ [
check-optimizer? on build-tree
build-tree optimize-tree analyze-recursive
normalize
propagate
cleanup
compute-def-use
remove-dead-code
compute-def-use
optimize-modular-arithmetic
] with-scope ; ] with-scope ;
: inlined? ( quot seq/word -- ? ) : inlined? ( quot seq/word -- ? )

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors sequences words memoize combinators USING: kernel accessors sequences words memoize combinators
classes classes.builtin classes.tuple math.partial-dispatch classes classes.builtin classes.tuple math.partial-dispatch
fry assocs fry assocs combinators.short-circuit
compiler.tree compiler.tree
compiler.tree.combinators compiler.tree.combinators
compiler.tree.propagation.info compiler.tree.propagation.info
@ -29,10 +29,12 @@ GENERIC: finalize* ( node -- nodes )
M: #copy finalize* drop f ; M: #copy finalize* drop f ;
M: #shuffle finalize* M: #shuffle finalize*
dup dup {
[ [ in-d>> ] [ out-d>> ] [ mapping>> ] tri '[ _ at ] map sequence= ] [ [ in-d>> length ] [ out-d>> length ] bi = ]
[ [ in-r>> ] [ out-r>> ] [ mapping>> ] tri '[ _ at ] map sequence= ] [ [ in-r>> length ] [ out-r>> length ] bi = ]
bi and [ drop f ] when ; [ [ in-d>> ] [ out-d>> ] [ mapping>> ] tri '[ _ at = ] 2all? ]
[ [ in-r>> ] [ out-r>> ] [ mapping>> ] tri '[ _ at = ] 2all? ]
} 1&& [ drop f ] when ;
MEMO: cached-expansion ( word -- nodes ) MEMO: cached-expansion ( word -- nodes )
def>> splice-final ; def>> splice-final ;
@ -46,6 +48,9 @@ M: predicate finalize-word
[ drop ] [ drop ]
} cond ; } cond ;
M: math-partial finalize-word
dup primitive? [ drop ] [ nip cached-expansion ] if ;
M: word finalize-word drop ; M: word finalize-word drop ;
M: #call finalize* M: #call finalize*

View File

@ -0,0 +1,2 @@
Slava Pestov
Daniel Ehrenberg

View File

@ -1,12 +1,15 @@
! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.modular-arithmetic.tests IN: compiler.tree.modular-arithmetic.tests
USING: kernel kernel.private tools.test math math.partial-dispatch USING: kernel kernel.private tools.test math math.partial-dispatch
math.private accessors slots.private sequences strings sbufs math.private accessors slots.private sequences strings sbufs
compiler.tree.builder compiler.tree.builder
compiler.tree.optimizer compiler.tree.normalization
compiler.tree.debugger ; compiler.tree.debugger
alien.accessors layouts combinators byte-arrays ;
: test-modular-arithmetic ( quot -- quot' ) : test-modular-arithmetic ( quot -- quot' )
build-tree optimize-tree nodes>quot ; cleaned-up-tree nodes>quot ;
[ [ >R >fixnum R> >fixnum fixnum+fast ] ] [ [ >R >fixnum R> >fixnum fixnum+fast ] ]
[ [ { integer integer } declare + >fixnum ] test-modular-arithmetic ] unit-test [ [ { integer integer } declare + >fixnum ] test-modular-arithmetic ] unit-test
@ -135,4 +138,36 @@ TUPLE: declared-fixnum { x fixnum } ;
] unit-test ] unit-test
[ [ >fixnum 255 fixnum-bitand ] ] [ [ >fixnum 255 fixnum-bitand ] ]
[ [ >integer 256 rem ] test-modular-arithmetic ] unit-test [ [ >integer 256 rem ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-unsigned-1 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-unsigned-1 ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-unsigned-2 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-unsigned-2 ] test-modular-arithmetic ] unit-test
cell {
{ 4 [ [ [ "COMPLEX SHUFFLE" fixnum+ "COMPLEX SHUFFLE" set-alien-unsigned-4 ] ] ] }
{ 8 [ [ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-unsigned-4 ] ] ] }
} case
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-unsigned-4 ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+ "COMPLEX SHUFFLE" set-alien-unsigned-8 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-unsigned-8 ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-signed-1 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-signed-1 ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-signed-2 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-signed-2 ] test-modular-arithmetic ] unit-test
cell {
{ 4 [ [ [ "COMPLEX SHUFFLE" fixnum+ "COMPLEX SHUFFLE" set-alien-signed-4 ] ] ] }
{ 8 [ [ [ "COMPLEX SHUFFLE" fixnum+fast "COMPLEX SHUFFLE" set-alien-signed-4 ] ] ] }
} case
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-signed-4 ] test-modular-arithmetic ] unit-test
[ [ "COMPLEX SHUFFLE" fixnum+ "COMPLEX SHUFFLE" set-alien-signed-8 ] ]
[ [ [ { fixnum fixnum } declare + ] 2dip set-alien-signed-8 ] test-modular-arithmetic ] unit-test
[ t ] [ [ { fixnum byte-array } declare [ + ] with map ] { + fixnum+ >fixnum } inlined? ] unit-test

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: math math.partial-dispatch namespaces sequences sets USING: math math.partial-dispatch namespaces sequences sets
accessors assocs words kernel memoize fry combinators accessors assocs words kernel memoize fry combinators
combinators.short-circuit combinators.short-circuit layouts alien.accessors
compiler.tree compiler.tree
compiler.tree.combinators compiler.tree.combinators
compiler.tree.def-use compiler.tree.def-use
@ -28,6 +28,16 @@ IN: compiler.tree.modular-arithmetic
{ bitand bitor bitxor bitnot } { bitand bitor bitxor bitnot }
[ t "modular-arithmetic" set-word-prop ] each [ t "modular-arithmetic" set-word-prop ] each
{
>fixnum
set-alien-unsigned-1 set-alien-signed-1
set-alien-unsigned-2 set-alien-signed-2
}
cell 8 = [
{ set-alien-unsigned-4 set-alien-signed-4 } append
] when
[ t "low-order" set-word-prop ] each
SYMBOL: modularize-values SYMBOL: modularize-values
: modular-value? ( value -- ? ) : modular-value? ( value -- ? )
@ -54,7 +64,7 @@ M: node maybe-modularize* 2drop ;
GENERIC: compute-modularized-values* ( node -- ) GENERIC: compute-modularized-values* ( node -- )
M: #call compute-modularized-values* M: #call compute-modularized-values*
dup word>> \ >fixnum eq? dup word>> "low-order" word-prop
[ in-d>> first maybe-modularize ] [ drop ] if ; [ in-d>> first maybe-modularize ] [ drop ] if ;
M: node compute-modularized-values* drop ; M: node compute-modularized-values* drop ;

View File

@ -0,0 +1,2 @@
Slava Pestov
Daniel Ehrenberg

View File

@ -0,0 +1,51 @@
! Copyright (C) 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
USING: compiler.tree.propagation.call-effect tools.test fry math effects kernel
compiler.tree.builder compiler.tree.optimizer compiler.tree.debugger sequences ;
IN: compiler.tree.propagation.call-effect.tests
[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
[ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
[ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
[ t ] [ [ + ] cached-effect (( a b -- c )) effect= ] unit-test
[ t ] [ 5 [ + ] curry cached-effect (( a -- c )) effect= ] unit-test
[ t ] [ 5 [ ] curry cached-effect (( -- c )) effect= ] unit-test
[ t ] [ [ dup ] [ drop ] compose cached-effect (( a -- b )) effect= ] unit-test
[ t ] [ [ drop ] [ dup ] compose cached-effect (( a b -- c d )) effect= ] unit-test
[ t ] [ [ 2drop ] [ dup ] compose cached-effect (( a b c -- d e )) effect= ] unit-test
[ t ] [ [ 1 2 3 ] [ 2drop ] compose cached-effect (( -- a )) effect= ] unit-test
[ t ] [ [ 1 2 ] [ 3drop ] compose cached-effect (( a -- )) effect= ] unit-test
: optimized-quot ( quot -- quot' )
build-tree optimize-tree nodes>quot ;
: compiled-call2 ( a quot: ( a -- b ) -- b )
call( a -- b ) ;
: compiled-execute2 ( a b word: ( a b -- c ) -- c )
execute( a b -- c ) ;
[ [ 3 ] ] [ [ 1 2 \ + execute( a b -- c ) ] optimized-quot ] unit-test
[ [ 3 ] ] [ [ 1 2 [ + ] call( a b -- c ) ] optimized-quot ] unit-test
[ [ 3 ] ] [ [ 1 2 '[ _ + ] call( a -- b ) ] optimized-quot ] unit-test
[ [ 3 ] ] [ [ 1 2 '[ _ ] [ + ] compose call( a -- b ) ] optimized-quot ] unit-test
[ 1 2 { [ + ] } first compiled-call2 ] must-fail
[ 3 ] [ 1 2 { + } first compiled-execute2 ] unit-test
[ 3 ] [ 1 2 '[ _ + ] compiled-call2 ] unit-test
[ 3 ] [ 1 2 '[ _ ] [ + ] compose compiled-call2 ] unit-test
[ 3 ] [ 1 2 \ + compiled-execute2 ] unit-test
[ 3 ] [ 1 2 { [ + ] } first call( a b -- c ) ] unit-test
[ 3 ] [ 1 2 { + } first execute( a b -- c ) ] unit-test
[ 3 ] [ 1 2 '[ _ + ] call( a -- b ) ] unit-test
[ 3 ] [ 1 2 '[ _ ] [ + ] compose call( a -- b ) ] unit-test
[ t ] [ [ 2 '[ _ ] [ + ] compose ] final-info first infer-value (( object -- object )) effect= ] unit-test
[ t ] [ [ 2 '[ _ ] 1 '[ _ + ] compose ] final-info first infer-value (( -- object )) effect= ] unit-test
[ t ] [ [ 2 '[ _ + ] ] final-info first infer-value (( object -- object )) effect= ] unit-test
[ f ] [ [ [ [ ] [ 1 ] if ] ] final-info first infer-value ] unit-test
[ f ] [ [ [ 1 ] '[ @ ] ] final-info first infer-value ] unit-test
[ f ] [ [ dup drop ] final-info first infer-value ] unit-test

View File

@ -1,9 +1,10 @@
! Copyright (C) 2009 Slava Pestov. ! Copyright (C) 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators combinators.private effects fry USING: accessors combinators combinators.private effects fry
kernel kernel.private make sequences continuations quotations kernel kernel.private make sequences continuations quotations
stack-checker stack-checker.transforms words math ; words math stack-checker stack-checker.transforms
IN: stack-checker.call-effect compiler.tree.propagation.info slots.private ;
IN: compiler.tree.propagation.call-effect
! call( and execute( have complex expansions. ! call( and execute( have complex expansions.
@ -84,18 +85,14 @@ M: quotation cached-effect
[ drop call-effect-slow ] [ drop call-effect-slow ]
if ; inline if ; inline
\ call-effect [ : call-effect-ic ( quot effect inline-cache -- )
inline-cache new '[ 3dup nip cache-hit?
_ [ drop call-effect-unsafe ]
3dup nip cache-hit? [ [ call-effect-fast ]
drop call-effect-unsafe if ; inline
] [
call-effect-fast
] if
]
] 0 define-transform
\ call-effect t "no-compile" set-word-prop : call-effect>quot ( effect -- quot )
inline-cache new '[ drop _ _ call-effect-ic ] ;
: execute-effect-slow ( word effect -- ) : execute-effect-slow ( word effect -- )
[ '[ _ execute ] ] dip call-effect-slow ; inline [ '[ _ execute ] ] dip call-effect-slow ; inline
@ -116,8 +113,72 @@ M: quotation cached-effect
if ; inline if ; inline
: execute-effect>quot ( effect -- quot ) : execute-effect>quot ( effect -- quot )
inline-cache new '[ _ _ execute-effect-ic ] ; inline-cache new '[ drop _ _ execute-effect-ic ] ;
\ execute-effect [ execute-effect>quot ] 1 define-transform : last2 ( seq -- penultimate ultimate )
2 tail* first2 ;
\ execute-effect t "no-compile" set-word-prop : top-two ( #call -- effect value )
in-d>> last2 [ value-info ] bi@
literal>> swap ;
ERROR: uninferable ;
: remove-effect-input ( effect -- effect' )
(( -- object )) swap compose-effects ;
: (infer-value) ( value-info -- effect )
dup class>> {
{ \ quotation [
literal>> [ uninferable ] unless* cached-effect
dup +unknown+ = [ uninferable ] when
] }
{ \ curry [
slots>> third (infer-value)
remove-effect-input
] }
{ \ compose [
slots>> last2 [ (infer-value) ] bi@
compose-effects
] }
[ uninferable ]
} case ;
: infer-value ( value-info -- effect/f )
[ (infer-value) ]
[ dup uninferable? [ 2drop f ] [ rethrow ] if ]
recover ;
: (value>quot) ( value-info -- quot )
dup class>> {
{ \ quotation [ literal>> '[ drop @ ] ] }
{ \ curry [
slots>> third (value>quot)
'[ [ obj>> ] [ quot>> @ ] bi ]
] }
{ \ compose [
slots>> last2 [ (value>quot) ] bi@
'[ [ first>> @ ] [ second>> @ ] bi ]
] }
} case ;
: value>quot ( value-info -- quot: ( code effect -- ) )
(value>quot) '[ drop @ ] ;
: call-inlining ( #call -- quot/f )
top-two dup infer-value [
pick effect<=
[ nip value>quot ]
[ drop call-effect>quot ] if
] [ drop call-effect>quot ] if* ;
\ call-effect [ call-inlining ] "custom-inlining" set-word-prop
: execute-inlining ( #call -- quot/f )
top-two >literal< [
2dup swap execute-effect-unsafe?
[ nip '[ 2drop _ execute ] ]
[ drop execute-effect>quot ] if
] [ drop execute-effect>quot ] if ;
\ execute-effect [ execute-inlining ] "custom-inlining" set-word-prop

View File

@ -6,14 +6,16 @@ math.parser math.order layouts words sequences sequences.private
arrays assocs classes classes.algebra combinators generic.math arrays assocs classes classes.algebra combinators generic.math
splitting fry locals classes.tuple alien.accessors splitting fry locals classes.tuple alien.accessors
classes.tuple.private slots.private definitions strings.private classes.tuple.private slots.private definitions strings.private
vectors hashtables generic vectors hashtables generic quotations
stack-checker.state stack-checker.state
compiler.tree.comparisons compiler.tree.comparisons
compiler.tree.propagation.info compiler.tree.propagation.info
compiler.tree.propagation.nodes compiler.tree.propagation.nodes
compiler.tree.propagation.slots compiler.tree.propagation.slots
compiler.tree.propagation.simple compiler.tree.propagation.simple
compiler.tree.propagation.constraints ; compiler.tree.propagation.constraints
compiler.tree.propagation.call-effect
compiler.tree.propagation.transforms ;
IN: compiler.tree.propagation.known-words IN: compiler.tree.propagation.known-words
\ fixnum \ fixnum
@ -226,39 +228,6 @@ generic-comparison-ops [
] "outputs" set-word-prop ] "outputs" set-word-prop
] assoc-each ] assoc-each
: rem-custom-inlining ( #call -- quot/f )
second value-info literal>> dup integer?
[ power-of-2? [ 1- bitand ] f ? ] [ drop f ] if ;
{
mod-integer-integer
mod-integer-fixnum
mod-fixnum-integer
fixnum-mod
} [
[
in-d>> dup first value-info interval>> [0,inf] interval-subset?
[ rem-custom-inlining ] [ drop f ] if
] "custom-inlining" set-word-prop
] each
\ rem [
in-d>> rem-custom-inlining
] "custom-inlining" set-word-prop
{
bitand-integer-integer
bitand-integer-fixnum
bitand-fixnum-integer
} [
[
in-d>> second value-info >literal< [
0 most-positive-fixnum between?
[ [ >fixnum ] bi@ fixnum-bitand ] f ?
] when
] "custom-inlining" set-word-prop
] each
{ numerator denominator } { numerator denominator }
[ [ drop integer <class-info> ] "outputs" set-word-prop ] each [ [ drop integer <class-info> ] "outputs" set-word-prop ] each
@ -313,15 +282,6 @@ generic-comparison-ops [
"outputs" set-word-prop "outputs" set-word-prop
] each ] each
! Generate more efficient code for common idiom
\ clone [
in-d>> first value-info literal>> {
{ V{ } [ [ drop { } 0 vector boa ] ] }
{ H{ } [ [ drop 0 <hashtable> ] ] }
[ drop f ]
} case
] "custom-inlining" set-word-prop
\ slot [ \ slot [
dup literal?>> dup literal?>>
[ literal>> swap value-info-slot ] [ 2drop object-info ] if [ literal>> swap value-info-slot ] [ 2drop object-info ] if
@ -345,17 +305,3 @@ generic-comparison-ops [
bi bi
] [ 2drop object-info ] if ] [ 2drop object-info ] if
] "outputs" set-word-prop ] "outputs" set-word-prop
\ instance? [
in-d>> second value-info literal>> dup class?
[ "predicate" word-prop '[ drop @ ] ] [ drop f ] if
] "custom-inlining" set-word-prop
\ equal? [
! If first input has a known type and second input is an
! object, we convert this to [ swap equal? ].
in-d>> first2 value-info class>> object class= [
value-info class>> \ equal? specific-method
[ swap equal? ] f ?
] [ drop f ] if
] "custom-inlining" set-word-prop

View File

@ -9,7 +9,7 @@ compiler.tree.propagation.info compiler.tree.def-use
compiler.tree.debugger compiler.tree.checker compiler.tree.debugger compiler.tree.checker
slots.private words hashtables classes assocs locals slots.private words hashtables classes assocs locals
specialized-arrays.double system sorting math.libm specialized-arrays.double system sorting math.libm
math.intervals quotations ; math.intervals quotations effects ;
IN: compiler.tree.propagation.tests IN: compiler.tree.propagation.tests
[ V{ } ] [ [ ] final-classes ] unit-test [ V{ } ] [ [ ] final-classes ] unit-test
@ -84,9 +84,9 @@ IN: compiler.tree.propagation.tests
[ float ] [ [ { float float } declare mod ] final-math-class ] unit-test [ float ] [ [ { float float } declare mod ] final-math-class ] unit-test
[ V{ integer } ] [ [ 255 bitand ] final-classes ] unit-test [ V{ fixnum } ] [ [ 255 bitand ] final-classes ] unit-test
[ V{ integer } ] [ [ V{ fixnum } ] [
[ [ 255 bitand ] [ 65535 bitand ] bi + ] final-classes [ [ 255 bitand ] [ 65535 bitand ] bi + ] final-classes
] unit-test ] unit-test
@ -640,6 +640,10 @@ MIXIN: empty-mixin
[ { bignum integer } declare [ shift ] keep ] final-classes [ { bignum integer } declare [ shift ] keep ] final-classes
] unit-test ] unit-test
[ V{ fixnum } ] [ [ >fixnum 15 bitand 1 swap shift ] final-classes ] unit-test
[ V{ fixnum } ] [ [ 15 bitand 1 swap shift ] final-classes ] unit-test
[ V{ fixnum } ] [ [ V{ fixnum } ] [
[ { fixnum } declare log2 ] final-classes [ { fixnum } declare log2 ] final-classes
] unit-test ] unit-test
@ -704,3 +708,39 @@ TUPLE: circle me ;
! Joe found an oversight ! Joe found an oversight
[ V{ integer } ] [ [ >integer ] final-classes ] unit-test [ V{ integer } ] [ [ >integer ] final-classes ] unit-test
TUPLE: foo bar ;
[ t ] [ [ foo new ] { new } inlined? ] unit-test
GENERIC: whatever ( x -- y )
M: number whatever drop foo ;
[ t ] [ [ 1 whatever new ] { new } inlined? ] unit-test
: that-thing ( -- class ) foo ;
[ f ] [ [ that-thing new ] { new } inlined? ] unit-test
GENERIC: whatever2 ( x -- y )
M: number whatever2 drop H{ { 1 1 } { 2 2 } { 3 3 } { 4 4 } { 5 6 } } ;
M: f whatever2 ;
[ t ] [ [ 1 whatever2 at ] { at* hashcode* } inlined? ] unit-test
[ f ] [ [ whatever2 at ] { at* hashcode* } inlined? ] unit-test
[ t ] [ [ { 1 2 3 } member? ] { member? } inlined? ] unit-test
[ f ] [ [ { 1 2 3 } swap member? ] { member? } inlined? ] unit-test
[ t ] [ [ { 1 2 3 } memq? ] { memq? } inlined? ] unit-test
[ f ] [ [ { 1 2 3 } swap memq? ] { memq? } inlined? ] unit-test
[ t ] [ [ V{ } clone ] { clone (clone) } inlined? ] unit-test
[ f ] [ [ { } clone ] { clone (clone) } inlined? ] unit-test
[ f ] [ [ instance? ] { instance? } inlined? ] unit-test
[ f ] [ [ 5 instance? ] { instance? } inlined? ] unit-test
[ t ] [ [ array instance? ] { instance? } inlined? ] unit-test
[ t ] [ [ (( a b c -- c b a )) shuffle ] { shuffle } inlined? ] unit-test
[ f ] [ [ { 1 2 3 } swap shuffle ] { shuffle } inlined? ] unit-test

View File

@ -0,0 +1,2 @@
Slava Pestov
Daniel Ehrenberg

View File

@ -0,0 +1,205 @@
! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences words fry generic accessors classes.tuple
classes classes.algebra definitions stack-checker.state quotations
classes.tuple.private math math.partial-dispatch math.private
math.intervals layouts math.order vectors hashtables
combinators effects generalizations assocs sets
combinators.short-circuit sequences.private locals
stack-checker namespaces compiler.tree.propagation.info ;
IN: compiler.tree.propagation.transforms
\ equal? [
! If first input has a known type and second input is an
! object, we convert this to [ swap equal? ].
in-d>> first2 value-info class>> object class= [
value-info class>> \ equal? specific-method
[ swap equal? ] f ?
] [ drop f ] if
] "custom-inlining" set-word-prop
: rem-custom-inlining ( #call -- quot/f )
second value-info literal>> dup integer?
[ power-of-2? [ 1- bitand ] f ? ] [ drop f ] if ;
{
mod-integer-integer
mod-integer-fixnum
mod-fixnum-integer
fixnum-mod
} [
[
in-d>> dup first value-info interval>> [0,inf] interval-subset?
[ rem-custom-inlining ] [ drop f ] if
] "custom-inlining" set-word-prop
] each
\ rem [
in-d>> rem-custom-inlining
] "custom-inlining" set-word-prop
{
bitand-integer-integer
bitand-integer-fixnum
bitand-fixnum-integer
bitand
} [
[
in-d>> second value-info >literal< [
0 most-positive-fixnum between?
[ [ >fixnum ] bi@ fixnum-bitand ] f ?
] when
] "custom-inlining" set-word-prop
] each
! Speeds up 2^
\ shift [
in-d>> first value-info literal>> 1 = [
cell-bits tag-bits get - 1 -
'[
>fixnum dup 0 < [ 2drop 0 ] [
dup _ < [ fixnum-shift ] [
fixnum-shift
] if
] if
]
] [ f ] if
] "custom-inlining" set-word-prop
! Generate more efficient code for common idiom
\ clone [
in-d>> first value-info literal>> {
{ V{ } [ [ drop { } 0 vector boa ] ] }
{ H{ } [ [ drop 0 <hashtable> ] ] }
[ drop f ]
} case
] "custom-inlining" set-word-prop
ERROR: bad-partial-eval quot word ;
: check-effect ( quot word -- )
2dup [ infer ] [ stack-effect ] bi* effect<=
[ 2drop ] [ bad-partial-eval ] if ;
:: define-partial-eval ( word quot n -- )
word [
in-d>> n tail*
[ value-info ] map
dup [ literal?>> ] all? [
[ literal>> ] map
n firstn
quot call dup [
[ n ndrop ] prepose
dup word check-effect
] when
] [ drop f ] if
] "custom-inlining" set-word-prop ;
: inline-new ( class -- quot/f )
dup tuple-class? [
dup inlined-dependency depends-on
[ all-slots [ initial>> literalize ] map ]
[ tuple-layout '[ _ <tuple-boa> ] ]
bi append >quotation
] [ drop f ] if ;
\ new [ inline-new ] 1 define-partial-eval
\ instance? [
dup class?
[ "predicate" word-prop ] [ drop f ] if
] 1 define-partial-eval
! Shuffling
: nths-quot ( indices -- quot )
[ [ '[ _ swap nth ] ] map ] [ length ] bi
'[ _ cleave _ narray ] ;
\ shuffle [
shuffle-mapping nths-quot
] 1 define-partial-eval
! Index search
\ index [
dup sequence? [
dup length 4 >= [
dup length zip >hashtable '[ _ at ]
] [ drop f ] if
] [ drop f ] if
] 1 define-partial-eval
: memq-quot ( seq -- newquot )
[ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
[ drop f ] suffix [ cond ] curry ;
\ memq? [
dup sequence? [ memq-quot ] [ drop f ] if
] 1 define-partial-eval
! Membership testing
: member-quot ( seq -- newquot )
dup length 4 <= [
[ drop f ] swap
[ literalize [ t ] ] { } map>assoc linear-case-quot
] [
unique [ key? ] curry
] if ;
\ member? [
dup sequence? [ member-quot ] [ drop f ] if
] 1 define-partial-eval
! Fast at for integer maps
CONSTANT: lookup-table-at-max 256
: lookup-table-at? ( assoc -- ? )
#! Can we use a fast byte array test here?
{
[ assoc-size 4 > ]
[ values [ ] all? ]
[ keys [ integer? ] all? ]
[ keys [ 0 lookup-table-at-max between? ] all? ]
} 1&& ;
: lookup-table-seq ( assoc -- table )
[ keys supremum 1+ ] keep '[ _ at ] { } map-as ;
: lookup-table-quot ( seq -- newquot )
lookup-table-seq
'[
_ over integer? [
2dup bounds-check? [
nth-unsafe dup >boolean
] [ 2drop f f ] if
] [ 2drop f f ] if
] ;
: fast-lookup-table-at? ( assoc -- ? )
values {
[ [ integer? ] all? ]
[ [ 0 254 between? ] all? ]
} 1&& ;
: fast-lookup-table-seq ( assoc -- table )
lookup-table-seq [ 255 or ] B{ } map-as ;
: fast-lookup-table-quot ( seq -- newquot )
fast-lookup-table-seq
'[
_ over integer? [
2dup bounds-check? [
nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
] [ 2drop f f ] if
] [ 2drop f f ] if
] ;
: at-quot ( assoc -- quot )
dup lookup-table-at? [
dup fast-lookup-table-at? [
fast-lookup-table-quot
] [
lookup-table-quot
] if
] [ drop f ] if ;
\ at* [ at-quot ] 1 define-partial-eval

View File

@ -27,4 +27,6 @@ SYMBOL: yield-hook
yield-hook [ [ ] ] initialize yield-hook [ [ ] ] initialize
: alist-max ( alist -- pair ) : alist-max ( alist -- pair )
[ ] [ [ [ second ] bi@ > ] most ] map-reduce ; [ ] [ [ [ second ] bi@ > ] most ] map-reduce ;
: penultimate ( seq -- elt ) [ length 2 - ] keep nth ;

View File

@ -76,18 +76,18 @@ HOOK: %or cpu ( dst src1 src2 -- )
HOOK: %or-imm cpu ( dst src1 src2 -- ) HOOK: %or-imm cpu ( dst src1 src2 -- )
HOOK: %xor cpu ( dst src1 src2 -- ) HOOK: %xor cpu ( dst src1 src2 -- )
HOOK: %xor-imm cpu ( dst src1 src2 -- ) HOOK: %xor-imm cpu ( dst src1 src2 -- )
HOOK: %shl cpu ( dst src1 src2 -- )
HOOK: %shl-imm cpu ( dst src1 src2 -- ) HOOK: %shl-imm cpu ( dst src1 src2 -- )
HOOK: %shr cpu ( dst src1 src2 -- )
HOOK: %shr-imm cpu ( dst src1 src2 -- ) HOOK: %shr-imm cpu ( dst src1 src2 -- )
HOOK: %sar cpu ( dst src1 src2 -- )
HOOK: %sar-imm cpu ( dst src1 src2 -- ) HOOK: %sar-imm cpu ( dst src1 src2 -- )
HOOK: %not cpu ( dst src -- ) HOOK: %not cpu ( dst src -- )
HOOK: %log2 cpu ( dst src -- ) HOOK: %log2 cpu ( dst src -- )
HOOK: %fixnum-add cpu ( src1 src2 -- ) HOOK: %fixnum-add cpu ( label dst src1 src2 -- )
HOOK: %fixnum-add-tail cpu ( src1 src2 -- ) HOOK: %fixnum-sub cpu ( label dst src1 src2 -- )
HOOK: %fixnum-sub cpu ( src1 src2 -- ) HOOK: %fixnum-mul cpu ( label dst src1 src2 -- )
HOOK: %fixnum-sub-tail cpu ( src1 src2 -- )
HOOK: %fixnum-mul cpu ( src1 src2 temp1 temp2 -- )
HOOK: %fixnum-mul-tail cpu ( src1 src2 temp1 temp2 -- )
HOOK: %integer>bignum cpu ( dst src temp -- ) HOOK: %integer>bignum cpu ( dst src temp -- )
HOOK: %bignum>integer cpu ( dst src temp -- ) HOOK: %bignum>integer cpu ( dst src temp -- )

View File

@ -51,8 +51,6 @@ M: x86.32 reserved-area-size 0 ;
M: x86.32 %alien-invoke 0 CALL rc-relative rel-dlsym ; M: x86.32 %alien-invoke 0 CALL rc-relative rel-dlsym ;
M: x86.32 %alien-invoke-tail 0 JMP rc-relative rel-dlsym ;
M: x86.32 return-struct-in-registers? ( c-type -- ? ) M: x86.32 return-struct-in-registers? ( c-type -- ? )
c-type c-type
[ return-in-registers?>> ] [ return-in-registers?>> ]

View File

@ -167,11 +167,6 @@ M: x86.64 %alien-invoke
rc-absolute-cell rel-dlsym rc-absolute-cell rel-dlsym
R11 CALL ; R11 CALL ;
M: x86.64 %alien-invoke-tail
R11 0 MOV
rc-absolute-cell rel-dlsym
R11 JMP ;
M: x86.64 %prepare-alien-indirect ( -- ) M: x86.64 %prepare-alien-indirect ( -- )
"unbox_alien" f %alien-invoke "unbox_alien" f %alien-invoke
RBP RAX MOV ; RBP RAX MOV ;

View File

@ -4,9 +4,14 @@ USING: accessors assocs alien alien.c-types arrays strings
cpu.x86.assembler cpu.x86.assembler.private cpu.architecture cpu.x86.assembler cpu.x86.assembler.private cpu.architecture
kernel kernel.private math memory namespaces make sequences kernel kernel.private math memory namespaces make sequences
words system layouts combinators math.order fry locals words system layouts combinators math.order fry locals
compiler.constants compiler.cfg.registers compiler.constants
compiler.cfg.instructions compiler.cfg.intrinsics compiler.cfg.registers
compiler.cfg.stack-frame compiler.codegen compiler.codegen.fixup ; compiler.cfg.instructions
compiler.cfg.intrinsics
compiler.cfg.comparisons
compiler.cfg.stack-frame
compiler.codegen
compiler.codegen.fixup ;
IN: cpu.x86 IN: cpu.x86
<< enable-fixnum-log2 >> << enable-fixnum-log2 >>
@ -124,83 +129,18 @@ M: x86 %log2 BSR ;
: ?MOV ( dst src -- ) : ?MOV ( dst src -- )
2dup = [ 2drop ] [ MOV ] if ; inline 2dup = [ 2drop ] [ MOV ] if ; inline
:: move>args ( src1 src2 -- ) :: overflow-template ( label dst src1 src2 insn -- )
{
{ [ src1 param-reg-2 = ] [ param-reg-1 src2 ?MOV param-reg-1 param-reg-2 XCHG ] }
{ [ src1 param-reg-1 = ] [ param-reg-2 src2 ?MOV ] }
{ [ src2 param-reg-1 = ] [ param-reg-2 src1 ?MOV param-reg-1 param-reg-2 XCHG ] }
{ [ src2 param-reg-2 = ] [ param-reg-1 src1 ?MOV ] }
[
param-reg-1 src1 MOV
param-reg-2 src2 MOV
]
} cond ;
HOOK: %alien-invoke-tail cpu ( func dll -- )
:: overflow-template ( src1 src2 insn inverse func -- )
<label> "no-overflow" set
src1 src2 insn call src1 src2 insn call
ds-reg [] src1 MOV label JO ; inline
"no-overflow" get JNO
src1 src2 inverse call
src1 src2 move>args
%prepare-alien-invoke
func f %alien-invoke
"no-overflow" resolve-label ; inline
:: overflow-template-tail ( src1 src2 insn inverse func -- ) M: x86 %fixnum-add ( label dst src1 src2 -- )
<label> "no-overflow" set [ ADD ] overflow-template ;
src1 src2 insn call
"no-overflow" get JNO
src1 src2 inverse call
src1 src2 move>args
%prepare-alien-invoke
func f %alien-invoke-tail
"no-overflow" resolve-label
ds-reg [] src1 MOV
0 RET ; inline
M: x86 %fixnum-add ( src1 src2 -- ) M: x86 %fixnum-sub ( label dst src1 src2 -- )
[ ADD ] [ SUB ] "overflow_fixnum_add" overflow-template ; [ SUB ] overflow-template ;
M: x86 %fixnum-add-tail ( src1 src2 -- ) M: x86 %fixnum-mul ( label dst src1 src2 -- )
[ ADD ] [ SUB ] "overflow_fixnum_add" overflow-template-tail ; [ swap IMUL2 ] overflow-template ;
M: x86 %fixnum-sub ( src1 src2 -- )
[ SUB ] [ ADD ] "overflow_fixnum_subtract" overflow-template ;
M: x86 %fixnum-sub-tail ( src1 src2 -- )
[ SUB ] [ ADD ] "overflow_fixnum_subtract" overflow-template-tail ;
M:: x86 %fixnum-mul ( src1 src2 temp1 temp2 -- )
"no-overflow" define-label
temp1 src1 MOV
temp1 tag-bits get SAR
src2 temp1 IMUL2
ds-reg [] temp1 MOV
"no-overflow" get JNO
src1 src2 move>args
param-reg-1 tag-bits get SAR
param-reg-2 tag-bits get SAR
%prepare-alien-invoke
"overflow_fixnum_multiply" f %alien-invoke
"no-overflow" resolve-label ;
M:: x86 %fixnum-mul-tail ( src1 src2 temp1 temp2 -- )
"overflow" define-label
temp1 src1 MOV
temp1 tag-bits get SAR
src2 temp1 IMUL2
"overflow" get JO
ds-reg [] temp1 MOV
0 RET
"overflow" resolve-label
src1 src2 move>args
param-reg-1 tag-bits get SAR
param-reg-2 tag-bits get SAR
%prepare-alien-invoke
"overflow_fixnum_multiply" f %alien-invoke-tail ;
: bignum@ ( reg n -- op ) : bignum@ ( reg n -- op )
cells bignum tag-number - [+] ; inline cells bignum tag-number - [+] ; inline
@ -411,6 +351,28 @@ M: x86.64 small-reg-native small-reg-8 ;
[ quot call ] with-save/restore [ quot call ] with-save/restore
] if ; inline ] if ; inline
: shift-count? ( reg -- ? ) { ECX RCX } memq? ;
:: emit-shift ( dst src1 src2 quot -- )
src2 shift-count? [
dst CL quot call
] [
dst shift-count? [
dst src2 XCHG
src2 CL quot call
dst src2 XCHG
] [
ECX small-reg-native [
CL src2 MOV
drop dst CL quot call
] with-save/restore
] if
] if ; inline
M: x86 %shl [ SHL ] emit-shift ;
M: x86 %shr [ SHR ] emit-shift ;
M: x86 %sar [ SAR ] emit-shift ;
M:: x86 %string-nth ( dst src index temp -- ) M:: x86 %string-nth ( dst src index temp -- )
"end" define-label "end" define-label
dst { src index temp } [| new-dst | dst { src index temp } [| new-dst |

View File

@ -258,6 +258,12 @@ M: no-word-error summary
M: no-word-error error. summary print ; M: no-word-error error. summary print ;
M: no-word-in-vocab summary
[ vocab>> ] [ word>> ] bi
[ "No word named ``" % % "'' found in ``" % % "'' vocabulary" % ] "" make ;
M: no-word-in-vocab error. summary print ;
M: ambiguous-use-error summary M: ambiguous-use-error summary
words>> first name>> words>> first name>>
"More than one vocabulary defines a word named ``" "''" surround ; "More than one vocabulary defines a word named ``" "''" surround ;

View File

@ -1,11 +1,11 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays classes.mixin classes.parser USING: accessors arrays classes.mixin classes.parser classes.singleton
classes.tuple classes.tuple.parser combinators effects classes.tuple classes.tuple.parser combinators effects effects.parser
effects.parser fry generic generic.parser generic.standard fry generic generic.parser generic.standard interpolate
interpolate io.streams.string kernel lexer locals.parser io.streams.string kernel lexer locals.parser locals.rewrite.closures
locals.rewrite.closures locals.types make namespaces parser locals.types make namespaces parser quotations sequences vocabs.parser
quotations sequences vocabs.parser words words.symbol ; words words.symbol ;
IN: functors IN: functors
! This is a hack ! This is a hack
@ -71,6 +71,14 @@ SYNTAX: `TUPLE:
} case } case
\ define-tuple-class parsed ; \ define-tuple-class parsed ;
SYNTAX: `SINGLETON:
scan-param parsed
\ define-singleton-class parsed ;
SYNTAX: `MIXIN:
scan-param parsed
\ define-mixin-class parsed ;
SYNTAX: `M: SYNTAX: `M:
scan-param parsed scan-param parsed
scan-param parsed scan-param parsed
@ -134,6 +142,8 @@ DEFER: ;FUNCTOR delimiter
: functor-words ( -- assoc ) : functor-words ( -- assoc )
H{ H{
{ "TUPLE:" POSTPONE: `TUPLE: } { "TUPLE:" POSTPONE: `TUPLE: }
{ "SINGLETON:" POSTPONE: `SINGLETON: }
{ "MIXIN:" POSTPONE: `MIXIN: }
{ "M:" POSTPONE: `M: } { "M:" POSTPONE: `M: }
{ "C:" POSTPONE: `C: } { "C:" POSTPONE: `C: }
{ ":" POSTPONE: `: } { ":" POSTPONE: `: }

View File

@ -2,7 +2,7 @@
! Slava Pestov. ! Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel math sequences arrays assocs sequences.private USING: kernel math sequences arrays assocs sequences.private
growable accessors math.order summary ; growable accessors math.order summary vectors ;
IN: heaps IN: heaps
GENERIC: heap-push* ( value key heap -- entry ) GENERIC: heap-push* ( value key heap -- entry )
@ -15,14 +15,14 @@ GENERIC: heap-size ( heap -- n )
<PRIVATE <PRIVATE
TUPLE: heap data ; TUPLE: heap { data vector } ;
: <heap> ( class -- heap ) : <heap> ( class -- heap )
[ V{ } clone ] dip boa ; inline [ V{ } clone ] dip boa ; inline
TUPLE: entry value key heap index ; TUPLE: entry value key heap index ;
: <entry> ( value key heap -- entry ) f entry boa ; : <entry> ( value key heap -- entry ) f entry boa ; inline
PRIVATE> PRIVATE>
@ -109,10 +109,10 @@ DEFER: up-heap
[ data-exchange ] 2keep up-heap [ data-exchange ] 2keep up-heap
] [ ] [
3drop 3drop
] if ; ] if ; inline recursive
: up-heap ( n heap -- ) : up-heap ( n heap -- )
over 0 > [ (up-heap) ] [ 2drop ] if ; over 0 > [ (up-heap) ] [ 2drop ] if ; inline recursive
: (child) ( m heap -- n ) : (child) ( m heap -- n )
2dup right-value 2dup right-value
@ -132,10 +132,10 @@ DEFER: down-heap
3drop 3drop
] [ ] [
[ data-exchange ] 2keep down-heap [ data-exchange ] 2keep down-heap
] if ; ] if ; inline recursive
: down-heap ( m heap -- ) : down-heap ( m heap -- )
2dup left-bounds-check? [ 2drop ] [ (down-heap) ] if ; 2dup left-bounds-check? [ 2drop ] [ (down-heap) ] if ; inline recursive
PRIVATE> PRIVATE>
@ -148,7 +148,7 @@ M: heap heap-push* ( value key heap -- entry )
[ swapd heap-push ] curry assoc-each ; [ swapd heap-push ] curry assoc-each ;
: >entry< ( entry -- key value ) : >entry< ( entry -- key value )
[ value>> ] [ key>> ] bi ; [ value>> ] [ key>> ] bi ; inline
M: heap heap-peek ( heap -- value key ) M: heap heap-peek ( heap -- value key )
data-first >entry< ; data-first >entry< ;

View File

@ -143,7 +143,7 @@ SYMBOL: vocab-articles
swap '[ swap '[
_ elements [ _ elements [
rest { { } { "" } } member? rest { { } { "" } } member?
[ "Empty description" throw ] when [ "Empty $description" simple-lint-error ] when
] each ] each
] each ; ] each ;

View File

@ -120,7 +120,7 @@ IN: math.matrices
PRIVATE> PRIVATE>
: cross ( vec1 vec2 -- vec3 ) [ i ] [ j ] [ k ] 2tri 3array ; : cross ( vec1 vec2 -- vec3 ) [ [ i ] [ j ] [ k ] 2tri ] keep 3sequence ;
: proj ( v u -- w ) : proj ( v u -- w )
[ [ v. ] [ norm-sq ] bi / ] keep n*v ; [ [ v. ] [ norm-sq ] bi / ] keep n*v ;

View File

@ -0,0 +1,41 @@
USING: alien help.markup help.syntax io kernel math quotations
opengl.gl assocs vocabs.loader sequences accessors colors words
opengl ;
IN: opengl.annotations
HELP: log-gl-error
{ $values { "function" word } }
{ $description "If the most recent OpenGL call resulted in an error, append it to the " { $link gl-error-log } "." }
{ $notes "Don't call this function directly. Call " { $link log-gl-errors } " to annotate every OpenGL function to automatically log errors." } ;
HELP: gl-error-log
{ $var-description "A vector of OpenGL errors logged by " { $link log-gl-errors } ". Each log entry has the following tuple slots:" }
{ $list
{ { $snippet "function" } " is the OpenGL function that raised the error." }
{ { $snippet "error" } " is the OpenGL error code." }
{ { $snippet "timestamp" } " is the time the error was logged." }
}
{ "The error log is emptied using the " { $link clear-gl-error-log } " word." } ;
HELP: clear-gl-error-log
{ $description "Empties the OpenGL error log populated by " { $link log-gl-errors } "." } ;
HELP: throw-gl-errors
{ $description "Annotate every OpenGL function to throw a " { $link gl-error } " if the function results in an error. Use " { $link reset-gl-functions } " to reverse this operation." } ;
HELP: log-gl-errors
{ $description "Annotate every OpenGL function to log using " { $link log-gl-error } " if the function results in an error. Use " { $link reset-gl-functions } " to reverse this operation." } ;
HELP: reset-gl-functions
{ $description "Removes any annotations from all OpenGL functions, such as those applied by " { $link throw-gl-errors } " or " { $link log-gl-errors } "." } ;
{ throw-gl-errors gl-error log-gl-errors log-gl-error clear-gl-error-log reset-gl-functions } related-words
ARTICLE: "opengl.annotations" "OpenGL error reporting"
"The " { $vocab-link "opengl.annotations" } " vocabulary provides some tools for tracking down GL errors:"
{ $subsection throw-gl-errors }
{ $subsection log-gl-errors }
{ $subsection clear-gl-error-log }
{ $subsection reset-gl-functions } ;
ABOUT: "opengl.annotations"

View File

@ -0,0 +1,42 @@
! Copyright (C) 2009 Joe Groff.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces combinators.short-circuit vocabs sequences
compiler.units tools.annotations tools.annotations.private fry words
opengl calendar accessors ascii ;
IN: opengl.annotations
TUPLE: gl-error-log
{ function word initial: t }
{ error gl-error }
{ timestamp timestamp } ;
gl-error-log [ V{ } clone ] initialize
: <gl-error-log> ( function code -- gl-error-log )
[ dup ] dip <gl-error> now gl-error-log boa ;
: log-gl-error ( function -- )
gl-error-code [ <gl-error-log> gl-error-log get push ] [ drop ] if* ;
: clear-gl-error-log ( -- )
V{ } clone gl-error-log set ;
: gl-function? ( word -- ? )
name>> { [ "glGetError" = not ] [ "gl" head? ] [ third LETTER? ] } 1&& ;
: gl-functions ( -- words )
"opengl.gl" vocab words [ gl-function? ] filter ;
: annotate-gl-functions ( quot -- )
[
[ gl-functions ] dip [ [ dup ] dip curry (annotate) ] curry each
] with-compilation-unit ;
: reset-gl-functions ( -- )
[ gl-functions [ (reset) ] each ] with-compilation-unit ;
: throw-gl-errors ( -- )
[ '[ @ _ (gl-error) ] ] annotate-gl-functions ;
: log-gl-errors ( -- )
[ '[ @ _ log-gl-error ] ] annotate-gl-functions ;

View File

@ -0,0 +1 @@
Joe Groff

View File

@ -0,0 +1,36 @@
! (c)2009 Joe Groff bsd license
USING: help.markup help.syntax multiline tools.continuations ;
IN: opengl.debug
HELP: G
{ $description "Makes the OpenGL context associated with " { $link G-world } " active for subsequent OpenGL calls. This is intended to be used from the listener, where interactively entered OpenGL calls can be directed to any window. Note that the Factor UI resets the OpenGL context every time a window is updated, so every code snippet entered in the listener must be prefixed with " { $snippet "G" } " in this use case." }
{ $examples { $code <" USING: opengl.debug ui ;
[ drop t ] find-window G-world set
G 0.0 0.0 1.0 1.0 glClearColor
G GL_COLOR_BUFFER_BIT glClear
"> } } ;
HELP: F
{ $description "Flushes the OpenGL context associated with " { $link G-world } ", thereby committing any outstanding drawing operations." } ;
HELP: G-world
{ $var-description "The world whose OpenGL context is made active by " { $link G } "." } ;
HELP: GB
{ $description "A shorthand for " { $link gl-break } "." } ;
HELP: gl-break
{ $description "Suspends the current thread and activates the walker like " { $link break } ", but also preserves the current OpenGL context, saves it to " { $link G-world } " for interactive use through " { $link G } ", and restores the current context when the suspended thread is continued. The shorthand word " { $link POSTPONE: GB } " can also be used." } ;
{ G F G-world POSTPONE: GB gl-break } related-words
ARTICLE: "opengl.debug" "Interactive debugging of OpenGL applications"
"The " { $vocab-link "opengl.debug" } " vocabulary provides words to assist with interactive debugging of OpenGL applications in the Factor UI."
{ $subsection G-world }
{ $subsection G }
{ $subsection F }
{ $subsection GB }
{ $subsection gl-break } ;
ABOUT: "opengl.debug"

View File

@ -0,0 +1,23 @@
! (c)2009 Joe Groff bsd license
USING: accessors kernel namespaces parser tools.continuations
ui.backend ui.gadgets.worlds words ;
IN: opengl.debug
SYMBOL: G-world
: G ( -- )
G-world get set-gl-context ;
: F ( -- )
G-world get handle>> flush-gl-context ;
: gl-break ( -- )
world get dup G-world set-global
[ break ] dip
set-gl-context ;
<< \ gl-break t "break?" set-word-prop >>
SYNTAX: GB
\ gl-break parsed ;

View File

@ -0,0 +1 @@
Helper words for breaking and interactively manipulating OpenGL applications

View File

@ -1,5 +1,5 @@
USING: alien help.markup help.syntax io kernel math quotations USING: alien help.markup help.syntax io kernel math quotations
opengl.gl assocs vocabs.loader sequences accessors colors ; opengl.gl assocs vocabs.loader sequences accessors colors words ;
IN: opengl IN: opengl
HELP: gl-color HELP: gl-color
@ -8,7 +8,7 @@ HELP: gl-color
{ $notes "See " { $link "colors" } "." } ; { $notes "See " { $link "colors" } "." } ;
HELP: gl-error HELP: gl-error
{ $description "If the most recent OpenGL call resulted in an error, print the error to " { $link output-stream } "." } ; { $description "If the most recent OpenGL call resulted in an error, throw a " { $snippet "gl-error" } " instance reporting the error." } ;
HELP: do-enabled HELP: do-enabled
{ $values { "what" integer } { "quot" quotation } } { $values { "what" integer } { "quot" quotation } }
@ -73,6 +73,8 @@ ARTICLE: "gl-utilities" "OpenGL utility words"
$nl $nl
"The " { $vocab-link "opengl.gl" } " and " { $vocab-link "opengl.glu" } " vocabularies have the actual OpenGL bindings." "The " { $vocab-link "opengl.gl" } " and " { $vocab-link "opengl.glu" } " vocabularies have the actual OpenGL bindings."
{ $subsection "opengl-low-level" } { $subsection "opengl-low-level" }
"Error reporting:"
{ $subsection gl-error }
"Wrappers:" "Wrappers:"
{ $subsection gl-color } { $subsection gl-color }
{ $subsection gl-translate } { $subsection gl-translate }

22
basis/opengl/opengl.factor Normal file → Executable file
View File

@ -2,9 +2,10 @@
! Portions copyright (C) 2007 Eduardo Cavazos. ! Portions copyright (C) 2007 Eduardo Cavazos.
! Portions copyright (C) 2008 Joe Groff. ! Portions copyright (C) 2008 Joe Groff.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types continuations kernel libc math macros USING: alien alien.c-types ascii calendar combinators.short-circuit
namespaces math.vectors math.parser opengl.gl combinators continuations kernel libc math macros namespaces math.vectors
combinators.smart arrays sequences splitting words byte-arrays assocs math.parser opengl.gl combinators combinators.smart arrays
sequences splitting words byte-arrays assocs vocabs
colors colors.constants accessors generalizations locals fry colors colors.constants accessors generalizations locals fry
specialized-arrays.float specialized-arrays.uint ; specialized-arrays.float specialized-arrays.uint ;
IN: opengl IN: opengl
@ -28,12 +29,19 @@ IN: opengl
{ HEX: 0506 "Invalid framebuffer operation" } { HEX: 0506 "Invalid framebuffer operation" }
} at "Unknown error" or ; } at "Unknown error" or ;
TUPLE: gl-error code string ; TUPLE: gl-error function code string ;
: <gl-error> ( function code -- gl-error )
dup error>string \ gl-error boa ; inline
: gl-error-code ( -- code/f )
glGetError dup 0 = [ drop f ] when ; inline
: (gl-error) ( function -- )
gl-error-code [ <gl-error> throw ] [ drop ] if* ;
: gl-error ( -- ) : gl-error ( -- )
glGetError dup 0 = [ drop ] [ f (gl-error) ; inline
dup error>string \ gl-error boa throw
] if ;
: do-enabled ( what quot -- ) : do-enabled ( what quot -- )
over glEnable dip glDisable ; inline over glEnable dip glDisable ; inline

View File

@ -1,5 +1,4 @@
USE: specialized-arrays.functor USE: specialized-arrays.functor
IN: specialized-arrays.alien IN: specialized-arrays.alien
<< "void*" define-array >> << "void*" define-array >>
<< "ptrdiff_t" define-array >>

View File

@ -0,0 +1,4 @@
USE: specialized-arrays.functor
IN: specialized-arrays.alien
<< "ptrdiff_t" define-array >>

View File

@ -1,6 +1,6 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: functors sequences sequences.private growable USING: accessors alien.c-types functors sequences sequences.private growable
prettyprint.custom kernel words classes math parser ; prettyprint.custom kernel words classes math parser ;
QUALIFIED: vectors.functor QUALIFIED: vectors.functor
IN: specialized-vectors.functor IN: specialized-vectors.functor
@ -21,6 +21,8 @@ V A <A> vectors.functor:define-vector
M: V contract 2drop ; M: V contract 2drop ;
M: V byte-length underlying>> byte-length ;
M: V pprint-delims drop \ V{ \ } ; M: V pprint-delims drop \ V{ \ } ;
M: V >pprint-sequence ; M: V >pprint-sequence ;

View File

@ -1 +0,0 @@
Slava Pestov

View File

@ -1,16 +0,0 @@
USING: stack-checker.call-effect tools.test kernel math effects ;
IN: stack-checker.call-effect.tests
[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
[ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
[ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
[ t ] [ [ + ] cached-effect (( a b -- c )) effect= ] unit-test
[ t ] [ 5 [ + ] curry cached-effect (( a -- c )) effect= ] unit-test
[ t ] [ 5 [ ] curry cached-effect (( -- c )) effect= ] unit-test
[ t ] [ [ dup ] [ drop ] compose cached-effect (( a -- b )) effect= ] unit-test
[ t ] [ [ drop ] [ dup ] compose cached-effect (( a b -- c d )) effect= ] unit-test
[ t ] [ [ 2drop ] [ dup ] compose cached-effect (( a b c -- d e )) effect= ] unit-test
[ t ] [ [ 1 2 3 ] [ 2drop ] compose cached-effect (( -- a )) effect= ] unit-test
[ t ] [ [ 1 2 ] [ 3drop ] compose cached-effect (( a -- )) effect= ] unit-test

View File

@ -1 +1,2 @@
Slava Pestov Slava Pestov
Daniel Ehrenberg

View File

@ -1,4 +1,4 @@
! Copyright (C) 2004, 2009 Slava Pestov. ! Copyright (C) 2004, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors alien alien.accessors arrays byte-arrays classes USING: fry accessors alien alien.accessors arrays byte-arrays classes
continuations.private effects generic hashtables continuations.private effects generic hashtables
@ -67,12 +67,18 @@ IN: stack-checker.known-words
[ length ensure-d ] keep zip [ length ensure-d ] keep zip
#declare, ; #declare, ;
\ declare [ infer-declare ] "special" set-word-prop
GENERIC: infer-call* ( value known -- ) GENERIC: infer-call* ( value known -- )
: (infer-call) ( value -- ) dup known infer-call* ; : (infer-call) ( value -- ) dup known infer-call* ;
: infer-call ( -- ) pop-d (infer-call) ; : infer-call ( -- ) pop-d (infer-call) ;
\ call [ infer-call ] "special" set-word-prop
\ (call) [ infer-call ] "special" set-word-prop
M: literal infer-call* M: literal infer-call*
[ 1array #drop, ] [ infer-literal-quot ] bi* ; [ 1array #drop, ] [ infer-literal-quot ] bi* ;
@ -103,10 +109,16 @@ M: object infer-call*
: infer-dip ( -- ) \ dip 1 infer-ndip ; : infer-dip ( -- ) \ dip 1 infer-ndip ;
\ dip [ infer-dip ] "special" set-word-prop
: infer-2dip ( -- ) \ 2dip 2 infer-ndip ; : infer-2dip ( -- ) \ 2dip 2 infer-ndip ;
\ 2dip [ infer-2dip ] "special" set-word-prop
: infer-3dip ( -- ) \ 3dip 3 infer-ndip ; : infer-3dip ( -- ) \ 3dip 3 infer-ndip ;
\ 3dip [ infer-3dip ] "special" set-word-prop
: infer-builder ( quot word -- ) : infer-builder ( quot word -- )
[ [
[ 2 consume-d ] dip [ 2 consume-d ] dip
@ -116,8 +128,12 @@ M: object infer-call*
: infer-curry ( -- ) [ <curried> ] \ curry infer-builder ; : infer-curry ( -- ) [ <curried> ] \ curry infer-builder ;
\ curry [ infer-curry ] "special" set-word-prop
: infer-compose ( -- ) [ <composed> ] \ compose infer-builder ; : infer-compose ( -- ) [ <composed> ] \ compose infer-builder ;
\ compose [ infer-compose ] "special" set-word-prop
: infer-execute ( -- ) : infer-execute ( -- )
pop-literal nip pop-literal nip
dup word? [ dup word? [
@ -127,11 +143,17 @@ M: object infer-call*
"execute must be given a word" time-bomb "execute must be given a word" time-bomb
] if ; ] if ;
\ execute [ infer-execute ] "special" set-word-prop
\ (execute) [ infer-execute ] "special" set-word-prop
: infer-<tuple-boa> ( -- ) : infer-<tuple-boa> ( -- )
\ <tuple-boa> \ <tuple-boa>
peek-d literal value>> second 1+ { tuple } <effect> peek-d literal value>> second 1+ { tuple } <effect>
apply-word/effect ; apply-word/effect ;
\ <tuple-boa> [ infer-<tuple-boa> ] "special" set-word-prop
: infer-effect-unsafe ( word -- ) : infer-effect-unsafe ( word -- )
pop-literal nip pop-literal nip
add-effect-input add-effect-input
@ -140,17 +162,30 @@ M: object infer-call*
: infer-execute-effect-unsafe ( -- ) : infer-execute-effect-unsafe ( -- )
\ (execute) infer-effect-unsafe ; \ (execute) infer-effect-unsafe ;
\ execute-effect-unsafe [ infer-execute-effect-unsafe ] "special" set-word-prop
: infer-call-effect-unsafe ( -- ) : infer-call-effect-unsafe ( -- )
\ call infer-effect-unsafe ; \ call infer-effect-unsafe ;
\ call-effect-unsafe [ infer-call-effect-unsafe ] "special" set-word-prop
: infer-exit ( -- ) : infer-exit ( -- )
\ exit (( n -- * )) apply-word/effect ; \ exit (( n -- * )) apply-word/effect ;
\ exit [ infer-exit ] "special" set-word-prop
: infer-load-locals ( -- ) : infer-load-locals ( -- )
pop-literal nip pop-literal nip
consume-d dup copy-values dup output-r consume-d dup copy-values dup output-r
[ [ f f ] dip ] [ swap zip ] 2bi #shuffle, ; [ [ f f ] dip ] [ swap zip ] 2bi #shuffle, ;
\ load-locals [ infer-load-locals ] "special" set-word-prop
: infer-load-local ( -- )
1 infer->r ;
\ load-local [ infer-load-local ] "special" set-word-prop
: infer-get-local ( -- ) : infer-get-local ( -- )
[let* | n [ pop-literal nip 1 swap - ] [let* | n [ pop-literal nip 1 swap - ]
in-r [ n consume-r ] in-r [ n consume-r ]
@ -163,36 +198,34 @@ M: object infer-call*
#shuffle, #shuffle,
] ; ] ;
\ get-local [ infer-get-local ] "special" set-word-prop
: infer-drop-locals ( -- ) : infer-drop-locals ( -- )
f f pop-literal nip consume-r f f #shuffle, ; f f pop-literal nip consume-r f f #shuffle, ;
\ drop-locals [ infer-drop-locals ] "special" set-word-prop
: infer-call-effect ( word -- )
1 ensure-d first literal value>>
add-effect-input add-effect-input
apply-word/effect ;
{ call-effect execute-effect } [
dup t "no-compile" set-word-prop
dup '[ _ infer-call-effect ] "special" set-word-prop
] each
\ do-primitive [ unknown-primitive-error ] "special" set-word-prop
\ if [ infer-if ] "special" set-word-prop
\ dispatch [ infer-dispatch ] "special" set-word-prop
\ alien-invoke [ infer-alien-invoke ] "special" set-word-prop
\ alien-indirect [ infer-alien-indirect ] "special" set-word-prop
\ alien-callback [ infer-alien-callback ] "special" set-word-prop
: infer-special ( word -- ) : infer-special ( word -- )
{ "special" word-prop call( -- ) ;
{ \ declare [ infer-declare ] }
{ \ call [ infer-call ] }
{ \ (call) [ infer-call ] }
{ \ dip [ infer-dip ] }
{ \ 2dip [ infer-2dip ] }
{ \ 3dip [ infer-3dip ] }
{ \ curry [ infer-curry ] }
{ \ compose [ infer-compose ] }
{ \ execute [ infer-execute ] }
{ \ (execute) [ infer-execute ] }
{ \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
{ \ call-effect-unsafe [ infer-call-effect-unsafe ] }
{ \ if [ infer-if ] }
{ \ dispatch [ infer-dispatch ] }
{ \ <tuple-boa> [ infer-<tuple-boa> ] }
{ \ exit [ infer-exit ] }
{ \ load-local [ 1 infer->r ] }
{ \ load-locals [ infer-load-locals ] }
{ \ get-local [ infer-get-local ] }
{ \ drop-locals [ infer-drop-locals ] }
{ \ do-primitive [ unknown-primitive-error ] }
{ \ alien-invoke [ infer-alien-invoke ] }
{ \ alien-indirect [ infer-alien-indirect ] }
{ \ alien-callback [ infer-alien-callback ] }
} case ;
: infer-local-reader ( word -- ) : infer-local-reader ( word -- )
(( -- value )) apply-word/effect ; (( -- value )) apply-word/effect ;
@ -209,10 +242,7 @@ M: object infer-call*
dispatch <tuple-boa> exit load-local load-locals get-local dispatch <tuple-boa> exit load-local load-locals get-local
drop-locals do-primitive alien-invoke alien-indirect drop-locals do-primitive alien-invoke alien-indirect
alien-callback alien-callback
} [ } [ t "no-compile" set-word-prop ] each
[ t "special" set-word-prop ]
[ t "no-compile" set-word-prop ] bi
] each
! Exceptions to the above ! Exceptions to the above
\ curry f "no-compile" set-word-prop \ curry f "no-compile" set-word-prop
@ -662,4 +692,4 @@ M: object infer-call*
\ reset-inline-cache-stats { } { } define-primitive \ reset-inline-cache-stats { } { } define-primitive
\ inline-cache-stats { } { array } define-primitive \ inline-cache-stats { } { array } define-primitive
\ optimized? { word } { object } define-primitive \ optimized? { word } { object } define-primitive

Some files were not shown because too many files have changed in this diff Show More