GNU bug report logs - #39573
[3.0.0] Compiler fails to optimize (logior 0 INT)

Previous Next

Package: guile;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Wed, 12 Feb 2020 11:51:01 UTC

Severity: normal

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 39573 in the body.
You can then email your comments to 39573 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to wingo <at> igalia.com, bug-guile <at> gnu.org:
bug#39573; Package guile. (Wed, 12 Feb 2020 11:51:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludo <at> gnu.org>:
New bug report received and forwarded. Copy sent to wingo <at> igalia.com, bug-guile <at> gnu.org. (Wed, 12 Feb 2020 11:51:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: bug-Guile <at> gnu.org
Subject: [3.0.0] Compiler fails to optimize out side-effect-free expression
Date: Wed, 12 Feb 2020 12:50:44 +0100
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’.




Information forwarded to bug-guile <at> gnu.org:
bug#39573; Package guile. (Wed, 12 Feb 2020 14:59:02 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> igalia.com>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: bug-Guile <at> gnu.org
Subject: Re: bug#39573: [3.0.0] Compiler fails to optimize out
 side-effect-free expression
Date: Wed, 12 Feb 2020 15:57:41 +0100
On Wed 12 Feb 2020 12:50, Ludovic Courtès <ludo <at> 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




Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Thu, 13 Feb 2020 11:37:01 GMT) Full text and rfc822 format available.

Notification sent to Ludovic Courtès <ludo <at> gnu.org>:
bug acknowledged by developer. (Thu, 13 Feb 2020 11:37:02 GMT) Full text and rfc822 format available.

Message #13 received at 39573-done <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Andy Wingo <wingo <at> igalia.com>
Cc: 39573-done <at> debbugs.gnu.org
Subject: Re: bug#39573: [3.0.0] Compiler fails to optimize out
 side-effect-free expression
Date: Thu, 13 Feb 2020 12:35:59 +0100
Hi Andy,

Andy Wingo <wingo <at> 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’.




Information forwarded to bug-guile <at> gnu.org:
bug#39573; Package guile. (Thu, 13 Feb 2020 15:12:02 GMT) Full text and rfc822 format available.

Message #16 received at 39573 <at> debbugs.gnu.org (full text, mbox):

From: Mikael Djurfeldt <mikael <at> djurfeldt.com>
To: 39573 <at> debbugs.gnu.org, Ludovic Courtès <ludo <at> gnu.org>
Cc: Andy Wingo <wingo <at> igalia.com>, 39573-done <at> debbugs.gnu.org
Subject: Re: bug#39573: [3.0.0] Compiler fails to optimize out
 side-effect-free expression
Date: Thu, 13 Feb 2020 16:11:11 +0100
[Message part 1 (text/plain, inline)]
Den tors 13 feb. 2020 12:37Ludovic Courtès <ludo <at> 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!

>
[Message part 2 (text/html, inline)]

Information forwarded to bug-guile <at> gnu.org:
bug#39573; Package guile. (Thu, 13 Feb 2020 15:12:02 GMT) Full text and rfc822 format available.

Changed bug title to '[3.0.0] Compiler fails to optimize (logior 0 INT)' from '[3.0.0] Compiler fails to optimize out side-effect-free expression' Request was from Ludovic Courtès <ludo <at> gnu.org> to control <at> debbugs.gnu.org. (Sun, 08 Mar 2020 14:57:01 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 06 Apr 2020 11:24:07 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 358 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.