[ frame-required? get [ <stack-frame> ] [ drop f ] if ]
bi ;
-: build-stack-frame ( cfg -- cfg )
+: build-stack-frame ( cfg -- )
0 param-area-size set
0 allot-area-size set
cell allot-area-align set
- dup compute-stack-frame >>stack-frame ;
+ [ compute-stack-frame ] keep stack-frame<< ;
! Just ensure that various CFGs build correctly.
: unit-test-builder ( quot -- )
- '[ _ test-builder [ [ optimize-cfg check-cfg ] with-cfg ] each ] [ ] swap unit-test ;
+ '[
+ _ test-builder [
+ [
+ [ optimize-cfg ] [ check-cfg ] bi
+ ] with-cfg
+ ] each
+ ] [ ] swap unit-test ;
: blahblah ( nodes -- ? )
{ fixnum } declare [
: test-ssa ( quot -- cfgs )
test-builder [
[
- optimize-cfg
+ dup optimize-cfg
] with-cfg
] map ;
: test-flat ( quot -- cfgs )
test-builder [
[
- optimize-cfg
- select-representations
- insert-gc-checks
- insert-save-contexts
+ dup optimize-cfg
+ dup select-representations
+ dup insert-gc-checks
+ dup insert-save-contexts
] with-cfg
] map ;
: test-regs ( quot -- cfgs )
test-builder [
[
- optimize-cfg
- finalize-cfg
+ dup optimize-cfg
+ dup finalize-cfg
] with-cfg
] map ;
compiler.cfg.scheduling compiler.cfg.gc-checks
compiler.cfg.write-barrier compiler.cfg.save-contexts
compiler.cfg.ssa.destruction compiler.cfg.build-stack-frame
-compiler.cfg.linear-scan compiler.cfg.stacks.vacant ;
+compiler.cfg.linear-scan compiler.cfg.stacks.vacant
+compiler.cfg.utilities ;
IN: compiler.cfg.finalization
-: finalize-cfg ( cfg -- cfg' )
- select-representations
- schedule-instructions
- insert-gc-checks
- eliminate-write-barriers
- dup compute-vacant-sets
- insert-save-contexts
- destruct-ssa
- linear-scan
- build-stack-frame ;
+: finalize-cfg ( cfg -- )
+ {
+ select-representations
+ schedule-instructions
+ insert-gc-checks
+ eliminate-write-barriers
+ compute-vacant-sets
+ insert-save-contexts
+ destruct-ssa
+ linear-scan
+ build-stack-frame
+ } apply-passes ;
<PRIVATE
HELP: insert-gc-checks
-{ $values { "cfg" cfg } { "cfg'" cfg } }
+{ $values { "cfg" cfg } }
{ $description "Inserts gc checks in each " { $link basic-block } " in the cfg where they are needed." } ;
HELP: insert-gc-check?
{ 2 tagged-rep }
} representations set
-[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ ] [ cfg get insert-gc-checks ] unit-test
[ ] [ 1 get successors>> first successors>> first 2 set ] unit-test
{ 3 tagged-rep }
} representations set
-[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ ] [ cfg get insert-gc-checks ] unit-test
[ ] [ 1 get successors>> first successors>> first 3 set ] unit-test
[ t ] [ 2 get successors>> first instructions>> first ##phi? ] unit-test
[ 2 ] [ 3 get instructions>> length ] unit-test
[ ] [ test-gc-checks ] unit-test
-[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ ] [ cfg get insert-gc-checks ] unit-test
[ ] [
0 get successors>> first predecessors>>
[ ] [ test-gc-checks ] unit-test
-[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ ] [ cfg get insert-gc-checks ] unit-test
! The GC check should come after the alien-invoke
[
[ ] [ test-gc-checks ] unit-test
-[ ] [ cfg get insert-gc-checks drop ] unit-test
+[ ] [ cfg get insert-gc-checks ] unit-test
[
V{
PRIVATE>
-: insert-gc-checks ( cfg -- cfg' )
- dup blocks-with-gc [
- [ dup needs-predecessors ] dip
+:: insert-gc-checks ( cfg -- )
+ cfg blocks-with-gc [
+ cfg needs-predecessors
[ process-block ] each
- dup cfg-changed
+ cfg cfg-changed
] unless-empty ;
[ [ frame-reg = not ] filter ] assoc-map
] when ;
-: linear-scan ( cfg -- cfg' )
- dup dup admissible-registers (linear-scan) ;
+: linear-scan ( cfg -- )
+ dup admissible-registers (linear-scan) ;
PRIVATE>
: linearization-order ( cfg -- bbs )
- needs-post-order needs-loops dup needs-predecessors
-
- dup linear-order>> [ ] [
- dup (linearization-order)
- >>linear-order linear-order>>
- ] ?if ;
+ {
+ [ needs-post-order ]
+ [ needs-loops ]
+ [ needs-predecessors ]
+ [
+ dup linear-order>> [ ] [
+ dup (linearization-order)
+ >>linear-order linear-order>>
+ ] ?if
+ ]
+ } cleave ;
SYMBOL: numbers
2 0 edge
: test-loop-detection ( -- )
- 0 get block>cfg needs-loops drop ;
+ 0 get block>cfg needs-loops ;
[ ] [ test-loop-detection ] unit-test
: current-loop-nesting ( -- n ) basic-block get loop-nesting-at ;
-: needs-loops ( cfg -- cfg' )
+: needs-loops ( cfg -- )
dup needs-predecessors
- dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless ;
+ dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless
+ drop ;
kernel sequences ;
IN: compiler.cfg.optimizer
-: optimize-cfg ( cfg -- cfg' )
- dup {
+: optimize-cfg ( cfg -- )
+ {
optimize-tail-calls
delete-useless-conditionals
split-branches
] unit-test
: test-representations ( -- )
- 0 get block>cfg dup cfg set select-representations drop ;
+ 0 get block>cfg dup cfg set select-representations ;
! Make sure cost calculation isn't completely wrong
V{
! are made. The appropriate conversion operations inserted
! after a cost analysis.
-: select-representations ( cfg -- cfg' )
- needs-loops
- dup {
+: select-representations ( cfg -- )
+ {
+ needs-loops
needs-predecessors
compute-components
compute-possibilities
: simple-analysis ( ... cfg quot: ( ... insns -- ... ) -- ... )
'[ _ analyze-basic-block ] each-basic-block ; inline
-: needs-post-order ( cfg -- cfg' )
- dup post-order drop ;
+: needs-post-order ( cfg -- )
+ post-order drop ;
IN: compiler.cfg.save-contexts
HELP: insert-save-contexts
-{ $values { "cfg" cfg } { "cfg'" cfg } }
+{ $values { "cfg" cfg } }
{ $description "Inserts " { $link ##save-context } " instructions in each " { $link basic-block } " in the cfg that needs them. Save contexts are needed after instructions that modify the context, or instructions that read parameter registers." }
{ $see-also needs-save-context? } ;
[ insert-nth ] change-instructions drop
] [ drop ] if ;
-: insert-save-contexts ( cfg -- cfg' )
- dup [ insert-save-context ] each-basic-block ;
+: insert-save-contexts ( cfg -- )
+ [ insert-save-context ] each-basic-block ;
IN: compiler.cfg.scheduling
HELP: schedule-instructions
-{ $values { "cfg" cfg } { "cfg'" cfg } }
+{ $values { "cfg" cfg } }
{ $description "Performs a instruction scheduling optimization pass over the CFG to attempt to reduce the number of spills. The step must be performed after " { $link normalize-height } " or else invalid peeks might be inserted into the CFG." } ;
T{ ##load-tagged }
T{ ##allot }
T{ ##set-slot-imm }
- } insns>cfg schedule-instructions cfg>insns [ insn#>> ] all?
+ } insns>cfg dup schedule-instructions cfg>insns [ insn#>> ] all?
] unit-test
: test-1187 ( -- insns )
: schedule-block ( bb -- )
[ reorder ] change-instructions drop ;
-! TODO: stack effect should be ( cfg -- )
-: schedule-instructions ( cfg -- cfg' )
- dup number-instructions
- dup reverse-post-order [ kill-block?>> not ] filter
- [ schedule-block ] each ;
+: schedule-instructions ( cfg -- )
+ [ number-instructions ]
+ [
+ reverse-post-order
+ [ kill-block?>> not ] filter
+ [ schedule-block ] each
+ ] bi ;
! Copyright (C) 2009, 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs fry locals kernel make
-namespaces sequences sequences.deep
-sets vectors
+USING: accessors arrays assocs combinators fry locals kernel
+make namespaces sequences sequences.deep sets vectors
cpu.architecture
compiler.cfg.rpo
compiler.cfg.def-use
PRIVATE>
-: destruct-ssa ( cfg -- cfg' )
- dup needs-dominance
- dup construct-cssa
- dup compute-defs
- dup compute-insns
- dup compute-live-sets
- dup compute-live-ranges
- dup prepare-coalescing
- process-copies
- dup cleanup-cfg
- dup compute-live-sets ;
+: destruct-ssa ( cfg -- )
+ {
+ [ needs-dominance ]
+ [ construct-cssa ]
+ [ compute-defs ]
+ [ compute-insns ]
+ [ compute-live-sets ]
+ [ compute-live-ranges ]
+ [ prepare-coalescing ]
+ [ drop process-copies ]
+ [ cleanup-cfg ]
+ [ compute-live-sets ]
+ } cleave ;
: visit-block ( bb -- )
[ predecessors>> ] keep '[ _ visit-edge ] each ;
-: finalize-stack-shuffling ( cfg -- cfg' )
- dup
+: finalize-stack-shuffling ( cfg -- )
[ needs-predecessors ]
[ [ visit-block ] each-basic-block ]
[ cfg-changed ] tri ;
[ replace-set assoc-union ] bi ;
! Main word
-: compute-global-sets ( cfg -- cfg' )
+: compute-global-sets ( cfg -- )
{
[ compute-anticip-sets ]
[ compute-live-sets ]
[ compute-pending-sets ]
[ compute-dead-sets ]
[ compute-avail-sets ]
- [ ]
} cleave ;
: end-stack-analysis ( -- )
cfg get
- compute-global-sets
- finalize-stack-shuffling
- drop ;
+ [ compute-global-sets ]
+ [ finalize-stack-shuffling ] bi ;
: ds-drop ( -- ) -1 inc-d ;
[ ] [
0 get block>cfg dup cfg set
- dup value-numbering
- select-representations
- destruct-ssa drop
+ [ value-numbering ]
+ [ select-representations ]
+ [ destruct-ssa ] tri
] unit-test
[ 1 ] [ 1 get successors>> length ] unit-test
H{ } clone copies set
[ eliminate-write-barrier ] filter! ;
-: eliminate-write-barriers ( cfg -- cfg )
- dup [ write-barriers-step ] simple-optimization ;
+: eliminate-write-barriers ( cfg -- )
+ [ write-barriers-step ] simple-optimization ;
: backend ( tree word -- )
build-cfg [
[
- optimize-cfg finalize-cfg
- [ generate ] [ label>> ] bi compiled get set-at
+ [ optimize-cfg ]
+ [ finalize-cfg ]
+ [ [ generate ] [ label>> ] bi compiled get set-at ]
+ tri
] with-cfg
] each ;
-USING: accessors assocs compiler compiler.cfg
+USING: accessors assocs combinators compiler compiler.cfg
compiler.cfg.debugger compiler.cfg.instructions
compiler.cfg.registers compiler.cfg.linear-scan
compiler.cfg.ssa.destruction compiler.cfg.build-stack-frame
IN: compiler.tests.low-level-ir
: compile-cfg ( cfg -- word )
- gensym
- [ linear-scan build-stack-frame generate ] dip
+ gensym [
+ [ linear-scan ] [ build-stack-frame ] [ generate ] tri
+ ] dip
[ associate >alist t t modify-code-heap ] keep ;
: compile-test-cfg ( -- word )
- 0 get block>cfg
- dup cfg set
- dup fake-representations
- destruct-ssa
- compile-cfg ;
+ 0 get block>cfg {
+ [ cfg set ]
+ [ fake-representations ]
+ [ destruct-ssa ]
+ [ compile-cfg ]
+ } cleave ;
: compile-test-bb ( insns -- result )
V{ T{ ##prologue } T{ ##branch } } [ clone ] map 0 test-bb
[ add-cfg-vertex ] [ add-cfg-edges ] bi
] each-basic-block ;
-: perform-pass ( cfg pass pass# -- cfg' )
- drop def>> call( cfg -- cfg' ) ;
+: perform-pass ( cfg pass pass# -- )
+ drop def>> call( cfg -- ) ;
: draw-cfg ( cfg pass pass# -- cfg )
[ dup cfgviz ]
SYMBOL: passes
: watch-pass ( cfg pass pass# -- cfg' )
- [ perform-pass ] 2keep draw-cfg ;
+ [ perform-pass ] 3keep draw-cfg ;
: begin-watching-passes ( cfg -- cfg )
\ build-cfg 0 draw-cfg ;
dup compute-avail-sets
[ gcse-step ] simple-optimization ;
-: value-numbering ( cfg -- cfg )
- dup {
+: value-numbering ( cfg -- )
+ {
needs-predecessors
determine-value-numbers
eliminate-common-subexpressions