Opened 6 years ago
Closed 6 years ago
#1620 closed defect (fixed)
Some let bindings are not replaced resulting in unnecessary CPS calls
| Reported by: | sjamaan | Owned by: | |
|---|---|---|---|
| Priority: | major | Milestone: | 5.2 |
| Component: | compiler | Version: | 5.0.0 |
| Keywords: | Cc: | ||
| Estimated difficulty: | hard |
Description (last modified by )
We've seen in #1604 that this is a performance killer:
This code is fast when compiled with -O5 -strict-types -fixnum-arithmetic:
(define (fib n)
(if (or (eq? n 0) (eq? n 1))
n
(+ (fib (- n 1)) (fib (- n 2)))))
(let loop ((n 0))
(when (< n 35)
(print "n=" n " => " (fib n))
(loop (+ n 1))))
This code is slow when compiled with the same options, even though the generated intermediate Scheme code is equivalent:
(define (fib n)
(if (or (= n 0) (= n 1))
n
(+ (fib (- n 1)) (fib (- n 2)))))
(let loop ((n 0))
(when (< n 35)
(print "n=" n " => " (fib n))
(loop (+ n 1))))
The reason is that in the first case, the eq? calls get replaced by (##core#inline "C_eqp" a b) while in the second case, the = calls get replaced by (let ((x a) (y b)) (##core_inline "C_eqp" x y)) and the let is not considered replacable even though (I think?) it should be.
That's because fib's arguments are marked by analyze-expression in core.scm as captured.
Fixing this could potentially make a lot of code a lot faster! We definitely should run the benchmarks with and without the fix to find out how dramatic the improvement is.
Change History (3)
comment:1 Changed 6 years ago by
| Description: | modified (diff) |
|---|
comment:2 Changed 6 years ago by
comment:3 Changed 6 years ago by
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
Fixed by 27dbbc02d32f91712b83f6b11ffa325da6454df8

Note: The
letbindings are actually necessary when the arguments of=are impure; you want side-effects or exceptions to happen before calling=. The expanded generated code contains a shortcuttingC_andcall introduced byfold-booleanand each of the arguments except the first and the last are repeated twice, so if we got rid of theletcompletely, the resulting code would not be semantically equivalent.However, if they just alias other variables, I think they should always be replacable.