1 ! Copyright (C) 2008, 2010 Slava Pestov, Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien.c-types kernel sequences words fry generic
4 generic.single accessors classes.tuple classes classes.algebra
5 definitions stack-checker.dependencies quotations
6 classes.tuple.private math math.partial-dispatch math.private
7 math.intervals sets.private math.floats.private
8 math.integers.private layouts math.order vectors hashtables
9 combinators effects generalizations sequences.generalizations
10 assocs sets combinators.short-circuit sequences.private locals
11 growable stack-checker namespaces compiler.tree.propagation.info
15 IN: compiler.tree.propagation.transforms
18 ! If first input has a known type and second input is an
19 ! object, we convert this to [ swap equal? ].
20 in-d>> first2 value-info class>> object class= [
21 value-info class>> \ equal? method-for-class
24 ] "custom-inlining" set-word-prop
26 : rem-custom-inlining ( #call -- quot/f )
27 second value-info literal>> dup integer?
28 [ power-of-2? [ 1 - bitand ] f ? ] [ drop f ] if ;
37 in-d>> dup first value-info interval>> [0,inf] interval-subset?
38 [ rem-custom-inlining ] [ drop f ] if
39 ] "custom-inlining" set-word-prop
43 in-d>> rem-custom-inlining
44 ] "custom-inlining" set-word-prop
46 : positive-fixnum? ( obj -- ? )
47 { [ fixnum? ] [ 0 >= ] } 1&& ;
49 : simplify-bitand? ( value1 value2 -- ? )
50 [ literal>> positive-fixnum? ]
51 [ class>> fixnum swap class<= ]
54 : all-ones? ( n -- ? ) dup 1 + bitand zero? ; inline
56 : redundant-bitand? ( value1 value2 -- ? )
57 [ interval>> ] [ literal>> ] bi* {
60 [ 0 swap [a,b] interval-subset? ]
63 : zero-bitand? ( value1 value2 -- ? )
64 [ interval>> ] [ literal>> ] bi* {
66 [ nip bitnot all-ones? ]
67 [ 0 swap bitnot [a,b] interval-subset? ]
71 bitand-integer-integer
77 in-d>> first2 [ value-info ] bi@ {
83 [ 2dup swap zero-bitand? ]
87 [ 2dup redundant-bitand? ]
91 [ 2dup swap redundant-bitand? ]
95 [ 2dup simplify-bitand? ]
96 [ 2drop [ >fixnum fixnum-bitand ] ]
99 [ 2dup swap simplify-bitand? ]
100 [ 2drop [ [ >fixnum ] dip fixnum-bitand ] ]
104 ] "custom-inlining" set-word-prop
109 in-d>> first value-info literal>> 1 eq? ;
113 cell-bits tag-bits get - 1 -
115 >fixnum dup 0 < [ 2drop 0 ] [
116 dup _ < [ fixnum-shift ] [
122 ] "custom-inlining" set-word-prop
124 { /i fixnum/i fixnum/i-fast bignum/i } [
126 in-d>> first2 [ value-info ] bi@ {
127 [ drop class>> integer class<= ]
128 [ drop interval>> 0 [a,a] interval>= ]
129 [ nip literal>> integer? ]
130 [ nip literal>> power-of-2? ]
131 } 2&& [ [ log2 neg shift ] ] [ f ] if
132 ] "custom-inlining" set-word-prop
135 ! Generate more efficient code for common idiom
137 in-d>> first value-info literal>> {
138 { V{ } [ [ drop { } 0 vector boa ] ] }
139 { H{ } [ [ drop 0 <hashtable> ] ] }
140 { HS{ } [ [ drop f fast-set ] ] }
143 ] "custom-inlining" set-word-prop
145 :: inline-instance ( node -- quot/f )
146 node in-d>> first2 [ value-info ] bi@ literal>> :> ( obj class )
150 [ obj class>> \ f class-not class-and class class<= ]
152 ! TODO: replace this with an implicit null check when
153 ! profitable, once Factor gets OSR implemented
156 class "predicate" word-prop '[ drop @ ]
160 \ instance? [ inline-instance ] "custom-inlining" set-word-prop
162 ERROR: bad-partial-eval quot word ;
164 : check-effect ( quot word -- )
165 2dup [ infer ] [ stack-effect ] bi* effect<=
166 [ 2drop ] [ bad-partial-eval ] if ;
168 :: define-partial-eval ( word quot n -- )
172 dup [ literal?>> ] all? [
177 dup word check-effect
180 ] "custom-inlining" set-word-prop ;
182 : inline-new ( class -- quot/f )
185 [ depends-on-tuple-layout ]
186 [ drop all-slots [ initial>> literalize ] [ ] map-as ]
192 \ new [ inline-new ] 1 define-partial-eval
195 : nths-quot ( indices -- quot )
196 [ [ '[ _ swap nth ] ] map ] [ length ] bi
197 '[ _ cleave _ narray ] ;
200 shuffle-mapping nths-quot
201 ] 1 define-partial-eval
207 dup length iota zip >hashtable '[ _ at ]
210 ] 1 define-partial-eval
212 : member-eq-quot ( seq -- newquot )
213 [ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
214 [ drop f ] suffix [ cond ] curry ;
217 dup sequence? [ member-eq-quot ] [ drop f ] if
218 ] 1 define-partial-eval
221 : member-quot ( seq -- newquot )
224 [ literalize [ t ] ] { } map>assoc linear-case-quot
230 dup sequence? [ member-quot ] [ drop f ] if
231 ] 1 define-partial-eval
233 ! Fast at for integer maps
234 CONSTANT: lookup-table-at-max 256
236 : lookup-table-at? ( assoc -- ? )
237 #! Can we use a fast byte array test here?
241 [ keys [ integer? ] all? ]
242 [ keys [ 0 lookup-table-at-max between? ] all? ]
245 : lookup-table-seq ( assoc -- table )
246 [ keys supremum 1 + iota ] keep '[ _ at ] { } map-as ;
248 : lookup-table-quot ( seq -- newquot )
253 nth-unsafe dup >boolean
258 : fast-lookup-table-at? ( assoc -- ? )
260 [ [ integer? ] all? ]
261 [ [ 0 254 between? ] all? ]
264 : fast-lookup-table-seq ( assoc -- table )
265 lookup-table-seq [ 255 or ] B{ } map-as ;
267 : fast-lookup-table-quot ( seq -- newquot )
268 fast-lookup-table-seq
272 nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
277 : at-quot ( assoc -- quot )
279 dup lookup-table-at? [
280 dup fast-lookup-table-at? [
281 fast-lookup-table-quot
288 \ at* [ at-quot ] 1 define-partial-eval
290 : diff-quot ( seq -- quot: ( seq' -- seq'' ) )
291 tester '[ [ [ @ not ] filter ] keep set-like ] ;
293 M\ set diff [ diff-quot ] 1 define-partial-eval
295 : intersect-quot ( seq -- quot: ( seq' -- seq'' ) )
296 tester '[ [ _ filter ] keep set-like ] ;
298 M\ set intersect [ intersect-quot ] 1 define-partial-eval
300 : fixnum-bits ( -- n )
301 cell-bits tag-bits get - ;
303 : bit-quot ( #call -- quot/f )
304 in-d>> second value-info interval>> 0 fixnum-bits [a,b] interval-subset?
305 [ [ >fixnum ] dip fixnum-bit? ] f ? ;
307 \ bit? [ bit-quot ] "custom-inlining" set-word-prop
309 ! Speeds up sum-file, sort and reverse-complement benchmarks by
310 ! compiling decoder-readln better
312 in-d>> second value-info class>> growable class<=
313 [ \ push def>> ] [ f ] if
314 ] "custom-inlining" set-word-prop
316 ! We want to constant-fold calls to heap-size, and recompile those
317 ! calls when a C type is redefined
319 [ depends-on-c-type ] [ heap-size '[ _ ] ] bi
320 ] 1 define-partial-eval
322 ! Eliminates a few redundant checks here and there
324 in-d>> first2 [ value-info class>> ] bi@ {
325 { [ 2dup [ fixnum classes-intersect? not ] either? ] [ [ 2drop f ] ] }
326 { [ 2dup [ fixnum class<= ] both? ] [ [ 2drop t ] ] }
327 { [ dup fixnum class<= ] [ [ drop fixnum? ] ] }
328 { [ over fixnum class<= ] [ [ nip fixnum? ] ] }
331 ] "custom-inlining" set-word-prop