diff --git a/example/std_example.rs b/example/std_example.rs index f16ff592d4c..26289818896 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -38,6 +38,11 @@ fn main() { assert_eq!(2.3f32.copysign(-1.0), -2.3f32); println!("{}", 2.3f32.powf(2.0)); + assert_eq!(-128i8, (-128i8).saturating_sub(1)); + assert_eq!(127i8, 127i8.saturating_sub(-128)); + assert_eq!(-128i8, (-128i8).saturating_add(-128)); + assert_eq!(127i8, 127i8.saturating_add(1)); + assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); diff --git a/src/intrinsics.rs b/src/intrinsics.rs index e09dc25f4ab..2cec9c57143 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -487,8 +487,8 @@ pub fn codegen_intrinsic_call<'tcx>( ); ret.write_cvalue(fx, res); }; - _ if intrinsic.starts_with("saturating_"), (c x, c y) { - assert_eq!(x.layout().ty, y.layout().ty); + _ if intrinsic.starts_with("saturating_"), (c lhs, c rhs) { + assert_eq!(lhs.layout().ty, rhs.layout().ty); let bin_op = match intrinsic { "saturating_add" => BinOp::Add, "saturating_sub" => BinOp::Sub, @@ -500,8 +500,8 @@ pub fn codegen_intrinsic_call<'tcx>( let checked_res = crate::num::trans_checked_int_binop( fx, bin_op, - x, - y, + lhs, + rhs, ); let (val, has_overflow) = checked_res.load_scalar_pair(fx); @@ -517,8 +517,18 @@ pub fn codegen_intrinsic_call<'tcx>( let val = match (intrinsic, signed) { ("saturating_add", false) => codegen_select(&mut fx.bcx, has_overflow, max, val), ("saturating_sub", false) => codegen_select(&mut fx.bcx, has_overflow, min, val), - ("saturating_add", true) => unimplemented!(), - ("saturating_sub", true) => unimplemented!(), + ("saturating_add", true) => { + let rhs = rhs.load_scalar(fx); + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let sat_val = codegen_select(&mut fx.bcx, rhs_ge_zero, max, min); + codegen_select(&mut fx.bcx, has_overflow, sat_val, val) + } + ("saturating_sub", true) => { + let rhs = rhs.load_scalar(fx); + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let sat_val = codegen_select(&mut fx.bcx, rhs_ge_zero, min, max); + codegen_select(&mut fx.bcx, has_overflow, sat_val, val) + } _ => unreachable!(), };