unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* (byte-compile '(append '(1 2) '(3 4)))
       [not found]         ` <87bk7p57yz.fsf@posteo.net>
@ 2024-03-16 12:16           ` Felician Nemeth
  2024-03-16 12:46             ` Philip Kaludercic
  0 siblings, 1 reply; 6+ messages in thread
From: Felician Nemeth @ 2024-03-16 12:16 UTC (permalink / raw)
  To: emacs-devel; +Cc: Philip Kaludercic

(disassemble (byte-compile '(append '(1 2) '(3 4))))

resuts in

byte code:
  args: nil
0	constant  append
1	constant  (1 2)
2	constant  (3 4)
3	call	  2
4	return	  

Instead I expected it to be something like

byte code:
  args: nil
0	constant  1
1	constant  2
2	constant  3
3	constant  4
4	list4	  
5	return	  

I've never looked at byte-code optimization before, and I'm guessing
this is not a huge improvement, but I still wonder when all the
arguments of side-effect-free function are constants would it make sense
to calculate the result at compile time.

Thanks.



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

* Re: (byte-compile '(append '(1 2) '(3 4)))
  2024-03-16 12:16           ` (byte-compile '(append '(1 2) '(3 4))) Felician Nemeth
@ 2024-03-16 12:46             ` Philip Kaludercic
  2024-03-16 13:23               ` Basil L. Contovounesios
  0 siblings, 1 reply; 6+ messages in thread
From: Philip Kaludercic @ 2024-03-16 12:46 UTC (permalink / raw)
  To: Felician Nemeth; +Cc: emacs-devel

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

Felician Nemeth <felician.nemeth@gmail.com> writes:

> (disassemble (byte-compile '(append '(1 2) '(3 4))))
>
> resuts in
>
> byte code:
>   args: nil
> 0	constant  append
> 1	constant  (1 2)
> 2	constant  (3 4)
> 3	call	  2
> 4	return	  
>
> Instead I expected it to be something like
>
> byte code:
>   args: nil
> 0	constant  1
> 1	constant  2
> 2	constant  3
> 3	constant  4
> 4	list4	  
> 5	return	  
>
> I've never looked at byte-code optimization before, and I'm guessing
> this is not a huge improvement, but I still wonder when all the
> arguments of side-effect-free function are constants would it make sense
> to calculate the result at compile time.

`byte-optimize-append' mentions:

  ;; There is (probably) too much code relying on `append' to return a
  ;; new list for us to do full constant-folding; these transformations
  ;; preserve the allocation semantics.

I am not sure what the danger is in the case of constant, quoted lists,
but I am not familiar with the byte compiler either.  It seems like this


[-- Attachment #2: Type: text/plain, Size: 650 bytes --]

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index f75be3f71ad..e6f18590705 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1599,6 +1599,12 @@ byte-optimize-append
                          (cdr args))
                    (cdr newargs)))
 
+            ;; (append '(C1...) ... '(C2...)) -> (append C1... ... C2...)
+            ((cl-loop for arg in args
+                      always (and (eq (car arg) 'quote)
+                                  (proper-list-p (cdr arg))))
+             `',(mapcan #'cadr args))
+
             ;; non-terminal arg
             ((cdr args)
              (cond

[-- Attachment #3: Type: text/plain, Size: 151 bytes --]


would do the trick, and the byte-code is even better:

byte code:
  args: nil
0	constant  (1 2 3 4)
1	return	  


-- 
	Philip Kaludercic on peregrine

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

* Re: (byte-compile '(append '(1 2) '(3 4)))
  2024-03-16 12:46             ` Philip Kaludercic
@ 2024-03-16 13:23               ` Basil L. Contovounesios
  2024-03-16 13:45                 ` Felician Nemeth
  2024-03-16 13:55                 ` Philip Kaludercic
  0 siblings, 2 replies; 6+ messages in thread
From: Basil L. Contovounesios @ 2024-03-16 13:23 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Felician Nemeth, emacs-devel

Philip Kaludercic [2024-03-16 12:46 +0000] wrote:

> I am not sure what the danger is in the case of constant, quoted lists,
> but I am not familiar with the byte compiler either.  It seems like this
>
> diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
> index f75be3f71ad..e6f18590705 100644
> --- a/lisp/emacs-lisp/byte-opt.el
> +++ b/lisp/emacs-lisp/byte-opt.el
> @@ -1599,6 +1599,12 @@ byte-optimize-append
>                           (cdr args))
>                     (cdr newargs)))
>  
> +            ;; (append '(C1...) ... '(C2...)) -> (append C1... ... C2...)
> +            ((cl-loop for arg in args
> +                      always (and (eq (car arg) 'quote)
> +                                  (proper-list-p (cdr arg))))
> +             `',(mapcan #'cadr args))
> +
>              ;; non-terminal arg
>              ((cdr args)
>               (cond
>
>
> would do the trick, and the byte-code is even better:
>
> byte code:
>   args: nil
> 0	constant  (1 2 3 4)
> 1	return	  

Is this correct?  According to its docstring, append's last argument
must be eq to the tail of its return value.

-- 
Basil



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

* Re: (byte-compile '(append '(1 2) '(3 4)))
  2024-03-16 13:23               ` Basil L. Contovounesios
@ 2024-03-16 13:45                 ` Felician Nemeth
  2024-03-16 13:55                 ` Philip Kaludercic
  1 sibling, 0 replies; 6+ messages in thread
From: Felician Nemeth @ 2024-03-16 13:45 UTC (permalink / raw)
  To: Basil L. Contovounesios; +Cc: Philip Kaludercic, emacs-devel

> According to its docstring, append's last argument must be eq to the
> tail of its return value.

So that is why the compiler does optimize out (append '(1 2) '(3 4)) in
(disassemble (byte-compile '(append (append '(1 2) '(3 4)) '(5 6)))) , but
does not optimize the same expression out in 
(disassemble (byte-compile '(append (append '(1 2) '(3 4))))) ?



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

* Re: (byte-compile '(append '(1 2) '(3 4)))
  2024-03-16 13:23               ` Basil L. Contovounesios
  2024-03-16 13:45                 ` Felician Nemeth
@ 2024-03-16 13:55                 ` Philip Kaludercic
  2024-03-16 23:42                   ` Basil L. Contovounesios
  1 sibling, 1 reply; 6+ messages in thread
From: Philip Kaludercic @ 2024-03-16 13:55 UTC (permalink / raw)
  To: Basil L. Contovounesios; +Cc: Felician Nemeth, emacs-devel

"Basil L. Contovounesios" <basil@contovou.net> writes:

> Philip Kaludercic [2024-03-16 12:46 +0000] wrote:
>
>> I am not sure what the danger is in the case of constant, quoted lists,
>> but I am not familiar with the byte compiler either.  It seems like this
>>
>> diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
>> index f75be3f71ad..e6f18590705 100644
>> --- a/lisp/emacs-lisp/byte-opt.el
>> +++ b/lisp/emacs-lisp/byte-opt.el
>> @@ -1599,6 +1599,12 @@ byte-optimize-append
>>                           (cdr args))
>>                     (cdr newargs)))
>>  
>> +            ;; (append '(C1...) ... '(C2...)) -> (append C1... ... C2...)
>> +            ((cl-loop for arg in args
>> +                      always (and (eq (car arg) 'quote)
>> +                                  (proper-list-p (cdr arg))))
>> +             `',(mapcan #'cadr args))
>> +
>>              ;; non-terminal arg
>>              ((cdr args)
>>               (cond
>>
>>
>> would do the trick, and the byte-code is even better:
>>
>> byte code:
>>   args: nil
>> 0	constant  (1 2 3 4)
>> 1	return	  
>
> Is this correct?  According to its docstring, append's last argument
> must be eq to the tail of its return value.

This little test indicates that it would still be eq:

((macro . (lambda (arg)
	    `(eq (cddadr (byte-optimize-append '(append '(1 2) ,arg)))
		 ,arg)))
 '(3 4)) ;=> t

since the mapcan or rather nconc makes the same promise.

-- 
	Philip Kaludercic on peregrine



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

* Re: (byte-compile '(append '(1 2) '(3 4)))
  2024-03-16 13:55                 ` Philip Kaludercic
@ 2024-03-16 23:42                   ` Basil L. Contovounesios
  0 siblings, 0 replies; 6+ messages in thread
From: Basil L. Contovounesios @ 2024-03-16 23:42 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Felician Nemeth, emacs-devel

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

Philip Kaludercic [2024-03-16 13:55 +0000] wrote:
> "Basil L. Contovounesios" <basil@contovou.net> writes:
>> Philip Kaludercic [2024-03-16 12:46 +0000] wrote:
>>
>>> I am not sure what the danger is in the case of constant, quoted lists,
>>> but I am not familiar with the byte compiler either.  It seems like this
>>>
>>> --- a/lisp/emacs-lisp/byte-opt.el
>>> +++ b/lisp/emacs-lisp/byte-opt.el
>>> @@ -1599,6 +1599,12 @@ byte-optimize-append
>>>                           (cdr args))
>>>                     (cdr newargs)))
>>>  
>>> +            ;; (append '(C1...) ... '(C2...)) -> (append C1... ... C2...)
>>> +            ((cl-loop for arg in args
>>> +                      always (and (eq (car arg) 'quote)
>>> +                                  (proper-list-p (cdr arg))))
>>> +             `',(mapcan #'cadr args))
>>> +
>>>              ;; non-terminal arg
>>>              ((cdr args)
>>>               (cond
>>>
>>> would do the trick, and the byte-code is even better:
>>>
>>> byte code:
>>>   args: nil
>>> 0	constant  (1 2 3 4)
>>> 1	return	  
>>
>> Is this correct?  According to its docstring, append's last argument
>> must be eq to the tail of its return value.
>
> This little test indicates that it would still be eq:
>
> ((macro . (lambda (arg)
> 	    `(eq (cddadr (byte-optimize-append '(append '(1 2) ,arg)))
> 		 ,arg)))
>  '(3 4)) ;=> t
>
> since the mapcan or rather nconc makes the same promise.

Right, it seems straightforward to keep the resulting tail eq to the
last argument.  I'm too squeamish to destructively modify the input
form, and Emacs doesn't build with the diff above, so I'm guessing you
meant something like this instead:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: append.diff --]
[-- Type: text/x-diff, Size: 857 bytes --]

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index f75be3f71ad..f0e543319c3 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1630,6 +1630,13 @@ byte-optimize-append
             ;; (append X) -> X
             ((null newargs) arg)
 
+            ;; (append '(X...) ... '(Y...)) -> '(X... Y...)
+            ((and (eq (car-safe arg) 'quote)
+                  (cl-loop for newarg in newargs
+                           always (and (eq (car-safe newarg) 'quote)
+                                       (proper-list-p (cadr newarg)))))
+             `',(apply #'append (mapcar #'cadr (nreverse (cons arg newargs)))))
+
             ;; (append ... (list Xs...) nil) -> (append ... (list Xs...))
             ((and (null arg) (eq (car-safe prev) 'list))
              (cons (car form) (nreverse newargs)))

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]


But then the problem is that you can't e.g.

  (setcar (append '(0) '(1)) t)

without it looking like the program is modifying a constant list.

-- 
Basil

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

end of thread, other threads:[~2024-03-16 23:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <87v8j28c2x.fsf@betli.tmit.bme.hu>
     [not found] ` <874jdipfp5.fsf@posteo.net>
     [not found]   ` <87cys6t734.fsf@betli.tmit.bme.hu>
     [not found]     ` <87r0gmnjq4.fsf@posteo.net>
     [not found]       ` <87o7bprr04.fsf@betli.tmit.bme.hu>
     [not found]         ` <87bk7p57yz.fsf@posteo.net>
2024-03-16 12:16           ` (byte-compile '(append '(1 2) '(3 4))) Felician Nemeth
2024-03-16 12:46             ` Philip Kaludercic
2024-03-16 13:23               ` Basil L. Contovounesios
2024-03-16 13:45                 ` Felician Nemeth
2024-03-16 13:55                 ` Philip Kaludercic
2024-03-16 23:42                   ` Basil L. Contovounesios

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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