1 ! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences words fry generic accessors
4 classes.tuple classes classes.algebra definitions
5 stack-checker.state quotations classes.tuple.private math
6 math.partial-dispatch math.private math.intervals sets.private
7 math.floats.private math.integers.private layouts math.order
8 vectors hashtables combinators effects generalizations assocs
9 sets combinators.short-circuit sequences.private locals
10 stack-checker namespaces compiler.tree.propagation.info ;
11 IN: compiler.tree.propagation.transforms
14 ! If first input has a known type and second input is an
15 ! object, we convert this to [ swap equal? ].
16 in-d>> first2 value-info class>> object class= [
17 value-info class>> \ equal? method-for-class
20 ] "custom-inlining" set-word-prop
22 : rem-custom-inlining ( #call -- quot/f )
23 second value-info literal>> dup integer?
24 [ power-of-2? [ 1 - bitand ] f ? ] [ drop f ] if ;
33 in-d>> dup first value-info interval>> [0,inf] interval-subset?
34 [ rem-custom-inlining ] [ drop f ] if
35 ] "custom-inlining" set-word-prop
39 in-d>> rem-custom-inlining
40 ] "custom-inlining" set-word-prop
42 : positive-fixnum? ( obj -- ? )
43 { [ fixnum? ] [ 0 >= ] } 1&& ;
45 : simplify-bitand? ( value1 value2 -- ? )
46 [ literal>> positive-fixnum? ]
47 [ class>> fixnum swap class<= ]
50 : all-ones? ( n -- ? ) dup 1 + bitand zero? ; inline
52 : redundant-bitand? ( value1 value2 -- ? )
53 [ interval>> ] [ literal>> ] bi* {
56 [ 0 swap [a,b] interval-subset? ]
59 : zero-bitand? ( value1 value2 -- ? )
60 [ interval>> ] [ literal>> ] bi* {
62 [ nip bitnot all-ones? ]
63 [ 0 swap bitnot [a,b] interval-subset? ]
67 bitand-integer-integer
73 in-d>> first2 [ value-info ] bi@ {
79 [ 2dup swap zero-bitand? ]
83 [ 2dup redundant-bitand? ]
87 [ 2dup swap redundant-bitand? ]
91 [ 2dup simplify-bitand? ]
92 [ 2drop [ >fixnum fixnum-bitand ] ]
95 [ 2dup swap simplify-bitand? ]
96 [ 2drop [ [ >fixnum ] dip fixnum-bitand ] ]
100 ] "custom-inlining" set-word-prop
105 in-d>> first2 [ value-info ] bi@
106 [ { [ literal>> 1 = ] [ class>> fixnum class<= ] } 1&& ]
107 [ class>> fixnum class<= ]
112 cell-bits tag-bits get - 1 -
114 >fixnum dup 0 < [ 2drop 0 ] [
115 dup _ < [ fixnum-shift ] [
121 ] "custom-inlining" set-word-prop
123 { /i fixnum/i fixnum/i-fast bignum/i } [
125 in-d>> first2 [ value-info ] bi@ {
126 [ drop class>> integer class<= ]
127 [ drop interval>> 0 [a,a] interval>= ]
128 [ nip literal>> integer? ]
129 [ nip literal>> power-of-2? ]
130 } 2&& [ [ log2 neg shift ] ] [ f ] if
131 ] "custom-inlining" set-word-prop
134 ! Integrate this with generic arithmetic optimization instead?
135 : both-inputs? ( #call class -- ? )
136 [ in-d>> first2 ] dip '[ value-info class>> _ class<= ] both? ;
140 { [ dup fixnum both-inputs? ] [ [ fixnum-min ] ] }
141 { [ dup float both-inputs? ] [ [ float-min ] ] }
144 ] "custom-inlining" set-word-prop
148 { [ dup fixnum both-inputs? ] [ [ fixnum-max ] ] }
149 { [ dup float both-inputs? ] [ [ float-max ] ] }
152 ] "custom-inlining" set-word-prop
154 ! Generate more efficient code for common idiom
156 in-d>> first value-info literal>> {
157 { V{ } [ [ drop { } 0 vector boa ] ] }
158 { H{ } [ [ drop 0 <hashtable> ] ] }
161 ] "custom-inlining" set-word-prop
163 ERROR: bad-partial-eval quot word ;
165 : check-effect ( quot word -- )
166 2dup [ infer ] [ stack-effect ] bi* effect<=
167 [ 2drop ] [ bad-partial-eval ] if ;
169 :: define-partial-eval ( word quot n -- )
173 dup [ literal?>> ] all? [
178 dup word check-effect
181 ] "custom-inlining" set-word-prop ;
183 : inline-new ( class -- quot/f )
185 dup inlined-dependency depends-on
186 [ all-slots [ initial>> literalize ] map ]
187 [ tuple-layout '[ _ <tuple-boa> ] ]
191 \ new [ inline-new ] 1 define-partial-eval
195 [ "predicate" word-prop ] [ drop f ] if
196 ] 1 define-partial-eval
199 : nths-quot ( indices -- quot )
200 [ [ '[ _ swap nth ] ] map ] [ length ] bi
201 '[ _ cleave _ narray ] ;
204 shuffle-mapping nths-quot
205 ] 1 define-partial-eval
211 dup length zip >hashtable '[ _ at ]
214 ] 1 define-partial-eval
216 : member-eq-quot ( seq -- newquot )
217 [ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
218 [ drop f ] suffix [ cond ] curry ;
221 dup sequence? [ member-eq-quot ] [ drop f ] if
222 ] 1 define-partial-eval
225 : member-quot ( seq -- newquot )
228 [ literalize [ t ] ] { } map>assoc linear-case-quot
230 unique [ key? ] curry
234 dup sequence? [ member-quot ] [ drop f ] if
235 ] 1 define-partial-eval
237 ! Fast at for integer maps
238 CONSTANT: lookup-table-at-max 256
240 : lookup-table-at? ( assoc -- ? )
241 #! Can we use a fast byte array test here?
245 [ keys [ integer? ] all? ]
246 [ keys [ 0 lookup-table-at-max between? ] all? ]
249 : lookup-table-seq ( assoc -- table )
250 [ keys supremum 1 + ] keep '[ _ at ] { } map-as ;
252 : lookup-table-quot ( seq -- newquot )
257 nth-unsafe dup >boolean
262 : fast-lookup-table-at? ( assoc -- ? )
264 [ [ integer? ] all? ]
265 [ [ 0 254 between? ] all? ]
268 : fast-lookup-table-seq ( assoc -- table )
269 lookup-table-seq [ 255 or ] B{ } map-as ;
271 : fast-lookup-table-quot ( seq -- newquot )
272 fast-lookup-table-seq
276 nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
281 : at-quot ( assoc -- quot )
283 dup lookup-table-at? [
284 dup fast-lookup-table-at? [
285 fast-lookup-table-quot
292 \ at* [ at-quot ] 1 define-partial-eval
294 : diff-quot ( seq -- quot: ( seq' -- seq'' ) )
295 tester '[ [ @ not ] filter ] ;
297 \ diff [ diff-quot ] 1 define-partial-eval
299 : intersect-quot ( seq -- quot: ( seq' -- seq'' ) )
300 tester '[ _ filter ] ;
302 \ intersect [ intersect-quot ] 1 define-partial-eval
304 : fixnum-bits ( -- n )
305 cell-bits tag-bits get - ;
307 : bit-quot ( #call -- quot/f )
308 in-d>> second value-info interval>> 0 fixnum-bits [a,b] interval-subset?
309 [ [ >fixnum ] dip fixnum-bit? ] f ? ;
311 \ bit? [ bit-quot ] "custom-inlining" set-word-prop