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

"Scott L. Burson" <[email protected]>
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CAF5LJ4AMPVR_vkr3NDKs0=Bir4_OcePreWeyxUa3aK6CqW1CaQ@mail.gmail.com>
On Fri, Jan 9, 2026 at 12:41 PM Stas Boukarev <[email protected]> wrote:
>
> Without modular arithmetic things turn out pretty badly if it's not
> recognized. So it's not a good idea to rely on 0 being excluded.

I'm sorry, I don't understand this at all.  As best I can tell, your
first sentence is
saying that if the operation is not constrained to fit in a word, either by type
declarations on the operand or by an explicit 'logand' or 'ldb' on the
result, and
therefore the expression is not recognized and transformed into 'tzcnt' or
equivalent, then "things turn out pretty badly" — I guess this rather vague
phrase means the generated code is not very efficient?  But why would you
expect good code if the user actually wants arbitrary-precision arithmetic,
or at least has failed to indicate that they don't?

And what does relying on zero-exclusion have to do with that?

At the risk of belaboring the obvious — if CL had a builtin function for this
operation, it would have to signal an error on zero, or at least return a
special value like -1; there's no finite correct result.  In an
arbitrary-precision
world, zero is not in the domain, just as it isn't for the reciprocal function.
Generated code would be obliged to check for zero explicitly, unless the
possibility could be ruled out statically.

Well, there's no CL builtin, so people write expressions that compute the
same result on nonzero operands as the builtin would.  On zero, these
expressions return some result, and I understand: if the compiler can't
rule out a zero operand, then it must exactly match the behavior of
the expression it was given.  But if it can rule out zero, where's the
problem in transforming it?

-- Scott

> On Fri, Jan 9, 2026 at 11:35 PM Scott L. Burson <[email protected]> wrote:
> >
> > On Wed, Dec 10, 2025 at 11:45 AM Stas Boukarev <[email protected]> wrote:
> > > 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.
> >
> > Speaking as someone who is actually using this operation -- doesn't the compiler
> > know whether n can be zero?  It seems to be so good at tracking the domains
> > of integer variables.
> >
> > I am literally doing (loop while (/= n 0) (let ((b (least-1-bit n)))
> > ...)) where least-1-bit
> > expands to one of the above expressions.  Surely, under these circumstances,
> > the compiler knows that n isn't zero, so it can match all of the three or four
> > expressions people use for this?
> >
> > -- Scott


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