]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/tree/propagation/transforms/transforms.factor
Merge branch 'master' of git://github.com/erikcharlebois/factor
[factor.git] / basis / compiler / tree / propagation / transforms / transforms.factor
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 accessors
4 classes.tuple classes classes.algebra definitions
5 stack-checker.dependencies 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 growable
10 stack-checker namespaces compiler.tree.propagation.info ;
11 FROM: math => float ;
12 IN: compiler.tree.propagation.transforms
13
14 \ equal? [
15     ! If first input has a known type and second input is an
16     ! object, we convert this to [ swap equal? ].
17     in-d>> first2 value-info class>> object class= [
18         value-info class>> \ equal? method-for-class
19         [ swap equal? ] f ?
20     ] [ drop f ] if
21 ] "custom-inlining" set-word-prop
22
23 : rem-custom-inlining ( #call -- quot/f )
24     second value-info literal>> dup integer?
25     [ power-of-2? [ 1 - bitand ] f ? ] [ drop f ] if ;
26
27 {
28     mod-integer-integer
29     mod-integer-fixnum
30     mod-fixnum-integer
31     fixnum-mod
32 } [
33     [
34         in-d>> dup first value-info interval>> [0,inf] interval-subset?
35         [ rem-custom-inlining ] [ drop f ] if
36     ] "custom-inlining" set-word-prop
37 ] each
38
39 \ rem [
40     in-d>> rem-custom-inlining
41 ] "custom-inlining" set-word-prop
42
43 : positive-fixnum? ( obj -- ? )
44     { [ fixnum? ] [ 0 >= ] } 1&& ;
45
46 : simplify-bitand? ( value1 value2 -- ? )
47     [ literal>> positive-fixnum? ]
48     [ class>> fixnum swap class<= ]
49     bi* and ;
50
51 : all-ones? ( n -- ? ) dup 1 + bitand zero? ; inline
52
53 : redundant-bitand? ( value1 value2 -- ? )
54     [ interval>> ] [ literal>> ] bi* {
55         [ nip integer? ]
56         [ nip all-ones? ]
57         [ 0 swap [a,b] interval-subset? ]
58     } 2&& ;
59
60 : zero-bitand? ( value1 value2 -- ? )
61     [ interval>> ] [ literal>> ] bi* {
62         [ nip integer? ]
63         [ nip bitnot all-ones? ]
64         [ 0 swap bitnot [a,b] interval-subset? ]
65     } 2&& ;
66
67 {
68     bitand-integer-integer
69     bitand-integer-fixnum
70     bitand-fixnum-integer
71     bitand
72 } [
73     [
74         in-d>> first2 [ value-info ] bi@ {
75             {
76                 [ 2dup zero-bitand? ]
77                 [ 2drop [ 2drop 0 ] ]
78             }
79             {
80                 [ 2dup swap zero-bitand? ]
81                 [ 2drop [ 2drop 0 ] ]
82             }
83             {
84                 [ 2dup redundant-bitand? ]
85                 [ 2drop [ drop ] ]
86             }
87             {
88                 [ 2dup swap redundant-bitand? ]
89                 [ 2drop [ nip ] ]
90             }
91             {
92                 [ 2dup simplify-bitand? ]
93                 [ 2drop [ >fixnum fixnum-bitand ] ]
94             }
95             {
96                 [ 2dup swap simplify-bitand? ]
97                 [ 2drop [ [ >fixnum ] dip fixnum-bitand ] ]
98             }
99             [ 2drop f ]
100         } cond
101     ] "custom-inlining" set-word-prop
102 ] each
103
104 ! Speeds up 2^
105 : 2^? ( #call -- ? )
106     in-d>> first2 [ value-info ] bi@
107     [ { [ literal>> 1 = ] [ class>> fixnum class<= ] } 1&& ]
108     [ class>> fixnum class<= ]
109     bi* and ;
110
111 \ shift [
112      2^? [
113         cell-bits tag-bits get - 1 -
114         '[
115             >fixnum dup 0 < [ 2drop 0 ] [
116                 dup _ < [ fixnum-shift ] [
117                     fixnum-shift
118                 ] if
119             ] if
120         ]
121     ] [ f ] if
122 ] "custom-inlining" set-word-prop
123
124 { /i fixnum/i fixnum/i-fast bignum/i } [
125     [
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
133 ] each
134
135 ! Generate more efficient code for common idiom
136 \ clone [
137     in-d>> first value-info literal>> {
138         { V{ } [ [ drop { } 0 vector boa ] ] }
139         { H{ } [ [ drop 0 <hashtable> ] ] }
140         [ drop f ]
141     } case
142 ] "custom-inlining" set-word-prop
143
144 ERROR: bad-partial-eval quot word ;
145
146 : check-effect ( quot word -- )
147     2dup [ infer ] [ stack-effect ] bi* effect<=
148     [ 2drop ] [ bad-partial-eval ] if ;
149
150 :: define-partial-eval ( word quot n -- )
151     word [
152         in-d>> n tail*
153         [ value-info ] map
154         dup [ literal?>> ] all? [
155             [ literal>> ] map
156             n firstn
157             quot call dup [
158                 [ n ndrop ] prepose
159                 dup word check-effect
160             ] when
161         ] [ drop f ] if
162     ] "custom-inlining" set-word-prop ;
163
164 : inline-new ( class -- quot/f )
165     dup tuple-class? [
166         dup inlined-dependency depends-on
167         [ all-slots [ initial>> literalize ] map ]
168         [ tuple-layout '[ _ <tuple-boa> ] ]
169         bi append >quotation
170     ] [ drop f ] if ;
171
172 \ new [ inline-new ] 1 define-partial-eval
173
174 \ instance? [
175     dup class?
176     [ "predicate" word-prop ] [ drop f ] if
177 ] 1 define-partial-eval
178
179 ! Shuffling
180 : nths-quot ( indices -- quot )
181     [ [ '[ _ swap nth ] ] map ] [ length ] bi
182     '[ _ cleave _ narray ] ;
183
184 \ shuffle [
185     shuffle-mapping nths-quot
186 ] 1 define-partial-eval
187
188 ! Index search
189 \ index [
190     dup sequence? [
191         dup length 4 >= [
192             dup length iota zip >hashtable '[ _ at ]
193         ] [ drop f ] if
194     ] [ drop f ] if
195 ] 1 define-partial-eval
196
197 : member-eq-quot ( seq -- newquot )
198     [ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
199     [ drop f ] suffix [ cond ] curry ;
200
201 \ member-eq? [
202     dup sequence? [ member-eq-quot ] [ drop f ] if
203 ] 1 define-partial-eval
204
205 ! Membership testing
206 : member-quot ( seq -- newquot )
207     dup length 4 <= [
208         [ drop f ] swap
209         [ literalize [ t ] ] { } map>assoc linear-case-quot
210     ] [
211         unique [ key? ] curry
212     ] if ;
213
214 \ member? [
215     dup sequence? [ member-quot ] [ drop f ] if
216 ] 1 define-partial-eval
217
218 ! Fast at for integer maps
219 CONSTANT: lookup-table-at-max 256
220
221 : lookup-table-at? ( assoc -- ? )
222     #! Can we use a fast byte array test here?
223     {
224         [ assoc-size 4 > ]
225         [ values [ ] all? ]
226         [ keys [ integer? ] all? ]
227         [ keys [ 0 lookup-table-at-max between? ] all? ]
228     } 1&& ;
229
230 : lookup-table-seq ( assoc -- table )
231     [ keys supremum 1 + iota ] keep '[ _ at ] { } map-as ;
232
233 : lookup-table-quot ( seq -- newquot )
234     lookup-table-seq
235     '[
236         _ over integer? [
237             2dup bounds-check? [
238                 nth-unsafe dup >boolean
239             ] [ 2drop f f ] if
240         ] [ 2drop f f ] if
241     ] ;
242
243 : fast-lookup-table-at? ( assoc -- ? )
244     values {
245         [ [ integer? ] all? ]
246         [ [ 0 254 between? ] all? ]
247     } 1&& ;
248
249 : fast-lookup-table-seq ( assoc -- table )
250     lookup-table-seq [ 255 or ] B{ } map-as ;
251
252 : fast-lookup-table-quot ( seq -- newquot )
253     fast-lookup-table-seq
254     '[
255         _ over integer? [
256             2dup bounds-check? [
257                 nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
258             ] [ 2drop f f ] if
259         ] [ 2drop f f ] if
260     ] ;
261
262 : at-quot ( assoc -- quot )
263     dup assoc? [
264         dup lookup-table-at? [
265             dup fast-lookup-table-at? [
266                 fast-lookup-table-quot
267             ] [
268                 lookup-table-quot
269             ] if
270         ] [ drop f ] if
271     ] [ drop f ] if ;
272
273 \ at* [ at-quot ] 1 define-partial-eval
274
275 : diff-quot ( seq -- quot: ( seq' -- seq'' ) )
276     tester '[ [ @ not ] filter ] ;
277
278 \ diff [ diff-quot ] 1 define-partial-eval
279
280 : intersect-quot ( seq -- quot: ( seq' -- seq'' ) )
281     tester '[ _ filter ] ;
282
283 \ intersect [ intersect-quot ] 1 define-partial-eval
284
285 ! Speeds up sum-file, sort and reverse-complement benchmarks by
286 ! compiling decoder-readln better
287 \ push [
288     in-d>> second value-info class>> growable class<=
289     [ \ push def>> ] [ f ] if
290 ] "custom-inlining" set-word-prop
291
292 ! We want to constant-fold calls to heap-size, and recompile those
293 ! calls when a C type is redefined
294 \ heap-size [
295     dup word? [
296         [ inlined-dependency depends-on ] [ heap-size '[ _ ] ] bi
297     ] [ drop f ] if
298 ] 1 define-partial-eval