Extract codegen_saturating_int_binop function
This commit is contained in:
parent
f200fbca10
commit
0980596271
2 changed files with 37 additions and 31 deletions
|
@ -507,37 +507,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let signed = type_sign(lhs.layout().ty);
|
let res = crate::num::codegen_saturating_int_binop(fx, bin_op, lhs, rhs);
|
||||||
|
|
||||||
let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
|
|
||||||
|
|
||||||
let (val, has_overflow) = checked_res.load_scalar_pair(fx);
|
|
||||||
let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
|
|
||||||
|
|
||||||
let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
|
|
||||||
|
|
||||||
let val = match (intrinsic, signed) {
|
|
||||||
(sym::saturating_add, false) => fx.bcx.ins().select(has_overflow, max, val),
|
|
||||||
(sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val),
|
|
||||||
(sym::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 = fx.bcx.ins().select(rhs_ge_zero, max, min);
|
|
||||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
|
||||||
}
|
|
||||||
(sym::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 = fx.bcx.ins().select(rhs_ge_zero, min, max);
|
|
||||||
fx.bcx.ins().select(has_overflow, sat_val, val)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let res = CValue::by_val(val, lhs.layout());
|
|
||||||
|
|
||||||
ret.write_cvalue(fx, res);
|
ret.write_cvalue(fx, res);
|
||||||
}
|
}
|
||||||
sym::rotate_left => {
|
sym::rotate_left => {
|
||||||
|
|
36
src/num.rs
36
src/num.rs
|
@ -309,6 +309,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
|
||||||
CValue::by_val_pair(res, has_overflow, out_layout)
|
CValue::by_val_pair(res, has_overflow, out_layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn codegen_saturating_int_binop<'tcx>(
|
||||||
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||||
|
bin_op: BinOp,
|
||||||
|
lhs: CValue<'tcx>,
|
||||||
|
rhs: CValue<'tcx>,
|
||||||
|
) -> CValue<'tcx> {
|
||||||
|
assert_eq!(lhs.layout().ty, rhs.layout().ty);
|
||||||
|
|
||||||
|
let signed = type_sign(lhs.layout().ty);
|
||||||
|
let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
|
||||||
|
let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
|
||||||
|
|
||||||
|
let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
|
||||||
|
let (val, has_overflow) = checked_res.load_scalar_pair(fx);
|
||||||
|
|
||||||
|
let val = match (bin_op, signed) {
|
||||||
|
(BinOp::Add, false) => fx.bcx.ins().select(has_overflow, max, val),
|
||||||
|
(BinOp::Sub, false) => fx.bcx.ins().select(has_overflow, min, val),
|
||||||
|
(BinOp::Add, true) => {
|
||||||
|
let rhs = rhs.load_scalar(fx);
|
||||||
|
let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||||
|
let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
|
||||||
|
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||||
|
}
|
||||||
|
(BinOp::Sub, true) => {
|
||||||
|
let rhs = rhs.load_scalar(fx);
|
||||||
|
let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
|
||||||
|
let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
|
||||||
|
fx.bcx.ins().select(has_overflow, sat_val, val)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
CValue::by_val(val, lhs.layout())
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn codegen_float_binop<'tcx>(
|
pub(crate) fn codegen_float_binop<'tcx>(
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||||
bin_op: BinOp,
|
bin_op: BinOp,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue