Hello! Consider this loop:
(let loop ((n (expt 2 18)) (i 1)) (unless (zero? n) (loop (- n 1) (logior 0 (ash i 1))))) Guile 2.2 strips away the computation of ‘i’ (it cannot throw, has no side effects, and the result is unused): --8<---------------cut here---------------start------------->8--- 0 (assert-nargs-ee/locals 1 4) ;; 5 slots (0 args) at (unknown file):16:10 1 (current-module 4) 2 (static-set! 4 74) ;; #f 4 (toplevel-box 4 84 72 82 #t) ;; `expt' 9 (box-ref 2 4) 10 (make-short-immediate 1 10) ;; 2 11 (make-short-immediate 0 74) ;; 18 12 (handle-interrupts) at (unknown file):16:24 13 (call 2 3) 15 (receive 0 2 5) 17 (load-u64 3 0 0) at (unknown file):18:11 20 (br-if-u64-=-scm 3 4 #f 12) ;; -> L2 23 (sub/immediate 4 4 1) at (unknown file):21:11 24 (br-if-u64-=-scm 3 4 #f 8) ;; -> L2 at (unknown file):18:11 L1: 27 (handle-interrupts) at (unknown file):21:11 28 (sub/immediate 4 4 1) 29 (br-if-u64-=-scm 3 4 #t -2) ;; -> L1 at (unknown file):18:11 L2: 32 (make-short-immediate 3 2052) ;; #<unspecified> at (unknown file):21:11 33 (handle-interrupts) 34 (return-values 2) ;; 1 value --8<---------------cut here---------------end--------------->8--- However, 3.0.0 keeps the computation of ‘i’: --8<---------------cut here---------------start------------->8--- 0 (instrument-entry 192) at (unknown file):383:9 2 (assert-nargs-ee/locals 1 5) ;; 6 slots (0 args) 3 (call-scm<-thread 5 62) 5 (static-set! 5 147) ;; #f 7 (static-ref 5 147) ;; #f 9 (immediate-tag=? 5 7 0) ;; heap-object? 11 (je 19) ;; -> L2 12 (static-ref 5 140) ;; #f 14 (static-ref 4 150) ;; expt 16 (call-scm<-scm-scm 5 5 4 40) 18 (immediate-tag=? 5 7 0) ;; heap-object? 20 (jne 8) ;; -> L1 21 (scm-ref/immediate 3 5 1) 22 (immediate-tag=? 3 4095 2308) ;; undefined? 24 (je 4) ;; -> L1 25 (static-set! 5 129) ;; #f 27 (j 3) ;; -> L2 L1: 28 (throw/value 4 156) ;; #(unbound-variable #f "Unbound variable: ~S") L2: 30 (scm-ref/immediate 2 5 1) 31 (make-short-immediate 1 10) ;; 2 32 (make-short-immediate 0 74) ;; 18 33 (handle-interrupts) at (unknown file):383:23 34 (call 3 3) 36 (receive 0 3 6) 38 (make-short-immediate 4 2) ;; 0 at (unknown file):385:11 39 (=? 5 4) 40 (je 24) ;; -> L4 41 (call-scm<-scm-uimm 5 5 1 3) at (unknown file):388:11 43 (load-s64 3 0 0) at (unknown file):389:11 46 (load-s64 2 0 2) 49 (ulogior 3 3 2) 50 (tag-fixnum 3 3) 51 (=? 5 4) at (unknown file):385:11 52 (je 12) ;; -> L4 L3: 53 (instrument-loop 139) 55 (handle-interrupts) 56 (call-scm<-scm-uimm 5 5 1 3) at (unknown file):388:11 58 (call-scm<-scm-uimm 3 3 1 34) at (unknown file):389:21 60 (call-scm<-scm-scm 3 4 3 10) at (unknown file):389:11 62 (=? 5 4) at (unknown file):385:11 63 (jne -10) ;; -> L3 L4: 64 (make-short-immediate 5 2052) ;; #<unspecified> at (unknown file):388:5 65 (reset-frame 1) ;; 1 slot 66 (handle-interrupts) 67 (return-values) --8<---------------cut here---------------end--------------->8--- I’m not sure where the optimization should be taking place. Perhaps it’s just a matter of amount-of-work threshold somewhere? Thanks, Ludo’.