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 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
@@ -355,6 +372,11 @@ constexpr uint64_t MinAlign(uint64_t A, uint64_t B) {
355
372
return (A | B) & (1 + ~(A | B));
356
373
}
357
374
375
+ // / Fallback when arguments aren't integral.
376
+ constexpr uint64_t MinAlign (uint64_t A, uint64_t B) {
377
+ return (A | B) & (1 + ~(A | B));
378
+ }
379
+
358
380
// / Returns the next power of two (in 64-bits) that is strictly greater than A.
359
381
// / Returns zero on overflow.
360
382
constexpr uint64_t NextPowerOf2 (uint64_t A) {
@@ -375,60 +397,17 @@ inline uint64_t PowerOf2Ceil(uint64_t A) {
375
397
return UINT64_C (1 ) << Log2_64_Ceil (A);
376
398
}
377
399
378
- // / Returns the next integer (mod 2**64) that is greater than or equal to
379
- // / \p Value and is a multiple of \p Align. \p Align must be non-zero.
380
- // /
381
- // / Examples:
382
- // / \code
383
- // / alignTo(5, 8) = 8
384
- // / alignTo(17, 8) = 24
385
- // / alignTo(~0LL, 8) = 0
386
- // / alignTo(321, 255) = 510
387
- // / \endcode
388
- // /
389
- // / May overflow.
390
- inline uint64_t alignTo (uint64_t Value, uint64_t Align) {
391
- assert (Align != 0u && " Align can't be 0." );
392
- return (Value + Align - 1 ) / Align * Align;
393
- }
394
-
395
- inline uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
396
- assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
397
- " Align must be a power of 2" );
398
- // Replace unary minus to avoid compilation error on Windows:
399
- // "unary minus operator applied to unsigned type, result still unsigned"
400
- uint64_t negAlign = (~Align) + 1 ;
401
- return (Value + Align - 1 ) & negAlign;
402
- }
403
-
404
- // / If non-zero \p Skew is specified, the return value will be a minimal integer
405
- // / that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
406
- // / some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
407
- // / Skew mod \p A'. \p Align must be non-zero.
408
- // /
409
- // / Examples:
410
- // / \code
411
- // / alignTo(5, 8, 7) = 7
412
- // / alignTo(17, 8, 1) = 17
413
- // / alignTo(~0LL, 8, 3) = 3
414
- // / alignTo(321, 255, 42) = 552
415
- // / \endcode
416
- inline uint64_t alignTo (uint64_t Value, uint64_t Align, uint64_t Skew) {
417
- assert (Align != 0u && " Align can't be 0." );
418
- Skew %= Align;
419
- return alignTo (Value - Skew, Align) + Skew;
420
- }
421
-
422
- // / Returns the next integer (mod 2**64) that is greater than or equal to
423
- // / \p Value and is a multiple of \c Align. \c Align must be non-zero.
424
- template <uint64_t Align> constexpr uint64_t alignTo (uint64_t Value) {
425
- static_assert (Align != 0u , " Align must be non-zero" );
426
- return (Value + Align - 1 ) / Align * Align;
427
- }
428
-
429
400
// / Returns the integer ceil(Numerator / Denominator). Unsigned version.
430
401
// / Guaranteed to never overflow.
431
- inline uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
402
+ template <typename U, typename V, typename T = common_uint<U, V>>
403
+ constexpr T divideCeil (U Numerator, V Denominator) {
404
+ assert (Denominator && " Division by zero" );
405
+ T Bias = (Numerator != 0 );
406
+ return (Numerator - Bias) / Denominator + Bias;
407
+ }
408
+
409
+ // / Fallback when arguments aren't integral.
410
+ constexpr uint64_t divideCeil (uint64_t Numerator, uint64_t Denominator) {
432
411
assert (Denominator && " Division by zero" );
433
412
uint64_t Bias = (Numerator != 0 );
434
413
return (Numerator - Bias) / Denominator + Bias;
@@ -437,12 +416,13 @@ inline uint64_t divideCeil(uint64_t Numerator, uint64_t Denominator) {
437
416
// / Returns the integer ceil(Numerator / Denominator). Signed version.
438
417
// / Guaranteed to never overflow, unless Numerator is INT64_MIN and Denominator
439
418
// / is -1.
440
- inline int64_t divideCeilSigned (int64_t Numerator, int64_t Denominator) {
419
+ template <typename U, typename V, typename T = common_sint<U, V>>
420
+ constexpr T divideCeilSigned (U Numerator, V Denominator) {
441
421
assert (Denominator && " Division by zero" );
442
422
if (!Numerator)
443
423
return 0 ;
444
424
// C's integer division rounds towards 0.
445
- int64_t Bias = ( Denominator >= 0 ? 1 : -1 ) ;
425
+ T Bias = Denominator >= 0 ? 1 : -1 ;
446
426
bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
447
427
return SameSign ? (Numerator - Bias) / Denominator + 1
448
428
: Numerator / Denominator;
@@ -451,36 +431,111 @@ inline int64_t divideCeilSigned(int64_t Numerator, int64_t Denominator) {
451
431
// / Returns the integer floor(Numerator / Denominator). Signed version.
452
432
// / Guaranteed to never overflow, unless Numerator is INT64_MIN and Denominator
453
433
// / is -1.
454
- inline int64_t divideFloorSigned (int64_t Numerator, int64_t Denominator) {
434
+ template <typename U, typename V, typename T = common_sint<U, V>>
435
+ constexpr T divideFloorSigned (U Numerator, V Denominator) {
455
436
assert (Denominator && " Division by zero" );
456
437
if (!Numerator)
457
438
return 0 ;
458
439
// C's integer division rounds towards 0.
459
- int64_t Bias = Denominator >= 0 ? -1 : 1 ;
440
+ T Bias = Denominator >= 0 ? -1 : 1 ;
460
441
bool SameSign = (Numerator >= 0 ) == (Denominator >= 0 );
461
442
return SameSign ? Numerator / Denominator
462
443
: (Numerator - Bias) / Denominator - 1 ;
463
444
}
464
445
465
446
// / Returns the remainder of the Euclidean division of LHS by RHS. Result is
466
447
// / always non-negative.
467
- inline int64_t mod (int64_t Numerator, int64_t Denominator) {
448
+ template <typename U, typename V, typename T = common_sint<U, V>>
449
+ constexpr T mod (U Numerator, V Denominator) {
468
450
assert (Denominator >= 1 && " Mod by non-positive number" );
469
- int64_t Mod = Numerator % Denominator;
451
+ T Mod = Numerator % Denominator;
470
452
return Mod < 0 ? Mod + Denominator : Mod;
471
453
}
472
454
473
455
// / Returns (Numerator / Denominator) rounded by round-half-up. Guaranteed to
474
456
// / never overflow.
475
- inline uint64_t divideNearest (uint64_t Numerator, uint64_t Denominator) {
457
+ template <typename U, typename V, typename T = common_uint<U, V>>
458
+ constexpr T divideNearest (U Numerator, V Denominator) {
476
459
assert (Denominator && " Division by zero" );
477
- uint64_t Mod = Numerator % Denominator;
478
- return (Numerator / Denominator) + (Mod > (Denominator - 1 ) / 2 );
460
+ T Mod = Numerator % Denominator;
461
+ return (Numerator / Denominator) +
462
+ (Mod > (static_cast <T>(Denominator) - 1 ) / 2 );
463
+ }
464
+
465
+ // / Returns the next integer (mod 2**nbits) that is greater than or equal to
466
+ // / \p Value and is a multiple of \p Align. \p Align must be non-zero.
467
+ // /
468
+ // / Examples:
469
+ // / \code
470
+ // / alignTo(5, 8) = 8
471
+ // / alignTo(17, 8) = 24
472
+ // / alignTo(~0LL, 8) = 0
473
+ // / alignTo(321, 255) = 510
474
+ // / \endcode
475
+ // /
476
+ // / Will overflow only if result is not representable in T.
477
+ template <typename U, typename V, typename T = common_uint<U, V>>
478
+ constexpr T alignTo (U Value, V Align) {
479
+ assert (Align != 0u && " Align can't be 0." );
480
+ T CeilDiv = divideCeil (Value, Align);
481
+ return CeilDiv * Align;
482
+ }
483
+
484
+ // / Fallback when arguments aren't integral.
485
+ constexpr uint64_t alignTo (uint64_t Value, uint64_t Align) {
486
+ assert (Align != 0u && " Align can't be 0." );
487
+ uint64_t CeilDiv = divideCeil (Value, Align);
488
+ return CeilDiv * Align;
489
+ }
490
+
491
+ constexpr uint64_t alignToPowerOf2 (uint64_t Value, uint64_t Align) {
492
+ assert (Align != 0 && (Align & (Align - 1 )) == 0 &&
493
+ " Align must be a power of 2" );
494
+ // Replace unary minus to avoid compilation error on Windows:
495
+ // "unary minus operator applied to unsigned type, result still unsigned"
496
+ uint64_t NegAlign = (~Align) + 1 ;
497
+ return (Value + Align - 1 ) & NegAlign;
498
+ }
499
+
500
+ // / If non-zero \p Skew is specified, the return value will be a minimal integer
501
+ // / that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
502
+ // / some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
503
+ // / Skew mod \p A'. \p Align must be non-zero.
504
+ // /
505
+ // / Examples:
506
+ // / \code
507
+ // / alignTo(5, 8, 7) = 7
508
+ // / alignTo(17, 8, 1) = 17
509
+ // / alignTo(~0LL, 8, 3) = 3
510
+ // / alignTo(321, 255, 42) = 552
511
+ // / \endcode
512
+ // /
513
+ // / May overflow.
514
+ template <typename U, typename V, typename W,
515
+ typename T = common_uint<common_uint<U, V>, W>>
516
+ constexpr T alignTo (U Value, V Align, W Skew) {
517
+ assert (Align != 0u && " Align can't be 0." );
518
+ Skew %= Align;
519
+ return alignTo (Value - Skew, Align) + Skew;
479
520
}
480
521
481
- // / Returns the largest uint64_t less than or equal to \p Value and is
482
- // / \p Skew mod \p Align. \p Align must be non-zero
483
- inline uint64_t alignDown (uint64_t Value, uint64_t Align, uint64_t Skew = 0 ) {
522
+ // / Returns the next integer (mod 2**nbits) that is greater than or equal to
523
+ // / \p Value and is a multiple of \c Align. \c Align must be non-zero.
524
+ // /
525
+ // / Will overflow only if result is not representable in T.
526
+ template <auto Align, typename V, typename T = common_uint<decltype(Align), V>>
527
+ constexpr T alignTo (V Value) {
528
+ static_assert (Align != 0u , " Align must be non-zero" );
529
+ T CeilDiv = divideCeil (Value, Align);
530
+ return CeilDiv * Align;
531
+ }
532
+
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 ) {
484
539
assert (Align != 0u && " Align can't be 0." );
485
540
Skew %= Align;
486
541
return (Value - Skew) / Align * Align + Skew;
@@ -524,8 +579,8 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
524
579
525
580
// / Subtract two unsigned integers, X and Y, of type T and return the absolute
526
581
// / value of the result.
527
- template <typename T >
528
- 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) {
529
584
return X > Y ? (X - Y) : (Y - X);
530
585
}
531
586
0 commit comments