Promote unchecked_add/sub/mul/shl/shr to mir::BinOp
This commit is contained in:
parent
8d1fa473dd
commit
39788e07ba
36 changed files with 504 additions and 215 deletions
|
@ -22,8 +22,8 @@ pub(crate) fn maybe_codegen<'tcx>(
|
||||||
|
|
||||||
match bin_op {
|
match bin_op {
|
||||||
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None,
|
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None,
|
||||||
BinOp::Add | BinOp::Sub => None,
|
BinOp::Add | BinOp::AddUnchecked | BinOp::Sub | BinOp::SubUnchecked => None,
|
||||||
BinOp::Mul => {
|
BinOp::Mul | BinOp::MulUnchecked => {
|
||||||
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
|
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
|
||||||
let ret_val = fx.lib_call(
|
let ret_val = fx.lib_call(
|
||||||
"__multi3",
|
"__multi3",
|
||||||
|
@ -69,7 +69,7 @@ pub(crate) fn maybe_codegen<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None,
|
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None,
|
||||||
BinOp::Shl | BinOp::Shr => None,
|
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,9 +131,10 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
|
||||||
fx.lib_call(name, param_types, vec![], &args);
|
fx.lib_call(name, param_types, vec![], &args);
|
||||||
Some(out_place.to_cvalue(fx))
|
Some(out_place.to_cvalue(fx))
|
||||||
}
|
}
|
||||||
|
BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
|
||||||
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
|
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
|
||||||
BinOp::Div | BinOp::Rem => unreachable!(),
|
BinOp::Div | BinOp::Rem => unreachable!(),
|
||||||
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(),
|
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(),
|
||||||
BinOp::Shl | BinOp::Shr => unreachable!(),
|
BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,10 +128,11 @@ pub(crate) fn codegen_int_binop<'tcx>(
|
||||||
let rhs = in_rhs.load_scalar(fx);
|
let rhs = in_rhs.load_scalar(fx);
|
||||||
|
|
||||||
let b = fx.bcx.ins();
|
let b = fx.bcx.ins();
|
||||||
|
// FIXME trap on overflow for the Unchecked versions
|
||||||
let val = match bin_op {
|
let val = match bin_op {
|
||||||
BinOp::Add => b.iadd(lhs, rhs),
|
BinOp::Add | BinOp::AddUnchecked => b.iadd(lhs, rhs),
|
||||||
BinOp::Sub => b.isub(lhs, rhs),
|
BinOp::Sub | BinOp::SubUnchecked => b.isub(lhs, rhs),
|
||||||
BinOp::Mul => b.imul(lhs, rhs),
|
BinOp::Mul | BinOp::MulUnchecked => b.imul(lhs, rhs),
|
||||||
BinOp::Div => {
|
BinOp::Div => {
|
||||||
if signed {
|
if signed {
|
||||||
b.sdiv(lhs, rhs)
|
b.sdiv(lhs, rhs)
|
||||||
|
@ -149,16 +150,19 @@ pub(crate) fn codegen_int_binop<'tcx>(
|
||||||
BinOp::BitXor => b.bxor(lhs, rhs),
|
BinOp::BitXor => b.bxor(lhs, rhs),
|
||||||
BinOp::BitAnd => b.band(lhs, rhs),
|
BinOp::BitAnd => b.band(lhs, rhs),
|
||||||
BinOp::BitOr => b.bor(lhs, rhs),
|
BinOp::BitOr => b.bor(lhs, rhs),
|
||||||
BinOp::Shl => b.ishl(lhs, rhs),
|
BinOp::Shl | BinOp::ShlUnchecked => b.ishl(lhs, rhs),
|
||||||
BinOp::Shr => {
|
BinOp::Shr | BinOp::ShrUnchecked => {
|
||||||
if signed {
|
if signed {
|
||||||
b.sshr(lhs, rhs)
|
b.sshr(lhs, rhs)
|
||||||
} else {
|
} else {
|
||||||
b.ushr(lhs, rhs)
|
b.ushr(lhs, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BinOp::Offset => unreachable!("Offset is not an integer operation"),
|
||||||
// Compare binops handles by `codegen_binop`.
|
// Compare binops handles by `codegen_binop`.
|
||||||
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
|
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => {
|
||||||
|
unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CValue::by_val(val, in_lhs.layout())
|
CValue::by_val(val, in_lhs.layout())
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
// all shifts). For 32- and 64-bit types, this matches the semantics
|
// all shifts). For 32- and 64-bit types, this matches the semantics
|
||||||
// of Java. (See related discussion on #1877 and #10183.)
|
// of Java. (See related discussion on #1877 and #10183.)
|
||||||
|
|
||||||
pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
pub fn build_masked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
lhs: Bx::Value,
|
lhs: Bx::Value,
|
||||||
rhs: Bx::Value,
|
rhs: Bx::Value,
|
||||||
|
@ -143,7 +143,7 @@ pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
bx.shl(lhs, rhs)
|
bx.shl(lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
pub fn build_masked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
lhs_t: Ty<'tcx>,
|
lhs_t: Ty<'tcx>,
|
||||||
lhs: Bx::Value,
|
lhs: Bx::Value,
|
||||||
|
|
|
@ -798,6 +798,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx.add(lhs, rhs)
|
bx.add(lhs, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mir::BinOp::AddUnchecked => {
|
||||||
|
if is_signed {
|
||||||
|
bx.unchecked_sadd(lhs, rhs)
|
||||||
|
} else {
|
||||||
|
bx.unchecked_uadd(lhs, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
mir::BinOp::Sub => {
|
mir::BinOp::Sub => {
|
||||||
if is_float {
|
if is_float {
|
||||||
bx.fsub(lhs, rhs)
|
bx.fsub(lhs, rhs)
|
||||||
|
@ -805,6 +812,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx.sub(lhs, rhs)
|
bx.sub(lhs, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mir::BinOp::SubUnchecked => {
|
||||||
|
if is_signed {
|
||||||
|
bx.unchecked_ssub(lhs, rhs)
|
||||||
|
} else {
|
||||||
|
bx.unchecked_usub(lhs, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
mir::BinOp::Mul => {
|
mir::BinOp::Mul => {
|
||||||
if is_float {
|
if is_float {
|
||||||
bx.fmul(lhs, rhs)
|
bx.fmul(lhs, rhs)
|
||||||
|
@ -812,6 +826,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx.mul(lhs, rhs)
|
bx.mul(lhs, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mir::BinOp::MulUnchecked => {
|
||||||
|
if is_signed {
|
||||||
|
bx.unchecked_smul(lhs, rhs)
|
||||||
|
} else {
|
||||||
|
bx.unchecked_umul(lhs, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
mir::BinOp::Div => {
|
mir::BinOp::Div => {
|
||||||
if is_float {
|
if is_float {
|
||||||
bx.fdiv(lhs, rhs)
|
bx.fdiv(lhs, rhs)
|
||||||
|
@ -848,8 +869,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx.inbounds_gep(llty, lhs, &[rhs])
|
bx.inbounds_gep(llty, lhs, &[rhs])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
|
mir::BinOp::Shl => common::build_masked_lshift(bx, lhs, rhs),
|
||||||
mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
|
mir::BinOp::ShlUnchecked => {
|
||||||
|
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
|
||||||
|
bx.shl(lhs, rhs)
|
||||||
|
}
|
||||||
|
mir::BinOp::Shr => common::build_masked_rshift(bx, input_ty, lhs, rhs),
|
||||||
|
mir::BinOp::ShrUnchecked => {
|
||||||
|
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
|
||||||
|
if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
|
||||||
|
}
|
||||||
mir::BinOp::Ne
|
mir::BinOp::Ne
|
||||||
| mir::BinOp::Lt
|
| mir::BinOp::Lt
|
||||||
| mir::BinOp::Gt
|
| mir::BinOp::Gt
|
||||||
|
|
|
@ -3,10 +3,13 @@ use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{self, FloatTy, Ty};
|
use rustc_middle::ty::{self, FloatTy, Ty};
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
use rustc_target::abi::Abi;
|
use rustc_target::abi::Abi;
|
||||||
|
|
||||||
use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
|
use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
|
||||||
|
|
||||||
|
use crate::fluent_generated as fluent;
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
|
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
|
||||||
/// and a boolean signifying the potential overflow to the destination.
|
/// and a boolean signifying the potential overflow to the destination.
|
||||||
|
@ -139,8 +142,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
) -> InterpResult<'tcx, (Scalar<M::Provenance>, bool, Ty<'tcx>)> {
|
) -> InterpResult<'tcx, (Scalar<M::Provenance>, bool, Ty<'tcx>)> {
|
||||||
use rustc_middle::mir::BinOp::*;
|
use rustc_middle::mir::BinOp::*;
|
||||||
|
|
||||||
|
let throw_ub_on_overflow = match bin_op {
|
||||||
|
AddUnchecked => Some(sym::unchecked_add),
|
||||||
|
SubUnchecked => Some(sym::unchecked_sub),
|
||||||
|
MulUnchecked => Some(sym::unchecked_mul),
|
||||||
|
ShlUnchecked => Some(sym::unchecked_shl),
|
||||||
|
ShrUnchecked => Some(sym::unchecked_shr),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
// Shift ops can have an RHS with a different numeric type.
|
// Shift ops can have an RHS with a different numeric type.
|
||||||
if bin_op == Shl || bin_op == Shr {
|
if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
|
||||||
let size = u128::from(left_layout.size.bits());
|
let size = u128::from(left_layout.size.bits());
|
||||||
// Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its
|
// Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its
|
||||||
// zero-extended form). This matches the codegen backend:
|
// zero-extended form). This matches the codegen backend:
|
||||||
|
@ -155,6 +167,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// integers are maximally 128bits wide, so negative shifts *always* overflow and we have
|
// integers are maximally 128bits wide, so negative shifts *always* overflow and we have
|
||||||
// consistent results for the same value represented at different bit widths.
|
// consistent results for the same value represented at different bit widths.
|
||||||
assert!(size <= 128);
|
assert!(size <= 128);
|
||||||
|
let original_r = r;
|
||||||
let overflow = r >= size;
|
let overflow = r >= size;
|
||||||
// The shift offset is implicitly masked to the type size, to make sure this operation
|
// The shift offset is implicitly masked to the type size, to make sure this operation
|
||||||
// is always defined. This is the one MIR operator that does *not* directly map to a
|
// is always defined. This is the one MIR operator that does *not* directly map to a
|
||||||
|
@ -166,19 +179,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
let result = if left_layout.abi.is_signed() {
|
let result = if left_layout.abi.is_signed() {
|
||||||
let l = self.sign_extend(l, left_layout) as i128;
|
let l = self.sign_extend(l, left_layout) as i128;
|
||||||
let result = match bin_op {
|
let result = match bin_op {
|
||||||
Shl => l.checked_shl(r).unwrap(),
|
Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
|
||||||
Shr => l.checked_shr(r).unwrap(),
|
Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
result as u128
|
result as u128
|
||||||
} else {
|
} else {
|
||||||
match bin_op {
|
match bin_op {
|
||||||
Shl => l.checked_shl(r).unwrap(),
|
Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
|
||||||
Shr => l.checked_shr(r).unwrap(),
|
Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let truncated = self.truncate(result, left_layout);
|
let truncated = self.truncate(result, left_layout);
|
||||||
|
|
||||||
|
if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
|
||||||
|
throw_ub_custom!(
|
||||||
|
fluent::const_eval_overflow_shift,
|
||||||
|
val = original_r,
|
||||||
|
name = intrinsic_name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty));
|
return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,9 +238,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
Rem if r == 0 => throw_ub!(RemainderByZero),
|
Rem if r == 0 => throw_ub!(RemainderByZero),
|
||||||
Div => Some(i128::overflowing_div),
|
Div => Some(i128::overflowing_div),
|
||||||
Rem => Some(i128::overflowing_rem),
|
Rem => Some(i128::overflowing_rem),
|
||||||
Add => Some(i128::overflowing_add),
|
Add | AddUnchecked => Some(i128::overflowing_add),
|
||||||
Sub => Some(i128::overflowing_sub),
|
Sub | SubUnchecked => Some(i128::overflowing_sub),
|
||||||
Mul => Some(i128::overflowing_mul),
|
Mul | MulUnchecked => Some(i128::overflowing_mul),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(op) = op {
|
if let Some(op) = op {
|
||||||
|
@ -242,11 +264,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// If that truncation loses any information, we have an overflow.
|
// If that truncation loses any information, we have an overflow.
|
||||||
let result = result as u128;
|
let result = result as u128;
|
||||||
let truncated = self.truncate(result, left_layout);
|
let truncated = self.truncate(result, left_layout);
|
||||||
return Ok((
|
let overflow = oflo || self.sign_extend(truncated, left_layout) != result;
|
||||||
Scalar::from_uint(truncated, size),
|
if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
|
||||||
oflo || self.sign_extend(truncated, left_layout) != result,
|
throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
|
||||||
left_layout.ty,
|
}
|
||||||
));
|
return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +285,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty),
|
BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty),
|
||||||
BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty),
|
BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty),
|
||||||
|
|
||||||
Add | Sub | Mul | Rem | Div => {
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => {
|
||||||
assert!(!left_layout.abi.is_signed());
|
assert!(!left_layout.abi.is_signed());
|
||||||
let op: fn(u128, u128) -> (u128, bool) = match bin_op {
|
let op: fn(u128, u128) -> (u128, bool) = match bin_op {
|
||||||
Add => u128::overflowing_add,
|
Add | AddUnchecked => u128::overflowing_add,
|
||||||
Sub => u128::overflowing_sub,
|
Sub | SubUnchecked => u128::overflowing_sub,
|
||||||
Mul => u128::overflowing_mul,
|
Mul | MulUnchecked => u128::overflowing_mul,
|
||||||
Div if r == 0 => throw_ub!(DivisionByZero),
|
Div if r == 0 => throw_ub!(DivisionByZero),
|
||||||
Rem if r == 0 => throw_ub!(RemainderByZero),
|
Rem if r == 0 => throw_ub!(RemainderByZero),
|
||||||
Div => u128::overflowing_div,
|
Div => u128::overflowing_div,
|
||||||
|
@ -279,11 +301,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// Truncate to target type.
|
// Truncate to target type.
|
||||||
// If that truncation loses any information, we have an overflow.
|
// If that truncation loses any information, we have an overflow.
|
||||||
let truncated = self.truncate(result, left_layout);
|
let truncated = self.truncate(result, left_layout);
|
||||||
return Ok((
|
let overflow = oflo || truncated != result;
|
||||||
Scalar::from_uint(truncated, size),
|
if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
|
||||||
oflo || truncated != result,
|
throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
|
||||||
left_layout.ty,
|
}
|
||||||
));
|
return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => span_bug!(
|
_ => span_bug!(
|
||||||
|
|
|
@ -16,7 +16,8 @@ use super::{ImmTy, InterpCx, Machine};
|
||||||
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
||||||
use rustc_middle::mir::BinOp::*;
|
use rustc_middle::mir::BinOp::*;
|
||||||
match op {
|
match op {
|
||||||
Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||||
|
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
|
||||||
Eq | Ne | Lt | Le | Gt | Ge => false,
|
Eq | Ne | Lt | Le | Gt | Ge => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +27,9 @@ fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
||||||
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
||||||
use rustc_middle::mir::BinOp::*;
|
use rustc_middle::mir::BinOp::*;
|
||||||
match op {
|
match op {
|
||||||
Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||||
Offset | Shl | Shr => false,
|
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
|
||||||
|
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -569,13 +569,18 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
| BinOp::Gt
|
| BinOp::Gt
|
||||||
| BinOp::Offset
|
| BinOp::Offset
|
||||||
| BinOp::Add
|
| BinOp::Add
|
||||||
|
| BinOp::AddUnchecked
|
||||||
| BinOp::Sub
|
| BinOp::Sub
|
||||||
|
| BinOp::SubUnchecked
|
||||||
| BinOp::Mul
|
| BinOp::Mul
|
||||||
|
| BinOp::MulUnchecked
|
||||||
| BinOp::BitXor
|
| BinOp::BitXor
|
||||||
| BinOp::BitAnd
|
| BinOp::BitAnd
|
||||||
| BinOp::BitOr
|
| BinOp::BitOr
|
||||||
| BinOp::Shl
|
| BinOp::Shl
|
||||||
| BinOp::Shr => {}
|
| BinOp::ShlUnchecked
|
||||||
|
| BinOp::Shr
|
||||||
|
| BinOp::ShrUnchecked => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.validate_operand(lhs)?;
|
self.validate_operand(lhs)?;
|
||||||
|
|
|
@ -556,7 +556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Shl | Shr => {
|
Shl | ShlUnchecked | Shr | ShrUnchecked => {
|
||||||
for x in [a, b] {
|
for x in [a, b] {
|
||||||
check_kinds!(
|
check_kinds!(
|
||||||
x,
|
x,
|
||||||
|
@ -601,6 +601,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AddUnchecked | SubUnchecked | MulUnchecked => {
|
||||||
|
for x in [a, b] {
|
||||||
|
check_kinds!(
|
||||||
|
x,
|
||||||
|
"Cannot perform unchecked arithmetic on type {:?}",
|
||||||
|
ty::Uint(..) | ty::Int(..)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if a != b {
|
||||||
|
self.fail(
|
||||||
|
location,
|
||||||
|
format!(
|
||||||
|
"Cannot perform unchecked arithmetic on unequal types {:?} and {:?}",
|
||||||
|
a, b
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rvalue::CheckedBinaryOp(op, vals) => {
|
Rvalue::CheckedBinaryOp(op, vals) => {
|
||||||
|
|
|
@ -1267,10 +1267,16 @@ pub enum UnOp {
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
/// The `+` operator (addition)
|
/// The `+` operator (addition)
|
||||||
Add,
|
Add,
|
||||||
|
/// Like `Add`, but with UB on overflow. (Integers only.)
|
||||||
|
AddUnchecked,
|
||||||
/// The `-` operator (subtraction)
|
/// The `-` operator (subtraction)
|
||||||
Sub,
|
Sub,
|
||||||
|
/// Like `Sub`, but with UB on overflow. (Integers only.)
|
||||||
|
SubUnchecked,
|
||||||
/// The `*` operator (multiplication)
|
/// The `*` operator (multiplication)
|
||||||
Mul,
|
Mul,
|
||||||
|
/// Like `Mul`, but with UB on overflow. (Integers only.)
|
||||||
|
MulUnchecked,
|
||||||
/// The `/` operator (division)
|
/// The `/` operator (division)
|
||||||
///
|
///
|
||||||
/// For integer types, division by zero is UB, as is `MIN / -1` for signed.
|
/// For integer types, division by zero is UB, as is `MIN / -1` for signed.
|
||||||
|
@ -1296,10 +1302,17 @@ pub enum BinOp {
|
||||||
///
|
///
|
||||||
/// The offset is truncated to the size of the first operand before shifting.
|
/// The offset is truncated to the size of the first operand before shifting.
|
||||||
Shl,
|
Shl,
|
||||||
|
/// Like `Shl`, but is UB if the RHS >= LHS::BITS
|
||||||
|
ShlUnchecked,
|
||||||
/// The `>>` operator (shift right)
|
/// The `>>` operator (shift right)
|
||||||
///
|
///
|
||||||
/// The offset is truncated to the size of the first operand before shifting.
|
/// The offset is truncated to the size of the first operand before shifting.
|
||||||
|
///
|
||||||
|
/// This is an arithmetic shift if the LHS is signed
|
||||||
|
/// and a logical shift if the LHS is unsigned.
|
||||||
Shr,
|
Shr,
|
||||||
|
/// Like `Shl`, but is UB if the RHS >= LHS::BITS
|
||||||
|
ShrUnchecked,
|
||||||
/// The `==` operator (equality)
|
/// The `==` operator (equality)
|
||||||
Eq,
|
Eq,
|
||||||
/// The `<` operator (less than)
|
/// The `<` operator (less than)
|
||||||
|
|
|
@ -235,8 +235,11 @@ impl<'tcx> BinOp {
|
||||||
// FIXME: handle SIMD correctly
|
// FIXME: handle SIMD correctly
|
||||||
match self {
|
match self {
|
||||||
&BinOp::Add
|
&BinOp::Add
|
||||||
|
| &BinOp::AddUnchecked
|
||||||
| &BinOp::Sub
|
| &BinOp::Sub
|
||||||
|
| &BinOp::SubUnchecked
|
||||||
| &BinOp::Mul
|
| &BinOp::Mul
|
||||||
|
| &BinOp::MulUnchecked
|
||||||
| &BinOp::Div
|
| &BinOp::Div
|
||||||
| &BinOp::Rem
|
| &BinOp::Rem
|
||||||
| &BinOp::BitXor
|
| &BinOp::BitXor
|
||||||
|
@ -246,7 +249,11 @@ impl<'tcx> BinOp {
|
||||||
assert_eq!(lhs_ty, rhs_ty);
|
assert_eq!(lhs_ty, rhs_ty);
|
||||||
lhs_ty
|
lhs_ty
|
||||||
}
|
}
|
||||||
&BinOp::Shl | &BinOp::Shr | &BinOp::Offset => {
|
&BinOp::Shl
|
||||||
|
| &BinOp::ShlUnchecked
|
||||||
|
| &BinOp::Shr
|
||||||
|
| &BinOp::ShrUnchecked
|
||||||
|
| &BinOp::Offset => {
|
||||||
lhs_ty // lhs_ty can be != rhs_ty
|
lhs_ty // lhs_ty can be != rhs_ty
|
||||||
}
|
}
|
||||||
&BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
|
&BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
|
||||||
|
@ -293,7 +300,14 @@ impl BinOp {
|
||||||
BinOp::Gt => hir::BinOpKind::Gt,
|
BinOp::Gt => hir::BinOpKind::Gt,
|
||||||
BinOp::Le => hir::BinOpKind::Le,
|
BinOp::Le => hir::BinOpKind::Le,
|
||||||
BinOp::Ge => hir::BinOpKind::Ge,
|
BinOp::Ge => hir::BinOpKind::Ge,
|
||||||
BinOp::Offset => unreachable!(),
|
BinOp::AddUnchecked
|
||||||
|
| BinOp::SubUnchecked
|
||||||
|
| BinOp::MulUnchecked
|
||||||
|
| BinOp::ShlUnchecked
|
||||||
|
| BinOp::ShrUnchecked
|
||||||
|
| BinOp::Offset => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,13 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
sym::wrapping_add
|
sym::wrapping_add
|
||||||
| sym::wrapping_sub
|
| sym::wrapping_sub
|
||||||
| sym::wrapping_mul
|
| sym::wrapping_mul
|
||||||
|
| sym::unchecked_add
|
||||||
|
| sym::unchecked_sub
|
||||||
|
| sym::unchecked_mul
|
||||||
| sym::unchecked_div
|
| sym::unchecked_div
|
||||||
| sym::unchecked_rem => {
|
| sym::unchecked_rem
|
||||||
|
| sym::unchecked_shl
|
||||||
|
| sym::unchecked_shr => {
|
||||||
let target = target.unwrap();
|
let target = target.unwrap();
|
||||||
let lhs;
|
let lhs;
|
||||||
let rhs;
|
let rhs;
|
||||||
|
@ -99,8 +104,13 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
sym::wrapping_add => BinOp::Add,
|
sym::wrapping_add => BinOp::Add,
|
||||||
sym::wrapping_sub => BinOp::Sub,
|
sym::wrapping_sub => BinOp::Sub,
|
||||||
sym::wrapping_mul => BinOp::Mul,
|
sym::wrapping_mul => BinOp::Mul,
|
||||||
|
sym::unchecked_add => BinOp::AddUnchecked,
|
||||||
|
sym::unchecked_sub => BinOp::SubUnchecked,
|
||||||
|
sym::unchecked_mul => BinOp::MulUnchecked,
|
||||||
sym::unchecked_div => BinOp::Div,
|
sym::unchecked_div => BinOp::Div,
|
||||||
sym::unchecked_rem => BinOp::Rem,
|
sym::unchecked_rem => BinOp::Rem,
|
||||||
|
sym::unchecked_shl => BinOp::ShlUnchecked,
|
||||||
|
sym::unchecked_shr => BinOp::ShrUnchecked,
|
||||||
_ => bug!("unexpected intrinsic"),
|
_ => bug!("unexpected intrinsic"),
|
||||||
};
|
};
|
||||||
block.statements.push(Statement {
|
block.statements.push(Statement {
|
||||||
|
|
|
@ -250,15 +250,20 @@ impl Stable for mir::BinOp {
|
||||||
use mir::BinOp;
|
use mir::BinOp;
|
||||||
match self {
|
match self {
|
||||||
BinOp::Add => stable_mir::mir::BinOp::Add,
|
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||||
|
BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked,
|
||||||
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
||||||
|
BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked,
|
||||||
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
||||||
|
BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked,
|
||||||
BinOp::Div => stable_mir::mir::BinOp::Div,
|
BinOp::Div => stable_mir::mir::BinOp::Div,
|
||||||
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
||||||
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
||||||
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
|
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
|
||||||
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
|
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
|
||||||
BinOp::Shl => stable_mir::mir::BinOp::Shl,
|
BinOp::Shl => stable_mir::mir::BinOp::Shl,
|
||||||
|
BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked,
|
||||||
BinOp::Shr => stable_mir::mir::BinOp::Shr,
|
BinOp::Shr => stable_mir::mir::BinOp::Shr,
|
||||||
|
BinOp::ShrUnchecked => stable_mir::mir::BinOp::ShrUnchecked,
|
||||||
BinOp::Eq => stable_mir::mir::BinOp::Eq,
|
BinOp::Eq => stable_mir::mir::BinOp::Eq,
|
||||||
BinOp::Lt => stable_mir::mir::BinOp::Lt,
|
BinOp::Lt => stable_mir::mir::BinOp::Lt,
|
||||||
BinOp::Le => stable_mir::mir::BinOp::Le,
|
BinOp::Le => stable_mir::mir::BinOp::Le,
|
||||||
|
|
|
@ -88,15 +88,20 @@ pub enum AssertMessage {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
Add,
|
Add,
|
||||||
|
AddUnchecked,
|
||||||
Sub,
|
Sub,
|
||||||
|
SubUnchecked,
|
||||||
Mul,
|
Mul,
|
||||||
|
MulUnchecked,
|
||||||
Div,
|
Div,
|
||||||
Rem,
|
Rem,
|
||||||
BitXor,
|
BitXor,
|
||||||
BitAnd,
|
BitAnd,
|
||||||
BitOr,
|
BitOr,
|
||||||
Shl,
|
Shl,
|
||||||
|
ShlUnchecked,
|
||||||
Shr,
|
Shr,
|
||||||
|
ShrUnchecked,
|
||||||
Eq,
|
Eq,
|
||||||
Lt,
|
Lt,
|
||||||
Le,
|
Le,
|
||||||
|
|
|
@ -78,8 +78,9 @@ pub(crate) fn destructure_const<'tcx>(
|
||||||
fn check_binop(op: mir::BinOp) -> bool {
|
fn check_binop(op: mir::BinOp) -> bool {
|
||||||
use mir::BinOp::*;
|
use mir::BinOp::*;
|
||||||
match op {
|
match op {
|
||||||
Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Shl | Shr | Eq | Lt | Le | Ne
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||||
| Ge | Gt => true,
|
| BitAnd | BitOr | Shl | ShlUnchecked | Shr | ShrUnchecked | Eq | Lt | Le | Ne | Ge
|
||||||
|
| Gt => true,
|
||||||
Offset => false,
|
Offset => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
|
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = _4 as u64 (IntToInt);
|
+ _5 = _4 as u64 (IntToInt);
|
||||||
+ _0 = unchecked_shl::<u64>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShlUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> bb1;
|
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> bb1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = _4 as u64 (IntToInt);
|
+ _5 = _4 as u64 (IntToInt);
|
||||||
+ _0 = unchecked_shl::<u64>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShlUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -15,10 +15,7 @@ fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = _2 as u64 (IntToInt);
|
_3 = _2 as u64 (IntToInt);
|
||||||
_0 = unchecked_shl::<u64>(_1, move _3) -> [return: bb1, unwind unreachable];
|
_0 = ShlUnchecked(_1, move _3);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,7 @@ fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = _2 as u64 (IntToInt);
|
_3 = _2 as u64 (IntToInt);
|
||||||
_0 = unchecked_shl::<u64>(_1, move _3) -> [return: bb1, unwind unreachable];
|
_0 = ShlUnchecked(_1, move _3);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
|
- _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ StorageLive(_6);
|
+ StorageLive(_6);
|
||||||
+ StorageLive(_7);
|
+ StorageLive(_7);
|
||||||
|
@ -32,10 +35,7 @@
|
||||||
+ assume(move _6);
|
+ assume(move _6);
|
||||||
+ StorageDead(_6);
|
+ StorageDead(_6);
|
||||||
+ _5 = _4 as u16 (IntToInt);
|
+ _5 = _4 as u16 (IntToInt);
|
||||||
+ _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShlUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1;
|
- _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ StorageLive(_6);
|
+ StorageLive(_6);
|
||||||
+ StorageLive(_7);
|
+ StorageLive(_7);
|
||||||
|
@ -32,10 +35,7 @@
|
||||||
+ assume(move _6);
|
+ assume(move _6);
|
||||||
+ StorageDead(_6);
|
+ StorageDead(_6);
|
||||||
+ _5 = _4 as u16 (IntToInt);
|
+ _5 = _4 as u16 (IntToInt);
|
||||||
+ _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShlUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -24,10 +24,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
|
||||||
assume(move _4);
|
assume(move _4);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_5 = _2 as u16 (IntToInt);
|
_5 = _2 as u16 (IntToInt);
|
||||||
_0 = unchecked_shl::<u16>(_1, move _5) -> [return: bb1, unwind unreachable];
|
_0 = ShlUnchecked(_1, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
|
||||||
assume(move _4);
|
assume(move _4);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_5 = _2 as u16 (IntToInt);
|
_5 = _2 as u16 (IntToInt);
|
||||||
_0 = unchecked_shl::<u16>(_1, move _5) -> [return: bb1, unwind unreachable];
|
_0 = ShlUnchecked(_1, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
|
- _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = _4 as i64 (IntToInt);
|
+ _5 = _4 as i64 (IntToInt);
|
||||||
+ _0 = unchecked_shr::<i64>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShrUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> bb1;
|
- _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> bb1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = _4 as i64 (IntToInt);
|
+ _5 = _4 as i64 (IntToInt);
|
||||||
+ _0 = unchecked_shr::<i64>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShrUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -15,10 +15,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = _2 as i64 (IntToInt);
|
_3 = _2 as i64 (IntToInt);
|
||||||
_0 = unchecked_shr::<i64>(_1, move _3) -> [return: bb1, unwind unreachable];
|
_0 = ShrUnchecked(_1, move _3);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,7 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = _2 as i64 (IntToInt);
|
_3 = _2 as i64 (IntToInt);
|
||||||
_0 = unchecked_shr::<i64>(_1, move _3) -> [return: bb1, unwind unreachable];
|
_0 = ShrUnchecked(_1, move _3);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
|
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ StorageLive(_6);
|
+ StorageLive(_6);
|
||||||
+ StorageLive(_7);
|
+ StorageLive(_7);
|
||||||
|
@ -32,10 +35,7 @@
|
||||||
+ assume(move _6);
|
+ assume(move _6);
|
||||||
+ StorageDead(_6);
|
+ StorageDead(_6);
|
||||||
+ _5 = _4 as i16 (IntToInt);
|
+ _5 = _4 as i16 (IntToInt);
|
||||||
+ _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShrUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
_4 = _2;
|
_4 = _2;
|
||||||
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1;
|
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- bb1: {
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ StorageLive(_6);
|
+ StorageLive(_6);
|
||||||
+ StorageLive(_7);
|
+ StorageLive(_7);
|
||||||
|
@ -32,10 +35,7 @@
|
||||||
+ assume(move _6);
|
+ assume(move _6);
|
||||||
+ StorageDead(_6);
|
+ StorageDead(_6);
|
||||||
+ _5 = _4 as i16 (IntToInt);
|
+ _5 = _4 as i16 (IntToInt);
|
||||||
+ _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable];
|
+ _0 = ShrUnchecked(_3, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
+ StorageDead(_5);
|
+ StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
|
|
|
@ -24,10 +24,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
|
||||||
assume(move _4);
|
assume(move _4);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_5 = _2 as i16 (IntToInt);
|
_5 = _2 as i16 (IntToInt);
|
||||||
_0 = unchecked_shr::<i16>(_1, move _5) -> [return: bb1, unwind unreachable];
|
_0 = ShrUnchecked(_1, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
|
||||||
assume(move _4);
|
assume(move _4);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_5 = _2 as i16 (IntToInt);
|
_5 = _2 as i16 (IntToInt);
|
||||||
_0 = unchecked_shr::<i16>(_1, move _5) -> [return: bb1, unwind unreachable];
|
_0 = ShrUnchecked(_1, move _5);
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,13 @@ pub fn wrapping(a: i32, b: i32) {
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.unchecked.LowerIntrinsics.diff
|
// EMIT_MIR lower_intrinsics.unchecked.LowerIntrinsics.diff
|
||||||
pub unsafe fn unchecked(a: i32, b: i32) {
|
pub unsafe fn unchecked(a: i32, b: i32) {
|
||||||
|
let _a = core::intrinsics::unchecked_add(a, b);
|
||||||
|
let _b = core::intrinsics::unchecked_sub(a, b);
|
||||||
|
let _c = core::intrinsics::unchecked_mul(a, b);
|
||||||
let _x = core::intrinsics::unchecked_div(a, b);
|
let _x = core::intrinsics::unchecked_div(a, b);
|
||||||
let _y = core::intrinsics::unchecked_rem(a, b);
|
let _y = core::intrinsics::unchecked_rem(a, b);
|
||||||
|
let _i = core::intrinsics::unchecked_shl(a, b);
|
||||||
|
let _j = core::intrinsics::unchecked_shr(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.size_of.LowerIntrinsics.diff
|
// EMIT_MIR lower_intrinsics.size_of.LowerIntrinsics.diff
|
||||||
|
|
|
@ -10,11 +10,41 @@
|
||||||
let mut _5: i32;
|
let mut _5: i32;
|
||||||
let mut _7: i32;
|
let mut _7: i32;
|
||||||
let mut _8: i32;
|
let mut _8: i32;
|
||||||
|
let mut _10: i32;
|
||||||
|
let mut _11: i32;
|
||||||
|
let mut _13: i32;
|
||||||
|
let mut _14: i32;
|
||||||
|
let mut _16: i32;
|
||||||
|
let mut _17: i32;
|
||||||
|
let mut _19: i32;
|
||||||
|
let mut _20: i32;
|
||||||
|
let mut _22: i32;
|
||||||
|
let mut _23: i32;
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug _x => _3;
|
debug _a => _3;
|
||||||
let _6: i32;
|
let _6: i32;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug _y => _6;
|
debug _b => _6;
|
||||||
|
let _9: i32;
|
||||||
|
scope 3 {
|
||||||
|
debug _c => _9;
|
||||||
|
let _12: i32;
|
||||||
|
scope 4 {
|
||||||
|
debug _x => _12;
|
||||||
|
let _15: i32;
|
||||||
|
scope 5 {
|
||||||
|
debug _y => _15;
|
||||||
|
let _18: i32;
|
||||||
|
scope 6 {
|
||||||
|
debug _i => _18;
|
||||||
|
let _21: i32;
|
||||||
|
scope 7 {
|
||||||
|
debug _j => _21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +54,8 @@
|
||||||
_4 = _1;
|
_4 = _1;
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = _2;
|
_5 = _2;
|
||||||
- _3 = unchecked_div::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
- _3 = unchecked_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
||||||
+ _3 = Div(move _4, move _5);
|
+ _3 = AddUnchecked(move _4, move _5);
|
||||||
+ goto -> bb1;
|
+ goto -> bb1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +67,85 @@
|
||||||
_7 = _1;
|
_7 = _1;
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = _2;
|
_8 = _2;
|
||||||
- _6 = unchecked_rem::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
- _6 = unchecked_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
||||||
+ _6 = Rem(move _7, move _8);
|
+ _6 = SubUnchecked(move _7, move _8);
|
||||||
+ goto -> bb2;
|
+ goto -> bb2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_8);
|
StorageDead(_8);
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
|
StorageLive(_9);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = _1;
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = _2;
|
||||||
|
- _9 = unchecked_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
|
||||||
|
+ _9 = MulUnchecked(move _10, move _11);
|
||||||
|
+ goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_11);
|
||||||
|
StorageDead(_10);
|
||||||
|
StorageLive(_12);
|
||||||
|
StorageLive(_13);
|
||||||
|
_13 = _1;
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = _2;
|
||||||
|
- _12 = unchecked_div::<i32>(move _13, move _14) -> [return: bb4, unwind unreachable];
|
||||||
|
+ _12 = Div(move _13, move _14);
|
||||||
|
+ goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_14);
|
||||||
|
StorageDead(_13);
|
||||||
|
StorageLive(_15);
|
||||||
|
StorageLive(_16);
|
||||||
|
_16 = _1;
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _2;
|
||||||
|
- _15 = unchecked_rem::<i32>(move _16, move _17) -> [return: bb5, unwind unreachable];
|
||||||
|
+ _15 = Rem(move _16, move _17);
|
||||||
|
+ goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_17);
|
||||||
|
StorageDead(_16);
|
||||||
|
StorageLive(_18);
|
||||||
|
StorageLive(_19);
|
||||||
|
_19 = _1;
|
||||||
|
StorageLive(_20);
|
||||||
|
_20 = _2;
|
||||||
|
- _18 = unchecked_shl::<i32>(move _19, move _20) -> [return: bb6, unwind unreachable];
|
||||||
|
+ _18 = ShlUnchecked(move _19, move _20);
|
||||||
|
+ goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_20);
|
||||||
|
StorageDead(_19);
|
||||||
|
StorageLive(_21);
|
||||||
|
StorageLive(_22);
|
||||||
|
_22 = _1;
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = _2;
|
||||||
|
- _21 = unchecked_shr::<i32>(move _22, move _23) -> [return: bb7, unwind unreachable];
|
||||||
|
+ _21 = ShrUnchecked(move _22, move _23);
|
||||||
|
+ goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
|
StorageDead(_21);
|
||||||
|
StorageDead(_18);
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageDead(_12);
|
||||||
|
StorageDead(_9);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -10,11 +10,41 @@
|
||||||
let mut _5: i32;
|
let mut _5: i32;
|
||||||
let mut _7: i32;
|
let mut _7: i32;
|
||||||
let mut _8: i32;
|
let mut _8: i32;
|
||||||
|
let mut _10: i32;
|
||||||
|
let mut _11: i32;
|
||||||
|
let mut _13: i32;
|
||||||
|
let mut _14: i32;
|
||||||
|
let mut _16: i32;
|
||||||
|
let mut _17: i32;
|
||||||
|
let mut _19: i32;
|
||||||
|
let mut _20: i32;
|
||||||
|
let mut _22: i32;
|
||||||
|
let mut _23: i32;
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug _x => _3;
|
debug _a => _3;
|
||||||
let _6: i32;
|
let _6: i32;
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug _y => _6;
|
debug _b => _6;
|
||||||
|
let _9: i32;
|
||||||
|
scope 3 {
|
||||||
|
debug _c => _9;
|
||||||
|
let _12: i32;
|
||||||
|
scope 4 {
|
||||||
|
debug _x => _12;
|
||||||
|
let _15: i32;
|
||||||
|
scope 5 {
|
||||||
|
debug _y => _15;
|
||||||
|
let _18: i32;
|
||||||
|
scope 6 {
|
||||||
|
debug _i => _18;
|
||||||
|
let _21: i32;
|
||||||
|
scope 7 {
|
||||||
|
debug _j => _21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +54,8 @@
|
||||||
_4 = _1;
|
_4 = _1;
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = _2;
|
_5 = _2;
|
||||||
- _3 = unchecked_div::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
- _3 = unchecked_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable];
|
||||||
+ _3 = Div(move _4, move _5);
|
+ _3 = AddUnchecked(move _4, move _5);
|
||||||
+ goto -> bb1;
|
+ goto -> bb1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +67,85 @@
|
||||||
_7 = _1;
|
_7 = _1;
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
_8 = _2;
|
_8 = _2;
|
||||||
- _6 = unchecked_rem::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
- _6 = unchecked_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable];
|
||||||
+ _6 = Rem(move _7, move _8);
|
+ _6 = SubUnchecked(move _7, move _8);
|
||||||
+ goto -> bb2;
|
+ goto -> bb2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_8);
|
StorageDead(_8);
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
|
StorageLive(_9);
|
||||||
|
StorageLive(_10);
|
||||||
|
_10 = _1;
|
||||||
|
StorageLive(_11);
|
||||||
|
_11 = _2;
|
||||||
|
- _9 = unchecked_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable];
|
||||||
|
+ _9 = MulUnchecked(move _10, move _11);
|
||||||
|
+ goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_11);
|
||||||
|
StorageDead(_10);
|
||||||
|
StorageLive(_12);
|
||||||
|
StorageLive(_13);
|
||||||
|
_13 = _1;
|
||||||
|
StorageLive(_14);
|
||||||
|
_14 = _2;
|
||||||
|
- _12 = unchecked_div::<i32>(move _13, move _14) -> [return: bb4, unwind unreachable];
|
||||||
|
+ _12 = Div(move _13, move _14);
|
||||||
|
+ goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_14);
|
||||||
|
StorageDead(_13);
|
||||||
|
StorageLive(_15);
|
||||||
|
StorageLive(_16);
|
||||||
|
_16 = _1;
|
||||||
|
StorageLive(_17);
|
||||||
|
_17 = _2;
|
||||||
|
- _15 = unchecked_rem::<i32>(move _16, move _17) -> [return: bb5, unwind unreachable];
|
||||||
|
+ _15 = Rem(move _16, move _17);
|
||||||
|
+ goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_17);
|
||||||
|
StorageDead(_16);
|
||||||
|
StorageLive(_18);
|
||||||
|
StorageLive(_19);
|
||||||
|
_19 = _1;
|
||||||
|
StorageLive(_20);
|
||||||
|
_20 = _2;
|
||||||
|
- _18 = unchecked_shl::<i32>(move _19, move _20) -> [return: bb6, unwind unreachable];
|
||||||
|
+ _18 = ShlUnchecked(move _19, move _20);
|
||||||
|
+ goto -> bb6;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_20);
|
||||||
|
StorageDead(_19);
|
||||||
|
StorageLive(_21);
|
||||||
|
StorageLive(_22);
|
||||||
|
_22 = _1;
|
||||||
|
StorageLive(_23);
|
||||||
|
_23 = _2;
|
||||||
|
- _21 = unchecked_shr::<i32>(move _22, move _23) -> [return: bb7, unwind unreachable];
|
||||||
|
+ _21 = ShrUnchecked(move _22, move _23);
|
||||||
|
+ goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_23);
|
||||||
|
StorageDead(_22);
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
|
StorageDead(_21);
|
||||||
|
StorageDead(_18);
|
||||||
|
StorageDead(_15);
|
||||||
|
StorageDead(_12);
|
||||||
|
StorageDead(_9);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,10 +7,9 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
|
||||||
scope 1 (inlined core::num::<impl u32>::checked_shl) {
|
scope 1 (inlined core::num::<impl u32>::checked_shl) {
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
debug rhs => _2;
|
debug rhs => _2;
|
||||||
let mut _7: u32;
|
let mut _7: bool;
|
||||||
let mut _8: bool;
|
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug a => _7;
|
debug a => _5;
|
||||||
debug b => _6;
|
debug b => _6;
|
||||||
}
|
}
|
||||||
scope 3 (inlined core::num::<impl u32>::overflowing_shl) {
|
scope 3 (inlined core::num::<impl u32>::overflowing_shl) {
|
||||||
|
@ -36,44 +35,38 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_6);
|
|
||||||
StorageLive(_7);
|
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
|
StorageLive(_6);
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = const 31_u32;
|
_3 = const 31_u32;
|
||||||
_4 = BitAnd(_2, move _3);
|
_4 = BitAnd(_2, move _3);
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
_5 = unchecked_shl::<u32>(_1, _4) -> [return: bb1, unwind unreachable];
|
_5 = ShlUnchecked(_1, _4);
|
||||||
|
StorageDead(_4);
|
||||||
|
_6 = Ge(_2, const _);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = unlikely(_6) -> [return: bb1, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_4);
|
switchInt(move _7) -> [0: bb2, otherwise: bb3];
|
||||||
_6 = Ge(_2, const _);
|
|
||||||
_7 = move _5;
|
|
||||||
StorageDead(_5);
|
|
||||||
StorageLive(_8);
|
|
||||||
_8 = unlikely(_6) -> [return: bb2, unwind unreachable];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
switchInt(move _8) -> [0: bb3, otherwise: bb4];
|
_0 = Option::<u32>::Some(_5);
|
||||||
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
_0 = Option::<u32>::Some(_7);
|
_0 = Option::<u32>::None;
|
||||||
goto -> bb5;
|
goto -> bb4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
_0 = Option::<u32>::None;
|
|
||||||
goto -> bb5;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb5: {
|
|
||||||
StorageDead(_8);
|
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,17 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
debug index => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
debug index => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
||||||
let mut _5: *mut [u32];
|
let mut _5: *mut [u32];
|
||||||
let mut _14: *mut [u32];
|
let mut _13: *mut [u32];
|
||||||
scope 2 {
|
scope 2 {
|
||||||
scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
||||||
debug self => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
debug self => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
||||||
debug slice => _5;
|
debug slice => _5;
|
||||||
let mut _7: *mut u32;
|
let mut _7: *mut u32;
|
||||||
let mut _8: *mut u32;
|
let mut _8: *mut u32;
|
||||||
let mut _9: usize;
|
let _15: usize;
|
||||||
let _16: usize;
|
let _16: usize;
|
||||||
let _17: usize;
|
|
||||||
scope 4 {
|
scope 4 {
|
||||||
debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, };
|
debug this => std::ops::Range<usize>{ .0 => _15, .1 => _16, };
|
||||||
scope 5 {
|
scope 5 {
|
||||||
let _6: usize;
|
let _6: usize;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
|
@ -37,30 +36,30 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
}
|
}
|
||||||
scope 14 (inlined slice_from_raw_parts_mut::<u32>) {
|
scope 14 (inlined slice_from_raw_parts_mut::<u32>) {
|
||||||
debug data => _8;
|
debug data => _8;
|
||||||
debug len => _9;
|
debug len => _6;
|
||||||
let mut _10: *mut ();
|
let mut _9: *mut ();
|
||||||
scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
|
scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
|
||||||
debug self => _8;
|
debug self => _8;
|
||||||
}
|
}
|
||||||
scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
|
scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
|
||||||
debug data_address => _10;
|
debug data_address => _9;
|
||||||
debug metadata => _9;
|
debug metadata => _6;
|
||||||
let mut _11: *const ();
|
let mut _10: *const ();
|
||||||
let mut _12: std::ptr::metadata::PtrComponents<[u32]>;
|
let mut _11: std::ptr::metadata::PtrComponents<[u32]>;
|
||||||
let mut _13: std::ptr::metadata::PtrRepr<[u32]>;
|
let mut _12: std::ptr::metadata::PtrRepr<[u32]>;
|
||||||
scope 17 {
|
scope 17 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
|
scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
|
||||||
debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, };
|
debug this => std::ops::Range<usize>{ .0 => _15, .1 => _16, };
|
||||||
debug slice => _5;
|
debug slice => _5;
|
||||||
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
|
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
|
||||||
debug self => _5;
|
debug self => _5;
|
||||||
let mut _15: *const [u32];
|
let mut _14: *const [u32];
|
||||||
scope 9 (inlined std::ptr::metadata::<[u32]>) {
|
scope 9 (inlined std::ptr::metadata::<[u32]>) {
|
||||||
debug ptr => _15;
|
debug ptr => _14;
|
||||||
scope 10 {
|
scope 10 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,46 +74,40 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
bb0: {
|
bb0: {
|
||||||
_3 = move (_2.0: usize);
|
_3 = move (_2.0: usize);
|
||||||
_4 = move (_2.1: usize);
|
_4 = move (_2.1: usize);
|
||||||
StorageLive(_14);
|
StorageLive(_13);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = &raw mut (*_1);
|
_5 = &raw mut (*_1);
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_14);
|
||||||
StorageLive(_15);
|
StorageLive(_15);
|
||||||
StorageLive(_16);
|
StorageLive(_16);
|
||||||
StorageLive(_17);
|
_6 = SubUnchecked(_4, _3);
|
||||||
StorageLive(_6);
|
|
||||||
_6 = unchecked_sub::<usize>(_4, _3) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
StorageLive(_7);
|
||||||
_7 = _5 as *mut u32 (PtrToPtr);
|
_7 = _5 as *mut u32 (PtrToPtr);
|
||||||
_8 = Offset(_7, _3);
|
_8 = Offset(_7, _3);
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = _6;
|
_9 = _8 as *mut () (PtrToPtr);
|
||||||
StorageLive(_10);
|
|
||||||
_10 = _8 as *mut () (PtrToPtr);
|
|
||||||
StorageLive(_13);
|
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
StorageLive(_11);
|
StorageLive(_11);
|
||||||
_11 = _10 as *const () (Pointer(MutToConstPointer));
|
StorageLive(_10);
|
||||||
_12 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _11, metadata: _9 };
|
_10 = _9 as *const () (Pointer(MutToConstPointer));
|
||||||
StorageDead(_11);
|
_11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 };
|
||||||
_13 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _12 };
|
|
||||||
StorageDead(_12);
|
|
||||||
_14 = (_13.1: *mut [u32]);
|
|
||||||
StorageDead(_13);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
|
_12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = (_12.1: *mut [u32]);
|
||||||
|
StorageDead(_12);
|
||||||
StorageDead(_9);
|
StorageDead(_9);
|
||||||
StorageDead(_8);
|
StorageDead(_8);
|
||||||
StorageDead(_6);
|
|
||||||
StorageDead(_17);
|
|
||||||
StorageDead(_16);
|
StorageDead(_16);
|
||||||
StorageDead(_15);
|
StorageDead(_15);
|
||||||
StorageDead(_5);
|
|
||||||
_0 = &mut (*_14);
|
|
||||||
StorageDead(_14);
|
StorageDead(_14);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
_0 = &mut (*_13);
|
||||||
|
StorageDead(_13);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,17 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
debug self => _1;
|
debug self => _1;
|
||||||
debug index => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
debug index => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
||||||
let mut _5: *mut [u32];
|
let mut _5: *mut [u32];
|
||||||
let mut _14: *mut [u32];
|
let mut _13: *mut [u32];
|
||||||
scope 2 {
|
scope 2 {
|
||||||
scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
||||||
debug self => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
debug self => std::ops::Range<usize>{ .0 => _3, .1 => _4, };
|
||||||
debug slice => _5;
|
debug slice => _5;
|
||||||
let mut _7: *mut u32;
|
let mut _7: *mut u32;
|
||||||
let mut _8: *mut u32;
|
let mut _8: *mut u32;
|
||||||
let mut _9: usize;
|
let _15: usize;
|
||||||
let _16: usize;
|
let _16: usize;
|
||||||
let _17: usize;
|
|
||||||
scope 4 {
|
scope 4 {
|
||||||
debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, };
|
debug this => std::ops::Range<usize>{ .0 => _15, .1 => _16, };
|
||||||
scope 5 {
|
scope 5 {
|
||||||
let _6: usize;
|
let _6: usize;
|
||||||
scope 6 {
|
scope 6 {
|
||||||
|
@ -37,30 +36,30 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
}
|
}
|
||||||
scope 14 (inlined slice_from_raw_parts_mut::<u32>) {
|
scope 14 (inlined slice_from_raw_parts_mut::<u32>) {
|
||||||
debug data => _8;
|
debug data => _8;
|
||||||
debug len => _9;
|
debug len => _6;
|
||||||
let mut _10: *mut ();
|
let mut _9: *mut ();
|
||||||
scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
|
scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
|
||||||
debug self => _8;
|
debug self => _8;
|
||||||
}
|
}
|
||||||
scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
|
scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
|
||||||
debug data_address => _10;
|
debug data_address => _9;
|
||||||
debug metadata => _9;
|
debug metadata => _6;
|
||||||
let mut _11: *const ();
|
let mut _10: *const ();
|
||||||
let mut _12: std::ptr::metadata::PtrComponents<[u32]>;
|
let mut _11: std::ptr::metadata::PtrComponents<[u32]>;
|
||||||
let mut _13: std::ptr::metadata::PtrRepr<[u32]>;
|
let mut _12: std::ptr::metadata::PtrRepr<[u32]>;
|
||||||
scope 17 {
|
scope 17 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
|
scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
|
||||||
debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, };
|
debug this => std::ops::Range<usize>{ .0 => _15, .1 => _16, };
|
||||||
debug slice => _5;
|
debug slice => _5;
|
||||||
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
|
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
|
||||||
debug self => _5;
|
debug self => _5;
|
||||||
let mut _15: *const [u32];
|
let mut _14: *const [u32];
|
||||||
scope 9 (inlined std::ptr::metadata::<[u32]>) {
|
scope 9 (inlined std::ptr::metadata::<[u32]>) {
|
||||||
debug ptr => _15;
|
debug ptr => _14;
|
||||||
scope 10 {
|
scope 10 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,46 +74,40 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
|
||||||
bb0: {
|
bb0: {
|
||||||
_3 = move (_2.0: usize);
|
_3 = move (_2.0: usize);
|
||||||
_4 = move (_2.1: usize);
|
_4 = move (_2.1: usize);
|
||||||
StorageLive(_14);
|
StorageLive(_13);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
_5 = &raw mut (*_1);
|
_5 = &raw mut (*_1);
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_14);
|
||||||
StorageLive(_15);
|
StorageLive(_15);
|
||||||
StorageLive(_16);
|
StorageLive(_16);
|
||||||
StorageLive(_17);
|
_6 = SubUnchecked(_4, _3);
|
||||||
StorageLive(_6);
|
|
||||||
_6 = unchecked_sub::<usize>(_4, _3) -> [return: bb1, unwind unreachable];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageLive(_8);
|
StorageLive(_8);
|
||||||
StorageLive(_7);
|
StorageLive(_7);
|
||||||
_7 = _5 as *mut u32 (PtrToPtr);
|
_7 = _5 as *mut u32 (PtrToPtr);
|
||||||
_8 = Offset(_7, _3);
|
_8 = Offset(_7, _3);
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = _6;
|
_9 = _8 as *mut () (PtrToPtr);
|
||||||
StorageLive(_10);
|
|
||||||
_10 = _8 as *mut () (PtrToPtr);
|
|
||||||
StorageLive(_13);
|
|
||||||
StorageLive(_12);
|
StorageLive(_12);
|
||||||
StorageLive(_11);
|
StorageLive(_11);
|
||||||
_11 = _10 as *const () (Pointer(MutToConstPointer));
|
StorageLive(_10);
|
||||||
_12 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _11, metadata: _9 };
|
_10 = _9 as *const () (Pointer(MutToConstPointer));
|
||||||
StorageDead(_11);
|
_11 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _10, metadata: _6 };
|
||||||
_13 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _12 };
|
|
||||||
StorageDead(_12);
|
|
||||||
_14 = (_13.1: *mut [u32]);
|
|
||||||
StorageDead(_13);
|
|
||||||
StorageDead(_10);
|
StorageDead(_10);
|
||||||
|
_12 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };
|
||||||
|
StorageDead(_11);
|
||||||
|
_13 = (_12.1: *mut [u32]);
|
||||||
|
StorageDead(_12);
|
||||||
StorageDead(_9);
|
StorageDead(_9);
|
||||||
StorageDead(_8);
|
StorageDead(_8);
|
||||||
StorageDead(_6);
|
|
||||||
StorageDead(_17);
|
|
||||||
StorageDead(_16);
|
StorageDead(_16);
|
||||||
StorageDead(_15);
|
StorageDead(_15);
|
||||||
StorageDead(_5);
|
|
||||||
_0 = &mut (*_14);
|
|
||||||
StorageDead(_14);
|
StorageDead(_14);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageDead(_5);
|
||||||
|
_0 = &mut (*_13);
|
||||||
|
StorageDead(_13);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue