@@ -117,21 +117,35 @@ template<typename taType, int64 taArraySize>
117117consteval 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?
121126constexpr bool gIsPow2 (int64 inValue) { return inValue != 0 && (inValue & (inValue - 1 )) == 0 ; }
122127constexpr int64 gAlignUp (int64 inValue, int64 inPow2Alignment) { return (inValue + (inPow2Alignment - 1 )) & ~(inPow2Alignment - 1 ); }
123128constexpr 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