unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
* bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression
@ 2020-02-12 11:50 Ludovic Courtès
  2020-02-12 14:57 ` Andy Wingo
  0 siblings, 1 reply; 4+ messages in thread
From: Ludovic Courtès @ 2020-02-12 11:50 UTC (permalink / raw)
  To: bug-Guile; +Cc: wingo

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’.





^ permalink raw reply	[flat|nested] 4+ messages in thread

* bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression
  2020-02-12 11:50 bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression Ludovic Courtès
@ 2020-02-12 14:57 ` Andy Wingo
  2020-02-13 11:35   ` Ludovic Courtès
  0 siblings, 1 reply; 4+ messages in thread
From: Andy Wingo @ 2020-02-12 14:57 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: bug-Guile

On Wed 12 Feb 2020 12:50, Ludovic Courtès <ludo@gnu.org> writes:

> 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):
>
[...]
> 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

Like specifically, it removes the logior call.

> However, 3.0.0 keeps the computation of ‘i’:
>
[...]
> 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

Hoo, we need to fix the disassembler to output something more sensible
than this :P  IP 56 appears to be the 1-, 58 is the lsh/immediate, and
60 is the logior.

> I’m not sure where the optimization should be taking place.  Perhaps
> it’s just a matter of amount-of-work threshold somewhere?

It's not an amount-of-work, that's only in peval which does nothing to
either of these (though it certainly could).

I took a look.  I just pushed something to make (logior 0 INT) reduce to
INT, but it doesn't remove the loop variable.

Then I thought it was surely dead code elimination that just wasn't
doing its thing.  The value is unused, so it must be that it thought
that the `ash' was effectful.  That `ash' gets compiled to
`lsh/immediate', which does indeed raise an exception if the operand
isn't an int; but here we prove that it is.  The problem was a missing
"type checker" implementation for lsh/immediate, a problem introduced in
the refactored compilation of `ash'.  So, fixed in git now:

L3:
  45    (instrument-loop 135)           
  47    (handle-interrupts)             
  48    (call-scm<-scm-uimm 5 5 1 3)                          at (unknown file):4:12
  50    (=? 5 4)                                              at (unknown file):3:12
  51    (jne -6)                        ;; -> L3

Cheers,

Andy





^ permalink raw reply	[flat|nested] 4+ messages in thread

* bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression
  2020-02-12 14:57 ` Andy Wingo
@ 2020-02-13 11:35   ` Ludovic Courtès
  2020-02-13 15:11     ` Mikael Djurfeldt
  0 siblings, 1 reply; 4+ messages in thread
From: Ludovic Courtès @ 2020-02-13 11:35 UTC (permalink / raw)
  To: Andy Wingo; +Cc: 39573-done

Hi Andy,

Andy Wingo <wingo@igalia.com> skribis:

>> However, 3.0.0 keeps the computation of ‘i’:
>>
> [...]
>> 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
>
> Hoo, we need to fix the disassembler to output something more sensible
> than this :P  IP 56 appears to be the 1-, 58 is the lsh/immediate, and
> 60 is the logior.

Oh, I hadn’t read that much into these lines.  :-)

>> I’m not sure where the optimization should be taking place.  Perhaps
>> it’s just a matter of amount-of-work threshold somewhere?
>
> It's not an amount-of-work, that's only in peval which does nothing to
> either of these (though it certainly could).
>
> I took a look.  I just pushed something to make (logior 0 INT) reduce to
> INT, but it doesn't remove the loop variable.

OK.

> Then I thought it was surely dead code elimination that just wasn't
> doing its thing.  The value is unused, so it must be that it thought
> that the `ash' was effectful.  That `ash' gets compiled to
> `lsh/immediate', which does indeed raise an exception if the operand
> isn't an int; but here we prove that it is.  The problem was a missing
> "type checker" implementation for lsh/immediate, a problem introduced in
> the refactored compilation of `ash'.  So, fixed in git now:
>
> L3:
>   45    (instrument-loop 135)           
>   47    (handle-interrupts)             
>   48    (call-scm<-scm-uimm 5 5 1 3)                          at (unknown file):4:12
>   50    (=? 5 4)                                              at (unknown file):3:12
>   51    (jne -6)                        ;; -> L3

Yay!  It’s nice to see how 7dc90a17e03045c7cd8894b14b027b845b68aa4f is
short and clear.

Thanks,
Ludo’.





^ permalink raw reply	[flat|nested] 4+ messages in thread

* bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression
  2020-02-13 11:35   ` Ludovic Courtès
@ 2020-02-13 15:11     ` Mikael Djurfeldt
  0 siblings, 0 replies; 4+ messages in thread
From: Mikael Djurfeldt @ 2020-02-13 15:11 UTC (permalink / raw)
  To: 39573, Ludovic Courtès; +Cc: Andy Wingo, 39573-done

[-- Attachment #1: Type: text/plain, Size: 285 bytes --]

Den tors 13 feb. 2020 12:37Ludovic Courtès <ludo@gnu.org> skrev:

> Yay!  It’s nice to see how 7dc90a17e03045c7cd8894b14b027b845b68aa4f is
> short and clear.
>
> Thanks,
> Ludo’.
>

(You're lucky, Ludo', that we don't take that statement literally. :-))

Thanks!

>

[-- Attachment #2: Type: text/html, Size: 816 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-02-13 15:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-12 11:50 bug#39573: [3.0.0] Compiler fails to optimize out side-effect-free expression Ludovic Courtès
2020-02-12 14:57 ` Andy Wingo
2020-02-13 11:35   ` Ludovic Courtès
2020-02-13 15:11     ` Mikael Djurfeldt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).