factor/unfinished/compiler/tree/dead-code/dead-code.factor

202 lines
5.2 KiB
Factor
Raw Normal View History

2008-07-20 05:24:37 -04:00
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: fry accessors namespaces assocs dequeues search-dequeues
kernel sequences words sets stack-checker.inlining compiler.tree
compiler.tree.combinators compiler.tree.def-use ;
IN: compiler.tree.dead-code
! Dead code elimination: remove #push and flushable #call whose
! outputs are unused.
SYMBOL: live-values
SYMBOL: work-list
: live-value? ( value -- ? )
live-values get at ;
: look-at-value ( values -- )
work-list get push-front ;
: look-at-values ( values -- )
work-list get '[ , push-front ] each ;
GENERIC: mark-live-values ( node -- )
: look-at-inputs ( node -- ) in-d>> look-at-values ;
: look-at-outputs ( node -- ) out-d>> look-at-values ;
M: #introduce mark-live-values look-at-outputs ;
M: #if mark-live-values look-at-inputs ;
M: #dispatch mark-live-values look-at-inputs ;
M: #call mark-live-values
dup word>> "flushable" word-prop [ drop ] [
[ look-at-inputs ]
[ look-at-outputs ]
bi
] if ;
M: #return mark-live-values
#! Values returned by local #recursive functions can be
#! killed if they're unused.
dup label>>
[ drop ] [ look-at-inputs ] if ;
M: node mark-live-values drop ;
GENERIC: propagate* ( value node -- )
M: #copy propagate*
#! If the output of a copy is live, then the corresponding
#! input is live also.
[ out-d>> index ] keep in-d>> nth look-at-value ;
M: #call propagate*
#! If any of the outputs of a call are live, then all
#! inputs and outputs must be live.
nip [ look-at-inputs ] [ look-at-outputs ] bi ;
M: #call-recursive propagate*
#! If the output of a copy is live, then the corresponding
#! inputs to #return nodes are live also.
[ out-d>> <reversed> index ] keep label>> returns>>
[ <reversed> nth look-at-value ] with each ;
M: #>r propagate* nip in-d>> first look-at-value ;
M: #r> propagate* nip in-r>> first look-at-value ;
M: #shuffle propagate* mapping>> at look-at-value ;
: look-at-corresponding ( value inputs outputs -- )
[ index ] dip over [ nth look-at-values ] [ 2drop ] if ;
M: #phi propagate*
#! If any of the outputs of a #phi are live, then the
#! corresponding inputs are live too.
2008-07-22 05:45:03 -04:00
[ [ out-d>> ] [ phi-in-d>> ] bi look-at-corresponding ]
[ [ out-r>> ] [ phi-in-r>> ] bi look-at-corresponding ]
2008-07-20 05:24:37 -04:00
2bi ;
M: node propagate* 2drop ;
: propogate-liveness ( value -- )
live-values get 2dup key? [
2drop
] [
dupd conjoin
dup defined-by propagate*
] if ;
: compute-live-values ( node -- )
#! We add f initially because #phi nodes can have f in their
#! inputs.
<hashed-dlist> work-list set
H{ { f f } } clone live-values set
[ mark-live-values ] each-node
work-list get [ propogate-liveness ] slurp-dequeue ;
GENERIC: remove-dead-values* ( node -- )
M: #>r remove-dead-values*
dup out-r>> first live-value? [ { } >>out-r ] unless
dup in-d>> first live-value? [ { } >>in-d ] unless
drop ;
M: #r> remove-dead-values*
dup out-d>> first live-value? [ { } >>out-d ] unless
dup in-r>> first live-value? [ { } >>in-r ] unless
drop ;
M: #push remove-dead-values*
dup out-d>> first live-value? [ { } >>out-d ] unless
drop ;
: filter-corresponding-values ( in out -- in' out' )
zip live-values get '[ drop _ , key? ] assoc-filter unzip ;
: remove-dead-copies ( node -- )
dup
[ in-d>> ] [ out-d>> ] bi
filter-corresponding-values
[ >>in-d ] [ >>out-d ] bi*
drop ;
: filter-live ( values -- values' )
[ live-value? ] filter ;
M: #shuffle remove-dead-values*
[ filter-live ] change-in-d
[ filter-live ] change-out-d
drop ;
M: #declare remove-dead-values* remove-dead-copies ;
M: #copy remove-dead-values* remove-dead-copies ;
: remove-dead-phi-d ( #phi -- #phi )
dup
2008-07-22 05:45:03 -04:00
[ phi-in-d>> ] [ out-d>> ] bi
2008-07-20 05:24:37 -04:00
filter-corresponding-values
2008-07-22 05:45:03 -04:00
[ >>phi-in-d ] [ >>out-d ] bi* ;
2008-07-20 05:24:37 -04:00
: remove-dead-phi-r ( #phi -- #phi )
dup
2008-07-22 05:45:03 -04:00
[ phi-in-r>> ] [ out-r>> ] bi
2008-07-20 05:24:37 -04:00
filter-corresponding-values
2008-07-22 05:45:03 -04:00
[ >>phi-in-r ] [ >>out-r ] bi* ;
2008-07-20 05:24:37 -04:00
M: #phi remove-dead-values*
remove-dead-phi-d
remove-dead-phi-r
drop ;
M: node remove-dead-values* drop ;
GENERIC: remove-dead-nodes* ( node -- newnode/t )
: live-call? ( #call -- ? )
out-d>> [ live-value? ] contains? ;
M: #call remove-dead-nodes*
dup live-call? [ drop t ] [
[ in-d>> #drop ] [ successor>> ] bi >>successor
] if ;
: prune-if ( node quot -- successor/t )
over >r call [ r> successor>> ] [ r> drop t ] if ;
inline
M: #shuffle remove-dead-nodes*
[ in-d>> empty? ] prune-if ;
M: #push remove-dead-nodes*
[ out-d>> empty? ] prune-if ;
M: #>r remove-dead-nodes*
[ in-d>> empty? ] prune-if ;
M: #r> remove-dead-nodes*
[ in-r>> empty? ] prune-if ;
M: node remove-dead-nodes* drop t ;
: (remove-dead-code) ( node -- newnode )
dup [
dup remove-dead-values*
dup remove-dead-nodes* dup t eq? [
drop dup [ (remove-dead-code) ] map-children
] [
nip (remove-dead-code)
] if
] when ;
: remove-dead-code ( node -- newnode )
[
[ compute-live-values ]
[ [ (remove-dead-code) ] transform-nodes ] bi
] with-scope ;