Re: [Sbcl-commits] master: Recognize (integer-length (ldb (byte 64 0) (1- (logand n (- n))))) as ctz

Stas Boukarev <[email protected]>
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CAF63=11qvOr6rt2yXjTriZz9pN7hBKM7fLQhXJ=JpgT-m3OkUw@mail.gmail.com>
On Wed, Dec 10, 2025 at 10:19 PM Christophe Rhodes via Sbcl-devel
<[email protected]> wrote:
>
> stassats via Sbcl-commits <[email protected]> writes:
>
> > The branch "master" has been updated in SBCL:
> >        via  2c3722ef6c309045afe6804fc99bc9e8d9b6c75a (commit)
> >       from  ab3fb8c0ecd1dbe07f6b4fcdd3d13a5ac084f00a (commit)
> >
> > - Log -----------------------------------------------------------------
> > commit 2c3722ef6c309045afe6804fc99bc9e8d9b6c75a
> > Author: Stas Boukarev <[email protected]>
> > Date:   Wed Dec 10 17:48:31 2025 +0300
> >
> >     Recognize (integer-length (ldb (byte 64 0) (1- (logand n (- n))))) as ctz
> > ---
> >  doc/manual/efficiency.texinfo  | 22 ++++++++++++++++
>
> Nice!  I think since this is documented, potentially fragile, and not
> directly exercised by anything else, this is a prime candidate for
> having a test that verifies that this recognition actually takes place.
> Whether that's a test of the emitted assembly, or a test that the
> `integer-length` transform fires successfully, I don't know.

IR1 can be matched. Although the ir1 tests only work with sb-devel.

> I guess
> I want to encourage adding tests of desired properties by default,
> whether that's from adding a new feature like this or fixing a bug.

I like adding tests, but I also like being lazy.

> The transform itself looks pretty horrible, and we're still tied to
> working from the outside operator?
>
> What does the equivalent for rotation look like?  The idiom is
>
>   (ldb (byte 64 0) (logior (ash x <n>) (ash x <n-64>)))

It also has to be non-horrible if it doesn't get translated. I had
trouble figuring out how to deal with 0, some code in the wild uses
things like
(1- (integer-length (logand n (- n)))) or (1- (logcount (logxor n (1-
n)))), but they return a different thing on 0. Maybe they should be
matched anyway and 0 handled with a conditional move or something.
And I decided against (logcount (ldb (byte 64 0) (lognor n (- n))))
because popcount is potentially expensive.

> but then does the modular rewriting happen first, so we'd need in fact
> to be recognizing
>
>   (logior/mod64 (ash/mod64 ...) (ash/mod64 ...))?

I specifically added (delay-ir1-transform node :ir1-phases) to reduce
variation, so that just the modular funs have to be chcked. Although
they get inserted first anyway, due to DFS, some unoptimized casts
added by cut-to-width were interfering. And, since it's matching
multiple forms, relevant reoptimizations do not always reach the outer
function of interest.


> (We'd presumably then want to bring the guts of sb-rotate-byte into the
> core system and leave just the interface as the contrib)
>
> Thanks,
>
> Christophe
>
>
> _______________________________________________
> Sbcl-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/sbcl-devel


_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.