C++ Logo

std-discussion

Advanced search

Re: small map instruction

From: Andrey Semashev <andrey.semashev_at_[hidden]>
Date: Wed, 6 Dec 2023 03:59:17 +0300
On 12/6/23 01:55, Bongo Ferno via Std-Discussion wrote:
> Should this be a new feature for the c++ language,or is it already
> implemented?
>
> I need to map a 64 bit unsigned integer from {0,1} to 64 bit double {1,-1}
>
> The available solutions are
>
> 1. An if
>
> double mapped = uintFlag ? double(-1.0) : double(1.0);
> // It's slow, because it introduces a branch

Branch isn't slow if it's predictable. In fact, it may be faster than
the non-branch variants that are latency-bound.

> 2. An arithmetic expression
> double mapped = 1 - 2 * int(uintFlag);
> // It's slow, because it needs type conversion
>
> 3. A constant array
> constexpr double mapArray[2] = {1.0, -1.0};
> double answer = mapArray[uintFlag];
> // It's slow, because it needs 10 cycles to fetch from memory, but
> tends to be faster, because it's branchless, and doesn't convert types.

4. Shift flag into the sign bit:

 double answer =
   bit_cast<double>(bit_cast<uint64_t>(1.0) | (uintFlag << 63u));

This one works well with all compilers.

5. Use conditional move instruction:

  double answer =
    bit_cast<double>(uintFlag ? bit_cast<uint64_t>(-1.0) :
      bit_cast<uint64_t>(1.0));

MSVC messes this one up quite a bit. Gcc also fails to use cmov, but not
as terrible as MSVC.

https://gcc.godbolt.org/z/dW9d9GfMf

Received on 2023-12-06 00:59:20