23
23
#include < type_traits>
24
24
25
25
namespace 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>>;
26
42
27
43
// / Mathematical constants.
28
44
namespace numbers {
@@ -346,7 +362,8 @@ inline unsigned Log2_64_Ceil(uint64_t Value) {
346
362
347
363
// / A and B are either alignments or offsets. Return the minimum alignment that
348
364
// / 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) {
350
367
// The largest power of 2 that divides both A and B.
351
368
//
352
369
// Replace "-Value" by "1+~Value" in the following commented code to avoid
@@ -375,7 +392,7 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
375
392
return UINT64_C (1 ) << Log2_64_Ceil (A);
376
393
}
377
394
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
379
396
// / \p Value and is a multiple of \p Align. \p Align must be non-zero.
380
397
// /
381
398
// / Examples:
@@ -386,19 +403,50 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
386
403
// / alignTo(321, 255) = 510
387
404
// / \endcode
388
405
// /
389
- // / May overflow.
390
- inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
406
+ // / Will overflow only if result is not representable.
407
+ template <typename U, typename V, typename T = common_uint<U, V>>
408
+ constexpr T alignTo (U Value, V Align) {
391
409
assert (Align != 0u && " Align can't be 0." );
392
- return (Value + Align - 1 ) / Align * Align;
410
+ T Bias = (Value != 0 );
411
+ T CeilDiv = (Value - Bias) / Align + Bias;
412
+ // If Value is negative, wrap will occur in the cast.
413
+ if (Value > 0 )
414
+ assert (CeilDiv <= (std::numeric_limits<T>::max () - 1 ) / Align &&
415
+ " alignTo would overflow" );
416
+ return CeilDiv * Align;
393
417
}
394
418
395
- inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
419
+ // / Fallback when arguments aren't integral.
420
+ constexpr inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
421
+ assert (Align != 0u && " Align can't be 0." );
422
+ uint64_t Bias = (Value != 0 );
423
+ uint64_t CeilDiv = (Value - Bias) / Align + Bias;
424
+ return CeilDiv * Align;
425
+ }
426
+
427
+ // / Will overflow only if result is not representable.
428
+ template <typename U, typename V, typename T = common_uint<U, V>>
429
+ constexpr T alignToPowerOf2 (U Value, V Align) {
396
430
assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
397
431
" Align must be a power of 2" );
398
432
// Replace unary minus to avoid compilation error on Windows:
399
433
// "unary minus operator applied to unsigned type, result still unsigned"
400
- uint64_t negAlign = (~Align) + 1 ;
401
- return (Value + Align - 1 ) & negAlign;
434
+ T NegAlign = (~Align) + 1 ;
435
+ // If Value is negative, wrap will occur in the cast.
436
+ if (Value > 0 )
437
+ assert (static_cast <T>(Value) - 1 <= std::numeric_limits<T>::max () - Align &&
438
+ " alignToPowerOf2 would overflow" );
439
+ return (Value - 1 + Align) & NegAlign;
440
+ }
441
+
442
+ // / Fallback when arguments aren't integral.
443
+ constexpr inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
444
+ assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
445
+ " Align must be a power of 2" );
446
+ // Replace unary minus to avoid compilation error on Windows:
447
+ // "unary minus operator applied to unsigned type, result still unsigned"
448
+ uint64_t NegAlign = (~Align) + 1 ;
449
+ return (Value - 1 + Align) & NegAlign;
402
450
}
403
451
404
452
// / If non-zero \p Skew is specified, the return value will be a minimal integer
@@ -413,72 +461,99 @@ inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
413
461
// / alignTo(~0LL, 8, 3) = 3
414
462
// / alignTo(321, 255, 42) = 552
415
463
// / \endcode
416
- inline uint64_t alignTo (uint64_t Value, uint64_t Align, uint64_t Skew) {
464
+ template <typename U, typename V, typename W,
465
+ typename T = common_uint<common_uint<U, V>, W>>
466
+ constexpr T alignTo (U Value, V Align, W Skew) {
417
467
assert (Align != 0u && " Align can't be 0." );
418
468
Skew %= Align;
419
469
return alignTo (Value - Skew, Align) + Skew;
420
470
}
421
471
422
- // / Returns the next integer (mod 2**64 ) that is greater than or equal to
472
+ // / Returns the next integer (mod 2**nbits ) that is greater than or equal to
423
473
// / \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) {
474
+ // /
475
+ // / Will overflow only if result is not representable.
476
+ template <auto Align, typename V, typename T = common_uint<decltype (Align), V>>
477
+ constexpr T alignTo (V Value) {
425
478
static_assert (Align != 0u , " Align must be non-zero" );
426
- return (Value + Align - 1 ) / Align * Align;
479
+ T Bias = (Value != 0 );
480
+ T CeilDiv = (Value - Bias) / Align + Bias;
481
+ // If Value is negative, wrap will occur in the cast.
482
+ if (Value > 0 )
483
+ assert (CeilDiv <= (std::numeric_limits<T>::max () - 1 ) / Align &&
484
+ " alignTo would overflow" );
485
+ return CeilDiv * Align;
427
486
}
428
487
429
488
// / Returns the integer ceil(Numerator / Denominator). Unsigned version.
430
489
// / Guaranteed to never overflow.
431
- inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
490
+ template <typename U, typename V, typename T = common_uint<U, V>>
491
+ constexpr T divideCeil (U Numerator, V Denominator) {
492
+ assert (Denominator && " Division by zero" );
493
+ T Bias = (Numerator != 0 );
494
+ return (Numerator - Bias) / Denominator + Bias;
495
+ }
496
+
497
+ // / Fallback when arguments aren't integral.
498
+ constexpr inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
432
499
assert (Denominator && " Division by zero" );
433
500
uint64_t Bias = (Numerator != 0 );
434
501
return (Numerator - Bias) / Denominator + Bias;
435
502
}
436
503
437
504
// / Returns the integer ceil(Numerator / Denominator). Signed version.
438
505
// / Guaranteed to never overflow.
439
- inline int64_t divideCeilSigned (int64_t Numerator, int64_t Denominator) {
506
+ template <typename U, typename V, typename T = common_sint<U, V>>
507
+ constexpr T divideCeilSigned (U Numerator, V Denominator) {
440
508
assert (Denominator && " Division by zero" );
441
509
if (!Numerator)
442
510
return 0 ;
443
511
// C's integer division rounds towards 0.
444
- int64_t Bias = ( Denominator >= 0 ? 1 : -1 ) ;
512
+ T Bias = Denominator >= 0 ? 1 : -1 ;
445
513
bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
446
514
return SameSign ? (Numerator - Bias) / Denominator + 1
447
515
: Numerator / Denominator;
448
516
}
449
517
450
518
// / Returns the integer floor(Numerator / Denominator). Signed version.
451
519
// / Guaranteed to never overflow.
452
- inline int64_t divideFloorSigned (int64_t Numerator, int64_t Denominator) {
520
+ template <typename U, typename V, typename T = common_sint<U, V>>
521
+ constexpr T divideFloorSigned (U Numerator, V Denominator) {
453
522
assert (Denominator && " Division by zero" );
454
523
if (!Numerator)
455
524
return 0 ;
456
525
// C's integer division rounds towards 0.
457
- int64_t Bias = Denominator >= 0 ? -1 : 1 ;
526
+ T Bias = Denominator >= 0 ? -1 : 1 ;
458
527
bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
459
528
return SameSign ? Numerator / Denominator
460
529
: (Numerator - Bias) / Denominator - 1 ;
461
530
}
462
531
463
532
// / Returns the remainder of the Euclidean division of LHS by RHS. Result is
464
533
// / always non-negative.
465
- inline int64_t mod (int64_t Numerator, int64_t Denominator) {
534
+ template <typename U, typename V, typename T = common_sint<U, V>>
535
+ constexpr T mod (U Numerator, V Denominator) {
466
536
assert (Denominator >= 1 && " Mod by non-positive number" );
467
- int64_t Mod = Numerator % Denominator;
537
+ T Mod = Numerator % Denominator;
468
538
return Mod < 0 ? Mod + Denominator : Mod;
469
539
}
470
540
471
541
// / Returns (Numerator / Denominator) rounded by round-half-up. Guaranteed to
472
542
// / never overflow.
473
- inline uint64_t divideNearest (uint64_t Numerator, uint64_t Denominator) {
543
+ template <typename U, typename V, typename T = common_uint<U, V>>
544
+ constexpr T divideNearest (U Numerator, V Denominator) {
474
545
assert (Denominator && " Division by zero" );
475
- uint64_t Mod = Numerator % Denominator;
476
- return (Numerator / Denominator) + (Mod > (Denominator - 1 ) / 2 );
546
+ T Mod = Numerator % Denominator;
547
+ return (Numerator / Denominator) +
548
+ (Mod > (static_cast <T>(Denominator) - 1 ) / 2 );
477
549
}
478
550
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 ) {
551
+ // / Returns the largest unsigned integer less than or equal to \p Value and is
552
+ // / \p Skew mod \p Align. \p Align must be non-zero. Guaranteed to never
553
+ // / overflow.
554
+ template <typename U, typename V, typename W = uint8_t ,
555
+ typename T = common_uint<common_uint<U, V>, W>>
556
+ constexpr T alignDown (U Value, V Align, W Skew = 0 ) {
482
557
assert (Align != 0u && " Align can't be 0." );
483
558
Skew %= Align;
484
559
return (Value - Skew) / Align * Align + Skew;
@@ -522,8 +597,8 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
522
597
523
598
// / Subtract two unsigned integers, X and Y, of type T and return the absolute
524
599
// / value of the result.
525
- template <typename T >
526
- std:: enable_if_t <std::is_unsigned_v<T>, T> AbsoluteDifference (T X, T Y) {
600
+ template <typename U, typename V, typename T = common_uint<U, V> >
601
+ constexpr T AbsoluteDifference (U X, V Y) {
527
602
return X > Y ? (X - Y) : (Y - X);
528
603
}
529
604
0 commit comments