constexpr with builtin

CLANG 3.2, just wondering if anyone can explain:

inline constexpr uint8_t test(uint64_t value)
{
  return value == 0 ? 0: __builtin_clzll(value);
}

Result: /Constexpr function never produces a constant expression/

While this compiles fine:

inline constexpr uint8_t test(uint64_t value)
{
  return value == value ? __builtin_clzll(value) : 0;
}

Any ideas?

Apologies, this is the code block that does not compile:

inline constexpr uint8_t test(uint64_t value)
{
  return __builtin_clzll(value);
}

I believe the simple test that makes the code above not compile does not evaluate potential results of conditional expressions: only one branch needs to be a constant expression, and the test does not reason about "value == value" always taking one branch. So the version with the tautological test will compile by itself, but you'll never be able to use it in a constexpr context, versus the simple function above is recognized as not being constexpr.

Making built-in functions with simple arithmetic meanings constexpr is a different issue.

Sebastian

Sebastian Redl wrote

I believe the simple test that makes the code above not compile does not
evaluate potential results of conditional expressions: only one branch
needs to be a constant expression, and the test does not reason about
"value == value" always taking one branch. So the version with the
tautological test will compile by itself, but you'll never be able to use
it in a constexpr context, versus the simple function above is recognized
as not being constexpr.

Making built-in functions with simple arithmetic meanings constexpr is a
different issue.

Thanks for the reply. Two questions:

1. know of a way to use builtin functions (like clz) in a constexpr context?
I am figuring I need to re-implement it, no way to use the CPU instruction
at compile time (?)
2. why does a branch allow it to be compiled? I would have thought that the
compiler would inspect both branches and insist they both be a const
friendly.

So, I should expect the branched version compile to fail if I actually use
it in a constexpr context? Should have tried that..

Regards, Fil.

Sebastian Redl wrote
> I believe the simple test that makes the code above not compile does not
> evaluate potential results of conditional expressions: only one branch
> needs to be a constant expression, and the test does not reason about
> "value == value" always taking one branch. So the version with the
> tautological test will compile by itself, but you'll never be able to use
> it in a constexpr context, versus the simple function above is recognized
> as not being constexpr.
>
> Making built-in functions with simple arithmetic meanings constexpr is a
> different issue.

Thanks for the reply. Two questions:

1. know of a way to use builtin functions (like clz) in a constexpr
context?
I am figuring I need to re-implement it, no way to use the CPU instruction
at compile time (?)

__builtin_clz works in constant expressions in recent Clang revisions. You
only need to upgrade =)

2. why does a branch allow it to be compiled? I would have thought that the

compiler would inspect both branches and insist they both be a const
friendly.

The compiler does inspect both branches, but it only insists that *one* of
them is constexpr-friendly. It's valid for a ?: to select between a
potentially-constant expression and a never-constant expression within a
constexpr function.

So, I should expect the branched version compile to fail if I actually use

it in a constexpr context?

Yes.

Richard Smith wrote

1. know of a way to use builtin functions (like clz) in a constexpr
context?
I am figuring I need to re-implement it, no way to use the CPU
instruction
at compile time (?)

__builtin_clz works in constant expressions in recent Clang revisions. You
only need to upgrade =)

Right.. good to know. Did this change come in 3.3 or very latest SVN?

Richard Smith wrote

2. why does a branch allow it to be compiled? I would have thought that
the

compiler would inspect both branches and insist they both be a const
friendly.

The compiler does inspect both branches, but it only insists that *one* of
them is constexpr-friendly. It's valid for a ?: to select between a
potentially-constant expression and a never-constant expression within a
constexpr function.

Gotcha. I expected it to be a bit more draconian on guaranteeing constexpr
in all branches. Thx for the follow up.

Regards, Fil.

Richard Smith wrote

  1. know of a way to use builtin functions (like clz) in a constexpr
    context?
    I am figuring I need to re-implement it, no way to use the CPU
    instruction
    at compile time (?)

__builtin_clz works in constant expressions in recent Clang revisions. You
only need to upgrade =)

Right… good to know. Did this change come in 3.3 or very latest SVN?

Sorry, I don’t remember. Maybe someone with 3.3 can test this for you. I think it was more recently than that, though.

fil <fil@pobox.com> writes:

__builtin_clz works in constant expressions in recent Clang
revisions. You only need to upgrade =)

Right.. good to know. Did this change come in 3.3 or very latest SVN?

This needs SVN. The change was made shortly after the 3.3 release.

Hi Justin,

Justin Bogner wrote

This needs SVN. The change was made shortly after the 3.3 release.

Thanks for the clarification. I found it worked exactly as described - now
running on the SVN latest. Looking forward to the 3.4 release.. :slight_smile: