Skip to content

Commit 080e2c5

Browse files
committed
Added gIsContantEvaluated
gCountLeadingZeros64 and gGetNextPow2 are now contexpr thanks to it.
1 parent b97691a commit 080e2c5

2 files changed

Lines changed: 27 additions & 5 deletions

File tree

Bedrock/Core.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
11
// SPDX-License-Identifier: MPL-2.0
22
#include <Bedrock/Core.h>
33

4+
5+
// Tests for the constexpr code in gCountLeadingZeros64.
6+
static_assert(gCountLeadingZeros64(0) == 64);
7+
static_assert(gCountLeadingZeros64(1) == 63);
8+
static_assert(gCountLeadingZeros64(cMaxUInt64) == 0);
9+
static_assert(gCountLeadingZeros64(cMaxUInt32) == 32);
10+

Bedrock/Core.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,35 @@ template<typename taType, int64 taArraySize>
117117
consteval int64 gElemCount(const taType (&)[taArraySize]) { return taArraySize; }
118118

119119

120+
// Return true if the calling function is evaluated in a constexpr context.
121+
// Equivalent to std::is_constant_evaluated.
122+
constexpr bool gIsContantEvaluated() { return __builtin_is_constant_evaluated(); }
123+
124+
120125
// Bit twiddling. Move elsewhere?
121126
constexpr bool gIsPow2(int64 inValue) { return inValue != 0 && (inValue & (inValue - 1)) == 0; }
122127
constexpr int64 gAlignUp(int64 inValue, int64 inPow2Alignment) { return (inValue + (inPow2Alignment - 1)) & ~(inPow2Alignment - 1); }
123128
constexpr int64 gAlignDown(int64 inValue, int64 inPow2Alignment) { return inValue & ~(inPow2Alignment - 1); }
124129

125-
#ifdef _MSC_VER
126-
extern "C" unsigned char _BitScanReverse64(unsigned long* _Index, unsigned __int64 _Mask);
127-
#endif
128130

129-
inline int gCountLeadingZeros64(uint64 inValue)
131+
constexpr int gCountLeadingZeros64(uint64 inValue)
130132
{
133+
if (gIsContantEvaluated())
134+
{
135+
int leading_zeroes = 0;
136+
for (; leading_zeroes < 64; leading_zeroes++)
137+
{
138+
if (inValue & ((uint64)1 << (63 - leading_zeroes)))
139+
break; // Found a one.
140+
}
141+
return leading_zeroes;
142+
}
143+
131144
gAssert(inValue != 0);
132145
#ifdef __clang__
133146
return __builtin_clzll(inValue);
134147
#elif _MSC_VER
148+
unsigned char _BitScanReverse64(unsigned long* _Index, unsigned __int64 _Mask);
135149
uint32 index;
136150
_BitScanReverse64(&index, inValue);
137151
return 63 - index;
@@ -140,7 +154,8 @@ inline int gCountLeadingZeros64(uint64 inValue)
140154
#endif
141155
}
142156

143-
inline int64 gGetNextPow2(int64 inValue)
157+
158+
constexpr int64 gGetNextPow2(int64 inValue)
144159
{
145160
if (inValue <= 1) [[unlikely]]
146161
return 1;

0 commit comments

Comments
 (0)