Skip to content

Commit 579420f

Browse files
committed
Check unchecked_div|rem's specialisation
Similarly to the simd intrinsics.
1 parent d2f41bd commit 579420f

File tree

8 files changed

+605
-404
lines changed

8 files changed

+605
-404
lines changed

src/libcore/intrinsics.rs

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -492,114 +492,172 @@ extern "rust-intrinsic" {
492492
pub fn roundf64(x: f64) -> f64;
493493

494494
/// Returns the number of bits set in a `u8`.
495+
#[cfg(stage0)]
495496
pub fn ctpop8(x: u8) -> u8;
496497
/// Returns the number of bits set in a `u16`.
498+
#[cfg(stage0)]
497499
pub fn ctpop16(x: u16) -> u16;
498500
/// Returns the number of bits set in a `u32`.
501+
#[cfg(stage0)]
499502
pub fn ctpop32(x: u32) -> u32;
500503
/// Returns the number of bits set in a `u64`.
504+
#[cfg(stage0)]
501505
pub fn ctpop64(x: u64) -> u64;
506+
/// Returns the number of bits set in an integer type `T`
507+
#[cfg(not(stage0))]
508+
pub fn ctpop<T>(x: T) -> T;
502509

503510
/// Returns the number of leading bits unset in a `u8`.
511+
#[cfg(stage0)]
504512
pub fn ctlz8(x: u8) -> u8;
505513
/// Returns the number of leading bits unset in a `u16`.
514+
#[cfg(stage0)]
506515
pub fn ctlz16(x: u16) -> u16;
507516
/// Returns the number of leading bits unset in a `u32`.
517+
#[cfg(stage0)]
508518
pub fn ctlz32(x: u32) -> u32;
509519
/// Returns the number of leading bits unset in a `u64`.
520+
#[cfg(stage0)]
510521
pub fn ctlz64(x: u64) -> u64;
522+
/// Returns the number of leading bits unset in an integer type `T`
523+
#[cfg(not(stage0))]
524+
pub fn ctlz<T>(x: T) -> T;
511525

512526
/// Returns the number of trailing bits unset in a `u8`.
527+
#[cfg(stage0)]
513528
pub fn cttz8(x: u8) -> u8;
514529
/// Returns the number of trailing bits unset in a `u16`.
530+
#[cfg(stage0)]
515531
pub fn cttz16(x: u16) -> u16;
516532
/// Returns the number of trailing bits unset in a `u32`.
533+
#[cfg(stage0)]
517534
pub fn cttz32(x: u32) -> u32;
518535
/// Returns the number of trailing bits unset in a `u64`.
536+
#[cfg(stage0)]
519537
pub fn cttz64(x: u64) -> u64;
538+
/// Returns the number of trailing bits unset in an integer type `T`
539+
#[cfg(not(stage0))]
540+
pub fn cttz<T>(x: T) -> T;
520541

521542
/// Reverses the bytes in a `u16`.
543+
#[cfg(stage0)]
522544
pub fn bswap16(x: u16) -> u16;
523545
/// Reverses the bytes in a `u32`.
546+
#[cfg(stage0)]
524547
pub fn bswap32(x: u32) -> u32;
525548
/// Reverses the bytes in a `u64`.
549+
#[cfg(stage0)]
526550
pub fn bswap64(x: u64) -> u64;
551+
/// Reverses the bytes in an integer type `T`.
552+
#[cfg(not(stage0))]
553+
pub fn bswap<T>(x: T) -> T;
527554

528555
/// Performs checked `i8` addition.
556+
#[cfg(stage0)]
529557
pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool);
530558
/// Performs checked `i16` addition.
559+
#[cfg(stage0)]
531560
pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool);
532561
/// Performs checked `i32` addition.
562+
#[cfg(stage0)]
533563
pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool);
534564
/// Performs checked `i64` addition.
565+
#[cfg(stage0)]
535566
pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool);
536567

537568
/// Performs checked `u8` addition.
569+
#[cfg(stage0)]
538570
pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool);
539571
/// Performs checked `u16` addition.
572+
#[cfg(stage0)]
540573
pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool);
541574
/// Performs checked `u32` addition.
575+
#[cfg(stage0)]
542576
pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool);
543577
/// Performs checked `u64` addition.
578+
#[cfg(stage0)]
544579
pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool);
545580

