Skip to content

Commit

Permalink
change intermediate representation for the bytecode optimizer
Browse files Browse the repository at this point in the history
Correct the second-biggest design flaw in the bytecode optimizer:
instead of using a de Bruijn-like representation of variable
references in the optimizer pass, use variable objects.

This change is intended to address limitations on programs like the
one in

 http://bugs.racket-lang.org/query/?cmd=view&pr=15244

where the optimizer could not perform a straightforward-seeming
transformation due to the constraints of its representation.

Besides handling the bug-report example better, there are other minor
optimization improvements as a side effect of refactoring the code. To
simplify the optimizer's implementation (e.g., eliminate code that I
didn't want to convert) and also preserve success for optimizer tests,
the optimizer ended up getting a little better at flattening and
eliminating `let` forms and `begin`--`let` combinations.

Overall, the optimizer tests in "optimize.rktl" pass, which helps
ensure that no optimizations were lost. I had to modify just a few
tests:

 * The test at line 2139 didn't actually check against reordering as
   intended, but was instead checking that the bug-report limitation
   was intact (and now it's not).

 * The tests around 3095 got extra `p` references, because the
   optimizer is now able to eliminate an unused `let` around the
   second case, but it still doesn't discover the unusedness of `p` in
   the first case soon enough to eliminate the `let`. The extra
   references prevent eliminating the `let` in both case, since that's
   not the point of the tests.

Thanks to Gustavo for taking a close look at the changes.

 LocalWords:  pkgs rkt
  • Loading branch information
mflatt committed Feb 17, 2016
1 parent bfc2611 commit 0c38da0
Show file tree
Hide file tree
Showing 27 changed files with 2,792 additions and 4,445 deletions.
2 changes: 1 addition & 1 deletion pkgs/base/info.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

(define collection 'multi)

(define version "6.4.0.7")
(define version "6.4.0.8")

(define deps `("racket-lib"
["racket" #:version ,version]))
Expand Down
42 changes: 25 additions & 17 deletions pkgs/racket-test-core/tests/racket/optimize.rktl
Original file line number Diff line number Diff line change
Expand Up @@ -879,20 +879,22 @@

))

(define (comp=? c1 c2)
(define (comp=? c1 c2 want-same?)
(let ([s1 (open-output-bytes)]
[s2 (open-output-bytes)])
(write c1 s1)
(write c2 s2)
(let ([t1 (get-output-bytes s1)]
[t2 (get-output-bytes s2)])
(or (bytes=? t1 t2)
(begin
(printf "~s\n~s\n"
(zo-parse (open-input-bytes t1))
(zo-parse (open-input-bytes t2)))
#f
)))))
(define same? (bytes=? t1 t2))
(when (and (not same?) want-same?)
(printf "~s\n~s\n"
(zo-parse (open-input-bytes t1))
(zo-parse (open-input-bytes t2))))
(unless (equal? same? want-same?)
;; Unquote to cause a failure to stop
'stop)
same?)))

(define test-comp
(case-lambda
Expand All @@ -902,7 +904,7 @@
;; Give `s` a minimal location, so that other macro locations
;; don't bleed through:
(datum->syntax #f s (vector 'here #f #f #f #f)))
(test same? `(compile ,same? ,expr2) (comp=? (compile (->stx expr1)) (compile (->stx expr2))))]))
(test same? `(compile ,same? ,expr2) (comp=? (compile (->stx expr1)) (compile (->stx expr2)) same?))]))

(let ([x (compile '(lambda (x) x))])
(test #t 'fixpt (eq? x (compile x))))
Expand Down Expand Up @@ -1742,7 +1744,6 @@
(begin (quote-syntax foo) 3))])
x)
'3)

(test-comp '(if (lambda () 10)
'ok
(quote-syntax no!))
Expand Down Expand Up @@ -2139,15 +2140,15 @@
(define z (random))
(define (f)
(let-values ([(a b) (values (cons 1 z) (cons 2 z))])
(list a b)))
(list b a)))
(set! z 5)))
'(module m racket/base
;; Reference to a ready module-level variable shouldn't
;; prevent let-values splitting
(#%plain-module-begin
(define z (random))
(define (f)
(list (cons 1 z) (cons 2 z)))
(list (cons 2 z) (cons 1 z)))
(set! z 5)))
#f)

Expand Down Expand Up @@ -3095,38 +3096,45 @@

(test-comp '(lambda (n)
(let ([p (fl+ n n)])
(list
(list
p p
(flonum? p)
(flonum? (begin (random) p))
(flonum? (letrec ([x (lambda (t) x)]) (x x) p)))))
'(lambda (n)
(let ([p (fl+ n n)])
(list
#t
p p
#t
(begin (random) #t)
(letrec ([x (lambda (t) x)]) (x x) #t)))))

(test-comp '(lambda (n)
(let ([p (fx+ n n)])
(list
(list
p p
(fixnum? p)
(fixnum? (begin (random) p))
(fixnum? (letrec ([x (lambda (t) x)]) (x x) p)))))
'(lambda (n)
(let ([p (fx+ n n)])
(list
p p
#t
(begin (random) #t)
(letrec ([x (lambda (t) x)]) (x x) #t)))))
(test-comp '(lambda (n)
(let ([p (extfl+ n n)])
(list
(list
p p
(extflonum? p)
(extflonum? (begin (random) p))
(extflonum? (letrec ([x (lambda (t) x)]) (x x) p)))))
'(lambda (n)
(let ([p (extfl+ n n)])
(list
#t
p p
#t
(begin (random) #t)
(letrec ([x (lambda (t) x)]) (x x) #t)))))

Expand Down
4 changes: 2 additions & 2 deletions pkgs/racket-test/tests/generic/base-interfaces.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@
;; ok if these don't raise unbound id errors
(check-equal? (with-output-to-string (lambda () (write (tuple 5)))) "#0=#0#")
(check-equal? (tuple 5) (tuple 5))
(check-equal? (equal-hash-code (tuple 5)) 54)
(check-equal? (equal-secondary-hash-code (tuple 5)) 45))
(check-equal? (equal-hash-code (tuple 5)) 55)
(check-equal? (equal-secondary-hash-code (tuple 5)) 46))
2 changes: 1 addition & 1 deletion pkgs/racket-test/tests/generic/equal+hash.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
(check-false (equal? (kons 1 2) 2))
(check-false (equal? 2 (kons 1 2)))
(check-false (equal? (kons 1 2) (kons 3 4)))
(check-equal? (equal-hash-code (kons 1 2)) 61)
(check-equal? (equal-hash-code (kons 1 2)) 62)
)
Loading

0 comments on commit 0c38da0

Please sign in to comment.