@@ -149,6 +149,8 @@ constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
149
149
150
150
// / Checks if an integer fits into the given bit width.
151
151
template <unsigned N> constexpr inline bool isInt (int64_t x) {
152
+ if constexpr (N == 0 )
153
+ return 0 == x;
152
154
if constexpr (N == 8 )
153
155
return static_cast <int8_t >(x) == x;
154
156
if constexpr (N == 16 )
@@ -164,15 +166,15 @@ template <unsigned N> constexpr inline bool isInt(int64_t x) {
164
166
// / Checks if a signed integer is an N bit number shifted left by S.
165
167
template <unsigned N, unsigned S>
166
168
constexpr inline bool isShiftedInt (int64_t x) {
167
- static_assert (
168
- N > 0 , " isShiftedInt<0> doesn't make sense (refers to a 0-bit number." );
169
+ static_assert (S < 64 , " isShiftedInt<N, S> with S >= 64 is too much." );
169
170
static_assert (N + S <= 64 , " isShiftedInt<N, S> with N + S > 64 is too wide." );
170
171
return isInt<N + S>(x) && (x % (UINT64_C (1 ) << S) == 0 );
171
172
}
172
173
173
174
// / Checks if an unsigned integer fits into the given bit width.
174
175
template <unsigned N> constexpr inline bool isUInt (uint64_t x) {
175
- static_assert (N > 0 , " isUInt<0> doesn't make sense" );
176
+ if constexpr (N == 0 )
177
+ return 0 == x;
176
178
if constexpr (N == 8 )
177
179
return static_cast <uint8_t >(x) == x;
178
180
if constexpr (N == 16 )
@@ -188,8 +190,7 @@ template <unsigned N> constexpr inline bool isUInt(uint64_t x) {
188
190
// / Checks if a unsigned integer is an N bit number shifted left by S.
189
191
template <unsigned N, unsigned S>
190
192
constexpr inline bool isShiftedUInt (uint64_t x) {
191
- static_assert (
192
- N > 0 , " isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)" );
193
+ static_assert (S < 64 , " isShiftedUInt<N, S> with S >= 64 is too much." );
193
194
static_assert (N + S <= 64 ,
194
195
" isShiftedUInt<N, S> with N + S > 64 is too wide." );
195
196
// Per the two static_asserts above, S must be strictly less than 64. So
@@ -199,29 +200,32 @@ constexpr inline bool isShiftedUInt(uint64_t x) {
199
200
200
201
// / Gets the maximum value for a N-bit unsigned integer.
201
202
inline uint64_t maxUIntN (uint64_t N) {
202
- assert (N > 0 && N <= 64 && " integer width out of range" );
203
+ assert (N <= 64 && " integer width out of range" );
203
204
204
205
// uint64_t(1) << 64 is undefined behavior, so we can't do
205
206
// (uint64_t(1) << N) - 1
206
207
// without checking first that N != 64. But this works and doesn't have a
207
- // branch.
208
- return UINT64_MAX >> (64 - N);
208
+ // branch for N != 0.
209
+ // Unfortunately, shifting a uint64_t right by 64 bit is undefined
210
+ // behavior, so the condition on N == 0 is necessary. Fortunately, most
211
+ // optimizers do not emit branches for this check.
212
+ return N == 0 ? 0 : UINT64_MAX >> (64 - N);
209
213
}
210
214
211
215
// / Gets the minimum value for a N-bit signed integer.
212
216
inline int64_t minIntN (int64_t N) {
213
- assert (N > 0 && N <= 64 && " integer width out of range" );
217
+ assert (N <= 64 && " integer width out of range" );
214
218
215
- return UINT64_C (1 ) + ~(UINT64_C (1 ) << (N - 1 ));
219
+ return N == 0 ? 0 : UINT64_C (1 ) + ~(UINT64_C (1 ) << (N - 1 ));
216
220
}
217
221
218
222
// / Gets the maximum value for a N-bit signed integer.
219
223
inline int64_t maxIntN (int64_t N) {
220
- assert (N > 0 && N <= 64 && " integer width out of range" );
224
+ assert (N <= 64 && " integer width out of range" );
221
225
222
226
// This relies on two's complement wraparound when N == 64, so we convert to
223
227
// int64_t only at the very end to avoid UB.
224
- return (UINT64_C (1 ) << (N - 1 )) - 1 ;
228
+ return N == 0 ? 0 : (UINT64_C (1 ) << (N - 1 )) - 1 ;
225
229
}
226
230
227
231
// / Checks if an unsigned integer fits into the given (dynamic) bit width.
@@ -432,35 +436,35 @@ inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
432
436
}
433
437
434
438
// / Sign-extend the number in the bottom B bits of X to a 32-bit integer.
435
- // / Requires 0 < B <= 32.
439
+ // / Requires B <= 32.
436
440
template <unsigned B> constexpr inline int32_t SignExtend32 (uint32_t X) {
437
- static_assert (B > 0 , " Bit width can't be 0." );
438
441
static_assert (B <= 32 , " Bit width out of range." );
442
+ if constexpr (B == 0 )
443
+ return 0 ;
439
444
return int32_t (X << (32 - B)) >> (32 - B);
440
445
}
441
446
442
447
// / Sign-extend the number in the bottom B bits of X to a 32-bit integer.
443
- // / Requires 0 < B <= 32.
448
+ // / Requires B <= 32.
444
449
inline int32_t SignExtend32 (uint32_t X, unsigned B) {
445
- assert (B > 0 && " Bit width can't be 0." );
446
450
assert (B <= 32 && " Bit width out of range." );
447
- return int32_t (X << (32 - B)) >> (32 - B);
451
+ return B == 0 ? 0 : int32_t (X << (32 - B)) >> (32 - B);
448
452
}
449
453
450
454
// / Sign-extend the number in the bottom B bits of X to a 64-bit integer.
451
- // / Requires 0 < B <= 64.
455
+ // / Requires B <= 64.
452
456
template <unsigned B> constexpr inline int64_t SignExtend64 (uint64_t x) {
453
- static_assert (B > 0 , " Bit width can't be 0." );
454
457
static_assert (B <= 64 , " Bit width out of range." );
458
+ if constexpr (B == 0 )
459
+ return 0 ;
455
460
return int64_t (x << (64 - B)) >> (64 - B);
456
461
}
457
462
458
463
// / Sign-extend the number in the bottom B bits of X to a 64-bit integer.
459
- // / Requires 0 < B <= 64.
464
+ // / Requires B <= 64.
460
465
inline int64_t SignExtend64 (uint64_t X, unsigned B) {
461
- assert (B > 0 && " Bit width can't be 0." );
462
466
assert (B <= 64 && " Bit width out of range." );
463
- return int64_t (X << (64 - B)) >> (64 - B);
467
+ return B == 0 ? 0 : int64_t (X << (64 - B)) >> (64 - B);
464
468
}
465
469
466
470
// / Subtract two unsigned integers, X and Y, of type T and return the absolute
@@ -564,7 +568,6 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
564
568
// / Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
565
569
extern const float huge_valf;
566
570
567
-
568
571
// / Add two signed integers, computing the two's complement truncated result,
569
572
// / returning true if overflow occurred.
570
573
template <typename T>
@@ -644,6 +647,6 @@ std::enable_if_t<std::is_signed_v<T>, T> MulOverflow(T X, T Y, T &Result) {
644
647
return UX > (static_cast <U>(std::numeric_limits<T>::max ())) / UY;
645
648
}
646
649
647
- } // End llvm namespace
650
+ } // namespace llvm
648
651
649
652
#endif
0 commit comments