From: kodifik
Subject: which one do you prefer?
Date: 
Message-ID: <6dc634ca.0411030627.49cd0b79@posting.google.com>
Is it better to write (* 2 n) than (+ n n)? Does it depend on
implementation? Even in that case, is it generally one of them better?
Does the situation change or even reverse when the code is interpreted
vs. compiled? What about floats instead of integers?
Kodifik-----"Doctors recommend Xanalys"

From: Gorbag
Subject: Re: which one do you prefer?
Date: 
Message-ID: <5i6id.3$qO4.2@bos-service2.ext.ray.com>
"kodifik" <·······@eurogaran.com> wrote in message
·································@posting.google.com...
> Is it better to write (* 2 n) than (+ n n)? Does it depend on
> implementation? Even in that case, is it generally one of them better?
> Does the situation change or even reverse when the code is interpreted
> vs. compiled? What about floats instead of integers?
> Kodifik-----"Doctors recommend Xanalys"

You forgot (ash n 1)

It's generally better to write what is clearest to the reader. If you are
optimizing code (which is what I presume you are doing because otherwise why
care about such things) you have to measure; the enclosing code, safety,
type decls, etc. may change what the compiler does for this expression. In
other words, you can't rely on a particular answer, except with respect to a
particular release of a particular implementation in a particular situation.
From: Pascal Bourguignon
Subject: Re: which one do you prefer?
Date: 
Message-ID: <87k6t3x9k3.fsf@naiad.informatimago.com>
·······@eurogaran.com (kodifik) writes:

> Is it better to write (* 2 n) than (+ n n)? Does it depend on
> implementation? Even in that case, is it generally one of them better?

It depends on the context, but if you want to double, in general it's
better to write (* 2 n).  

If n is a fixnum, I'd expect any compiler worth its bits to use the
fastest op-codes for the target, for example: (left-shift acc)  rather
than (add  acc acc) or (mul acc (imm 2)). And of course, (+ n n)
could generate the same code as (* 2 n).

> Does the situation change or even reverse when the code is interpreted
> vs. compiled? 

In case of an interpreter, it matters even less.


> What about floats instead of integers?

fadd r0,r0 could be faster than fmul r0,#2.  But this has little to do
with why you write (* 2 n) or (+ n n)...

For example compare the code generated for the following
functions. Can you see any significant difference?  Try the following
sexps and compare the  ADDI $NL3,$NL3,4 generate in both cases with
the rest. If a MULI was used instead of an ADDI do you think it would
make any difference?



(disassemble (compile nil (lambda (x) (declare (fixnum x)) (the fixnum (+ (the fixnum x) (the fixnum x))))))

