Re: [PATCH] Transform (+ base (* index {2, 4, 8})) to use LEA instruction
Christophe Rhodes via Sbcl-devel <[email protected]>
| Newsgroups | gmane.lisp.steel-bank.devel |
|---|---|
| Message-ID | <[email protected]> |
Anthony Green <[email protected]> writes: > The transform only applies at (safety 0) since LEA does not check for > overflow, matching the behavior of regular fixnum addition at that > safety level. Just to clarify: (SAFETY 0) does not imply no checks for overflow: there is no such thing as "overflow" from the point of view of the language semantics: (defun foo (x y) (declare (type fixnum x y) (optimize (safety 0))) (+ x y)) has disassembly including: ; C1: 4801FA ADD RDX, RDI ; C4: 48D1E2 SHL RDX, 1 ; C7: 710A JNO L0 ; C9: 48D1DA RCR RDX, 1 ; CC: FF1425B0060050 CALL [#x500006B0] ; #xB800002680: ALLOC-SIGNED-BIGNUM-IN-RDX Instead, it means "trust any user declarations", so (defun bar (x y) (declare (type fixnum x y) (optimize (safety 0))) (the fixnum (+ x y))) will indeed compile to an add (well, ironically in this context, a LEA :-) with no overflow check. I haven't thought this through completely, but it should be possible to do the transformation you're proposing here on code of the form (defun baz (x y) (declare (type fixnum x y)) (+ x (* 2 y))) where either the compiler can prove that x+2y is always a fixnum (intermediate overflows are OK by the same logic as for modular arithmetic transforms), or the user has provided a trustable declaration of such. That should be doable using the return value type of DEFTRANSFORM. (I believe that it was primarily Allegro Common Lisp which defaulted to treating fixnum arithmetic as always returning fixnums at high speed and low safety qualities: certainly as of ACL 4.3, vintage 1996, the `compiler:declared-fixnums-remain-fixnums-switch` is documented to be true at (speed 3) (safety 0). I don't believe SBCL has ever had this behaviour at any compiler optimization levels, and I wouldn't want it to.) Christophe