Skip to content

Commit a5fbb3a

Browse files
committed
Auto merge of #29316 - GBGamer:change-unchecked-div-generic, r=eddyb
Similarly to the simd intrinsics. I believe this is a better solution than #29288, and I could implement it as well for overflowing_add/sub/mul. Also rename from udiv/sdiv to div, and same for rem.
2 parents b252f4c + 579420f commit a5fbb3a

File tree

8 files changed

+605
-404
lines changed

8 files changed

+605
-404
lines changed

src/libcore/intrinsics.rs

+75-17
Original file line numberDiff line numberDiff line change
@@ -511,114 +511,172 @@ extern "rust-intrinsic" {
511511
pub fn roundf64(x: f64) -> f64;
512512

513513
/// Returns the number of bits set in a `u8`.
514+
#[cfg(stage0)]
514515
pub fn ctpop8(x: u8) -> u8;
515516
/// Returns the number of bits set in a `u16`.
517+
#[cfg(stage0)]
516518
pub fn ctpop16(x: u16) -> u16;
517519
/// Returns the number of bits set in a `u32`.
520+
#[cfg(stage0)]
518521
pub fn ctpop32(x: u32) -> u32;
519522
/// Returns the number of bits set in a `u64`.
523+
#[cfg(stage0)]
520524
pub fn ctpop64(x: u64) -> u64;
525+
/// Returns the number of bits set in an integer type `T`
526+
#[cfg(not(stage0))]
527+
pub fn ctpop<T>(x: T) -> T;
521528

522529
/// Returns the number of leading bits unset in a `u8`.
530+
#[cfg(stage0)]
523531
pub fn ctlz8(x: u8) -> u8;
524532
/// Returns the number of leading bits unset in a `u16`.
533+
#[cfg(stage0)]
525534
pub fn ctlz16(x: u16) -> u16;
526535
/// Returns the number of leading bits unset in a `u32`.
536+
#[cfg(stage0)]
527537
pub fn ctlz32(x: u32) -> u32;
528538
/// Returns the number of leading bits unset in a `u64`.
539+
#[cfg(stage0)]
529540
pub fn ctlz64(x: u64) -> u64;
541+
/// Returns the number of leading bits unset in an integer type `T`
542+
#[cfg(not(stage0))]
543+
pub fn ctlz<T>(x: T) -> T;
530544

531545
/// Returns the number of trailing bits unset in a `u8`.
546+
#[cfg(stage0)]
532547
pub fn cttz8(x: u8) -> u8;
533548
/// Returns the number of trailing bits unset in a `u16`.
549+
#[cfg(stage0)]
534550
pub fn cttz16(x: u16) -> u16;
535551
/// Returns the number of trailing bits unset in a `u32`.
552+
#[cfg(stage0)]
536553
pub fn cttz32(x: u32) -> u32;
537554
/// Returns the number of trailing bits unset in a `u64`.
555+
#[cfg(stage0)]
538556
pub fn cttz64(x: u64) -> u64;
557+
/// Returns the number of trailing bits unset in an integer type `T`
558+
#[cfg(not(stage0))]
559+
pub fn cttz<T>(x: T) -> T;
539560

540561
/// Reverses the bytes in a `u16`.
562+
#[cfg(stage0)]
541563
pub fn bswap16(x: u16) -> u16;
542564
/// Reverses the bytes in a `u32`.
565+
#[cfg(stage0)]
543566
pub fn bswap32(x: u32) -> u32;
544567
/// Reverses the bytes in a `u64`.
568+
#[cfg(stage0)]
545569
pub fn bswap64(x: u64) -> u64;
570+
/// Reverses the bytes in an integer type `T`.
571+
#[cfg(not(stage0))]
572+
pub fn bswap<T>(x: T) -> T;
546573

547574
/// Performs checked `i8` addition.
575+
#[cfg(stage0)]
548576
pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool);
549577
/// Performs checked `i16` addition.
578+
#[cfg(stage0)]
550579
pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool);
551580
/// Performs checked `i32` addition.
581+
#[cfg(stage0)]
552582
pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool);
553583
/// Performs checked `i64` addition.
584+
#[cfg(stage0)]
554585
pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool);
555586

556587
/// Performs checked `u8` addition.
588+
#[cfg(stage0)]
557589
pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool);
558590
/// Performs checked `u16` addition.
591+
#[cfg(stage0)]
559592
pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool);
560593
/// Performs checked `u32` addition.
594+
#[cfg(stage0)]
561595
pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool);
562596
/// Performs checked `u64` addition.
597+
#[cfg(stage0)]
563598
pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool);
564599

600+
/// Performs checked integer addition.
601+
#[cfg(not(stage0))]
602+
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
603+
565604
/// Performs checked `i8` subtraction.
605+
#[cfg(stage0)]
566606
pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool);
567607
/// Performs checked `i16` subtraction.
608+
#[cfg(stage0)]
568609
pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool);
569610
/// Performs checked `i32` subtraction.
611+
#[cfg(stage0)]
570612
pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool);
571613
/// Performs checked `i64` subtraction.
614+
#[cfg(stage0)]
572615
pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool);
573616