[...]
;;; [5] (THE FIXNUM (+ # #))

;      B00:       CMPWI CR0,$NARGS,0
;      B04:       ADDI $NL3,$ZERO,0
;      B08:       BT  EQ,L2
;      B0C:       ADDI $NL0,$NL2,-4

;      B10: L1:   LWZX $FDEFN,$OCFP,$NL3
;      B14:       ADDI $NL3,$NL3,4
;      B18:       CMPW CR0,$NL3,$NARGS
;      B1C:       STWX $NL0,$FDEFN,$NL3

;      B20:       BF  EQ,L1
;      B24: L2:   ADD $CSP,$NL2,$NL3
;      B28:       LWZ $FDEFN,52($CFP)
;      B2C:       LWZ $A0,48($CFP)
;      B30:       LWZ $A1,44($CFP)
[...]


(disassemble (compile nil (lambda (x) (declare (fixnum x)) (the fixnum (* (the fixnum 2) (the fixnum x))))))

[...]
;;; [5] (THE FIXNUM (* # #))

;      644:       LWZ $NL2,56($CFP)
;      648:       CMPWI CR0,$NARGS,0
;      64C:       ADDI $NL3,$ZERO,0
;      650:       BT  EQ,L3
;      654:       ADDI $NL0,$NL2,-4

;      658: L2:   LWZX $FDEFN,$OCFP,$NL3
;      65C:       ADDI $NL3,$NL3,4
;      660:       CMPW CR0,$NL3,$NARGS
;      664:       STWX $NL0,$FDEFN,$NL3

;      668:       BF  EQ,L2
;      66C: L3:   ADD $CSP,$NL2,$NL3
;      670:       LWZ $FDEFN,48($CFP)
;      674:       LWZ $A0,44($CFP)
;      678:       LWZ $A1,40($CFP)
[...]

-- 
__Pascal Bourguignon__
From: Steven M. Haflich
Subject: Re: which one do you prefer?
Date: 
Message-ID: <fiBid.4814$zx1.2045@newssvr13.news.prodigy.com>
Pascal Bourguignon wrote:

  > If n is a fixnum, I'd expect any compiler worth its bits to use the
> fastest op-codes for the target, for example: (left-shift acc)  rather
> than (add  acc acc) or (mul acc (imm 2)). And of course, (+ n n)
> could generate the same code as (* 2 n).

This is well intentioned but semantically preposterous.  Even n is
a fixnum it is not necessary that (ash n 1) be a fixnum.  Neither
is it true that if m and n are both fixnums that (+ m n) is a fixnum.
From: Pascal Bourguignon
Subject: Re: which one do you prefer?
Date: 
Message-ID: <87lldgvrxg.fsf@naiad.informatimago.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> Pascal Bourguignon wrote:
> 
>   > If n is a fixnum, I'd expect any compiler worth its bits to use the
> > fastest op-codes for the target, for example: (left-shift acc)  rather
> > than (add  acc acc) or (mul acc (imm 2)). And of course, (+ n n)
> > could generate the same code as (* 2 n).
> 
> This is well intentioned but semantically preposterous.  Even n is
> a fixnum it is not necessary that (ash n 1) be a fixnum.  Neither
> is it true that if m and n are both fixnums that (+ m n) is a fixnum.

Didn't I paste real generated code?
Let me see, where's my post...
Ah yes, there. WHY DID YOU CUT IT OUT?  
And CAN'T YOU INFER THAT I WROTE PSEUDO-CODE ABSTRACTING THAT KIND OF DETAILS?


> (disassemble (compile nil (lambda (x) (declare (fixnum x)) (the fixnum (+ (the fixnum x) (the fixnum x))))))
> 
> [...]
> ;;; [5] (THE FIXNUM (+ # #))
> 
> ;      B00:       CMPWI CR0,$NARGS,0
> ;      B04:       ADDI $NL3,$ZERO,0
> ;      B08:       BT  EQ,L2
> ;      B0C:       ADDI $NL0,$NL2,-4
> 
> ;      B10: L1:   LWZX $FDEFN,$OCFP,$NL3
> ;      B14:       ADDI $NL3,$NL3,4
> ;      B18:       CMPW CR0,$NL3,$NARGS
> ;      B1C:       STWX $NL0,$FDEFN,$NL3
> 
> ;      B20:       BF  EQ,L1
> ;      B24: L2:   ADD $CSP,$NL2,$NL3
> ;      B28:       LWZ $FDEFN,52($CFP)
> ;      B2C:       LWZ $A0,48($CFP)
> ;      B30:       LWZ $A1,44($CFP)
> [...]
> 
> 
> (disassemble (compile nil (lambda (x) (declare (fixnum x)) (the fixnum (* (the fixnum 2) (the fixnum x))))))
> 
> [...]
> ;;; [5] (THE FIXNUM (* # #))
> 
> ;      644:       LWZ $NL2,56($CFP)
> ;      648:       CMPWI CR0,$NARGS,0
> ;      64C:       ADDI $NL3,$ZERO,0
> ;      650:       BT  EQ,L3
> ;      654:       ADDI $NL0,$NL2,-4
> 
> ;      658: L2:   LWZX $FDEFN,$OCFP,$NL3
> ;      65C:       ADDI $NL3,$NL3,4
> ;      660:       CMPW CR0,$NL3,$NARGS
> ;      664:       STWX $NL0,$FDEFN,$NL3
> 
> ;      668:       BF  EQ,L2
> ;      66C: L3:   ADD $CSP,$NL2,$NL3
> ;      670:       LWZ $FDEFN,48($CFP)
> ;      674:       LWZ $A0,44($CFP)
> ;      678:       LWZ $A1,40($CFP)
> [...]

 
-- 
__Pascal Bourguignon__
From: Alan Crowe
Subject: Re: which one do you prefer?
Date: 
Message-ID: <86vfcm24o9.fsf@cawtech.freeserve.co.uk>
kodifik asks
> Is it better to write (* 2 n) than (+ n n)?

They suggest very different things to this human reader.

(* 2 n) makes a huge commitment to the number two.

Consider whether you would prefer to be maintaining

(defconstant foo-scale 2)
(defconstant bar-scale 2)
...(* foo-scale n)...(* foo-scale n)...(* bar-scale n)...

or maintaining

...(* 2 n)...(* 2 n)...(* 2 n)...

(+ n n) suggests summing two numbers, coincidentally equal,
for the moment, with a hint that version two of the
program will likely read (+ n1 n2) and version three 
(+ n1 n2 ... nr)

The search for `le mot juste' is the attempt to communicate
to your future self, and other readers of your code.

The era of transforming 2*x to x+x to get better code out of
your compiler was over 20 years ago.

Alan Crowe
Edinburgh
Scotland