Luke Wagner (2014-01-20T18:08:57.000Z)
It seems to me that we *must* have Math.clz perform ToUint32() on its input.  Otherwise (if ToInt32() is used), even if the expression is written "Math.clz(x >>> 0)", asm.js/type-inference won't be able to optimize away the <0 branch since the ToInt32() in the semantics of Math.clz will convert a large unsigned integer argument into a negative integer.

Secondly, I think clz(0) should be 32, not 0:
 - for x86's bsr, since the result is undefined if the input is zero, we need a branch or cmov *anyway* to deal with zero.
 - to make up for bsr's shortcomings, newer x86 chips have lzcnt (which JITs can emit after testing the right cpuid bit), which defines clz(0) == 32.
 - ARM's clz also defines clz(0) == 32.

The only reason not to do this I could imagine is if there was a de facto standard among all x86 chips (such that the JIT could rely on it) to have bsr(0) == 0, but I couldn't find any evidence of this.

Cheers,
Luke

----- Original Message -----
> Adam Ahmed wrote:
> > Just noting that this actually works:
> >  Math.ceil(Math.log(0 + 1) / Math.LN2) === 0
> >
> > However:
> > Math.ceil(Math.log(-1 + 1) / Math.LN2) === -Infinity
> 
> That's pretty sweet, but then try -2 or -3 or below and you get NaN.
> 
> > Not sure how that affects a Negative NaN-cy option :)
> 
> Heh.
> 
> I think we should make sure (per Jason and Jens) that, given type
> inference or asm.js-style type-checking, we can select a single common
> machine instruction. After that, we should consider more abstract
> "prettiness" properties such as the one you show for -1. And given the
> -Infinity then NaN inconsistency, perhaps NaN wins. But Jens' point
> about Infinity (bit length in two's complement infinite precision of any
> negative number) is strangely compelling.
> 
> Need to hear from type-inference and asm.js gurus. Cc'ing a few. The
> issue is, given
> 
>    Math.bitlen(x)
> 
> where x has inferred type int32, what do we need in the way of a guard
> for negative values? We need something, we cannot use BSR directly
> without getting 32 for -1.
> 
> /be
>
forbes at lindesay.co.uk (2014-01-28T23:10:42.473Z)
It seems to me that we *must* have `Math.clz` perform `ToUint32()` on its input.  Otherwise (if `ToInt32()` is used), even if the expression is written `Math.clz(x >>> 0)`, asm.js/type-inference won't be able to optimize away the `<0` branch since the `ToInt32()` in the semantics of `Math.clz` will convert a large unsigned integer argument into a negative integer.

Secondly, I think `clz(0)` should be `32`, not `0`:
 - for x86's `bsr`, since the result is undefined if the input is zero, we need a branch or cmov *anyway* to deal with zero.
 - to make up for `bsr`'s shortcomings, newer x86 chips have `lzcnt` (which JITs can emit after testing the right cpuid bit), which defines `clz(0) == 32`.
 - ARM's `clz` also defines `clz(0) == 32`.

The only reason not to do this I could imagine is if there was a de facto standard among all x86 chips (such that the JIT could rely on it) to have `bsr(0) == 0`, but I couldn't find any evidence of this.