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:
@@ -385,18 +402,46 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
385
402
// / alignTo(~0LL, 8) = 0
386
403
// / alignTo(321, 255) = 510
387
404
// / \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 (static_cast <T>(Value) <=
411
+ std::numeric_limits<T>::max () - (Align - 1 ) &&
412
+ " alignTo would overflow" );
413
+ return (Value + Align - 1 ) / Align * Align;
414
+ }
415
+
416
+ // Fallback when arguments aren't integral.
417
+ constexpr inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
389
418
assert (Align != 0u && " Align can't be 0." );
390
419
return (Value + Align - 1 ) / Align * Align;
391
420
}
392
421
393
- inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
422
+ template <typename U, typename V, typename T = common_uint<U, V>>
423
+ constexpr T alignToPowerOf2 (U Value, V Align) {
394
424
assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
395
425
" Align must be a power of 2" );
426
+ // If Value is negative, wrap will occur in the cast.
427
+ if (Value > 0 )
428
+ assert (static_cast <T>(Value) <=
429
+ std::numeric_limits<T>::max () - (Align - 1 ) &&
430
+ " alignToPowerOf2 would overflow" );
396
431
// Replace unary minus to avoid compilation error on Windows:
397
432
// "unary minus operator applied to unsigned type, result still unsigned"
398
- uint64_t negAlign = (~Align) + 1 ;
399
- return (Value + Align - 1 ) & negAlign;
433
+ T NegAlign = (~Align) + 1 ;
434
+ return (Value + Align - 1 ) & NegAlign;
435
+ }
436
+
437
+ // Fallback when arguments aren't integral.
438
+ constexpr inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
439
+ assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
440
+ " Align must be a power of 2" );
441
+ // Replace unary minus to avoid compilation error on Windows:
442
+ // "unary minus operator applied to unsigned type, result still unsigned"
443
+ uint64_t NegAlign = (~Align) + 1 ;
444
+ return (Value + Align - 1 ) & NegAlign;
400
445
}
401
446
402
447
// / If non-zero \p Skew is specified, the return value will be a minimal integer
@@ -411,64 +456,86 @@ inline uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align) {
411
456
// / alignTo(~0LL, 8, 3) = 3
412
457
// / alignTo(321, 255, 42) = 552
413
458
// / \endcode
414
- inline uint64_t alignTo (uint64_t Value, uint64_t Align, uint64_t Skew) {
459
+ template <typename U, typename V, typename W,
460
+ typename T = common_uint<common_uint<U, V>, W>>
461
+ constexpr T alignTo (U Value, V Align, W Skew) {
415
462
assert (Align != 0u && " Align can't be 0." );
416
463
Skew %= Align;
417
464
return alignTo (Value - Skew, Align) + Skew;
418
465
}
419
466
420
467
// / Returns the next integer (mod 2**64) that is greater than or equal to
421
468
// / \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) {
469
+ template <uint64_t Align> constexpr uint64_t alignTo (uint64_t Value) {
423
470
static_assert (Align != 0u , " Align must be non-zero" );
424
471
return (Value + Align - 1 ) / Align * Align;
425
472
}
426
473
427
- // / Returns the integer ceil(Numerator / Denominator). Unsigned integer version.
428
- inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
474
+ // / Returns the integer ceil(Numerator / Denominator). Unsigned version.
475
+ template <typename U, typename V, typename T = common_uint<U, V>>
476
+ constexpr T divideCeil (U Numerator, V Denominator) {
429
477
return alignTo (Numerator, Denominator) / Denominator;
430
478
}
431
479
432
- // / Returns the integer ceil(Numerator / Denominator). Signed integer version.
433
- inline int64_t divideCeilSigned (int64_t Numerator, int64_t Denominator) {
480
+ // Fallback when arguments aren't integral.
481
+ constexpr inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
482
+ return alignTo (Numerator, Denominator) / Denominator;
483
+ }
484
+
485
+ // / Returns the integer ceil(Numerator / Denominator). Signed version.
486
+ // / Guaranteed to never overflow.
487
+ template <typename U, typename V, typename T = common_sint<U, V>>
488
+ constexpr T divideCeilSigned (U Numerator, V Denominator) {
434
489
assert (Denominator && " Division by zero" );
435
490
if (!Numerator)
436
491
return 0 ;
437
492
// C's integer division rounds towards 0.
438
- int64_t X = (Denominator > 0 ) ? -1 : 1 ;
493
+ T X = (Denominator > 0 ) ? -1 : 1 ;
439
494
bool SameSign = (Numerator > 0 ) == (Denominator > 0 );
440
495
return SameSign ? ((Numerator + X) / Denominator) + 1
441
496
: Numerator / Denominator;
442
497
}
443
498
444
- // / Returns the integer floor(Numerator / Denominator). Signed integer version.
445
- inline int64_t divideFloorSigned (int64_t Numerator, int64_t Denominator) {
499
+ // / Returns the integer floor(Numerator / Denominator). Signed version.
500
+ // / Guaranteed to never overflow.
501
+ template <typename U, typename V, typename T = common_sint<U, V>>
502
+ constexpr T divideFloorSigned (U Numerator, V Denominator) {
446
503
assert (Denominator && " Division by zero" );
447
504
if (!Numerator)
448
505
return 0 ;
449
506
// C's integer division rounds towards 0.
450
- int64_t X = (Denominator > 0 ) ? -1 : 1 ;
507
+ T X = (Denominator > 0 ) ? -1 : 1 ;
451
508
bool SameSign = (Numerator > 0 ) == (Denominator > 0 );
452
509
return SameSign ? Numerator / Denominator
453
510
: -((-Numerator + X) / Denominator) - 1 ;
454
511
}
455
512
456
513
// / 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) {
514
+ // / always non-negative. Signed version. Guaranteed to never overflow.
515
+ template <typename U, typename V, typename T = common_sint<U, V>>
516
+ constexpr T mod (U Numerator, V Denominator) {
459
517
assert (Denominator >= 1 && " Mod by non-positive number" );
460
- int64_t Mod = Numerator % Denominator;
518
+ T Mod = Numerator % Denominator;
461
519
return Mod < 0 ? Mod + Denominator : Mod;
462
520
}
463
521
464
522
// / Returns the integer nearest(Numerator / Denominator).
465
- inline uint64_t divideNearest (uint64_t Numerator, uint64_t Denominator) {
523
+ template <typename U, typename V, typename T = common_uint<U, V>>
524
+ constexpr T divideNearest (U Numerator, V Denominator) {
525
+ // If Value is negative, wrap will occur in the cast.
526
+ if (Numerator > 0 )
527
+ assert (static_cast <T>(Numerator) <=
528
+ std::numeric_limits<T>::max () - (Denominator / 2 ) &&
529
+ " divideNearest would overflow" );
466
530
return (Numerator + (Denominator / 2 )) / Denominator;
467
531
}
468
532
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 ) {
533
+ // / Returns the largest unsigned integer less than or equal to \p Value and is
534
+ // / \p Skew mod \p Align. \p Align must be non-zero. Guaranteed to never
535
+ // / overflow.
536
+ template <typename U, typename V, typename W = uint8_t ,
537
+ typename T = common_uint<common_uint<U, V>, W>>
538
+ constexpr T alignDown (U Value, V Align, W Skew = 0 ) {
472
539
assert (Align != 0u && " Align can't be 0." );
473
540
Skew %= Align;
474
541
return (Value - Skew) / Align * Align + Skew;
@@ -512,8 +579,8 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
512
579
513
580
// / Subtract two unsigned integers, X and Y, of type T and return the absolute
514
581
// / value of the result.
515
- template <typename T >
516
- std:: enable_if_t <std::is_unsigned_v<T>, T> AbsoluteDifference (T X, T Y) {
582
+ template <typename U, typename V, typename T = common_uint<U, V> >
583
+ constexpr T AbsoluteDifference (U X, V Y) {
517
584
return X > Y ? (X - Y) : (Y - X);
518
585
}
519
586
0 commit comments