2323#include < type_traits>
2424
2525namespace llvm {
26+ // / Some template parameter helpers to optimize for bitwidth, for functions that
27+ // / take multiple arguments.
28+
29+ // We can't verify signedness, since callers rely on implicit coercions to
30+ // signed/unsigned.
31+ template <typename T, typename U>
32+ using enableif_int =
33+ std::enable_if_t <std::is_integral_v<T> && std::is_integral_v<U>>;
34+
35+ // Use std::common_type_t to widen only up to the widest argument.
36+ template <typename T, typename U, typename = enableif_int<T, U>>
37+ using common_uint =
38+ std::common_type_t <std::make_unsigned_t <T>, std::make_unsigned_t <U>>;
39+ template <typename T, typename U, typename = enableif_int<T, U>>
40+ using common_sint =
41+ std::common_type_t <std::make_signed_t <T>, std::make_signed_t <U>>;
2642
2743// / Mathematical constants.
2844namespace numbers {
@@ -346,7 +362,8 @@ inline unsigned Log2_64_Ceil(uint64_t Value) {
346362
347363// / A and B are either alignments or offsets. Return the minimum alignment that
348364// / may be assumed after adding the two together.
349- constexpr inline uint64_t MinAlign (uint64_t A, uint64_t B) {
365+ template <typename U, typename V, typename T = common_uint<U, V>>
366+ constexpr T MinAlign (U A, V B) {
350367 // The largest power of 2 that divides both A and B.
351368 //
352369 // Replace "-Value" by "1+~Value" in the following commented code to avoid
@@ -375,7 +392,7 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
375392 return UINT64_C (1 ) << Log2_64_Ceil (A);
376393}
377394
378- // / Returns the next integer (mod 2**64 ) that is greater than or equal to
395+ // / Returns the next integer (mod 2**nbits ) that is greater than or equal to
379396// / \p Value and is a multiple of \p Align. \p Align must be non-zero.
380397// /
381398// / Examples:
@@ -385,18 +402,44 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
385402// / alignTo(~0LL, 8) = 0
386403// / alignTo(321, 255) = 510
387404// / \endcode
388- inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
405+ template <typename U, typename V, typename T = common_uint<U, V>>
406+ constexpr T alignTo (U Value, V Align) {
407+ assert (Align != 0u && " Align can't be 0." );
408+ // If Value is negative, wrap will occur in the cast.
409+ if (Value > 0 )
410+ assert ((T)Value <= std::numeric_limits<T>::max () - (Align - 1 ) &&
411+ " alignTo would overflow" );
412+ return (Value + Align - 1 ) / Align * Align;
413+ }
414+
415+ // Fallback when arguments aren't integral.
416+ constexpr inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
389417 assert (Align != 0u && " Align can't be 0." );
390418 return (Value + Align - 1 ) / Align * Align;
391419}
392420
393- inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
421+ template <typename U, typename V, typename T = common_uint<U, V>>
422+ constexpr T alignToPowerOf2 (U Value, V Align) {
394423 assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
395424 " Align must be a power of 2" );
425+ // If Value is negative, wrap will occur in the cast.
426+ if (Value > 0 )
427+ assert ((T)Value <= std::numeric_limits<T>::max () - (Align - 1 ) &&
428+ " alignToPowerOf2 would overflow" );
396429 // Replace unary minus to avoid compilation error on Windows:
397430 // "unary minus operator applied to unsigned type, result still unsigned"
398- uint64_t negAlign = (~Align) + 1 ;
399- return (Value + Align - 1 ) & negAlign;
431+ T NegAlign = (~Align) + 1 ;
432+ return (Value + Align - 1 ) & NegAlign;
433+ }
434+
435+ // Fallback when arguments aren't integral.
436+ constexpr inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
437+ assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
438+ " Align must be a power of 2" );
439+ // Replace unary minus to avoid compilation error on Windows:
440+ // "unary minus operator applied to unsigned type, result still unsigned"
441+ uint64_t NegAlign = (~Align) + 1 ;
442+ return (Value + Align - 1 ) & NegAlign;
400443}
401444
402445// / If non-zero \p Skew is specified, the return value will be a minimal integer
@@ -411,64 +454,85 @@ inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
411454// / alignTo(~0LL, 8, 3) = 3
412455// / alignTo(321, 255, 42) = 552
413456// / \endcode
414- inline uint64_t alignTo (uint64_t Value, uint64_t Align, uint64_t Skew) {
457+ template <typename U, typename V, typename W,
458+ typename T = common_uint<common_uint<U, V>, W>>
459+ constexpr T alignTo (U Value, V Align, W Skew) {
415460 assert (Align != 0u && " Align can't be 0." );
416461 Skew %= Align;
417462 return alignTo (Value - Skew, Align) + Skew;
418463}
419464
420465// / Returns the next integer (mod 2**64) that is greater than or equal to
421466// / \p Value and is a multiple of \c Align. \c Align must be non-zero.
422- template <uint64_t Align> constexpr inline uint64_t alignTo (uint64_t Value) {
467+ template <uint64_t Align> constexpr uint64_t alignTo (uint64_t Value) {
423468 static_assert (Align != 0u , " Align must be non-zero" );
424469 return (Value + Align - 1 ) / Align * Align;
425470}
426471
427- // / Returns the integer ceil(Numerator / Denominator). Unsigned integer version.
428- inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
472+ // / Returns the integer ceil(Numerator / Denominator). Unsigned version.
473+ template <typename U, typename V, typename T = common_uint<U, V>>
474+ constexpr T divideCeil (U Numerator, V Denominator) {
429475 return alignTo (Numerator, Denominator) / Denominator;
430476}
431477
432- // / Returns the integer ceil(Numerator / Denominator). Signed integer version.
433- inline int64_t divideCeilSigned (int64_t Numerator, int64_t Denominator) {
478+ // Fallback when arguments aren't integral.
479+ constexpr inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
480+ return alignTo (Numerator, Denominator) / Denominator;
481+ }
482+
483+ // / Returns the integer ceil(Numerator / Denominator). Signed version.
484+ // / Guaranteed to never overflow.
485+ template <typename U, typename V, typename T = common_sint<U, V>>
486+ constexpr T divideCeilSigned (U Numerator, V Denominator) {
434487 assert (Denominator && " Division by zero" );
435488 if (!Numerator)
436489 return 0 ;
437490 // C's integer division rounds towards 0.
438- int64_t X = (Denominator > 0 ) ? -1 : 1 ;
491+ T X = (Denominator > 0 ) ? -1 : 1 ;
439492 bool SameSign = (Numerator > 0 ) == (Denominator > 0 );
440493 return SameSign ? ((Numerator + X) / Denominator) + 1
441494 : Numerator / Denominator;
442495}
443496
444- // / Returns the integer floor(Numerator / Denominator). Signed integer version.
445- inline int64_t divideFloorSigned (int64_t Numerator, int64_t Denominator) {
497+ // / Returns the integer floor(Numerator / Denominator). Signed version.
498+ // / Guaranteed to never overflow.
499+ template <typename U, typename V, typename T = common_sint<U, V>>
500+ constexpr T divideFloorSigned (U Numerator, V Denominator) {
446501 assert (Denominator && " Division by zero" );
447502 if (!Numerator)
448503 return 0 ;
449504 // C's integer division rounds towards 0.
450- int64_t X = (Denominator > 0 ) ? -1 : 1 ;
505+ T X = (Denominator > 0 ) ? -1 : 1 ;
451506 bool SameSign = (Numerator > 0 ) == (Denominator > 0 );
452507 return SameSign ? Numerator / Denominator
453508 : -((-Numerator + X) / Denominator) - 1 ;
454509}
455510
456511// / Returns the remainder of the Euclidean division of LHS by RHS. Result is
457- // / always non-negative.
458- inline int64_t mod (int64_t Numerator, int64_t Denominator) {
512+ // / always non-negative. Signed version. Guaranteed to never overflow.
513+ template <typename U, typename V, typename T = common_sint<U, V>>
514+ constexpr T mod (U Numerator, V Denominator) {
459515 assert (Denominator >= 1 && " Mod by non-positive number" );
460- int64_t Mod = Numerator % Denominator;
516+ T Mod = Numerator % Denominator;
461517 return Mod < 0 ? Mod + Denominator : Mod;
462518}
463519
464520// / Returns the integer nearest(Numerator / Denominator).
465- inline uint64_t divideNearest (uint64_t Numerator, uint64_t Denominator) {
521+ template <typename U, typename V, typename T = common_uint<U, V>>
522+ constexpr T divideNearest (U Numerator, V Denominator) {
523+ // If Value is negative, wrap will occur in the cast.
524+ if (Numerator > 0 )
525+ assert ((T)Numerator <= std::numeric_limits<T>::max () - (Denominator / 2 ) &&
526+ " divideNearest would overflow" );
466527 return (Numerator + (Denominator / 2 )) / Denominator;
467528}
468529
469- // / Returns the largest uint64_t less than or equal to \p Value and is
470- // / \p Skew mod \p Align. \p Align must be non-zero
471- inline uint64_t alignDown (uint64_t Value, uint64_t Align, uint64_t Skew = 0 ) {
530+ // / Returns the largest unsigned integer less than or equal to \p Value and is
531+ // / \p Skew mod \p Align. \p Align must be non-zero. Guaranteed to never
532+ // / overflow.
533+ template <typename U, typename V, typename W = uint8_t ,
534+ typename T = common_uint<common_uint<U, V>, W>>
535+ constexpr T alignDown (U Value, V Align, W Skew = 0 ) {
472536 assert (Align != 0u && " Align can't be 0." );
473537 Skew %= Align;
474538 return (Value - Skew) / Align * Align + Skew;
@@ -512,8 +576,8 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
512576
513577// / Subtract two unsigned integers, X and Y, of type T and return the absolute
514578// / value of the result.
515- template <typename T >
516- std:: enable_if_t <std::is_unsigned_v<T>, T> AbsoluteDifference (T X, T Y) {
579+ template <typename U, typename V, typename T = common_uint<U, V> >
580+ constexpr T AbsoluteDifference (U X, V Y) {
517581 return X > Y ? (X - Y) : (Y - X);
518582}
519583
0 commit comments