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
@@ -355,6 +372,11 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
355372 return (A | B) & (1 + ~(A | B));
356373}
357374
375+ // / Fallback when arguments aren't integral.
376+ constexpr inline uint64_t MinAlign (uint64_t A, uint64_t B) {
377+ return (A | B) & (1 + ~(A | B));
378+ }
379+
358380// / Returns the next power of two (in 64-bits) that is strictly greater than A.
359381// / Returns zero on overflow.
360382constexpr inline uint64_t NextPowerOf2 (uint64_t A) {
@@ -375,7 +397,7 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
375397 return UINT64_C (1 ) << Log2_64_Ceil (A);
376398}
377399
378- // / Returns the next integer (mod 2**64 ) that is greater than or equal to
400+ // / Returns the next integer (mod 2**nbits ) that is greater than or equal to
379401// / \p Value and is a multiple of \p Align. \p Align must be non-zero.
380402// /
381403// / Examples:
@@ -386,19 +408,30 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
386408// / alignTo(321, 255) = 510
387409// / \endcode
388410// /
389- // / May overflow.
390- inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
411+ // / Will overflow only if result is not representable in T.
412+ template <typename U, typename V, typename T = common_uint<U, V>>
413+ constexpr T alignTo (U Value, V Align) {
414+ assert (Align != 0u && " Align can't be 0." );
415+ T Bias = (Value != 0 );
416+ T CeilDiv = (Value - Bias) / Align + Bias;
417+ return CeilDiv * Align;
418+ }
419+
420+ // / Fallback when arguments aren't integral.
421+ constexpr inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
391422 assert (Align != 0u && " Align can't be 0." );
392- return (Value + Align - 1 ) / Align * Align;
423+ uint64_t Bias = (Value != 0 );
424+ uint64_t CeilDiv = (Value - Bias) / Align + Bias;
425+ return CeilDiv * Align;
393426}
394427
395- inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
428+ constexpr inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
396429 assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
397430 " Align must be a power of 2" );
398431 // Replace unary minus to avoid compilation error on Windows:
399432 // "unary minus operator applied to unsigned type, result still unsigned"
400- uint64_t negAlign = (~Align) + 1 ;
401- return (Value + Align - 1 ) & negAlign ;
433+ uint64_t NegAlign = (~Align) + 1 ;
434+ return (Value + Align - 1 ) & NegAlign ;
402435}
403436
404437// / If non-zero \p Skew is specified, the return value will be a minimal integer
@@ -413,72 +446,97 @@ inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
413446// / alignTo(~0LL, 8, 3) = 3
414447// / alignTo(321, 255, 42) = 552
415448// / \endcode
416- inline uint64_t alignTo (uint64_t Value, uint64_t Align, uint64_t Skew) {
449+ // /
450+ // / Will overflow only if result is not representable in T.
451+ template <typename U, typename V, typename W,
452+ typename T = common_uint<common_uint<U, V>, W>>
453+ constexpr T alignTo (U Value, V Align, W Skew) {
417454 assert (Align != 0u && " Align can't be 0." );
418455 Skew %= Align;
419456 return alignTo (Value - Skew, Align) + Skew;
420457}
421458
422- // / Returns the next integer (mod 2**64 ) that is greater than or equal to
459+ // / Returns the next integer (mod 2**nbits ) that is greater than or equal to
423460// / \p Value and is a multiple of \c Align. \c Align must be non-zero.
424- template <uint64_t Align> constexpr inline uint64_t alignTo (uint64_t Value) {
461+ // /
462+ // / Will overflow only if result is not representable in T.
463+ template <auto Align, typename V, typename T = common_uint<decltype (Align), V>>
464+ constexpr T alignTo (V Value) {
425465 static_assert (Align != 0u , " Align must be non-zero" );
426- return (Value + Align - 1 ) / Align * Align;
466+ T Bias = (Value != 0 );
467+ T CeilDiv = (Value - Bias) / Align + Bias;
468+ return CeilDiv * Align;
427469}
428470
429471// / Returns the integer ceil(Numerator / Denominator). Unsigned version.
430472// / Guaranteed to never overflow.
431- inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
473+ template <typename U, typename V, typename T = common_uint<U, V>>
474+ constexpr T divideCeil (U Numerator, V Denominator) {
475+ assert (Denominator && " Division by zero" );
476+ T Bias = (Numerator != 0 );
477+ return (Numerator - Bias) / Denominator + Bias;
478+ }
479+
480+ // / Fallback when arguments aren't integral.
481+ constexpr inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
432482 assert (Denominator && " Division by zero" );
433483 uint64_t Bias = (Numerator != 0 );
434484 return (Numerator - Bias) / Denominator + Bias;
435485}
436486
437487// / Returns the integer ceil(Numerator / Denominator). Signed version.
438488// / Guaranteed to never overflow.
439- inline int64_t divideCeilSigned (int64_t Numerator, int64_t Denominator) {
489+ template <typename U, typename V, typename T = common_sint<U, V>>
490+ constexpr T divideCeilSigned (U Numerator, V Denominator) {
440491 assert (Denominator && " Division by zero" );
441492 if (!Numerator)
442493 return 0 ;
443494 // C's integer division rounds towards 0.
444- int64_t Bias = ( Denominator >= 0 ? 1 : -1 ) ;
495+ T Bias = Denominator >= 0 ? 1 : -1 ;
445496 bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
446497 return SameSign ? (Numerator - Bias) / Denominator + 1
447498 : Numerator / Denominator;
448499}
449500
450501// / Returns the integer floor(Numerator / Denominator). Signed version.
451502// / Guaranteed to never overflow.
452- inline int64_t divideFloorSigned (int64_t Numerator, int64_t Denominator) {
503+ template <typename U, typename V, typename T = common_sint<U, V>>
504+ constexpr T divideFloorSigned (U Numerator, V Denominator) {
453505 assert (Denominator && " Division by zero" );
454506 if (!Numerator)
455507 return 0 ;
456508 // C's integer division rounds towards 0.
457- int64_t Bias = Denominator >= 0 ? -1 : 1 ;
509+ T Bias = Denominator >= 0 ? -1 : 1 ;
458510 bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
459511 return SameSign ? Numerator / Denominator
460512 : (Numerator - Bias) / Denominator - 1 ;
461513}
462514
463515// / Returns the remainder of the Euclidean division of LHS by RHS. Result is
464516// / always non-negative.
465- inline int64_t mod (int64_t Numerator, int64_t Denominator) {
517+ template <typename U, typename V, typename T = common_sint<U, V>>
518+ constexpr T mod (U Numerator, V Denominator) {
466519 assert (Denominator >= 1 && " Mod by non-positive number" );
467- int64_t Mod = Numerator % Denominator;
520+ T Mod = Numerator % Denominator;
468521 return Mod < 0 ? Mod + Denominator : Mod;
469522}
470523
471524// / Returns (Numerator / Denominator) rounded by round-half-up. Guaranteed to
472525// / never overflow.
473- inline uint64_t divideNearest (uint64_t Numerator, uint64_t Denominator) {
526+ template <typename U, typename V, typename T = common_uint<U, V>>
527+ constexpr T divideNearest (U Numerator, V Denominator) {
474528 assert (Denominator && " Division by zero" );
475- uint64_t Mod = Numerator % Denominator;
476- return (Numerator / Denominator) + (Mod > (Denominator - 1 ) / 2 );
529+ T Mod = Numerator % Denominator;
530+ return (Numerator / Denominator) +
531+ (Mod > (static_cast <T>(Denominator) - 1 ) / 2 );
477532}
478533
479- // / Returns the largest uint64_t less than or equal to \p Value and is
480- // / \p Skew mod \p Align. \p Align must be non-zero
481- inline uint64_t alignDown (uint64_t Value, uint64_t Align, uint64_t Skew = 0 ) {
534+ // / Returns the largest unsigned integer less than or equal to \p Value and is
535+ // / \p Skew mod \p Align. \p Align must be non-zero. Guaranteed to never
536+ // / overflow.
537+ template <typename U, typename V, typename W = uint8_t ,
538+ typename T = common_uint<common_uint<U, V>, W>>
539+ constexpr T alignDown (U Value, V Align, W Skew = 0 ) {
482540 assert (Align != 0u && " Align can't be 0." );
483541 Skew %= Align;
484542 return (Value - Skew) / Align * Align + Skew;
@@ -522,8 +580,8 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
522580
523581// / Subtract two unsigned integers, X and Y, of type T and return the absolute
524582// / value of the result.
525- template <typename T >
526- std:: enable_if_t <std::is_unsigned_v<T>, T> AbsoluteDifference (T X, T Y) {
583+ template <typename U, typename V, typename T = common_uint<U, V> >
584+ constexpr T AbsoluteDifference (U X, V Y) {
527585 return X > Y ? (X - Y) : (Y - X);
528586}
529587
0 commit comments