574617
/// Performs checked `u8` subtraction.
618+
#[cfg(stage0)]
575619
pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool);
576620
/// Performs checked `u16` subtraction.
621+
#[cfg(stage0)]
577622
pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool);
578623
/// Performs checked `u32` subtraction.
624+
#[cfg(stage0)]
579625
pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool);
580626
/// Performs checked `u64` subtraction.
627+
#[cfg(stage0)]
581628
pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool);
582629

630+
/// Performs checked integer subtraction
631+
#[cfg(not(stage0))]
632+
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
633+
583634
/// Performs checked `i8` multiplication.
635+
#[cfg(stage0)]
584636
pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool);
585637
/// Performs checked `i16` multiplication.
638+
#[cfg(stage0)]
586639
pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool);
587640
/// Performs checked `i32` multiplication.
641+
#[cfg(stage0)]
588642
pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool);
589643
/// Performs checked `i64` multiplication.
644+
#[cfg(stage0)]
590645
pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool);
591646

592647
/// Performs checked `u8` multiplication.
648+
#[cfg(stage0)]
593649
pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool);
594650
/// Performs checked `u16` multiplication.
651+
#[cfg(stage0)]
595652
pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool);
596653
/// Performs checked `u32` multiplication.
654+
#[cfg(stage0)]
597655
pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool);
598656
/// Performs checked `u64` multiplication.
657+
#[cfg(stage0)]
599658
pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
600659

601-
/// Returns (a + b) mod 2^N, where N is the width of N in bits.
660+
/// Performs checked integer multiplication
661+
#[cfg(not(stage0))]
662+
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
663+
664+
/// Performs an unchecked division, resulting in undefined behavior
665+
/// where y = 0 or x = `T::min_value()` and y = -1
666+
#[cfg(not(stage0))]
667+
pub fn unchecked_div<T>(x: T, y: T) -> T;
668+
/// Returns the remainder of an unchecked division, resulting in
669+
/// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
670+
#[cfg(not(stage0))]
671+
pub fn unchecked_rem<T>(x: T, y: T) -> T;
672+
673+
/// Returns (a + b) mod 2^N, where N is the width of T in bits.
602674
pub fn overflowing_add<T>(a: T, b: T) -> T;
603-
/// Returns (a - b) mod 2^N, where N is the width of N in bits.
675+
/// Returns (a - b) mod 2^N, where N is the width of T in bits.
604676
pub fn overflowing_sub<T>(a: T, b: T) -> T;
605-
/// Returns (a * b) mod 2^N, where N is the width of N in bits.
677+
/// Returns (a * b) mod 2^N, where N is the width of T in bits.
606678
pub fn overflowing_mul<T>(a: T, b: T) -> T;
607679

608-
/// Performs an unchecked signed division, which results in undefined behavior,
609-
/// in cases where y == 0, or x == isize::MIN and y == -1
610-
pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
611-
/// Performs an unchecked unsigned division, which results in undefined behavior,
612-
/// in cases where y == 0
613-
pub fn unchecked_udiv<T>(x: T, y: T) -> T;
614-
615-
/// Returns the remainder of an unchecked signed division, which results in
616-
/// undefined behavior, in cases where y == 0, or x == isize::MIN and y == -1
617-
pub fn unchecked_srem<T>(x: T, y: T) -> T;
618-
/// Returns the remainder of an unchecked unsigned division, which results in
619-
/// undefined behavior, in cases where y == 0
620-
pub fn unchecked_urem<T>(x: T, y: T) -> T;
621-
622680
/// Returns the value of the discriminant for the variant in 'v',
623681
/// cast to a `u64`; if `T` has no discriminant, returns 0.
624682
pub fn discriminant_value<T>(v: &T) -> u64;

src/libcore/num/bignum.rs

+11
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,24 @@ macro_rules! impl_full_ops {
5555
($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
5656
$(
5757
impl FullOps for $ty {
58+
#[cfg(stage0)]
5859
fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
5960
// this cannot overflow, the output is between 0 and 2*2^nbits - 1
6061
// FIXME will LLVM optimize this into ADC or similar???
6162
let (v, carry1) = unsafe { $addfn(self, other) };
6263
let (v, carry2) = unsafe { $addfn(v, if carry {1} else {0}) };
6364
(carry1 || carry2, v)
6465
}
66+
#[cfg(not(stage0))]
67+
fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
68+
// this cannot overflow, the output is between 0 and 2*2^nbits - 1
69+
// FIXME will LLVM optimize this into ADC or similar???
70+
let (v, carry1) = unsafe { intrinsics::add_with_overflow(self, other) };
71+
let (v, carry2) = unsafe {
72+
intrinsics::add_with_overflow(v, if carry {1} else {0})
73+
};
74+
(carry1 || carry2, v)
75+
}
6576

6677
fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
6778
// this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)

0 commit comments

Comments
 (0)