From 56983cf3c6367f13fb94f6ada05537156f513e6c Mon Sep 17 00:00:00 2001 From: yvt Date: Fri, 1 Apr 2022 12:55:00 +0900 Subject: [PATCH 1/5] test: Remove redundant code from `tests/run/int.rs` --- tests/run/int.rs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/tests/run/int.rs b/tests/run/int.rs index 49376012c40..7139b8d4f5d 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -3,32 +3,13 @@ // Run-time: // status: 0 -#![feature(arbitrary_self_types, auto_traits, core_intrinsics, lang_items, start, intrinsics)] +#![feature(core_intrinsics, start)] #![no_std] -mod intrinsics { - extern "rust-intrinsic" { - pub fn abort() -> !; - } -} - -/* - * Core - */ - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn puts(s: *const u8) -> i32; - } -} - #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo) -> ! { - unsafe { - core::intrinsics::abort(); - } + core::intrinsics::abort(); } /* From 837a4467bc98471d5619e76cc47eac3b9a471d28 Mon Sep 17 00:00:00 2001 From: yvt Date: Wed, 6 Apr 2022 01:25:13 +0900 Subject: [PATCH 2/5] test: Test more integer types and checked arithmetic in `tests/run/int.rs` --- tests/run/int.rs | 437 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 324 insertions(+), 113 deletions(-) diff --git a/tests/run/int.rs b/tests/run/int.rs index 7139b8d4f5d..8d2db9096f7 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -3,7 +3,7 @@ // Run-time: // status: 0 -#![feature(core_intrinsics, start)] +#![feature(bench_black_box, core_intrinsics, start)] #![no_std] @@ -17,118 +17,329 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! { */ #[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { - let var = 134217856_u128; - let var2 = 10475372733397991552_u128; - let var3 = 193236519889708027473620326106273939584_u128; - let var4 = 123236519889708027473620326106273939584_u128; - let var5 = 153236519889708027473620326106273939584_u128; - let var6 = 18446744073709551616_i128; - let var7 = 170141183460469231731687303715884105728_u128; - - // Shifts. - assert_eq!(var << (argc as u128 - 1), var); - assert_eq!(var << argc as u128, 268435712); - assert_eq!(var << (argc + 32) as u128, 1152922604118474752); - assert_eq!(var << (argc + 48) as u128, 75557935783508361347072); - assert_eq!(var << (argc + 60) as u128, 309485304969250248077606912); - assert_eq!(var << (argc + 62) as u128, 1237941219877000992310427648); - assert_eq!(var << (argc + 63) as u128, 2475882439754001984620855296); - assert_eq!(var << (argc + 80) as u128, 324518863143436548128224745357312); - - assert_eq!(var2 << argc as u128, 20950745466795983104); - assert_eq!(var2 << (argc as u128 - 1), var2); - assert_eq!(var2 << (argc + 32) as u128, 89982766606709001335848566784); - assert_eq!(var2 << (argc + 48) as u128, 5897110592337281111546171672756224); - assert_eq!(var2 << (argc + 60) as u128, 24154564986213503432893119171609493504); - assert_eq!(var2 << (argc + 62) as u128, 96618259944854013731572476686437974016); - assert_eq!(var2 << (argc + 63) as u128, 193236519889708027463144953372875948032); - - assert_eq!(var3 << argc as u128, 46190672858477591483866044780779667712); - assert_eq!(var3 << (argc as u128 - 1), var3); - assert_eq!(var3 << (argc + 32) as u128, 21267668304951024224840338247585366016); - assert_eq!(var3 << (argc + 48) as u128, 1335125106377253154015353231953100800); - assert_eq!(var3 << (argc + 60) as u128, 24154564986213503432893119171609493504); - assert_eq!(var3 << (argc + 62) as u128, 96618259944854013731572476686437974016); - assert_eq!(var3 << (argc + 63) as u128, 193236519889708027463144953372875948032); - - assert_eq!((2220326408_u32 + argc as u32) >> (32 - 6), 33); - - assert_eq!(var >> (argc as u128 - 1), var); - assert_eq!(var >> argc as u128, 67108928); - assert_eq!(var >> (argc + 32) as u128, 0); - assert_eq!(var >> (argc + 48) as u128, 0); - assert_eq!(var >> (argc + 60) as u128, 0); - assert_eq!(var >> (argc + 62) as u128, 0); - assert_eq!(var >> (argc + 63) as u128, 0); - - assert_eq!(var2 >> argc as u128, 5237686366698995776); - assert_eq!(var2 >> (argc as u128 - 1), var2); - assert_eq!(var2 >> (argc + 32) as u128, 1219493888); - assert_eq!(var2 >> (argc + 48) as u128, 18608); - assert_eq!(var2 >> (argc + 60) as u128, 4); - assert_eq!(var2 >> (argc + 62) as u128, 1); - assert_eq!(var2 >> (argc + 63) as u128, 0); - - assert_eq!(var3 >> (argc as u128 - 1), var3); - assert_eq!(var3 >> argc as u128, 96618259944854013736810163053136969792); - assert_eq!(var3 >> (argc + 32) as u128, 22495691651677250335181635584); - assert_eq!(var3 >> (argc + 48) as u128, 343257013727985387194544); - assert_eq!(var3 >> (argc + 60) as u128, 83802981867183932420); - assert_eq!(var3 >> (argc + 62) as u128, 20950745466795983105); - assert_eq!(var3 >> (argc + 63) as u128, 10475372733397991552); - assert_eq!(var3 >> (argc + 80) as u128, 79920751444992); - - assert_eq!(var6 >> argc as u128, 9223372036854775808); - assert_eq!((var6 - 1) >> argc as u128, 9223372036854775807); - assert_eq!(var7 >> argc as u128, 85070591730234615865843651857942052864); - - // Casts - assert_eq!((var >> (argc + 32) as u128) as u64, 0); - assert_eq!((var >> argc as u128) as u64, 67108928); - - // Addition. - assert_eq!(var + argc as u128, 134217857); - - assert_eq!(var2 + argc as u128, 10475372733397991553); - assert_eq!(var2 + (var2 + argc as u128) as u128, 20950745466795983105); - - assert_eq!(var3 + argc as u128, 193236519889708027473620326106273939585); - - // Subtraction - assert_eq!(var - argc as u128, 134217855); - - assert_eq!(var2 - argc as u128, 10475372733397991551); - - assert_eq!(var3 - argc as u128, 193236519889708027473620326106273939583); - - // Multiplication - assert_eq!(var * (argc + 1) as u128, 268435712); - assert_eq!(var * (argc as u128 + var2), 1405982069077538020949770368); - - assert_eq!(var2 * (argc + 1) as u128, 20950745466795983104); - assert_eq!(var2 * (argc as u128 + var2), 109733433903618109003204073240861360256); - - assert_eq!(var3 * argc as u128, 193236519889708027473620326106273939584); - - assert_eq!(var4 * (argc + 1) as u128, 246473039779416054947240652212547879168); - - assert_eq!(var5 * (argc + 1) as u128, 306473039779416054947240652212547879168); - - // Division. - assert_eq!(var / (argc + 1) as u128, 67108928); - assert_eq!(var / (argc + 2) as u128, 44739285); - - assert_eq!(var2 / (argc + 1) as u128, 5237686366698995776); - assert_eq!(var2 / (argc + 2) as u128, 3491790911132663850); - - assert_eq!(var3 / (argc + 1) as u128, 96618259944854013736810163053136969792); - assert_eq!(var3 / (argc + 2) as u128, 64412173296569342491206775368757979861); - assert_eq!(var3 / (argc as u128 + var4), 1); - assert_eq!(var3 / (argc as u128 + var2), 18446744073709551615); - - assert_eq!(var4 / (argc + 1) as u128, 61618259944854013736810163053136969792); - assert_eq!(var4 / (argc + 2) as u128, 41078839963236009157873442035424646528); +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let one: isize = core::hint::black_box(1); + + macro_rules! check { + ($ty:ty, $expr:expr) => { + { + const EXPECTED: $ty = { + #[allow(non_upper_case_globals)] + #[allow(dead_code)] + const one: isize = 1; + $expr + }; + assert_eq!($expr, EXPECTED); + } + }; + } + + check!(u32, (2220326408_u32 + one as u32) >> (32 - 6)); + + /// Generate `check!` tests for integer types at least as wide as 128 bits. + macro_rules! check_ops128 { + () => { + check_ops64!(); + + // Shifts. + check!(T, VAL1 << (one + 63) as T); + check!(T, VAL1 << (one + 80) as T); + check!(T, VAL3 << (one + 62) as T); + check!(T, VAL3 << (one + 63) as T); + + check!(T, VAL1 >> (one + 63) as T); + check!(T, VAL2 >> (one + 63) as T); + check!(T, VAL3 >> (one + 63) as T); + check!(T, VAL3 >> (one + 80) as T); + }; + } + + /// Generate `check!` tests for integer types at least as wide as 64 bits. + macro_rules! check_ops64 { + () => { + check_ops32!(); + + // Shifts. + check!(T, VAL2 << (one + 32) as T); + check!(T, VAL2 << (one + 48) as T); + check!(T, VAL2 << (one + 60) as T); + check!(T, VAL2 << (one + 62) as T); + + check!(T, VAL3 << (one + 32) as T); + check!(T, VAL3 << (one + 48) as T); + check!(T, VAL3 << (one + 60) as T); + + check!(T, VAL1 >> (one + 32) as T); + check!(T, VAL1 >> (one + 48) as T); + check!(T, VAL1 >> (one + 60) as T); + check!(T, VAL1 >> (one + 62) as T); + + check!(T, VAL2 >> (one + 32) as T); + check!(T, VAL2 >> (one + 48) as T); + check!(T, VAL2 >> (one + 60) as T); + check!(T, VAL2 >> (one + 62) as T); + + check!(T, VAL3 >> (one + 32) as T); + check!(T, VAL3 >> (one + 48) as T); + check!(T, VAL3 >> (one + 60) as T); + check!(T, VAL3 >> (one + 62) as T); + }; + } + + /// Generate `check!` tests for integer types at least as wide as 32 bits. + macro_rules! check_ops32 { + () => { + // Shifts. + check!(T, VAL2 << one as T); + check!(T, VAL2 << (one as T - 1)); + + check!(T, VAL3 << one as T); + check!(T, VAL3 << (one as T - 1)); + + check!(T, VAL1.wrapping_shl(one as u32 - 1)); + check!(T, VAL1.wrapping_shl(one as u32)); + check!(T, VAL1.wrapping_shl((one + 32) as u32)); + check!(T, VAL1.wrapping_shl((one + 48) as u32)); + check!(T, VAL1.wrapping_shl((one + 60) as u32)); + check!(T, VAL1.wrapping_shl((one + 62) as u32)); + check!(T, VAL1.wrapping_shl((one + 63) as u32)); + check!(T, VAL1.wrapping_shl((one + 80) as u32)); + + check!(Option, VAL1.checked_shl(one as u32 - 1)); + check!(Option, VAL1.checked_shl(one as u32)); + check!(Option, VAL1.checked_shl((one + 32) as u32)); + check!(Option, VAL1.checked_shl((one + 48) as u32)); + check!(Option, VAL1.checked_shl((one + 60) as u32)); + check!(Option, VAL1.checked_shl((one + 62) as u32)); + check!(Option, VAL1.checked_shl((one + 63) as u32)); + check!(Option, VAL1.checked_shl((one + 80) as u32)); + + check!(T, VAL1 >> (one as T - 1)); + check!(T, VAL1 >> one as T); + + check!(T, VAL2 >> one as T); + check!(T, VAL2 >> (one as T - 1)); + + check!(T, VAL3 >> (one as T - 1)); + check!(T, VAL3 >> one as T); + + check!(T, VAL1.wrapping_shr(one as u32 - 1)); + check!(T, VAL1.wrapping_shr(one as u32)); + check!(T, VAL1.wrapping_shr((one + 32) as u32)); + check!(T, VAL1.wrapping_shr((one + 48) as u32)); + check!(T, VAL1.wrapping_shr((one + 60) as u32)); + check!(T, VAL1.wrapping_shr((one + 62) as u32)); + check!(T, VAL1.wrapping_shr((one + 63) as u32)); + check!(T, VAL1.wrapping_shr((one + 80) as u32)); + + check!(Option, VAL1.checked_shr(one as u32 - 1)); + check!(Option, VAL1.checked_shr(one as u32)); + check!(Option, VAL1.checked_shr((one + 32) as u32)); + check!(Option, VAL1.checked_shr((one + 48) as u32)); + check!(Option, VAL1.checked_shr((one + 60) as u32)); + check!(Option, VAL1.checked_shr((one + 62) as u32)); + check!(Option, VAL1.checked_shr((one + 63) as u32)); + check!(Option, VAL1.checked_shr((one + 80) as u32)); + + // Casts + check!(u64, (VAL1 >> one as T) as u64); + + // Addition. + check!(T, VAL1 + one as T); + check!(T, VAL2 + one as T); + check!(T, VAL2 + (VAL2 + one as T) as T); + check!(T, VAL3 + one as T); + + check!(Option, VAL1.checked_add(one as T)); + check!(Option, VAL2.checked_add(one as T)); + check!(Option, VAL2.checked_add((VAL2 + one as T) as T)); + check!(Option, VAL3.checked_add(T::MAX)); + check!(Option, VAL3.checked_add(T::MIN)); + + check!(T, VAL1.wrapping_add(one as T)); + check!(T, VAL2.wrapping_add(one as T)); + check!(T, VAL2.wrapping_add((VAL2 + one as T) as T)); + check!(T, VAL3.wrapping_add(T::MAX)); + check!(T, VAL3.wrapping_add(T::MIN)); + + check!((T, bool), VAL1.overflowing_add(one as T)); + check!((T, bool), VAL2.overflowing_add(one as T)); + check!((T, bool), VAL2.overflowing_add((VAL2 + one as T) as T)); + check!((T, bool), VAL3.overflowing_add(T::MAX)); + check!((T, bool), VAL3.overflowing_add(T::MIN)); + + check!(T, VAL1.saturating_add(one as T)); + check!(T, VAL2.saturating_add(one as T)); + check!(T, VAL2.saturating_add((VAL2 + one as T) as T)); + check!(T, VAL3.saturating_add(T::MAX)); + check!(T, VAL3.saturating_add(T::MIN)); + + // Subtraction + check!(T, VAL1 - one as T); + check!(T, VAL2 - one as T); + check!(T, VAL3 - one as T); + + check!(Option, VAL1.checked_sub(one as T)); + check!(Option, VAL2.checked_sub(one as T)); + check!(Option, VAL2.checked_sub((VAL2 + one as T) as T)); + check!(Option, VAL3.checked_sub(T::MAX)); + check!(Option, VAL3.checked_sub(T::MIN)); + + check!(T, VAL1.wrapping_sub(one as T)); + check!(T, VAL2.wrapping_sub(one as T)); + check!(T, VAL2.wrapping_sub((VAL2 + one as T) as T)); + check!(T, VAL3.wrapping_sub(T::MAX)); + check!(T, VAL3.wrapping_sub(T::MIN)); + + check!((T, bool), VAL1.overflowing_sub(one as T)); + check!((T, bool), VAL2.overflowing_sub(one as T)); + check!((T, bool), VAL2.overflowing_sub((VAL2 + one as T) as T)); + check!((T, bool), VAL3.overflowing_sub(T::MAX)); + check!((T, bool), VAL3.overflowing_sub(T::MIN)); + + check!(T, VAL1.saturating_sub(one as T)); + check!(T, VAL2.saturating_sub(one as T)); + check!(T, VAL2.saturating_sub((VAL2 + one as T) as T)); + check!(T, VAL3.saturating_sub(T::MAX)); + check!(T, VAL3.saturating_sub(T::MIN)); + + // Multiplication + check!(T, VAL1 * (one + 1) as T); + check!(T, VAL1 * (one as T + VAL2)); + check!(T, VAL2 * (one + 1) as T); + check!(T, VAL2 * (one as T + VAL2)); + check!(T, VAL3 * one as T); + check!(T, VAL4 * (one + 1) as T); + check!(T, VAL5 * (one + 1) as T); + + check!(Option, VAL1.checked_mul((one + 1) as T)); + check!(Option, VAL1.checked_mul((one as T + VAL2))); + check!(Option, VAL3.checked_mul(VAL3)); + check!(Option, VAL4.checked_mul((one + 1) as T)); + check!(Option, VAL5.checked_mul((one + 1) as T)); + + check!(T, VAL1.wrapping_mul((one + 1) as T)); + check!(T, VAL1.wrapping_mul((one as T + VAL2))); + check!(T, VAL3.wrapping_mul(VAL3)); + check!(T, VAL4.wrapping_mul((one + 1) as T)); + check!(T, VAL5.wrapping_mul((one + 1) as T)); + + check!((T, bool), VAL1.overflowing_mul((one + 1) as T)); + check!((T, bool), VAL1.overflowing_mul((one as T + VAL2))); + check!((T, bool), VAL3.overflowing_mul(VAL3)); + check!((T, bool), VAL4.overflowing_mul((one + 1) as T)); + check!((T, bool), VAL5.overflowing_mul((one + 1) as T)); + + check!(T, VAL1.saturating_mul((one + 1) as T)); + check!(T, VAL1.saturating_mul((one as T + VAL2))); + check!(T, VAL3.saturating_mul(VAL3)); + check!(T, VAL4.saturating_mul((one + 1) as T)); + check!(T, VAL5.saturating_mul((one + 1) as T)); + + // Division. + check!(T, VAL1 / (one + 1) as T); + check!(T, VAL1 / (one + 2) as T); + + check!(T, VAL2 / (one + 1) as T); + check!(T, VAL2 / (one + 2) as T); + + check!(T, VAL3 / (one + 1) as T); + check!(T, VAL3 / (one + 2) as T); + check!(T, VAL3 / (one as T + VAL4)); + check!(T, VAL3 / (one as T + VAL2)); + + check!(T, VAL4 / (one + 1) as T); + check!(T, VAL4 / (one + 2) as T); + + check!(Option, VAL1.checked_div((one + 1) as T)); + check!(Option, VAL1.checked_div((one as T + VAL2))); + check!(Option, VAL3.checked_div(VAL3)); + check!(Option, VAL4.checked_div((one + 1) as T)); + check!(Option, VAL5.checked_div((one + 1) as T)); + check!(Option, (T::MIN).checked_div((0 as T).wrapping_sub(one as T))); + check!(Option, VAL5.checked_div((one - 1) as T)); // var5 / 0 + + check!(T, VAL1.wrapping_div((one + 1) as T)); + check!(T, VAL1.wrapping_div((one as T + VAL2))); + check!(T, VAL3.wrapping_div(VAL3)); + check!(T, VAL4.wrapping_div((one + 1) as T)); + check!(T, VAL5.wrapping_div((one + 1) as T)); + check!(T, (T::MIN).wrapping_div((0 as T).wrapping_sub(one as T))); + + check!((T, bool), VAL1.overflowing_div((one + 1) as T)); + check!((T, bool), VAL1.overflowing_div((one as T + VAL2))); + check!((T, bool), VAL3.overflowing_div(VAL3)); + check!((T, bool), VAL4.overflowing_div((one + 1) as T)); + check!((T, bool), VAL5.overflowing_div((one + 1) as T)); + check!((T, bool), (T::MIN).overflowing_div((0 as T).wrapping_sub(one as T))); + + check!(T, VAL1.saturating_div((one + 1) as T)); + check!(T, VAL1.saturating_div((one as T + VAL2))); + check!(T, VAL3.saturating_div(VAL3)); + check!(T, VAL4.saturating_div((one + 1) as T)); + check!(T, VAL5.saturating_div((one + 1) as T)); + check!(T, (T::MIN).saturating_div((0 as T).wrapping_sub(one as T))); + }; + } + + { + type T = u32; + const VAL1: T = 14162_u32; + const VAL2: T = 14556_u32; + const VAL3: T = 323656954_u32; + const VAL4: T = 2023651954_u32; + const VAL5: T = 1323651954_u32; + check_ops32!(); + } + + { + type T = i32; + const VAL1: T = 13456_i32; + const VAL2: T = 10475_i32; + const VAL3: T = 923653954_i32; + const VAL4: T = 993198738_i32; + const VAL5: T = 1023653954_i32; + check_ops32!(); + } + + { + type T = u64; + const VAL1: T = 134217856_u64; + const VAL2: T = 104753732_u64; + const VAL3: T = 12323651988970863954_u64; + const VAL4: T = 7323651988970863954_u64; + const VAL5: T = 8323651988970863954_u64; + check_ops64!(); + } + + { + type T = i64; + const VAL1: T = 134217856_i64; + const VAL2: T = 104753732_i64; + const VAL3: T = 6323651988970863954_i64; + const VAL4: T = 2323651988970863954_i64; + const VAL5: T = 3323651988970863954_i64; + check_ops64!(); + } + + { + type T = u128; + const VAL1: T = 134217856_u128; + const VAL2: T = 10475372733397991552_u128; + const VAL3: T = 193236519889708027473620326106273939584_u128; + const VAL4: T = 123236519889708027473620326106273939584_u128; + const VAL5: T = 153236519889708027473620326106273939584_u128; + check_ops128!(); + } + { + type T = i128; + const VAL1: T = 134217856_i128; + const VAL2: T = 10475372733397991552_i128; + const VAL3: T = 83236519889708027473620326106273939584_i128; + const VAL4: T = 63236519889708027473620326106273939584_i128; + const VAL5: T = 73236519889708027473620326106273939584_i128; + check_ops128!(); + } 0 } From 00677e51596f89325551e99c2d30bd39ae381e0c Mon Sep 17 00:00:00 2001 From: yvt Date: Fri, 1 Apr 2022 13:54:51 +0900 Subject: [PATCH 3/5] Implement `saturating_{add, sub}` for non-native integer types Updates their unsigned code paths to use the `Builder::gcc_` methods that automatically lower non-native integer operations to native ones. Also updates the signed code path of `saturating_add` to support non- native integer types. That of `saturating_sub` already supports this, so no major changes have been made. --- src/intrinsic/mod.rs | 92 +++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 08e584a46f3..84395e96763 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -967,34 +967,55 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } fn saturating_add(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> { - let func = self.current_func.borrow().expect("func"); - + let result_type = lhs.get_type(); if signed { - // Algorithm from: https://stackoverflow.com/a/56531252/389119 - let after_block = func.new_block("after"); - let func_name = - match width { - 8 => "__builtin_add_overflow", - 16 => "__builtin_add_overflow", - 32 => "__builtin_sadd_overflow", - 64 => "__builtin_saddll_overflow", - 128 => "__builtin_add_overflow", - _ => unreachable!(), - }; - let overflow_func = self.context.get_builtin_function(func_name); - let result_type = lhs.get_type(); + // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 + let func = self.current_func.borrow().expect("func"); let res = func.new_local(None, result_type, "saturating_sum"); - let overflow = self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None); + let supports_native_type = self.is_native_int_type(result_type); + let overflow = + if supports_native_type { + let func_name = + match width { + 8 => "__builtin_add_overflow", + 16 => "__builtin_add_overflow", + 32 => "__builtin_sadd_overflow", + 64 => "__builtin_saddll_overflow", + 128 => "__builtin_add_overflow", + _ => unreachable!(), + }; + let overflow_func = self.context.get_builtin_function(func_name); + self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None) + } + else { + let func_name = + match width { + 128 => "__rust_i128_addo", + _ => unreachable!(), + }; + let param_a = self.context.new_parameter(None, result_type, "a"); + let param_b = self.context.new_parameter(None, result_type, "b"); + let result_field = self.context.new_field(None, result_type, "result"); + let overflow_field = self.context.new_field(None, self.bool_type, "overflow"); + let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]); + let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false); + let result = self.context.new_call(None, func, &[lhs, rhs]); + let overflow = result.access_field(None, overflow_field); + let int_result = result.access_field(None, result_field); + self.llbb().add_assignment(None, res, int_result); + overflow + }; let then_block = func.new_block("then"); + let after_block = func.new_block("after"); - let unsigned_type = self.context.new_int_type(width as i32 / 8, false); - let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1); - let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type, - self.context.new_rvalue_from_int(unsigned_type, 0) - ); - let int_max = uint_max >> self.context.new_rvalue_one(unsigned_type); - then_block.add_assignment(None, res, self.context.new_cast(None, shifted + int_max, result_type)); + // Return `result_type`'s maximum or minimum value on overflow + // NOTE: convert the type to unsigned to have an unsigned shift. + let unsigned_type = result_type.to_unsigned(&self.cx); + let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1)); + let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0)); + let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1)); + then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type)); then_block.end_with_jump(None, after_block); self.llbb().end_with_conditional(None, overflow, then_block, after_block); @@ -1006,20 +1027,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { res.to_rvalue() } else { + assert!(!signed); // Algorithm from: http://locklessinc.com/articles/sat_arithmetic/ - let res = lhs + rhs; - let res_type = res.get_type(); - let cond = self.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); - let value = self.context.new_unary_op(None, UnaryOp::Minus, res_type, self.context.new_cast(None, cond, res_type)); - res | value + let res = self.gcc_add(lhs, rhs); + let cond = self.gcc_icmp(IntPredicate::IntULT, res, lhs); + let value = self.gcc_neg(self.gcc_int_cast(cond, result_type)); + self.gcc_or(res, value) } } // Algorithm from: https://locklessinc.com/articles/sat_arithmetic/ fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> { + let result_type = lhs.get_type(); if signed { - // Also based on algorithm from: https://stackoverflow.com/a/56531252/389119 - let result_type = lhs.get_type(); + // Based on algorithm from: https://stackoverflow.com/a/56531252/389119 let func = self.current_func.borrow().expect("func"); let res = func.new_local(None, result_type, "saturating_diff"); let supports_native_type = self.is_native_int_type(result_type); @@ -1059,6 +1080,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let then_block = func.new_block("then"); let after_block = func.new_block("after"); + // Return `result_type`'s maximum or minimum value on overflow // NOTE: convert the type to unsigned to have an unsigned shift. let unsigned_type = result_type.to_unsigned(&self.cx); let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1)); @@ -1076,11 +1098,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { res.to_rvalue() } else { - let res = lhs - rhs; - let comparison = self.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); - let comparison = self.context.new_cast(None, comparison, lhs.get_type()); - let unary_op = self.context.new_unary_op(None, UnaryOp::Minus, comparison.get_type(), comparison); - self.and(res, unary_op) + assert!(!signed); + let res = self.gcc_sub(lhs, rhs); + let comparison = self.gcc_icmp(IntPredicate::IntULE, res, lhs); + let value = self.gcc_neg(self.gcc_int_cast(comparison, result_type)); + self.gcc_and(res, value) } } } From 5061e3ad163a75e81ed7b69e2113b5db135bc51a Mon Sep 17 00:00:00 2001 From: yvt Date: Wed, 6 Apr 2022 21:49:54 +0900 Subject: [PATCH 4/5] Remove redundant assertions --- src/intrinsic/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 84395e96763..d885bc8bf1f 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1027,7 +1027,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { res.to_rvalue() } else { - assert!(!signed); // Algorithm from: http://locklessinc.com/articles/sat_arithmetic/ let res = self.gcc_add(lhs, rhs); let cond = self.gcc_icmp(IntPredicate::IntULT, res, lhs); @@ -1098,7 +1097,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { res.to_rvalue() } else { - assert!(!signed); let res = self.gcc_sub(lhs, rhs); let comparison = self.gcc_icmp(IntPredicate::IntULE, res, lhs); let value = self.gcc_neg(self.gcc_int_cast(comparison, result_type)); From a7a09d556ab222f3b24d76defe1d2b2f99aa2c6f Mon Sep 17 00:00:00 2001 From: yvt Date: Wed, 6 Apr 2022 22:07:02 +0900 Subject: [PATCH 5/5] Wrap numbers with `black_box` in-line, remove `one` --- tests/run/int.rs | 353 +++++++++++++++++++++++------------------------ 1 file changed, 174 insertions(+), 179 deletions(-) diff --git a/tests/run/int.rs b/tests/run/int.rs index 8d2db9096f7..2b90e4ae8d8 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -3,7 +3,7 @@ // Run-time: // status: 0 -#![feature(bench_black_box, core_intrinsics, start)] +#![feature(bench_black_box, const_black_box, core_intrinsics, start)] #![no_std] @@ -18,23 +18,18 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! { #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { - let one: isize = core::hint::black_box(1); + use core::hint::black_box; macro_rules! check { ($ty:ty, $expr:expr) => { { - const EXPECTED: $ty = { - #[allow(non_upper_case_globals)] - #[allow(dead_code)] - const one: isize = 1; - $expr - }; + const EXPECTED: $ty = $expr; assert_eq!($expr, EXPECTED); } }; } - check!(u32, (2220326408_u32 + one as u32) >> (32 - 6)); + check!(u32, (2220326408_u32 + black_box(1)) >> (32 - 6)); /// Generate `check!` tests for integer types at least as wide as 128 bits. macro_rules! check_ops128 { @@ -42,15 +37,15 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { check_ops64!(); // Shifts. - check!(T, VAL1 << (one + 63) as T); - check!(T, VAL1 << (one + 80) as T); - check!(T, VAL3 << (one + 62) as T); - check!(T, VAL3 << (one + 63) as T); - - check!(T, VAL1 >> (one + 63) as T); - check!(T, VAL2 >> (one + 63) as T); - check!(T, VAL3 >> (one + 63) as T); - check!(T, VAL3 >> (one + 80) as T); + check!(T, VAL1 << black_box(64)); + check!(T, VAL1 << black_box(81)); + check!(T, VAL3 << black_box(63)); + check!(T, VAL3 << black_box(64)); + + check!(T, VAL1 >> black_box(64)); + check!(T, VAL2 >> black_box(64)); + check!(T, VAL3 >> black_box(64)); + check!(T, VAL3 >> black_box(81)); }; } @@ -60,29 +55,29 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { check_ops32!(); // Shifts. - check!(T, VAL2 << (one + 32) as T); - check!(T, VAL2 << (one + 48) as T); - check!(T, VAL2 << (one + 60) as T); - check!(T, VAL2 << (one + 62) as T); - - check!(T, VAL3 << (one + 32) as T); - check!(T, VAL3 << (one + 48) as T); - check!(T, VAL3 << (one + 60) as T); - - check!(T, VAL1 >> (one + 32) as T); - check!(T, VAL1 >> (one + 48) as T); - check!(T, VAL1 >> (one + 60) as T); - check!(T, VAL1 >> (one + 62) as T); - - check!(T, VAL2 >> (one + 32) as T); - check!(T, VAL2 >> (one + 48) as T); - check!(T, VAL2 >> (one + 60) as T); - check!(T, VAL2 >> (one + 62) as T); - - check!(T, VAL3 >> (one + 32) as T); - check!(T, VAL3 >> (one + 48) as T); - check!(T, VAL3 >> (one + 60) as T); - check!(T, VAL3 >> (one + 62) as T); + check!(T, VAL2 << black_box(33)); + check!(T, VAL2 << black_box(49)); + check!(T, VAL2 << black_box(61)); + check!(T, VAL2 << black_box(63)); + + check!(T, VAL3 << black_box(33)); + check!(T, VAL3 << black_box(49)); + check!(T, VAL3 << black_box(61)); + + check!(T, VAL1 >> black_box(33)); + check!(T, VAL1 >> black_box(49)); + check!(T, VAL1 >> black_box(61)); + check!(T, VAL1 >> black_box(63)); + + check!(T, VAL2 >> black_box(33)); + check!(T, VAL2 >> black_box(49)); + check!(T, VAL2 >> black_box(61)); + check!(T, VAL2 >> black_box(63)); + + check!(T, VAL3 >> black_box(33)); + check!(T, VAL3 >> black_box(49)); + check!(T, VAL3 >> black_box(61)); + check!(T, VAL3 >> black_box(63)); }; } @@ -90,195 +85,195 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { macro_rules! check_ops32 { () => { // Shifts. - check!(T, VAL2 << one as T); - check!(T, VAL2 << (one as T - 1)); - - check!(T, VAL3 << one as T); - check!(T, VAL3 << (one as T - 1)); - - check!(T, VAL1.wrapping_shl(one as u32 - 1)); - check!(T, VAL1.wrapping_shl(one as u32)); - check!(T, VAL1.wrapping_shl((one + 32) as u32)); - check!(T, VAL1.wrapping_shl((one + 48) as u32)); - check!(T, VAL1.wrapping_shl((one + 60) as u32)); - check!(T, VAL1.wrapping_shl((one + 62) as u32)); - check!(T, VAL1.wrapping_shl((one + 63) as u32)); - check!(T, VAL1.wrapping_shl((one + 80) as u32)); - - check!(Option, VAL1.checked_shl(one as u32 - 1)); - check!(Option, VAL1.checked_shl(one as u32)); - check!(Option, VAL1.checked_shl((one + 32) as u32)); - check!(Option, VAL1.checked_shl((one + 48) as u32)); - check!(Option, VAL1.checked_shl((one + 60) as u32)); - check!(Option, VAL1.checked_shl((one + 62) as u32)); - check!(Option, VAL1.checked_shl((one + 63) as u32)); - check!(Option, VAL1.checked_shl((one + 80) as u32)); - - check!(T, VAL1 >> (one as T - 1)); - check!(T, VAL1 >> one as T); - - check!(T, VAL2 >> one as T); - check!(T, VAL2 >> (one as T - 1)); - - check!(T, VAL3 >> (one as T - 1)); - check!(T, VAL3 >> one as T); - - check!(T, VAL1.wrapping_shr(one as u32 - 1)); - check!(T, VAL1.wrapping_shr(one as u32)); - check!(T, VAL1.wrapping_shr((one + 32) as u32)); - check!(T, VAL1.wrapping_shr((one + 48) as u32)); - check!(T, VAL1.wrapping_shr((one + 60) as u32)); - check!(T, VAL1.wrapping_shr((one + 62) as u32)); - check!(T, VAL1.wrapping_shr((one + 63) as u32)); - check!(T, VAL1.wrapping_shr((one + 80) as u32)); - - check!(Option, VAL1.checked_shr(one as u32 - 1)); - check!(Option, VAL1.checked_shr(one as u32)); - check!(Option, VAL1.checked_shr((one + 32) as u32)); - check!(Option, VAL1.checked_shr((one + 48) as u32)); - check!(Option, VAL1.checked_shr((one + 60) as u32)); - check!(Option, VAL1.checked_shr((one + 62) as u32)); - check!(Option, VAL1.checked_shr((one + 63) as u32)); - check!(Option, VAL1.checked_shr((one + 80) as u32)); + check!(T, VAL2 << black_box(1)); + check!(T, VAL2 << black_box(0)); + + check!(T, VAL3 << black_box(1)); + check!(T, VAL3 << black_box(0)); + + check!(T, VAL1.wrapping_shl(black_box(0))); + check!(T, VAL1.wrapping_shl(black_box(1))); + check!(T, VAL1.wrapping_shl(black_box(33))); + check!(T, VAL1.wrapping_shl(black_box(49))); + check!(T, VAL1.wrapping_shl(black_box(61))); + check!(T, VAL1.wrapping_shl(black_box(63))); + check!(T, VAL1.wrapping_shl(black_box(64))); + check!(T, VAL1.wrapping_shl(black_box(81))); + + check!(Option, VAL1.checked_shl(black_box(0))); + check!(Option, VAL1.checked_shl(black_box(1))); + check!(Option, VAL1.checked_shl(black_box(33))); + check!(Option, VAL1.checked_shl(black_box(49))); + check!(Option, VAL1.checked_shl(black_box(61))); + check!(Option, VAL1.checked_shl(black_box(63))); + check!(Option, VAL1.checked_shl(black_box(64))); + check!(Option, VAL1.checked_shl(black_box(81))); + + check!(T, VAL1 >> black_box(0)); + check!(T, VAL1 >> black_box(1)); + + check!(T, VAL2 >> black_box(1)); + check!(T, VAL2 >> black_box(0)); + + check!(T, VAL3 >> black_box(0)); + check!(T, VAL3 >> black_box(1)); + + check!(T, VAL1.wrapping_shr(black_box(0))); + check!(T, VAL1.wrapping_shr(black_box(1))); + check!(T, VAL1.wrapping_shr(black_box(33))); + check!(T, VAL1.wrapping_shr(black_box(49))); + check!(T, VAL1.wrapping_shr(black_box(61))); + check!(T, VAL1.wrapping_shr(black_box(63))); + check!(T, VAL1.wrapping_shr(black_box(64))); + check!(T, VAL1.wrapping_shr(black_box(81))); + + check!(Option, VAL1.checked_shr(black_box(0))); + check!(Option, VAL1.checked_shr(black_box(1))); + check!(Option, VAL1.checked_shr(black_box(33))); + check!(Option, VAL1.checked_shr(black_box(49))); + check!(Option, VAL1.checked_shr(black_box(61))); + check!(Option, VAL1.checked_shr(black_box(63))); + check!(Option, VAL1.checked_shr(black_box(64))); + check!(Option, VAL1.checked_shr(black_box(81))); // Casts - check!(u64, (VAL1 >> one as T) as u64); + check!(u64, (VAL1 >> black_box(1)) as u64); // Addition. - check!(T, VAL1 + one as T); - check!(T, VAL2 + one as T); - check!(T, VAL2 + (VAL2 + one as T) as T); - check!(T, VAL3 + one as T); - - check!(Option, VAL1.checked_add(one as T)); - check!(Option, VAL2.checked_add(one as T)); - check!(Option, VAL2.checked_add((VAL2 + one as T) as T)); + check!(T, VAL1 + black_box(1)); + check!(T, VAL2 + black_box(1)); + check!(T, VAL2 + (VAL2 + black_box(1))); + check!(T, VAL3 + black_box(1)); + + check!(Option, VAL1.checked_add(black_box(1))); + check!(Option, VAL2.checked_add(black_box(1))); + check!(Option, VAL2.checked_add(VAL2 + black_box(1))); check!(Option, VAL3.checked_add(T::MAX)); check!(Option, VAL3.checked_add(T::MIN)); - check!(T, VAL1.wrapping_add(one as T)); - check!(T, VAL2.wrapping_add(one as T)); - check!(T, VAL2.wrapping_add((VAL2 + one as T) as T)); + check!(T, VAL1.wrapping_add(black_box(1))); + check!(T, VAL2.wrapping_add(black_box(1))); + check!(T, VAL2.wrapping_add(VAL2 + black_box(1))); check!(T, VAL3.wrapping_add(T::MAX)); check!(T, VAL3.wrapping_add(T::MIN)); - check!((T, bool), VAL1.overflowing_add(one as T)); - check!((T, bool), VAL2.overflowing_add(one as T)); - check!((T, bool), VAL2.overflowing_add((VAL2 + one as T) as T)); + check!((T, bool), VAL1.overflowing_add(black_box(1))); + check!((T, bool), VAL2.overflowing_add(black_box(1))); + check!((T, bool), VAL2.overflowing_add(VAL2 + black_box(1))); check!((T, bool), VAL3.overflowing_add(T::MAX)); check!((T, bool), VAL3.overflowing_add(T::MIN)); - check!(T, VAL1.saturating_add(one as T)); - check!(T, VAL2.saturating_add(one as T)); - check!(T, VAL2.saturating_add((VAL2 + one as T) as T)); + check!(T, VAL1.saturating_add(black_box(1))); + check!(T, VAL2.saturating_add(black_box(1))); + check!(T, VAL2.saturating_add(VAL2 + black_box(1))); check!(T, VAL3.saturating_add(T::MAX)); check!(T, VAL3.saturating_add(T::MIN)); // Subtraction - check!(T, VAL1 - one as T); - check!(T, VAL2 - one as T); - check!(T, VAL3 - one as T); + check!(T, VAL1 - black_box(1)); + check!(T, VAL2 - black_box(1)); + check!(T, VAL3 - black_box(1)); - check!(Option, VAL1.checked_sub(one as T)); - check!(Option, VAL2.checked_sub(one as T)); - check!(Option, VAL2.checked_sub((VAL2 + one as T) as T)); + check!(Option, VAL1.checked_sub(black_box(1))); + check!(Option, VAL2.checked_sub(black_box(1))); + check!(Option, VAL2.checked_sub(VAL2 + black_box(1))); check!(Option, VAL3.checked_sub(T::MAX)); check!(Option, VAL3.checked_sub(T::MIN)); - check!(T, VAL1.wrapping_sub(one as T)); - check!(T, VAL2.wrapping_sub(one as T)); - check!(T, VAL2.wrapping_sub((VAL2 + one as T) as T)); + check!(T, VAL1.wrapping_sub(black_box(1))); + check!(T, VAL2.wrapping_sub(black_box(1))); + check!(T, VAL2.wrapping_sub(VAL2 + black_box(1))); check!(T, VAL3.wrapping_sub(T::MAX)); check!(T, VAL3.wrapping_sub(T::MIN)); - check!((T, bool), VAL1.overflowing_sub(one as T)); - check!((T, bool), VAL2.overflowing_sub(one as T)); - check!((T, bool), VAL2.overflowing_sub((VAL2 + one as T) as T)); + check!((T, bool), VAL1.overflowing_sub(black_box(1))); + check!((T, bool), VAL2.overflowing_sub(black_box(1))); + check!((T, bool), VAL2.overflowing_sub(VAL2 + black_box(1))); check!((T, bool), VAL3.overflowing_sub(T::MAX)); check!((T, bool), VAL3.overflowing_sub(T::MIN)); - check!(T, VAL1.saturating_sub(one as T)); - check!(T, VAL2.saturating_sub(one as T)); - check!(T, VAL2.saturating_sub((VAL2 + one as T) as T)); + check!(T, VAL1.saturating_sub(black_box(1))); + check!(T, VAL2.saturating_sub(black_box(1))); + check!(T, VAL2.saturating_sub(VAL2 + black_box(1))); check!(T, VAL3.saturating_sub(T::MAX)); check!(T, VAL3.saturating_sub(T::MIN)); // Multiplication - check!(T, VAL1 * (one + 1) as T); - check!(T, VAL1 * (one as T + VAL2)); - check!(T, VAL2 * (one + 1) as T); - check!(T, VAL2 * (one as T + VAL2)); - check!(T, VAL3 * one as T); - check!(T, VAL4 * (one + 1) as T); - check!(T, VAL5 * (one + 1) as T); - - check!(Option, VAL1.checked_mul((one + 1) as T)); - check!(Option, VAL1.checked_mul((one as T + VAL2))); + check!(T, VAL1 * black_box(2)); + check!(T, VAL1 * (black_box(1) + VAL2)); + check!(T, VAL2 * black_box(2)); + check!(T, VAL2 * (black_box(1) + VAL2)); + check!(T, VAL3 * black_box(1)); + check!(T, VAL4 * black_box(2)); + check!(T, VAL5 * black_box(2)); + + check!(Option, VAL1.checked_mul(black_box(2))); + check!(Option, VAL1.checked_mul(black_box(1) + VAL2)); check!(Option, VAL3.checked_mul(VAL3)); - check!(Option, VAL4.checked_mul((one + 1) as T)); - check!(Option, VAL5.checked_mul((one + 1) as T)); + check!(Option, VAL4.checked_mul(black_box(2))); + check!(Option, VAL5.checked_mul(black_box(2))); - check!(T, VAL1.wrapping_mul((one + 1) as T)); - check!(T, VAL1.wrapping_mul((one as T + VAL2))); + check!(T, VAL1.wrapping_mul(black_box(2))); + check!(T, VAL1.wrapping_mul((black_box(1) + VAL2))); check!(T, VAL3.wrapping_mul(VAL3)); - check!(T, VAL4.wrapping_mul((one + 1) as T)); - check!(T, VAL5.wrapping_mul((one + 1) as T)); + check!(T, VAL4.wrapping_mul(black_box(2))); + check!(T, VAL5.wrapping_mul(black_box(2))); - check!((T, bool), VAL1.overflowing_mul((one + 1) as T)); - check!((T, bool), VAL1.overflowing_mul((one as T + VAL2))); + check!((T, bool), VAL1.overflowing_mul(black_box(2))); + check!((T, bool), VAL1.overflowing_mul(black_box(1) + VAL2)); check!((T, bool), VAL3.overflowing_mul(VAL3)); - check!((T, bool), VAL4.overflowing_mul((one + 1) as T)); - check!((T, bool), VAL5.overflowing_mul((one + 1) as T)); + check!((T, bool), VAL4.overflowing_mul(black_box(2))); + check!((T, bool), VAL5.overflowing_mul(black_box(2))); - check!(T, VAL1.saturating_mul((one + 1) as T)); - check!(T, VAL1.saturating_mul((one as T + VAL2))); + check!(T, VAL1.saturating_mul(black_box(2))); + check!(T, VAL1.saturating_mul(black_box(1) + VAL2)); check!(T, VAL3.saturating_mul(VAL3)); - check!(T, VAL4.saturating_mul((one + 1) as T)); - check!(T, VAL5.saturating_mul((one + 1) as T)); + check!(T, VAL4.saturating_mul(black_box(2))); + check!(T, VAL5.saturating_mul(black_box(2))); // Division. - check!(T, VAL1 / (one + 1) as T); - check!(T, VAL1 / (one + 2) as T); + check!(T, VAL1 / black_box(2)); + check!(T, VAL1 / black_box(3)); - check!(T, VAL2 / (one + 1) as T); - check!(T, VAL2 / (one + 2) as T); + check!(T, VAL2 / black_box(2)); + check!(T, VAL2 / black_box(3)); - check!(T, VAL3 / (one + 1) as T); - check!(T, VAL3 / (one + 2) as T); - check!(T, VAL3 / (one as T + VAL4)); - check!(T, VAL3 / (one as T + VAL2)); + check!(T, VAL3 / black_box(2)); + check!(T, VAL3 / black_box(3)); + check!(T, VAL3 / (black_box(1) + VAL4)); + check!(T, VAL3 / (black_box(1) + VAL2)); - check!(T, VAL4 / (one + 1) as T); - check!(T, VAL4 / (one + 2) as T); + check!(T, VAL4 / black_box(2)); + check!(T, VAL4 / black_box(3)); - check!(Option, VAL1.checked_div((one + 1) as T)); - check!(Option, VAL1.checked_div((one as T + VAL2))); + check!(Option, VAL1.checked_div(black_box(2))); + check!(Option, VAL1.checked_div(black_box(1) + VAL2)); check!(Option, VAL3.checked_div(VAL3)); - check!(Option, VAL4.checked_div((one + 1) as T)); - check!(Option, VAL5.checked_div((one + 1) as T)); - check!(Option, (T::MIN).checked_div((0 as T).wrapping_sub(one as T))); - check!(Option, VAL5.checked_div((one - 1) as T)); // var5 / 0 + check!(Option, VAL4.checked_div(black_box(2))); + check!(Option, VAL5.checked_div(black_box(2))); + check!(Option, (T::MIN).checked_div(black_box(0 as T).wrapping_sub(1))); + check!(Option, VAL5.checked_div(black_box(0))); // var5 / 0 - check!(T, VAL1.wrapping_div((one + 1) as T)); - check!(T, VAL1.wrapping_div((one as T + VAL2))); + check!(T, VAL1.wrapping_div(black_box(2))); + check!(T, VAL1.wrapping_div(black_box(1) + VAL2)); check!(T, VAL3.wrapping_div(VAL3)); - check!(T, VAL4.wrapping_div((one + 1) as T)); - check!(T, VAL5.wrapping_div((one + 1) as T)); - check!(T, (T::MIN).wrapping_div((0 as T).wrapping_sub(one as T))); + check!(T, VAL4.wrapping_div(black_box(2))); + check!(T, VAL5.wrapping_div(black_box(2))); + check!(T, (T::MIN).wrapping_div(black_box(0 as T).wrapping_sub(1))); - check!((T, bool), VAL1.overflowing_div((one + 1) as T)); - check!((T, bool), VAL1.overflowing_div((one as T + VAL2))); + check!((T, bool), VAL1.overflowing_div(black_box(2))); + check!((T, bool), VAL1.overflowing_div(black_box(1) + VAL2)); check!((T, bool), VAL3.overflowing_div(VAL3)); - check!((T, bool), VAL4.overflowing_div((one + 1) as T)); - check!((T, bool), VAL5.overflowing_div((one + 1) as T)); - check!((T, bool), (T::MIN).overflowing_div((0 as T).wrapping_sub(one as T))); + check!((T, bool), VAL4.overflowing_div(black_box(2))); + check!((T, bool), VAL5.overflowing_div(black_box(2))); + check!((T, bool), (T::MIN).overflowing_div(black_box(0 as T).wrapping_sub(1))); - check!(T, VAL1.saturating_div((one + 1) as T)); - check!(T, VAL1.saturating_div((one as T + VAL2))); + check!(T, VAL1.saturating_div(black_box(2))); + check!(T, VAL1.saturating_div((black_box(1) + VAL2))); check!(T, VAL3.saturating_div(VAL3)); - check!(T, VAL4.saturating_div((one + 1) as T)); - check!(T, VAL5.saturating_div((one + 1) as T)); - check!(T, (T::MIN).saturating_div((0 as T).wrapping_sub(one as T))); + check!(T, VAL4.saturating_div(black_box(2))); + check!(T, VAL5.saturating_div(black_box(2))); + check!(T, (T::MIN).saturating_div((0 as T).wrapping_sub(black_box(1)))); }; }