! Copyright (C) 2008, 2010 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays assocs classes.algebra combinators compiler.tree compiler.tree.dead-code.liveness compiler.tree.propagation.info fry kernel locals math math.private namespaces sequences stack-checker.backend stack-checker.dependencies words ; IN: compiler.tree.dead-code.simple : flushable-call? ( call# -- ? ) dup word>> dup flushable? [ word>input-infos [ [ node-input-infos ] dip [ value-info<= ] 2all? ] [ drop t ] if* ] [ 2drop f ] if ; M: call# mark-live-values* dup flushable-call? [ drop ] [ look-at-inputs ] if ; M: alien-node# mark-live-values* look-at-inputs ; M: return# mark-live-values* look-at-inputs ; : look-at-mapping ( value inputs outputs -- ) [ index ] dip over [ nth look-at-value ] [ 2drop ] if ; M: copy# compute-live-values* ! If the output of a copy is live, then the corresponding ! input is live also. [ out-d>> ] [ in-d>> ] bi look-at-mapping ; M: call# compute-live-values* nip look-at-inputs ; M: shuffle# compute-live-values* mapping>> at look-at-value ; M: alien-node# compute-live-values* nip look-at-inputs ; : filter-mapping ( assoc -- assoc' ) live-values get '[ drop _ key? ] assoc-filter ; : filter-corresponding ( new old -- old' ) zip filter-mapping values ; : filter-live ( values -- values' ) dup empty? [ live-values get '[ _ at ] filter ] unless ; :: drop-values ( inputs outputs mapping-keys mapping-values -- shuffle# ) inputs outputs outputs mapping-keys mapping-values filter-corresponding zip ; inline :: drop-dead-values ( outputs -- shuffle# ) outputs length make-values :> new-outputs outputs filter-live :> live-outputs new-outputs live-outputs outputs new-outputs drop-values ; : drop-dead-outputs ( node -- shuffle# ) dup out-d>> drop-dead-values [ in-d>> >>out-d drop ] keep ; : some-outputs-dead? ( call# -- ? ) out-d>> [ live-value? not ] any? ; : maybe-drop-dead-outputs ( node -- nodes ) dup some-outputs-dead? [ dup drop-dead-outputs 2array ] when ; M: introduce# remove-dead-code* ( introduce# -- nodes ) maybe-drop-dead-outputs ; M: push# remove-dead-code* dup out-d>> first live-value? [ drop f ] unless ; : dead-flushable-call? ( call# -- ? ) dup flushable-call? [ out-d>> [ live-value? not ] all? ] [ drop f ] if ; : remove-flushable-call ( call# -- node ) [ word>> add-depends-on-flushable ] [ in-d>> remove-dead-code* ] bi ; : define-simplifications ( word seq -- ) "simplifications" set-word-prop ; ! true if dead \ /mod { { { f t } /i } { { t f } mod } } define-simplifications \ fixnum/mod { { { f t } fixnum/i } { { t f } fixnum-mod } } define-simplifications \ bignum/mod { { { f t } bignum/i } { { t f } bignum-mod } } define-simplifications : out-d-matches? ( out-d seq -- ? ) [ swap live-value? xor ] 2all? ; : (simplify-call) ( call# -- new-word/f ) [ out-d>> ] [ word>> "simplifications" word-prop ] bi [ first out-d-matches? ] with find nip dup [ second ] when ; : simplify-call ( call# -- nodes ) dup (simplify-call) [ >>word [ filter-live ] change-out-d ] [ maybe-drop-dead-outputs ] if* ; M: call# remove-dead-code* { { [ dup dead-flushable-call? ] [ remove-flushable-call ] } { [ dup word>> "simplifications" word-prop ] [ simplify-call ] } [ maybe-drop-dead-outputs ] } cond ; M: shuffle# remove-dead-code* [ filter-live ] change-in-d [ filter-live ] change-out-d [ filter-live ] change-in-r [ filter-live ] change-out-r [ filter-mapping ] change-mapping dup [ in-d>> empty? ] [ in-r>> empty? ] bi and [ drop f ] when ; M: copy# remove-dead-code* [ in-d>> ] [ out-d>> ] bi 2dup swap zip remove-dead-code* ; M: terminate# remove-dead-code* [ filter-live ] change-in-d [ filter-live ] change-in-r ; M: alien-node# remove-dead-code* maybe-drop-dead-outputs ; M: alien-callback# remove-dead-code* [ (remove-dead-code) ] change-child ;