581+
/// Performs checked integer addition.
582+
#[cfg(not(stage0))]
583+
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
584+
546585
/// Performs checked `i8` subtraction.
586+
#[cfg(stage0)]
547587
pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool);
548588
/// Performs checked `i16` subtraction.
589+
#[cfg(stage0)]
549590
pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool);
550591
/// Performs checked `i32` subtraction.
592+
#[cfg(stage0)]
551593
pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool);
552594
/// Performs checked `i64` subtraction.
595+
#[cfg(stage0)]
553596
pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool);
554597

555598
/// Performs checked `u8` subtraction.
599+
#[cfg(stage0)]
556600
pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool);
557601
/// Performs checked `u16` subtraction.
602+
#[cfg(stage0)]
558603
pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool);
559604
/// Performs checked `u32` subtraction.
605+
#[cfg(stage0)]
560606
pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool);
561607
/// Performs checked `u64` subtraction.
608+
#[cfg(stage0)]
562609
pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool);
563610

611+
/// Performs checked integer subtraction
612+
#[cfg(not(stage0))]
613+
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
614+
564615
/// Performs checked `i8` multiplication.
616+
#[cfg(stage0)]
565617
pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool);
566618
/// Performs checked `i16` multiplication.
619+
#[cfg(stage0)]
567620
pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool);
568621
/// Performs checked `i32` multiplication.
622+
#[cfg(stage0)]
569623
pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool);
570624
/// Performs checked `i64` multiplication.
625+
#[cfg(stage0)]
571626
pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool);
572627

573628
/// Performs checked `u8` multiplication.
629+
#[cfg(stage0)]
574630
pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool);
575631
/// Performs checked `u16` multiplication.
632+
#[cfg(stage0)]
576633
pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool);
577634
/// Performs checked `u32` multiplication.
635+
#[cfg(stage0)]
578636
pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool);
579637
/// Performs checked `u64` multiplication.
638+
#[cfg(stage0)]
580639
pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
581640

582-
/// Returns (a + b) mod 2^N, where N is the width of N in bits.
641+
/// Performs checked integer multiplication
642+
#[cfg(not(stage0))]
643+
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
644+
645+
/// Performs an unchecked division, resulting in undefined behavior
646+
/// where y = 0 or x = `T::min_value()` and y = -1
647+
#[cfg(not(stage0))]
648+
pub fn unchecked_div<T>(x: T, y: T) -> T;
649+
/// Returns the remainder of an unchecked division, resulting in
650+
/// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
651+
#[cfg(not(stage0))]
652+
pub fn unchecked_rem<T>(x: T, y: T) -> T;
653+
654+
/// Returns (a + b) mod 2^N, where N is the width of T in bits.
583655
pub fn overflowing_add<T>(a: T, b: T) -> T;
584-
/// Returns (a - b) mod 2^N, where N is the width of N in bits.
656+
/// Returns (a - b) mod 2^N, where N is the width of T in bits.
585657
pub fn overflowing_sub<T>(a: T, b: T) -> T;
586-
/// Returns (a * b) mod 2^N, where N is the width of N in bits.
658+
/// Returns (a * b) mod 2^N, where N is the width of T in bits.
587659
pub fn overflowing_mul<T>(a: T, b: T) -> T;
588660

589-
/// Performs an unchecked signed division, which results in undefined behavior,
590-
/// in cases where y == 0, or x == isize::MIN and y == -1
591-
pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
592-
/// Performs an unchecked unsigned division, which results in undefined behavior,
593-
/// in cases where y == 0
594-
pub fn unchecked_udiv<T>(x: T, y: T) -> T;
595-
596-
/// Returns the remainder of an unchecked signed division, which results in
597-
/// undefined behavior, in cases where y == 0, or x == isize::MIN and y == -1
598-
pub fn unchecked_srem<T>(x: T, y: T) -> T;
599-
/// Returns the remainder of an unchecked unsigned division, which results in
600-
/// undefined behavior, in cases where y == 0
601-
pub fn unchecked_urem<T>(x: T, y: T) -> T;
602-
603661
/// Returns the value of the discriminant for the variant in 'v',
604662
/// cast to a `u64`; if `T` has no discriminant, returns 0.
605663
pub fn discriminant_value<T>(v: &T) -> u64;

src/libcore/num/bignum.rs

Lines changed: 11 additions & 0 deletions
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)