1 ! Copyright (C) 2008, 2011 Slava Pestov, Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types assocs classes classes.algebra
4 classes.tuple classes.tuple.private combinators
5 combinators.short-circuit compiler.tree.propagation.info effects
6 fry generalizations generic generic.single growable hash-sets
7 hashtables kernel layouts locals math math.integers.private
8 math.intervals math.order math.partial-dispatch math.private
9 namespaces quotations sequences sequences.generalizations
10 sequences.private sets sets.private stack-checker
11 stack-checker.dependencies vectors words ;
13 FROM: sets => set members ;
14 IN: compiler.tree.propagation.transforms
17 ! If first input has a known type and second input is an
18 ! object, we convert this to [ swap equal? ].
19 in-d>> first2 value-info class>> object class= [
20 value-info class>> \ equal? method-for-class
23 ] "custom-inlining" set-word-prop
25 : rem-custom-inlining ( inputs -- quot/f )
26 dup first value-info class>> integer class<= [
27 second value-info literal>> dup integer?
28 [ power-of-2? [ 1 - bitand ] f ? ] [ drop f ] if
38 in-d>> dup first value-info interval>> [0,inf] interval-subset?
39 [ rem-custom-inlining ] [ drop f ] if
40 ] "custom-inlining" set-word-prop
44 in-d>> rem-custom-inlining
45 ] "custom-inlining" set-word-prop
47 : non-negative-fixnum? ( obj -- ? )
48 { [ fixnum? ] [ 0 >= ] } 1&& ;
50 : simplify-bitand? ( value1 value2 -- ? )
51 [ literal>> non-negative-fixnum? ]
52 [ class>> fixnum swap class<= ]
55 : all-ones? ( n -- ? ) dup 1 + bitand zero? ; inline
57 : redundant-bitand? ( value1 value2 -- ? )
58 [ interval>> ] [ literal>> ] bi* {
61 [ 0 swap [a,b] interval-subset? ]
64 : zero-bitand? ( value1 value2 -- ? )
65 [ interval>> ] [ literal>> ] bi* {
67 [ nip bitnot all-ones? ]
68 [ 0 swap bitnot [a,b] interval-subset? ]
72 bitand-integer-integer
78 in-d>> first2 [ value-info ] bi@ {
84 [ 2dup swap zero-bitand? ]
88 [ 2dup redundant-bitand? ]
92 [ 2dup swap redundant-bitand? ]
96 [ 2dup simplify-bitand? ]
97 [ 2drop [ integer>fixnum fixnum-bitand ] ]
100 [ 2dup swap simplify-bitand? ]
101 [ 2drop [ [ integer>fixnum ] dip fixnum-bitand ] ]
105 ] "custom-inlining" set-word-prop
110 in-d>> first value-info literal>> 1 eq? ;
112 : shift-2^ ( -- quot )
113 cell-bits tag-bits get - 1 -
115 integer>fixnum-strict dup 0 < [ 2drop 0 ] [
116 dup _ < [ fixnum-shift ] [
124 in-d>> second value-info literal>> -1 eq? ;
126 : shift-2/ ( -- quot )
129 { [ over fixnum? ] [ fixnum-shift ] }
130 { [ over bignum? ] [ bignum-shift ] }
131 [ drop \ shift no-method ]
137 { [ dup 2^? ] [ drop shift-2^ ] }
138 { [ dup 2/? ] [ drop shift-2/ ] }
141 ] "custom-inlining" set-word-prop
143 { /i fixnum/i fixnum/i-fast bignum/i } [
145 in-d>> first2 [ value-info ] bi@ {
146 [ drop class>> integer class<= ]
147 [ drop interval>> 0 [a,a] interval>= ]
148 [ nip literal>> integer? ]
149 [ nip literal>> power-of-2? ]
150 } 2&& [ [ log2 neg shift ] ] [ f ] if
151 ] "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> ] ] }
159 { HS{ } [ [ drop 0 <hash-set> ] ] }
162 ] "custom-inlining" set-word-prop
164 ERROR: bad-partial-eval quot word ;
166 : check-effect ( quot word -- )
167 2dup [ infer ] [ stack-effect ] bi* effect<=
168 [ 2drop ] [ bad-partial-eval ] if ;
170 :: define-partial-eval ( word quot n -- )
174 dup [ literal?>> ] all? [
179 dup word check-effect
182 ] "custom-inlining" set-word-prop ;
184 : inline-new ( class -- quot/f )
187 [ add-depends-on-tuple-layout ]
188 [ drop all-slots [ initial>> literalize ] [ ] map-as ]
194 \ new [ inline-new ] 1 define-partial-eval
200 ! union{ and intersection{ have useless expansions, and recurse infinitely
201 dup { [ length 2 >= ] [ second \ instance? = ] } 1&& [
205 ] 1 define-partial-eval
208 : nths-quot ( indices -- quot )
209 [ [ '[ _ swap nth ] ] map ] [ length ] bi
210 '[ _ cleave _ narray ] ;
213 shuffle-mapping nths-quot
214 ] 1 define-partial-eval
220 H{ } zip-index-as '[ _ at ]
223 ] 1 define-partial-eval
225 : member-eq-quot ( seq -- newquot )
226 [ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
227 [ drop f ] suffix [ cond ] curry ;
230 dup sequence? [ member-eq-quot ] [ drop f ] if
231 ] 1 define-partial-eval
234 : member-quot ( seq -- newquot )
237 [ literalize [ t ] ] { } map>assoc linear-case-quot
243 dup sequence? [ member-quot ] [ drop f ] if
244 ] 1 define-partial-eval
246 ! Fast at for integer maps
247 CONSTANT: lookup-table-at-max 256
249 : lookup-table-at? ( assoc -- ? )
250 #! Can we use a fast byte array test here?
254 [ keys [ integer? ] all? ]
255 [ keys [ 0 lookup-table-at-max between? ] all? ]
258 : lookup-table-seq ( assoc -- table )
259 [ keys supremum 1 + iota ] keep '[ _ at ] { } map-as ;
261 : lookup-table-quot ( seq -- newquot )
266 nth-unsafe dup >boolean
271 : fast-lookup-table-at? ( assoc -- ? )
273 [ [ integer? ] all? ]
274 [ [ 0 254 between? ] all? ]
277 : fast-lookup-table-seq ( assoc -- table )
278 lookup-table-seq [ 255 or ] B{ } map-as ;
280 : fast-lookup-table-quot ( seq -- newquot )
281 fast-lookup-table-seq
285 nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
290 : at-quot ( assoc -- quot )
292 dup lookup-table-at? [
293 dup fast-lookup-table-at? [
294 fast-lookup-table-quot
301 \ at* [ at-quot ] 1 define-partial-eval
303 : diff-quot ( seq -- quot: ( seq' -- seq'' ) )
304 [ tester ] keep '[ members [ @ not ] filter _ set-like ] ;
306 M\ set diff [ diff-quot ] 1 define-partial-eval
308 : intersect-quot ( seq -- quot: ( seq' -- seq'' ) )
309 [ tester ] keep '[ members _ filter _ set-like ] ;
311 M\ set intersect [ intersect-quot ] 1 define-partial-eval
313 : intersects?-quot ( seq -- quot: ( seq' -- seq'' ) )
314 tester '[ members _ any? ] ;
316 M\ set intersects? [ intersects?-quot ] 1 define-partial-eval
318 : bit-quot ( #call -- quot/f )
319 in-d>> second value-info interval>> 0 fixnum-bits [a,b] interval-subset?
320 [ [ integer>fixnum ] dip fixnum-bit? ] f ? ;
322 \ bit? [ bit-quot ] "custom-inlining" set-word-prop
324 ! Speeds up sum-file, sort and reverse-complement benchmarks by
325 ! compiling decoder-readln better
327 in-d>> second value-info class>> growable class<=
328 [ \ push def>> ] [ f ] if
329 ] "custom-inlining" set-word-prop
331 : custom-inline-fixnum ( #call method -- y )
332 [ in-d>> first value-info class>> fixnum \ f class-or class<= ] dip
333 '[ [ dup [ _ no-method ] unless ] ] [ f ] if ;
335 ! Speeds up fasta benchmark
336 { >fixnum integer>fixnum integer>fixnum-strict } [
337 dup '[ _ custom-inline-fixnum ] "custom-inlining" set-word-prop
340 ! We want to constant-fold calls to heap-size, and recompile those
341 ! calls when a C type is redefined
343 [ add-depends-on-c-type ] [ heap-size '[ _ ] ] bi
344 ] 1 define-partial-eval
346 ! Eliminates a few redundant checks here and there
348 in-d>> first2 [ value-info class>> ] bi@ {
349 { [ 2dup [ fixnum classes-intersect? not ] either? ] [ [ 2drop f ] ] }
350 { [ 2dup [ fixnum class<= ] both? ] [ [ 2drop t ] ] }
351 { [ dup fixnum class<= ] [ [ drop fixnum? ] ] }
352 { [ over fixnum class<= ] [ [ nip fixnum? ] ] }
355 ] "custom-inlining" set-word-prop