]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/tests/optimizer.factor
alien.data: remove second quotation parameter from with-out-parameters, now all value...
[factor.git] / basis / compiler / tests / optimizer.factor
1 USING: accessors arrays compiler.units generic hashtables
2 stack-checker kernel kernel.private math prettyprint sequences
3 sbufs strings tools.test vectors words sequences.private
4 quotations classes classes.algebra classes.tuple.private
5 continuations growable namespaces hints alien.accessors
6 compiler.tree.builder compiler.tree.optimizer sequences.deep
7 compiler.test definitions generic.single shuffle math.order
8 compiler.cfg.debugger classes.struct alien.syntax alien.data ;
9 IN: compiler.tests.optimizer
10
11 GENERIC: xyz ( obj -- obj )
12 M: array xyz xyz ;
13
14 [ t ] [ M\ array xyz optimized? ] unit-test
15
16 ! Test predicate inlining
17 : pred-test-1 ( a -- b c )
18     dup fixnum? [
19         dup integer? [ "integer" ] [ "nope" ] if
20     ] [
21         "not a fixnum"
22     ] if ;
23
24 [ 1 "integer" ] [ 1 pred-test-1 ] unit-test
25
26 TUPLE: pred-test ;
27
28 : pred-test-2 ( a -- b c )
29     dup tuple? [
30         dup pred-test? [ "pred-test" ] [ "nope" ] if
31     ] [
32         "not a tuple"
33     ] if ;
34
35 [ T{ pred-test } "pred-test" ] [ T{ pred-test } pred-test-2 ] unit-test
36
37 : pred-test-3 ( a -- b c )
38     dup pred-test? [
39         dup tuple? [ "pred-test" ] [ "nope" ] if
40     ] [
41         "not a tuple"
42     ] if ;
43
44 [ T{ pred-test } "pred-test" ] [ T{ pred-test } pred-test-3 ] unit-test
45
46 : inline-test ( a -- b )
47     "nom" = ;
48
49 [ t ] [ "nom" inline-test ] unit-test
50 [ f ] [ "shayin" inline-test ] unit-test
51 [ f ] [ 3 inline-test ] unit-test
52
53 : fixnum-declarations ( a -- b ) >fixnum 24 shift 1234 bitxor ;
54
55 [ ] [ 1000000 fixnum-declarations . ] unit-test
56
57 ! regression
58
59 : literal-not-branch ( -- ) 0 not [ ] [ ] if ;
60
61 [ ] [ literal-not-branch ] unit-test
62
63 ! regression
64
65 : bad-kill-1 ( a b -- c d e ) [ 3 f ] [ dup bad-kill-1 ] if ; inline recursive
66 : bad-kill-2 ( a b -- c d ) bad-kill-1 drop ;
67
68 [ 3 ] [ t bad-kill-2 ] unit-test
69
70 ! regression
71 : (the-test) ( x -- y ) dup 0 > [ 1 - (the-test) ] when ; inline recursive
72 : the-test ( -- x y ) 2 dup (the-test) ;
73
74 [ 2 0 ] [ the-test ] unit-test
75
76 ! regression
77 : (double-recursion) ( start end -- )
78     < [
79         6 1 (double-recursion)
80         3 2 (double-recursion)
81     ] when ; inline recursive
82
83 : double-recursion ( -- ) 0 2 (double-recursion) ;
84
85 [ ] [ double-recursion ] unit-test
86
87 ! regression
88 : double-label-1 ( a b c -- d )
89     [ f double-label-1 ] [ swap nth-unsafe ] if ; inline recursive
90
91 : double-label-2 ( a -- b )
92     dup array? [ ] [ ] if 0 t double-label-1 ;
93
94 [ 0 ] [ 10 iota double-label-2 ] unit-test
95
96 ! regression
97 GENERIC: void-generic ( obj -- * )
98 : breakage ( -- * ) "hi" void-generic ;
99 [ t ] [ \ breakage optimized? ] unit-test
100 [ breakage ] must-fail
101
102 ! regression
103 : branch-fold-regression-0 ( m -- n )
104     t [ ] [ 1 + branch-fold-regression-0 ] if ; inline recursive
105
106 : branch-fold-regression-1 ( -- m )
107     10 branch-fold-regression-0 ;
108
109 [ 10 ] [ branch-fold-regression-1 ] unit-test
110
111 ! another regression
112 : constant-branch-fold-0 ( -- value ) "hey" ; foldable
113 : constant-branch-fold-1 ( -- ? ) constant-branch-fold-0 "hey" = ; inline
114 [ 1 ] [ [ constant-branch-fold-1 [ 1 ] [ 2 ] if ] compile-call ] unit-test
115
116 ! another regression
117 : foo ( -- value ) f ;
118 : bar ( -- ? ) foo 4 4 = and ;
119 [ f ] [ bar ] unit-test
120
121 ! compiling <tuple> with a non-literal class failed
122 : <tuple>-regression ( class -- tuple ) <tuple> ;
123
124 [ t ] [ \ <tuple>-regression optimized? ] unit-test
125
126 ! regression
127 : constant-fold-2 ( -- value ) f ; foldable
128 : constant-fold-3 ( -- value ) 4 ; foldable
129
130 [ f t ] [
131     [ constant-fold-2 constant-fold-3 4 = ] compile-call
132 ] unit-test
133
134 : constant-fold-4 ( -- value ) f ; foldable
135 : constant-fold-5 ( -- value ) f ; foldable
136
137 [ f ] [
138     [ constant-fold-4 constant-fold-5 or ] compile-call
139 ] unit-test
140
141 [ 5 ] [ 5 [ 0 + ] compile-call ] unit-test
142 [ 5 ] [ 5 [ 0 swap + ] compile-call ] unit-test
143
144 [ 5 ] [ 5 [ 0 - ] compile-call ] unit-test
145 [ -5 ] [ 5 [ 0 swap - ] compile-call ] unit-test
146 [ 0 ] [ 5 [ dup - ] compile-call ] unit-test
147
148 [ 5 ] [ 5 [ 1 * ] compile-call ] unit-test
149 [ 5 ] [ 5 [ 1 swap * ] compile-call ] unit-test
150 [ 0 ] [ 5 [ 0 * ] compile-call ] unit-test
151 [ 0 ] [ 5 [ 0 swap * ] compile-call ] unit-test
152 [ -5 ] [ 5 [ -1 * ] compile-call ] unit-test
153 [ -5 ] [ 5 [ -1 swap * ] compile-call ] unit-test
154
155 [ 0 ] [ 5 [ 1 mod ] compile-call ] unit-test
156 [ 0 ] [ 5 [ 1 rem ] compile-call ] unit-test
157
158 [ 5 ] [ 5 [ -1 bitand ] compile-call ] unit-test
159 [ 0 ] [ 5 [ 0 bitand ] compile-call ] unit-test
160 [ 5 ] [ 5 [ -1 swap bitand ] compile-call ] unit-test
161 [ 0 ] [ 5 [ 0 swap bitand ] compile-call ] unit-test
162 [ 5 ] [ 5 [ dup bitand ] compile-call ] unit-test
163
164 [ 5 ] [ 5 [ 0 bitor ] compile-call ] unit-test
165 [ -1 ] [ 5 [ -1 bitor ] compile-call ] unit-test
166 [ 5 ] [ 5 [ 0 swap bitor ] compile-call ] unit-test
167 [ -1 ] [ 5 [ -1 swap bitor ] compile-call ] unit-test
168 [ 5 ] [ 5 [ dup bitor ] compile-call ] unit-test
169
170 [ 5 ] [ 5 [ 0 bitxor ] compile-call ] unit-test
171 [ 5 ] [ 5 [ 0 swap bitxor ] compile-call ] unit-test
172 [ -6 ] [ 5 [ -1 bitxor ] compile-call ] unit-test
173 [ -6 ] [ 5 [ -1 swap bitxor ] compile-call ] unit-test
174 [ 0 ] [ 5 [ dup bitxor ] compile-call ] unit-test
175
176 [ 0 ] [ 5 [ 0 swap shift ] compile-call ] unit-test
177 [ 5 ] [ 5 [ 0 shift ] compile-call ] unit-test
178
179 [ f ] [ 5 [ dup < ] compile-call ] unit-test
180 [ t ] [ 5 [ dup <= ] compile-call ] unit-test
181 [ f ] [ 5 [ dup > ] compile-call ] unit-test
182 [ t ] [ 5 [ dup >= ] compile-call ] unit-test
183
184 [ t ] [ 5 [ dup eq? ] compile-call ] unit-test
185 [ t ] [ 5 [ dup = ] compile-call ] unit-test
186 [ t ] [ 5 [ dup number= ] compile-call ] unit-test
187 [ t ] [ \ vector [ \ vector = ] compile-call ] unit-test
188
189 GENERIC: detect-number ( obj -- obj )
190 M: number detect-number ;
191
192 [ 10 f [ <array> 0 + detect-number ] compile-call ] must-fail
193
194 ! Regression
195 [ 4 [ + ] ] [ 2 2 [ [ + ] [ call ] keep ] compile-call ] unit-test
196
197 ! Regression
198 : empty-compound ( -- ) ;
199
200 : node-successor-f-bug ( x -- * )
201     [ 3 throw ] [ empty-compound ] compose [ 3 throw ] if ;
202
203 [ t ] [ \ node-successor-f-bug optimized? ] unit-test
204
205 [ ] [ [ new ] build-tree optimize-tree drop ] unit-test
206
207 [ ] [ [ <tuple> ] build-tree optimize-tree drop ] unit-test
208
209 ! Regression
210 : lift-throw-tail-regression ( obj -- obj str )
211     dup integer? [ "an integer" ] [
212         dup string? [ "a string" ] [
213             "error" throw
214         ] if
215     ] if ;
216
217 [ t ] [ \ lift-throw-tail-regression optimized? ] unit-test
218 [ 3 "an integer" ] [ 3 lift-throw-tail-regression ] unit-test
219 [ "hi" "a string" ] [ "hi" lift-throw-tail-regression ] unit-test
220
221 : lift-loop-tail-test-1 ( a quot: ( -- ) -- )
222     over even? [
223         [ [ 3 - ] dip call ] keep lift-loop-tail-test-1
224     ] [
225         over 0 < [
226             2drop
227         ] [
228             [ [ 2 - ] dip call ] keep lift-loop-tail-test-1
229         ] if
230     ] if ; inline recursive
231
232 : lift-loop-tail-test-2 ( -- a b c )
233     10 [ ] lift-loop-tail-test-1 1 2 3 ;
234
235 \ lift-loop-tail-test-2 def>> must-infer
236
237 [ 1 2 3 ] [ lift-loop-tail-test-2 ] unit-test
238
239 ! Forgot a recursive inline check
240 : recursive-inline-hang ( a -- a )
241     dup array? [ recursive-inline-hang ] when ;
242
243 HINTS: recursive-inline-hang array ;
244
245 : recursive-inline-hang-1 ( -- a )
246     { } recursive-inline-hang ;
247
248 [ t ] [ \ recursive-inline-hang-1 optimized? ] unit-test
249
250 DEFER: recursive-inline-hang-3
251
252 : recursive-inline-hang-2 ( a -- a )
253     dup array? [ recursive-inline-hang-3 ] when ;
254
255 HINTS: recursive-inline-hang-2 array ;
256
257 : recursive-inline-hang-3 ( a -- a )
258     dup array? [ recursive-inline-hang-2 ] when ;
259
260 HINTS: recursive-inline-hang-3 array ;
261
262 ! Regression
263 [ ] [ { 3append-as } compile ] unit-test
264
265 ! Wow
266 : counter-example ( a b c d -- a' b' c' d' )
267     dup 0 > [ 1 - [ rot 2 * ] dip counter-example ] when ; inline recursive
268
269 : counter-example' ( -- a' b' c' d' )
270     1 2 3.0 3 counter-example ;
271
272 [ 2 4 6.0 0 ] [ counter-example' ] unit-test
273
274 : member-test ( obj -- ? ) { + - * / /i } member? ;
275
276 \ member-test def>> must-infer
277 [ ] [ \ member-test build-tree optimize-tree drop ] unit-test
278 [ t ] [ \ + member-test ] unit-test
279 [ f ] [ \ append member-test ] unit-test
280
281 ! Infinite expansion
282 TUPLE: cons car cdr ;
283
284 UNION: improper-list cons POSTPONE: f ;
285
286 PREDICATE: list < improper-list
287     [ cdr>> list instance? ] [ t ] if* ;
288
289 [ t ] [
290     T{ cons f 1 T{ cons f 2 T{ cons f 3 f } } }
291     [ list instance? ] compile-call
292 ] unit-test
293
294 ! Regression
295 : interval-inference-bug ( obj -- obj x )
296     dup "a" get { array-capacity } declare >=
297     [ dup "b" get { array-capacity } declare >= [ 3 ] [ 4 ] if ] [ 5 ] if ;
298
299 [ t ] [ \ interval-inference-bug optimized? ] unit-test
300
301 [ ] [ 1 "a" set 2 "b" set ] unit-test
302 [ 2 3 ] [ 2 interval-inference-bug ] unit-test
303 [ 1 4 ] [ 1 interval-inference-bug ] unit-test
304 [ 0 5 ] [ 0 interval-inference-bug ] unit-test
305
306 : aggressive-flush-regression ( a -- b )
307     f over [ <array> drop ] dip 1 + ;
308
309 [ 1.0 aggressive-flush-regression drop ] must-fail
310
311 [ 1 [ "hi" + drop ] compile-call ] must-fail
312
313 [ "hi" f [ <array> drop ] compile-call ] must-fail
314
315 TUPLE: some-tuple x ;
316
317 : allot-regression ( a -- b )
318     [ ] curry some-tuple boa ;
319
320 [ T{ some-tuple f [ 3 ] } ] [ 3 allot-regression ] unit-test
321
322 [ 1 ] [ B{ 0 0 0 0 } [ 0 alien-signed-4 1 + ] compile-call ] unit-test
323 [ 1 ] [ B{ 0 0 0 0 } [ 0 alien-unsigned-4 1 + ] compile-call ] unit-test
324 [ 1 ] [ B{ 0 0 0 0 0 0 0 0 } [ 0 alien-signed-8 1 + ] compile-call ] unit-test
325 [ 1 ] [ B{ 0 0 0 0 0 0 0 0 } [ 0 alien-unsigned-8 1 + ] compile-call ] unit-test
326 [ 1 ] [ B{ 0 0 0 0 0 0 0 0 } [ 0 alien-signed-cell 1 + ] compile-call ] unit-test
327 [ 1 ] [ B{ 0 0 0 0 0 0 0 0 } [ 0 alien-unsigned-cell 1 + ] compile-call ] unit-test
328
329 : deep-find-test ( seq -- ? ) [ 5 = ] deep-find ;
330
331 [ 5 ] [ { 1 2 { 3 { 4 5 } } } deep-find-test ] unit-test
332 [ f ] [ { 1 2 { 3 { 4 } } } deep-find-test ] unit-test
333
334 [ B{ 0 1 2 3 4 5 6 7 } ] [ [ 8 iota [ ] B{ } map-as ] compile-call ] unit-test
335
336 [ 0 ] [ 1234 [ { fixnum } declare -64 shift ] compile-call ] unit-test
337
338 ! Loop detection problem found by doublec
339 SYMBOL: counter
340
341 DEFER: loop-bbb
342
343 : loop-aaa ( -- )
344     counter inc counter get 2 < [ loop-bbb ] when ; inline recursive
345
346 : loop-bbb ( -- )
347     [ loop-aaa ] with-scope ; inline recursive
348
349 : loop-ccc ( -- ) loop-bbb ;
350
351 [ 0 ] [ 0 counter set loop-ccc counter get ] unit-test
352
353 ! Type inference issue
354 [ 4 3 ] [
355     1 >bignum 2 >bignum
356     [ { bignum integer } declare [ shift ] keep 1 + ] compile-call
357 ] unit-test
358
359 : broken-declaration ( -- ) \ + declare ;
360
361 [ f ] [ \ broken-declaration optimized? ] unit-test
362
363 [ ] [ [ \ broken-declaration forget ] with-compilation-unit ] unit-test
364
365 ! Interval inference issue
366 [ f ] [
367     10 70
368     [
369         dup 70 >=
370         [ dup 700 <= [ swap 1024 rem rem ] [ 2drop 70 ] if ]
371         [ 2drop 70 ] if
372         70 >=
373     ] compile-call
374 ] unit-test
375
376 ! Modular arithmetic bug
377 : modular-arithmetic-bug ( a -- b ) >integer 256 mod ;
378
379 [ 1 ] [ 257 modular-arithmetic-bug ] unit-test
380 [ -10 ] [ -10 modular-arithmetic-bug ] unit-test
381
382 ! Optimizer needs to ignore invalid generics
383 GENERIC# bad-dispatch-position-test* 3 ( -- )
384
385 M: object bad-dispatch-position-test* ;
386
387 : bad-dispatch-position-test ( -- ) bad-dispatch-position-test* ;
388
389 [ 1 2 3 4 bad-dispatch-position-test ] must-fail
390
391 [ ] [
392     [
393         \ bad-dispatch-position-test forget
394         \ bad-dispatch-position-test* forget
395     ] with-compilation-unit
396 ] unit-test
397
398 [ 16 ] [
399     [
400         0 2
401         [
402             nip
403             [
404                 1 + {
405                     [ 16 ]
406                     [ 16 ]
407                     [ 16 ]
408                 } dispatch
409             ] [
410                 {
411                     [ ]
412                     [ ]
413                     [ ]
414                 } dispatch
415             ] bi
416         ] each-integer
417     ] compile-call
418 ] unit-test
419
420 : dispatch-branch-problem ( a b c -- d )
421     dup 0 < [ "boo" throw ] when
422     1 + { [ + ] [ - ] [ * ] } dispatch ;
423
424 [ 3 4 -1 dispatch-branch-problem ] [ "boo" = ] must-fail-with
425 [ -1 ] [ 3 4 0 dispatch-branch-problem ] unit-test
426 [ 12 ] [ 3 4 1 dispatch-branch-problem ] unit-test
427
428 [ 1024 bignum ] [ 10 [ 1 >bignum swap >fixnum shift ] compile-call dup class ] unit-test
429
430 TUPLE: grid-mesh-tuple { length read-only } { step read-only } ;
431
432 : grid-mesh-test-case ( -- vertices )
433     1.0 1.0 { 2 } first /f [ /i 1 + ] keep grid-mesh-tuple boa
434     1 f <array>
435     [
436         [ drop length>> >fixnum 2 min ] 2keep
437         [
438             [ step>> 1 * ] dip
439             0 swap set-nth-unsafe
440         ] 2curry times
441     ] keep ;
442
443 [ { 0.5 } ] [ grid-mesh-test-case ] unit-test
444
445 [ { 1 } "bar" ] [ { 1 } [ [ [ [ "foo" throw ] [ "bar" throw ] recover ] attempt-all f ] [ ] recover ] compile-call ] unit-test
446
447 GENERIC: bad-push-test-case ( a -- b )
448 M: object bad-push-test-case "foo" throw ; inline
449 [ { 1 } "bar" ] [ { 1 } [ [ [ [ bad-push-test-case ] [ "bar" throw ] recover ] attempt-all f ] [ ] recover ] compile-call ] unit-test
450
451 STRUCT: BitmapData { Scan0 void* } ;
452
453 [ ALIEN: 123 ] [
454     [
455         { BitmapData }
456         [ BitmapData memory>struct ALIEN: 123 >>Scan0 drop ]
457         with-out-parameters Scan0>>
458     ] compile-call
459 ] unit-test