2009-07-10 00:09:49 -04:00
|
|
|
! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
|
2008-09-12 19:08:38 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2009-08-15 19:42:41 -04:00
|
|
|
USING: math math.private math.partial-dispatch namespaces sequences
|
|
|
|
sets accessors assocs words kernel memoize fry combinators
|
2009-07-10 00:07:38 -04:00
|
|
|
combinators.short-circuit layouts alien.accessors
|
2008-09-12 19:08:38 -04:00
|
|
|
compiler.tree
|
|
|
|
compiler.tree.combinators
|
2009-08-15 19:42:41 -04:00
|
|
|
compiler.tree.propagation.info
|
2008-09-12 19:08:38 -04:00
|
|
|
compiler.tree.def-use
|
|
|
|
compiler.tree.def-use.simplified
|
|
|
|
compiler.tree.late-optimizations ;
|
|
|
|
IN: compiler.tree.modular-arithmetic
|
|
|
|
|
|
|
|
! This is a late-stage optimization.
|
|
|
|
! See the comment in compiler.tree.late-optimizations.
|
|
|
|
|
|
|
|
! Modular arithmetic optimization pass.
|
|
|
|
!
|
|
|
|
! { integer integer } declare + >fixnum
|
|
|
|
! ==>
|
|
|
|
! [ >fixnum ] bi@ fixnum+fast
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
! Words where the low-order bits of the output only depends on the
|
|
|
|
! low-order bits of the input. If the output is only used for its
|
|
|
|
! low-order bits, then the word can be converted into a form that is
|
|
|
|
! cheaper to compute.
|
2008-09-12 19:08:38 -04:00
|
|
|
{ + - * bitand bitor bitxor } [
|
|
|
|
[
|
|
|
|
t "modular-arithmetic" set-word-prop
|
|
|
|
] each-integer-derived-op
|
|
|
|
] each
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
{ bitand bitor bitxor bitnot >integer }
|
2008-09-12 19:08:38 -04:00
|
|
|
[ t "modular-arithmetic" set-word-prop ] each
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
! Words that only use the low-order bits of their input. If the input
|
|
|
|
! is a modular arithmetic word, then the input can be converted into
|
|
|
|
! a form that is cheaper to compute.
|
2009-07-10 00:07:38 -04:00
|
|
|
{
|
2009-08-15 19:42:41 -04:00
|
|
|
>fixnum bignum>fixnum float>fixnum
|
2009-07-10 00:07:38 -04:00
|
|
|
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
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
! Values which only have their low-order bits used. This set starts out
|
|
|
|
! big and is gradually refined.
|
|
|
|
SYMBOL: modular-values
|
2008-09-12 19:08:38 -04:00
|
|
|
|
|
|
|
: modular-value? ( value -- ? )
|
2009-08-15 19:42:41 -04:00
|
|
|
modular-values get key? ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: modular-value ( value -- )
|
|
|
|
modular-values get conjoin ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
! Values which are known to be fixnums.
|
|
|
|
SYMBOL: fixnum-values
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: fixnum-value? ( value -- ? )
|
|
|
|
fixnum-values get key? ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: fixnum-value ( value -- )
|
|
|
|
fixnum-values get conjoin ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
GENERIC: compute-modular-candidates* ( node -- )
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
M: #push compute-modular-candidates*
|
|
|
|
[ out-d>> first ] [ literal>> ] bi
|
|
|
|
real? [ [ modular-value ] [ fixnum-value ] bi ] [ drop ] if ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
M: #call compute-modular-candidates*
|
|
|
|
{
|
|
|
|
{
|
|
|
|
[ dup word>> "modular-arithmetic" word-prop ]
|
|
|
|
[ out-d>> first [ modular-value ] [ fixnum-value ] bi ]
|
|
|
|
}
|
|
|
|
{
|
|
|
|
[ dup word>> "low-order" word-prop ]
|
|
|
|
[ in-d>> first modular-value ]
|
|
|
|
}
|
|
|
|
[ drop ]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
M: node compute-modular-candidates*
|
|
|
|
drop ;
|
|
|
|
|
|
|
|
: compute-modular-candidates ( nodes -- )
|
|
|
|
H{ } clone modular-values set
|
|
|
|
H{ } clone fixnum-values set
|
|
|
|
[ compute-modular-candidates* ] each-node ;
|
|
|
|
|
|
|
|
GENERIC: only-reads-low-order? ( node -- ? )
|
|
|
|
|
|
|
|
M: #call only-reads-low-order?
|
|
|
|
{
|
|
|
|
[ word>> "low-order" word-prop ]
|
|
|
|
[
|
|
|
|
{
|
|
|
|
[ word>> "modular-arithmetic" word-prop ]
|
|
|
|
[ out-d>> first modular-values get key? ]
|
|
|
|
} 1&&
|
|
|
|
]
|
|
|
|
} 1|| ;
|
|
|
|
|
|
|
|
M: node only-reads-low-order? drop f ;
|
|
|
|
|
|
|
|
SYMBOL: changed?
|
|
|
|
|
|
|
|
: only-used-as-low-order? ( value -- ? )
|
|
|
|
actually-used-by [ node>> only-reads-low-order? ] all? ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: (compute-modular-values) ( -- )
|
|
|
|
modular-values get keys [
|
|
|
|
dup only-used-as-low-order?
|
|
|
|
[ drop ] [ modular-values get delete-at changed? on ] if
|
|
|
|
] each ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: compute-modular-values ( -- )
|
|
|
|
[ changed? off (compute-modular-values) changed? get ] loop ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
|
|
|
GENERIC: optimize-modular-arithmetic* ( node -- nodes )
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
M: #push optimize-modular-arithmetic*
|
|
|
|
dup out-d>> first modular-value? [
|
|
|
|
[ >fixnum ] change-literal
|
|
|
|
] when ;
|
|
|
|
|
|
|
|
: input-will-be-fixnum? ( #call -- ? )
|
|
|
|
in-d>> first actually-defined-by
|
|
|
|
[ value>> { [ modular-value? ] [ fixnum-value? ] } 1&& ] all? ;
|
|
|
|
|
|
|
|
: output-will-be-coerced? ( #call -- ? )
|
|
|
|
out-d>> first modular-value? ;
|
|
|
|
|
2008-09-12 19:08:38 -04:00
|
|
|
: redundant->fixnum? ( #call -- ? )
|
2009-08-15 19:42:41 -04:00
|
|
|
{
|
|
|
|
[ input-will-be-fixnum? ]
|
|
|
|
[ output-will-be-coerced? ]
|
|
|
|
} 1|| ;
|
2008-09-12 19:08:38 -04:00
|
|
|
|
|
|
|
: optimize->fixnum ( #call -- nodes )
|
|
|
|
dup redundant->fixnum? [ drop f ] when ;
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: should-be->fixnum? ( #call -- ? )
|
|
|
|
out-d>> first modular-value? ;
|
|
|
|
|
2009-05-07 13:54:23 -04:00
|
|
|
: optimize->integer ( #call -- nodes )
|
2009-08-15 19:42:41 -04:00
|
|
|
dup should-be->fixnum? [ \ >fixnum >>word ] when ;
|
2009-05-07 13:54:23 -04:00
|
|
|
|
2008-09-12 19:08:38 -04:00
|
|
|
MEMO: fixnum-coercion ( flags -- nodes )
|
2009-08-15 19:42:41 -04:00
|
|
|
! flags indicate which input parameters are already known to be fixnums,
|
|
|
|
! and don't need a coercion as a result.
|
2008-09-12 19:08:38 -04:00
|
|
|
[ [ ] [ >fixnum ] ? ] map '[ _ spread ] splice-quot ;
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: modular-value-info ( #call -- alist )
|
|
|
|
[ in-d>> ] [ out-d>> ] bi append
|
|
|
|
fixnum <class-info> '[ _ ] { } map>assoc ;
|
|
|
|
|
2008-09-12 19:08:38 -04:00
|
|
|
: optimize-modular-op ( #call -- nodes )
|
|
|
|
dup out-d>> first modular-value? [
|
|
|
|
[ in-d>> ] [ word>> integer-op-input-classes ] [ ] tri
|
|
|
|
[
|
|
|
|
[
|
2009-08-15 19:42:41 -04:00
|
|
|
[ actually-defined-by [ value>> modular-value? ] all? ]
|
2008-09-12 19:08:38 -04:00
|
|
|
[ fixnum eq? ]
|
|
|
|
bi* or
|
|
|
|
] 2map fixnum-coercion
|
|
|
|
] [ [ modular-variant ] change-word ] bi* suffix
|
|
|
|
] when ;
|
|
|
|
|
2009-08-15 19:42:41 -04:00
|
|
|
: optimize-low-order-op ( #call -- nodes )
|
|
|
|
dup in-d>> first modular-value? [
|
|
|
|
[ ] [ in-d>> first ] [ info>> ] tri
|
|
|
|
[ drop fixnum <class-info> ] change-at
|
|
|
|
] when ;
|
|
|
|
|
2008-09-12 19:08:38 -04:00
|
|
|
M: #call optimize-modular-arithmetic*
|
|
|
|
dup word>> {
|
2009-08-15 19:42:41 -04:00
|
|
|
{ [ dup { >fixnum bignum>fixnum float>fixnum } memq? ] [ drop optimize->fixnum ] }
|
2009-05-07 13:54:23 -04:00
|
|
|
{ [ dup \ >integer eq? ] [ drop optimize->integer ] }
|
2008-09-12 19:08:38 -04:00
|
|
|
{ [ dup "modular-arithmetic" word-prop ] [ drop optimize-modular-op ] }
|
2009-08-15 19:42:41 -04:00
|
|
|
{ [ dup "low-order" word-prop ] [ drop optimize-low-order-op ] }
|
2008-09-12 19:08:38 -04:00
|
|
|
[ drop ]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
M: node optimize-modular-arithmetic* ;
|
|
|
|
|
|
|
|
: optimize-modular-arithmetic ( nodes -- nodes' )
|
2009-08-15 19:42:41 -04:00
|
|
|
dup compute-modular-candidates compute-modular-values
|
2008-09-12 19:08:38 -04:00
|
|
|
[ optimize-modular-arithmetic* ] map-nodes ;
|