factor/basis/compiler/tree/cleanup/cleanup.factor

172 lines
4.9 KiB
Factor
Raw Normal View History

! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors sequences sequences.deep combinators fry
2008-08-28 23:28:34 -04:00
classes.algebra namespaces assocs words math math.private
2008-08-29 01:26:47 -04:00
math.partial-dispatch math.intervals classes classes.tuple
classes.tuple.private layouts definitions stack-checker.state
stack-checker.branches
compiler.intrinsics
compiler.tree
compiler.tree.combinators
compiler.tree.propagation.info
compiler.tree.propagation.branches ;
IN: compiler.tree.cleanup
! A phase run after propagation to finish the job, so to speak.
! Codifies speculative inlining decisions, deletes branches
! marked as never taken, and flattens local recursive blocks
2008-08-19 18:11:33 -04:00
! that do not call themselves.
2008-08-15 00:35:19 -04:00
GENERIC: delete-node ( node -- )
M: #call-recursive delete-node
dup label>> [ [ eq? not ] with filter ] change-calls drop ;
M: #return-recursive delete-node
label>> f >>return drop ;
M: node delete-node drop ;
: delete-nodes ( nodes -- ) [ delete-node ] each-node ;
GENERIC: cleanup* ( node -- node/nodes )
: cleanup ( nodes -- nodes' )
#! We don't recurse into children here, instead the methods
#! do it since the logic is a bit more involved
2008-08-22 16:30:57 -04:00
[ cleanup* ] map flatten ;
: cleanup-folding? ( #call -- ? )
2008-07-30 18:36:24 -04:00
node-output-infos dup empty?
[ drop f ] [ [ literal?>> ] all? ] if ;
: cleanup-folding ( #call -- nodes )
#! Replace a #call having a known result with a #drop of its
#! inputs followed by #push nodes for the outputs.
2008-08-30 03:31:27 -04:00
[ word>> inlined-dependency depends-on ]
[
[ node-output-infos ] [ out-d>> ] bi
[ [ literal>> ] dip #push ] 2map
]
2008-08-22 18:38:23 -04:00
[ in-d>> #drop ]
tri prefix ;
2008-08-30 03:31:27 -04:00
: add-method-dependency ( #call -- )
dup method>> word? [
2008-08-31 02:34:00 -04:00
[ word>> ] [ class>> ] bi depends-on-generic
2008-08-30 03:31:27 -04:00
] [ drop ] if ;
: cleanup-inlining ( #call -- nodes )
[
dup method>>
2008-08-30 03:31:27 -04:00
[ add-method-dependency ]
[ word>> inlined-dependency depends-on ] if
] [ body>> cleanup ] bi ;
! Removing overflow checks
: no-overflow-variant ( op -- fast-op )
H{
{ fixnum+ fixnum+fast }
{ fixnum- fixnum-fast }
{ fixnum* fixnum*fast }
{ fixnum-shift fixnum-shift-fast }
} at ;
2008-08-29 01:26:47 -04:00
: (remove-overflow-check?) ( #call -- ? )
node-output-infos first class>> fixnum class<= ;
: small-shift? ( #call -- ? )
node-input-infos second interval>>
2008-08-29 05:23:39 -04:00
cell-bits tag-bits get - [ neg ] keep [a,b] interval-subset? ;
2008-08-29 01:26:47 -04:00
: remove-overflow-check? ( #call -- ? )
2008-08-29 01:26:47 -04:00
{
{ [ dup word>> \ fixnum-shift eq? ] [ [ (remove-overflow-check?) ] [ small-shift? ] bi and ] }
{ [ dup word>> no-overflow-variant ] [ (remove-overflow-check?) ] }
[ drop f ]
} cond ;
: remove-overflow-check ( #call -- #call )
[ in-d>> ] [ out-d>> ] [ word>> no-overflow-variant ] tri #call cleanup* ;
M: #call cleanup*
{
{ [ dup body>> ] [ cleanup-inlining ] }
{ [ dup cleanup-folding? ] [ cleanup-folding ] }
{ [ dup remove-overflow-check? ] [ remove-overflow-check ] }
[ ]
} cond ;
2008-08-13 15:17:04 -04:00
M: #declare cleanup* drop f ;
: delete-unreachable-branches ( #branch -- )
dup live-branches>> '[
,
[ [ [ drop ] [ delete-nodes ] if ] 2each ]
[ select-children ]
2bi
] change-children drop ;
: fold-only-branch ( #branch -- node/nodes )
#! If only one branch is live we don't need to branch at
#! all; just drop the condition value.
dup live-children sift dup length {
{ 0 [ 2drop f ] }
{ 1 [ first swap in-d>> #drop prefix ] }
[ 2drop ]
} case ;
SYMBOL: live-branches
: cleanup-children ( #branch -- )
[ [ cleanup ] map ] change-children drop ;
M: #branch cleanup*
{
[ delete-unreachable-branches ]
[ cleanup-children ]
[ fold-only-branch ]
2008-08-10 00:00:27 -04:00
[ live-branches>> live-branches set ]
} cleave ;
: output-fs ( values -- nodes )
[ f swap #push ] map ;
2008-08-19 18:11:33 -04:00
: eliminate-single-phi ( #phi -- node )
[ phi-in-d>> first ] [ out-d>> ] bi over [ +bottom+ eq? ] all?
[ [ drop ] [ output-fs ] bi* ]
2008-08-19 18:11:33 -04:00
[ #copy ]
if ;
2008-08-18 22:30:10 -04:00
: eliminate-phi ( #phi -- node )
live-branches get sift length {
{ 0 [ out-d>> output-fs ] }
2008-08-19 18:11:33 -04:00
{ 1 [ eliminate-single-phi ] }
2008-08-18 22:30:10 -04:00
[ drop ]
} case ;
M: #phi cleanup*
#! Remove #phi function inputs which no longer exist.
live-branches get
[ '[ , sift-children ] change-phi-in-d ]
[ '[ , sift-children ] change-phi-info-d ]
[ '[ , sift-children ] change-terminated ] tri
2008-08-18 22:30:10 -04:00
eliminate-phi
2008-08-10 00:00:27 -04:00
live-branches off ;
: >copy ( node -- #copy ) [ in-d>> ] [ out-d>> ] bi #copy ;
: flatten-recursive ( #recursive -- nodes )
#! convert #enter-recursive and #return-recursive into
#! #copy nodes.
child>>
unclip >copy prefix
unclip-last >copy suffix ;
M: #recursive cleanup*
#! Inline bodies of #recursive blocks with no calls left.
[ cleanup ] change-child
dup label>> calls>> empty? [ flatten-recursive ] when ;
M: node cleanup* ;