Extra instruction in generated code for (ldb (byte 3 29) x)
Describe the bug
There appears to be an extra instruction in computing (ldb (byte 3 29) x)
, which gets the top 3 bits of a 32-bit number.
The test function is
(defun hi3 (x)
(declare (type (unsigned-byte 32) x)
(optimize (speed 3) (safety 0)))
(ldb (byte 3 (- 32 3)) x))
To Reproduce
Steps to reproduce the behavior:
- Put the test function above in a file, say "hi3.lisp"
- `(compile-file "hi3" :load t :trace-file t)
-
(disassemble 'hi3)
or look at the trace file.
Expected behavior
The disassembly shows, in part:
a6: L1: shr edx, #x1d ; No-arg-parsing entry point
; [:non-local-entry]
a9: and edx, #x7
ac: shl edx, #x2
So we correctly did a logical right shift of 29 bits to move the high
3 bits to the lowest 3 bits of the register. But then we and
that
with 7. There's no need to do this and
operation since we're
shifting out the top 3 bits of the 32-bit integer.
Probably a deficiency in ldb
not recognizing that we've shifted in
zeroes. If, say, we weren't getting the top 3 bits, then the and
operation would be needed to clear out the bits we don't want.
Definitely needed for something like (ldb (byte 3 20 x)
.
This is pretty minor micro optimization that we could do.
Desktop (please complete the following information):
- OS: All x86
- Version: 21e