diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5d2dda8b0e7cc..f196bd04d0e8f 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1557,9 +1557,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { ); } - &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => { + &Rvalue::Discriminant(place) => { let af = match *rvalue { - Rvalue::Len(..) => Some(ArtificialField::ArrayLength), Rvalue::Discriminant(..) => None, _ => unreachable!(), }; diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 99dd0b2dd4664..c2ad6fcb4b799 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -306,16 +306,11 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { self.consume_operand(location, op); } - &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => { - let af = match rvalue { - Rvalue::Len(..) => Some(ArtificialField::ArrayLength), - Rvalue::Discriminant(..) => None, - _ => unreachable!(), - }; + &Rvalue::Discriminant(place) => { self.access_place( location, place, - (Shallow(af), Read(ReadKind::Copy)), + (Shallow(None), Read(ReadKind::Copy)), LocalMutationIsAllowed::No, ); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8c5447fe1e9e7..dcedf0b153221 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1631,7 +1631,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(..) | Rvalue::RawPtr(..) | Rvalue::ThreadLocalRef(..) - | Rvalue::Len(..) | Rvalue::Discriminant(..) | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {} } @@ -2201,7 +2200,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::Repeat(..) | Rvalue::Ref(..) | Rvalue::RawPtr(..) - | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) | Rvalue::BinaryOp(..) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 3a28dd7e73cb3..41e11e1de6163 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -834,12 +834,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: fx.bcx.ins().nop(); } } - Rvalue::Len(place) => { - let place = codegen_place(fx, place); - let usize_layout = fx.layout_of(fx.tcx.types.usize); - let len = codegen_array_len(fx, place); - lval.write_cvalue(fx, CValue::by_val(len, usize_layout)); - } Rvalue::ShallowInitBox(ref operand, content_ty) => { let content_ty = fx.monomorphize(content_ty); let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty)); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f8755874014d3..c30e6a505058d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -7,9 +7,9 @@ use rustc_middle::{bug, mir, span_bug}; use rustc_session::config::OptLevel; use tracing::{debug, instrument}; +use super::FunctionCx; use super::operand::{OperandRef, OperandRefBuilder, OperandValue}; use super::place::{PlaceRef, PlaceValue, codegen_tag_value}; -use super::{FunctionCx, LocalRef}; use crate::common::{IntPredicate, TypeKind}; use crate::traits::*; use crate::{MemFlags, base}; @@ -510,14 +510,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_place_to_pointer(bx, place, mk_ptr) } - mir::Rvalue::Len(place) => { - let size = self.evaluate_array_len(bx, place); - OperandRef { - val: OperandValue::Immediate(size), - layout: bx.cx().layout_of(bx.tcx().types.usize), - } - } - mir::Rvalue::BinaryOp(op_with_overflow, box (ref lhs, ref rhs)) if let Some(op) = op_with_overflow.overflowing_to_wrapping() => { @@ -749,21 +741,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value { - // ZST are passed as operands and require special handling - // because codegen_place() panics if Local is operand. - if let Some(index) = place.as_local() - && let LocalRef::Operand(op) = self.locals[index] - && let ty::Array(_, n) = op.layout.ty.kind() - { - let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen"); - return bx.cx().const_usize(n); - } - // use common size calculation for non zero-sized types - let cg_value = self.codegen_place(bx, place.as_ref()); - cg_value.len(bx.cx()) - } - /// Codegen an `Rvalue::RawPtr` or `Rvalue::Ref` fn codegen_place_to_pointer( &mut self, diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index ca707b50d50d9..3397bd9a68e4c 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -573,8 +573,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Use(_) | Rvalue::CopyForDeref(..) | Rvalue::Repeat(..) - | Rvalue::Discriminant(..) - | Rvalue::Len(_) => {} + | Rvalue::Discriminant(..) => {} Rvalue::Aggregate(kind, ..) => { if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref() diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index faf41f1658b70..34d1fdd8c8694 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -232,9 +232,7 @@ where Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) } - Rvalue::Discriminant(place) | Rvalue::Len(place) => { - in_place::(cx, in_local, place.as_ref()) - } + Rvalue::Discriminant(place) => in_place::(cx, in_local, place.as_ref()), Rvalue::CopyForDeref(place) => in_place::(cx, in_local, place.as_ref()), diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index d98e5027e4d6b..664dda8701a63 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -197,7 +197,6 @@ where | mir::Rvalue::CopyForDeref(..) | mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::Repeat(..) - | mir::Rvalue::Len(..) | mir::Rvalue::BinaryOp(..) | mir::Rvalue::NullaryOp(..) | mir::Rvalue::UnaryOp(..) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 46950d60f8c78..923e00ad4cf1a 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -17,7 +17,7 @@ use tracing::{info, instrument, trace}; use super::{ FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy, - Projectable, Scalar, interp_ok, throw_ub, throw_unsup_format, + Projectable, interp_ok, throw_ub, throw_unsup_format, }; use crate::interpret::EnteredTraceSpan; use crate::{enter_trace_span, util}; @@ -225,12 +225,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_repeat(operand, &dest)?; } - Len(place) => { - let src = self.eval_place(place)?; - let len = src.len(self)?; - self.write_scalar(Scalar::from_target_usize(len, self), &dest)?; - } - Ref(_, borrow_kind, place) => { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f9d0a5f0a3b66..96148fd5b9269 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1062,7 +1062,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { pretty_print_const(b, fmt, false)?; write!(fmt, "]") } - Len(ref a) => write!(fmt, "Len({a:?})"), Cast(ref kind, ref place, ref ty) => { with_no_trimmed_paths!(write!(fmt, "{place:?} as {ty} ({kind:?})")) } diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index ec2a8e86077d0..28294b47e90f2 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -697,7 +697,6 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::Ref(_, _, _) | Rvalue::ThreadLocalRef(_) | Rvalue::RawPtr(_, _) - | Rvalue::Len(_) | Rvalue::Cast( CastKind::IntToInt | CastKind::FloatToInt @@ -739,7 +738,6 @@ impl<'tcx> Rvalue<'tcx> { let place_ty = place.ty(local_decls, tcx).ty; Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy()) } - Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { let lhs_ty = lhs.ty(local_decls, tcx); diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index d402ea4b04f9c..e6c8512564edc 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1407,16 +1407,6 @@ pub enum Rvalue<'tcx> { /// model. RawPtr(RawPtrKind, Place<'tcx>), - /// Yields the length of the place, as a `usize`. - /// - /// If the type of the place is an array, this is the array length. For slices (`[T]`, not - /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is - /// ill-formed for places of other types. - /// - /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only - /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing. - Len(Place<'tcx>), - /// Performs essentially all of the casts that can be performed via `as`. /// /// This allows for casts from/to a variety of types. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b498b7b8912cc..07a15b3cd18a7 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -717,14 +717,6 @@ macro_rules! make_mir_visitor { self.visit_place(path, ctx, location); } - Rvalue::Len(path) => { - self.visit_place( - path, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), - location - ); - } - Rvalue::Cast(_cast_kind, operand, ty) => { self.visit_operand(operand, location); self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 41d3aefcbe6b5..54490e0050902 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -229,6 +229,11 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let source = self.parse_operand(args[0])?; Ok(Rvalue::Cast(CastKind::PtrToPtr, source, expr.ty)) }, + @call(mir_cast_unsize, args) => { + let source = self.parse_operand(args[0])?; + let kind = CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, CoercionSource::AsCast); + Ok(Rvalue::Cast(kind, source, expr.ty)) + }, @call(mir_checked, args) => { parse_by_kind!(self, args[0], _, "binary op", ExprKind::Binary { op, lhs, rhs } => { @@ -247,7 +252,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let offset = self.parse_operand(args[1])?; Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset)))) }, - @call(mir_len, args) => Ok(Rvalue::Len(self.parse_place(args[0])?)), @call(mir_ptr_metadata, args) => Ok(Rvalue::UnaryOp(UnOp::PtrMetadata, self.parse_operand(args[0])?)), @call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)), ExprKind::Borrow { borrow_kind, arg } => Ok( diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 7c851ec465bdc..5a6bd2f413c2d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -663,7 +663,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// For arrays it'll be `Operand::Constant` with the actual length; /// For slices it'll be `Operand::Move` of a local using `PtrMetadata`. - fn len_of_slice_or_array( + pub(in crate::builder) fn len_of_slice_or_array( &mut self, block: BasicBlock, place: Place<'tcx>, diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d03794fe2d584..1b6d96e49f0c1 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -309,7 +309,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let actual = self.temp(usize_ty, test.span); // actual = len(place) - self.cfg.push_assign(block, source_info, actual, Rvalue::Len(place)); + let length_op = self.len_of_slice_or_array(block, place, test.span, source_info); + self.cfg.push_assign(block, source_info, actual, Rvalue::Use(length_op)); // expected = let expected = self.push_usize(block, source_info, len); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 9abb83434321d..a4e4e30a8bb6c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -91,7 +91,6 @@ where | Rvalue::Use(..) | Rvalue::ThreadLocalRef(..) | Rvalue::Repeat(..) - | Rvalue::Len(..) | Rvalue::BinaryOp(..) | Rvalue::NullaryOp(..) | Rvalue::UnaryOp(..) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 48718cad597a8..f38bb44582400 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -413,7 +413,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { Rvalue::Ref(..) | Rvalue::RawPtr(..) | Rvalue::Discriminant(..) - | Rvalue::Len(..) | Rvalue::NullaryOp( NullOp::SizeOf | NullOp::AlignOf diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index fe53de31f7583..5c984984d3cc3 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -412,18 +412,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state: &mut State>, ) -> ValueOrPlace> { let val = match rvalue { - Rvalue::Len(place) => { - let place_ty = place.ty(self.local_decls, self.tcx); - if let ty::Array(_, len) = place_ty.ty.kind() { - Const::Ty(self.tcx.types.usize, *len) - .try_eval_scalar(self.tcx, self.typing_env) - .map_or(FlatSet::Top, FlatSet::Elem) - } else if let [ProjectionElem::Deref] = place.projection[..] { - state.get_len(place.local.into(), &self.map) - } else { - FlatSet::Top - } - } Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); @@ -465,15 +453,23 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { let (val, _overflow) = self.binary_op(state, *op, left, right); val } - Rvalue::UnaryOp(op, operand) => match self.eval_operand(operand, state) { - FlatSet::Elem(value) => self - .ecx - .unary_op(*op, &value) - .discard_err() - .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)), - FlatSet::Bottom => FlatSet::Bottom, - FlatSet::Top => FlatSet::Top, - }, + Rvalue::UnaryOp(op, operand) => { + if let UnOp::PtrMetadata = op + && let Some(place) = operand.place() + && let Some(len) = self.map.find_len(place.as_ref()) + { + return ValueOrPlace::Place(len); + } + match self.eval_operand(operand, state) { + FlatSet::Elem(value) => self + .ecx + .unary_op(*op, &value) + .discard_err() + .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)), + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, + } + } Rvalue::NullaryOp(null_op, ty) => { let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bf6aa800d20f4..30e68a3f65058 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -200,8 +200,6 @@ enum Value<'tcx> { Projection(VnIndex, ProjectionElem), /// Discriminant of the given value. Discriminant(VnIndex), - /// Length of an array or slice. - Len(VnIndex), // Operations. NullaryOp(NullOp<'tcx>, Ty<'tcx>), @@ -477,11 +475,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.ecx.discriminant_for_variant(base.layout.ty, variant).discard_err()?; discr_value.into() } - Len(slice) => { - let slice = self.evaluated[slice].as_ref()?; - let len = slice.len(&self.ecx).discard_err()?; - ImmTy::from_uint(len, ty).into() - } NullaryOp(null_op, arg_ty) => { let arg_layout = self.ecx.layout_of(arg_ty).ok()?; if let NullOp::SizeOf | NullOp::AlignOf = null_op @@ -841,7 +834,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } // Operations. - Rvalue::Len(ref mut place) => return self.simplify_len(place, location), Rvalue::Cast(ref mut kind, ref mut value, to) => { return self.simplify_cast(kind, value, to, location); } @@ -1049,7 +1041,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { if op == UnOp::PtrMetadata { let mut was_updated = false; loop { - match self.get(arg_index) { + arg_index = match self.get(arg_index) { // Pointer casts that preserve metadata, such as // `*const [i32]` <-> `*mut [i32]` <-> `*mut [f32]`. // It's critical that this not eliminate cases like @@ -1061,9 +1053,19 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Value::Cast { kind: CastKind::PtrToPtr, value: inner } if self.pointers_have_same_metadata(self.ty(*inner), arg_ty) => { - arg_index = *inner; - was_updated = true; - continue; + *inner + } + + // We have an unsizing cast, which assigns the length to wide pointer metadata. + Value::Cast { + kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _), + value: from, + } if let Some(from) = self.ty(*from).builtin_deref(true) + && let ty::Array(_, len) = from.kind() + && let Some(to) = self.ty(arg_index).builtin_deref(true) + && let ty::Slice(..) = to.kind() => + { + return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); } // `&mut *p`, `&raw *p`, etc don't change metadata. @@ -1072,18 +1074,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { place.as_ref() && let Some(local_index) = self.locals[local] => { - arg_index = local_index; - was_updated = true; - continue; + local_index } - _ => { - if was_updated && let Some(op) = self.try_as_operand(arg_index, location) { - *arg_op = op; - } - break; - } - } + _ => break, + }; + was_updated = true; + } + + if was_updated && let Some(op) = self.try_as_operand(arg_index, location) { + *arg_op = op; } } @@ -1407,39 +1407,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Some(self.insert(to, Value::Cast { kind, value })) } - fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option { - // Trivial case: we are fetching a statically known length. - let place_ty = place.ty(self.local_decls, self.tcx).ty; - if let ty::Array(_, len) = place_ty.kind() { - return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); - } - - let mut inner = self.simplify_place_value(place, location)?; - - // The length information is stored in the wide pointer. - // Reborrowing copies length information from one pointer to the other. - while let Value::Address { place: borrowed, .. } = self.get(inner) - && let [PlaceElem::Deref] = borrowed.projection[..] - && let Some(borrowed) = self.locals[borrowed.local] - { - inner = borrowed; - } - - // We have an unsizing cast, which assigns the length to wide pointer metadata. - if let Value::Cast { kind, value: from } = self.get(inner) - && let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind - && let Some(from) = self.ty(*from).builtin_deref(true) - && let ty::Array(_, len) = from.kind() - && let Some(to) = self.ty(inner).builtin_deref(true) - && let ty::Slice(..) = to.kind() - { - return Some(self.insert_constant(Const::Ty(self.tcx.types.usize, *len))); - } - - // Fallback: a symbolic `Len`. - Some(self.insert(self.tcx.types.usize, Value::Len(inner))) - } - fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>, right_ptr_ty: Ty<'tcx>) -> bool { let left_meta_ty = left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); let right_meta_ty = right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx); diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 481c794190925..aaacc5866a2ae 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -441,7 +441,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | Rvalue::Use(..) | Rvalue::CopyForDeref(..) | Rvalue::Repeat(..) - | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) | Rvalue::Discriminant(..) @@ -604,20 +603,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - Len(place) => { - let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind() - { - n.try_to_target_usize(self.tcx)? - } else { - match self.get_const(place)? { - Value::Immediate(src) => src.len(&self.ecx).discard_err()?, - Value::Aggregate { fields, .. } => fields.len() as u64, - Value::Uninit => return None, - } - }; - ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into() - } - Ref(..) | RawPtr(..) => return None, NullaryOp(ref null_op, ty) => { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 9ea2eb4f25d91..a0b0c8c990f33 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -437,9 +437,7 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(op)? } - Rvalue::Discriminant(place) | Rvalue::Len(place) => { - self.validate_place(place.as_ref())? - } + Rvalue::Discriminant(place) => self.validate_place(place.as_ref())?, Rvalue::ThreadLocalRef(_) => return Err(Unpromotable), diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 99e4782e4700c..c8a9a88dc3fe3 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1064,14 +1064,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } Rvalue::Ref(..) => {} - Rvalue::Len(p) => { - let pty = p.ty(&self.body.local_decls, self.tcx).ty; - check_kinds!( - pty, - "Cannot compute length of non-array type {:?}", - ty::Array(..) | ty::Slice(..) - ); - } Rvalue::BinaryOp(op, vals) => { use BinOp::*; let a = vals.0.ty(&self.body.local_decls, self.tcx); diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index be8ee80bed3c0..b10af6526ead5 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -215,7 +215,6 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { mutability.stable(tables, cx), place.stable(tables, cx), ), - Len(place) => crate::mir::Rvalue::Len(place.stable(tables, cx)), Cast(cast_kind, op, ty) => crate::mir::Rvalue::Cast( cast_kind.stable(tables, cx), op.stable(tables, cx), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cdb0b5b58da6d..16b8b46f97cf3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1413,6 +1413,7 @@ symbols! { mir_call, mir_cast_ptr_to_ptr, mir_cast_transmute, + mir_cast_unsize, mir_checked, mir_copy_for_deref, mir_debuginfo, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 55dcf7cd47e97..a800ef1cb9375 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -233,7 +233,8 @@ //! //! - Operands implicitly convert to `Use` rvalues. //! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue. -//! - [`Discriminant`], [`Len`], and [`CopyForDeref`] have associated functions. +//! - [`CopyForDeref`], [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`] +//! have associated functions. //! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc. //! - The binary operation `Offset` can be created via [`Offset`]. //! - Checked binary operations are represented by wrapping the associated binop in [`Checked`]. @@ -401,7 +402,6 @@ define!("mir_storage_dead", fn StorageDead(local: T)); define!("mir_assume", fn Assume(operand: bool)); define!("mir_deinit", fn Deinit(place: T)); define!("mir_checked", fn Checked(binop: T) -> (T, bool)); -define!("mir_len", fn Len(place: T) -> usize); define!( "mir_ptr_metadata", fn PtrMetadata(place: *const P) ->

::Metadata @@ -491,6 +491,13 @@ define!( /// This allows bypassing normal validation to generate strange casts. fn CastPtrToPtr(operand: T) -> U ); +define!( + "mir_cast_unsize", + /// Emits a `CastKind::PointerCoercion(Unsize)` cast. + /// + /// This allows bypassing normal validation to generate strange casts. + fn CastUnsize(operand: T) -> U +); define!( "mir_make_place", #[doc(hidden)] diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 68f0b5ea25589..40fd2cdeb86fd 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -126,7 +126,7 @@ fn check_rvalue<'tcx>( ) -> McfResult { match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { + Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => { check_place(cx, *place, span, body, msrv) }, Rvalue::CopyForDeref(place) => check_place(cx, *place, span, body, msrv), diff --git a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir index 30d11e31e4d4e..f9f24c8eabe4d 100644 --- a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir +++ b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir @@ -3,12 +3,16 @@ fn arrays() -> usize { let mut _0: usize; let mut _1: [i32; C]; - let mut _2: usize; + let mut _2: *const [i32; C]; + let mut _3: *const [i32]; + let mut _4: usize; bb0: { _1 = [const 5_i32; C]; - _2 = Len(_1); - _0 = copy _2; + _2 = &raw const _1; + _3 = copy _2 as *const [i32] (PointerCoercion(Unsize, AsCast)); + _4 = PtrMetadata(copy _3); + _0 = copy _4; return; } } diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs index 4bd6f93e11340..e9cdded4a0e68 100644 --- a/tests/mir-opt/building/custom/arrays.rs +++ b/tests/mir-opt/building/custom/arrays.rs @@ -10,7 +10,9 @@ fn arrays() -> usize { mir! { { let x = [5_i32; C]; - let c = Len(x); + let y = &raw const x; + let z = CastUnsize::<_, *const [i32]>(y); + let c = PtrMetadata(z); RET = c; Return() } diff --git a/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir new file mode 100644 index 0000000000000..8d16f074b1e34 --- /dev/null +++ b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-abort.mir @@ -0,0 +1,155 @@ +// MIR for `const_array_len` after built + +fn const_array_len(_1: [T; 5]) -> () { + debug x => _1; + let mut _0: (); + let _6: (); + let mut _7: T; + let _8: (); + let mut _9: T; + let _10: (); + let mut _11: [T; 2]; + let _12: (); + let mut _13: T; + scope 1 { + debug a => _2; + debug b => _3; + debug rest => _4; + debug e => _5; + let _2: T; + let _3: T; + let _4: [T; 2]; + let _5: T; + } + + bb0: { + PlaceMention(_1); + falseEdge -> [real: bb2, imaginary: bb1]; + } + + bb1: { + goto -> bb7; + } + + bb2: { + StorageLive(_2); + _2 = move _1[0 of 5]; + StorageLive(_3); + _3 = move _1[1 of 5]; + StorageLive(_4); + _4 = move _1[2..4]; + StorageLive(_5); + _5 = move _1[4 of 5]; + StorageLive(_6); + StorageLive(_7); + _7 = move _2; + _6 = opaque::(move _7) -> [return: bb3, unwind: bb17]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = move _3; + _8 = opaque::(move _9) -> [return: bb4, unwind: bb16]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = move _4; + _10 = opaque::<[T; 2]>(move _11) -> [return: bb5, unwind: bb15]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = move _5; + _12 = opaque::(move _13) -> [return: bb6, unwind: bb14]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + _0 = const (); + drop(_5) -> [return: bb8, unwind: bb19]; + } + + bb7: { + _0 = const (); + goto -> bb12; + } + + bb8: { + StorageDead(_5); + drop(_4) -> [return: bb9, unwind: bb20]; + } + + bb9: { + StorageDead(_4); + drop(_3) -> [return: bb10, unwind: bb21]; + } + + bb10: { + StorageDead(_3); + drop(_2) -> [return: bb11, unwind: bb22]; + } + + bb11: { + StorageDead(_2); + goto -> bb12; + } + + bb12: { + drop(_1) -> [return: bb13, unwind: bb23]; + } + + bb13: { + return; + } + + bb14 (cleanup): { + drop(_13) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + drop(_11) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb16 (cleanup): { + drop(_9) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + drop(_7) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb18 (cleanup): { + drop(_5) -> [return: bb19, unwind terminate(cleanup)]; + } + + bb19 (cleanup): { + drop(_4) -> [return: bb20, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + drop(_3) -> [return: bb21, unwind terminate(cleanup)]; + } + + bb21 (cleanup): { + drop(_2) -> [return: bb22, unwind terminate(cleanup)]; + } + + bb22 (cleanup): { + drop(_1) -> [return: bb23, unwind terminate(cleanup)]; + } + + bb23 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir new file mode 100644 index 0000000000000..8d16f074b1e34 --- /dev/null +++ b/tests/mir-opt/building/match/array_len.const_array_len.built.after.panic-unwind.mir @@ -0,0 +1,155 @@ +// MIR for `const_array_len` after built + +fn const_array_len(_1: [T; 5]) -> () { + debug x => _1; + let mut _0: (); + let _6: (); + let mut _7: T; + let _8: (); + let mut _9: T; + let _10: (); + let mut _11: [T; 2]; + let _12: (); + let mut _13: T; + scope 1 { + debug a => _2; + debug b => _3; + debug rest => _4; + debug e => _5; + let _2: T; + let _3: T; + let _4: [T; 2]; + let _5: T; + } + + bb0: { + PlaceMention(_1); + falseEdge -> [real: bb2, imaginary: bb1]; + } + + bb1: { + goto -> bb7; + } + + bb2: { + StorageLive(_2); + _2 = move _1[0 of 5]; + StorageLive(_3); + _3 = move _1[1 of 5]; + StorageLive(_4); + _4 = move _1[2..4]; + StorageLive(_5); + _5 = move _1[4 of 5]; + StorageLive(_6); + StorageLive(_7); + _7 = move _2; + _6 = opaque::(move _7) -> [return: bb3, unwind: bb17]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = move _3; + _8 = opaque::(move _9) -> [return: bb4, unwind: bb16]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = move _4; + _10 = opaque::<[T; 2]>(move _11) -> [return: bb5, unwind: bb15]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = move _5; + _12 = opaque::(move _13) -> [return: bb6, unwind: bb14]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + _0 = const (); + drop(_5) -> [return: bb8, unwind: bb19]; + } + + bb7: { + _0 = const (); + goto -> bb12; + } + + bb8: { + StorageDead(_5); + drop(_4) -> [return: bb9, unwind: bb20]; + } + + bb9: { + StorageDead(_4); + drop(_3) -> [return: bb10, unwind: bb21]; + } + + bb10: { + StorageDead(_3); + drop(_2) -> [return: bb11, unwind: bb22]; + } + + bb11: { + StorageDead(_2); + goto -> bb12; + } + + bb12: { + drop(_1) -> [return: bb13, unwind: bb23]; + } + + bb13: { + return; + } + + bb14 (cleanup): { + drop(_13) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + drop(_11) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb16 (cleanup): { + drop(_9) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + drop(_7) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb18 (cleanup): { + drop(_5) -> [return: bb19, unwind terminate(cleanup)]; + } + + bb19 (cleanup): { + drop(_4) -> [return: bb20, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + drop(_3) -> [return: bb21, unwind terminate(cleanup)]; + } + + bb21 (cleanup): { + drop(_2) -> [return: bb22, unwind terminate(cleanup)]; + } + + bb22 (cleanup): { + drop(_1) -> [return: bb23, unwind terminate(cleanup)]; + } + + bb23 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/match/array_len.rs b/tests/mir-opt/building/match/array_len.rs new file mode 100644 index 0000000000000..0d889ada9b602 --- /dev/null +++ b/tests/mir-opt/building/match/array_len.rs @@ -0,0 +1,31 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ compile-flags: -Zmir-opt-level=0 + +fn opaque(x: T) {} + +// EMIT_MIR array_len.const_array_len.built.after.mir +fn const_array_len(x: [T; 5]) { + // CHECK-LABEL: fn const_array_len( + // CHECK-NOT: Len + // CHECK-NOT: PtrMetadata + // CHECK: = const 5_usize; + if let [a, b, rest @ .., e] = x { + opaque(a); + opaque(b); + opaque(rest); + opaque(e); + } +} + +// EMIT_MIR array_len.slice_len.built.after.mir +fn slice_len(x: &[T]) { + // CHECK-LABEL: fn slice_len( + // CHECK-NOT: Len + // CHECK: = PtrMetadata(copy _1); + if let [a, b, rest @ .., e] = x { + opaque(a); + opaque(b); + opaque(rest); + opaque(e); + } +} diff --git a/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir new file mode 100644 index 0000000000000..d73f5a1b6f716 --- /dev/null +++ b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-abort.mir @@ -0,0 +1,115 @@ +// MIR for `slice_len` after built + +fn slice_len(_1: &[T]) -> () { + debug x => _1; + let mut _0: (); + let mut _2: usize; + let mut _3: usize; + let mut _4: usize; + let mut _5: bool; + let _10: (); + let mut _11: &T; + let _12: (); + let mut _13: &T; + let _14: (); + let mut _15: &[T]; + let _16: (); + let mut _17: &T; + scope 1 { + debug a => _6; + debug b => _7; + debug rest => _8; + debug e => _9; + let _6: &T; + let _7: &T; + let _8: &[T]; + let _9: &T; + } + + bb0: { + PlaceMention(_1); + _3 = PtrMetadata(copy _1); + _2 = move _3; + _4 = const 3_usize; + _5 = Ge(move _2, move _4); + switchInt(move _5) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + goto -> bb9; + } + + bb2: { + falseEdge -> [real: bb4, imaginary: bb1]; + } + + bb3: { + goto -> bb1; + } + + bb4: { + StorageLive(_6); + _6 = &(*_1)[0 of 3]; + StorageLive(_7); + _7 = &(*_1)[1 of 3]; + StorageLive(_8); + _8 = &(*_1)[2:-1]; + StorageLive(_9); + _9 = &(*_1)[-1 of 3]; + StorageLive(_10); + StorageLive(_11); + _11 = copy _6; + _10 = opaque::<&T>(move _11) -> [return: bb5, unwind: bb11]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = copy _7; + _12 = opaque::<&T>(move _13) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = copy _8; + _14 = opaque::<&[T]>(move _15) -> [return: bb7, unwind: bb11]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = copy _9; + _16 = opaque::<&T>(move _17) -> [return: bb8, unwind: bb11]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + goto -> bb10; + } + + bb9: { + _0 = const (); + goto -> bb10; + } + + bb10: { + return; + } + + bb11 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir new file mode 100644 index 0000000000000..d73f5a1b6f716 --- /dev/null +++ b/tests/mir-opt/building/match/array_len.slice_len.built.after.panic-unwind.mir @@ -0,0 +1,115 @@ +// MIR for `slice_len` after built + +fn slice_len(_1: &[T]) -> () { + debug x => _1; + let mut _0: (); + let mut _2: usize; + let mut _3: usize; + let mut _4: usize; + let mut _5: bool; + let _10: (); + let mut _11: &T; + let _12: (); + let mut _13: &T; + let _14: (); + let mut _15: &[T]; + let _16: (); + let mut _17: &T; + scope 1 { + debug a => _6; + debug b => _7; + debug rest => _8; + debug e => _9; + let _6: &T; + let _7: &T; + let _8: &[T]; + let _9: &T; + } + + bb0: { + PlaceMention(_1); + _3 = PtrMetadata(copy _1); + _2 = move _3; + _4 = const 3_usize; + _5 = Ge(move _2, move _4); + switchInt(move _5) -> [0: bb1, otherwise: bb2]; + } + + bb1: { + goto -> bb9; + } + + bb2: { + falseEdge -> [real: bb4, imaginary: bb1]; + } + + bb3: { + goto -> bb1; + } + + bb4: { + StorageLive(_6); + _6 = &(*_1)[0 of 3]; + StorageLive(_7); + _7 = &(*_1)[1 of 3]; + StorageLive(_8); + _8 = &(*_1)[2:-1]; + StorageLive(_9); + _9 = &(*_1)[-1 of 3]; + StorageLive(_10); + StorageLive(_11); + _11 = copy _6; + _10 = opaque::<&T>(move _11) -> [return: bb5, unwind: bb11]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = copy _7; + _12 = opaque::<&T>(move _13) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = copy _8; + _14 = opaque::<&[T]>(move _15) -> [return: bb7, unwind: bb11]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = copy _9; + _16 = opaque::<&T>(move _17) -> [return: bb8, unwind: bb11]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + goto -> bb10; + } + + bb9: { + _0 = const (); + goto -> bb10; + } + + bb10: { + return; + } + + bb11 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff new file mode 100644 index 0000000000000..fd9ef54fe775f --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: u32; + let mut _2: &[u32]; + let mut _3: &[u32; 3]; + let _4: &[u32; 3]; + let _5: [u32; 3]; + let _6: usize; + let mut _7: usize; + let mut _8: bool; + let mut _10: &[u32]; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + let mut _14: &[u32; 3]; + scope 1 { + debug local => _1; + let _9: u32; + scope 2 { + debug constant => _9; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _14 = const main::promoted[0]; + _4 = copy _14; + _3 = copy _4; + _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); + StorageDead(_3); + StorageLive(_6); + _6 = const 1_usize; +- _7 = PtrMetadata(copy _2); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; + StorageDead(_6); + StorageDead(_4); + StorageDead(_2); + StorageLive(_9); + StorageLive(_10); + _10 = const main::SLICE; + StorageLive(_11); + _11 = const 1_usize; +- _12 = PtrMetadata(copy _10); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; ++ _12 = const 3_usize; ++ _13 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; + } + + bb2: { +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; + StorageDead(_11); + StorageDead(_10); + _0 = const (); + StorageDead(_9); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff new file mode 100644 index 0000000000000..1fec08c256201 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: u32; + let mut _2: &[u32]; + let mut _3: &[u32; 3]; + let _4: &[u32; 3]; + let _5: [u32; 3]; + let _6: usize; + let mut _7: usize; + let mut _8: bool; + let mut _10: &[u32]; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + let mut _14: &[u32; 3]; + scope 1 { + debug local => _1; + let _9: u32; + scope 2 { + debug constant => _9; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _14 = const main::promoted[0]; + _4 = copy _14; + _3 = copy _4; + _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); + StorageDead(_3); + StorageLive(_6); + _6 = const 1_usize; +- _7 = PtrMetadata(copy _2); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; + } + + bb1: { +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; + StorageDead(_6); + StorageDead(_4); + StorageDead(_2); + StorageLive(_9); + StorageLive(_10); + _10 = const main::SLICE; + StorageLive(_11); + _11 = const 1_usize; +- _12 = PtrMetadata(copy _10); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; ++ _12 = const 3_usize; ++ _13 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; + } + + bb2: { +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; + StorageDead(_11); + StorageDead(_10); + _0 = const (); + StorageDead(_9); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff new file mode 100644 index 0000000000000..fd9ef54fe775f --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: u32; + let mut _2: &[u32]; + let mut _3: &[u32; 3]; + let _4: &[u32; 3]; + let _5: [u32; 3]; + let _6: usize; + let mut _7: usize; + let mut _8: bool; + let mut _10: &[u32]; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + let mut _14: &[u32; 3]; + scope 1 { + debug local => _1; + let _9: u32; + scope 2 { + debug constant => _9; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _14 = const main::promoted[0]; + _4 = copy _14; + _3 = copy _4; + _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); + StorageDead(_3); + StorageLive(_6); + _6 = const 1_usize; +- _7 = PtrMetadata(copy _2); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind unreachable]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; + StorageDead(_6); + StorageDead(_4); + StorageDead(_2); + StorageLive(_9); + StorageLive(_10); + _10 = const main::SLICE; + StorageLive(_11); + _11 = const 1_usize; +- _12 = PtrMetadata(copy _10); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind unreachable]; ++ _12 = const 3_usize; ++ _13 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind unreachable]; + } + + bb2: { +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; + StorageDead(_11); + StorageDead(_10); + _0 = const (); + StorageDead(_9); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff new file mode 100644 index 0000000000000..1fec08c256201 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff @@ -0,0 +1,77 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let _1: u32; + let mut _2: &[u32]; + let mut _3: &[u32; 3]; + let _4: &[u32; 3]; + let _5: [u32; 3]; + let _6: usize; + let mut _7: usize; + let mut _8: bool; + let mut _10: &[u32]; + let _11: usize; + let mut _12: usize; + let mut _13: bool; + let mut _14: &[u32; 3]; + scope 1 { + debug local => _1; + let _9: u32; + scope 2 { + debug constant => _9; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _14 = const main::promoted[0]; + _4 = copy _14; + _3 = copy _4; + _2 = move _3 as &[u32] (PointerCoercion(Unsize, AsCast)); + StorageDead(_3); + StorageLive(_6); + _6 = const 1_usize; +- _7 = PtrMetadata(copy _2); +- _8 = Lt(copy _6, copy _7); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, copy _6) -> [success: bb1, unwind continue]; ++ _7 = const 3_usize; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb1, unwind continue]; + } + + bb1: { +- _1 = copy (*_2)[_6]; ++ _1 = copy (*_2)[1 of 2]; + StorageDead(_6); + StorageDead(_4); + StorageDead(_2); + StorageLive(_9); + StorageLive(_10); + _10 = const main::SLICE; + StorageLive(_11); + _11 = const 1_usize; +- _12 = PtrMetadata(copy _10); +- _13 = Lt(copy _11, copy _12); +- assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, copy _11) -> [success: bb2, unwind continue]; ++ _12 = const 3_usize; ++ _13 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> [success: bb2, unwind continue]; + } + + bb2: { +- _9 = copy (*_10)[_11]; ++ _9 = copy (*_10)[1 of 2]; + StorageDead(_11); + StorageDead(_10); + _0 = const (); + StorageDead(_9); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs new file mode 100644 index 0000000000000..e0e68f9fde54a --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -0,0 +1,34 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ test-mir-pass: DataflowConstProp +//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR slice_len.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( +fn main() { + // CHECK: debug local => [[local:_.*]]; + // CHECK: debug constant => [[constant:_.*]]; + + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, + + // CHECK: [[local]] = copy (*{{_.*}})[1 of 2]; + let local = (&[1u32, 2, 3] as &[u32])[1]; + + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + const SLICE: &[u32] = &[1, 2, 3]; + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, + + // CHECK-NOT: [[constant]] = {{copy|move}} (*{{_.*}})[_ + // CHECK: [[constant]] = copy (*{{_.*}})[1 of 2]; + let constant = SLICE[1]; +} diff --git a/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff b/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff index 0d0477fe7729f..59b65a52f4ee6 100644 --- a/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.array_len.GVN.panic-abort.diff @@ -12,8 +12,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); _3 = &(*_1); _2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit)); @@ -23,8 +22,7 @@ - _0 = PtrMetadata(move _4); + _0 = const 42_usize; StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff b/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff index 0d0477fe7729f..59b65a52f4ee6 100644 --- a/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.array_len.GVN.panic-unwind.diff @@ -12,8 +12,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); _3 = &(*_1); _2 = move _3 as &[i32] (PointerCoercion(Unsize, Implicit)); @@ -23,8 +22,7 @@ - _0 = PtrMetadata(move _4); + _0 = const 42_usize; StorageDead(_4); -- StorageDead(_2); -+ nop; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff new file mode 100644 index 0000000000000..feba0fe7c4a21 --- /dev/null +++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff @@ -0,0 +1,71 @@ +- // MIR for `norm2` before InstSimplify-after-simplifycfg ++ // MIR for `norm2` after InstSimplify-after-simplifycfg + + fn norm2(_1: [f32; 2]) -> f32 { + debug x => _1; + let mut _0: f32; + let _2: f32; + let _3: usize; + let mut _4: bool; + let _6: usize; + let mut _7: bool; + let mut _8: f32; + let mut _9: f32; + let mut _10: f32; + let mut _11: f32; + let mut _12: f32; + let mut _13: f32; + scope 1 { + debug a => _2; + let _5: f32; + scope 2 { + debug b => _5; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 0_usize; + _4 = Lt(copy _3, const 2_usize); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _2 = copy _1[_3]; + StorageDead(_3); + StorageLive(_5); + StorageLive(_6); + _6 = const 1_usize; + _7 = Lt(copy _6, const 2_usize); + assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind unreachable]; + } + + bb2: { + _5 = copy _1[_6]; + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = copy _2; + StorageLive(_10); + _10 = copy _2; + _8 = Mul(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = copy _5; + StorageLive(_13); + _13 = copy _5; + _11 = Mul(move _12, move _13); + StorageDead(_13); + StorageDead(_12); + _0 = Add(move _8, move _11); + StorageDead(_11); + StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff new file mode 100644 index 0000000000000..0ccf6a825c49a --- /dev/null +++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff @@ -0,0 +1,71 @@ +- // MIR for `norm2` before InstSimplify-after-simplifycfg ++ // MIR for `norm2` after InstSimplify-after-simplifycfg + + fn norm2(_1: [f32; 2]) -> f32 { + debug x => _1; + let mut _0: f32; + let _2: f32; + let _3: usize; + let mut _4: bool; + let _6: usize; + let mut _7: bool; + let mut _8: f32; + let mut _9: f32; + let mut _10: f32; + let mut _11: f32; + let mut _12: f32; + let mut _13: f32; + scope 1 { + debug a => _2; + let _5: f32; + scope 2 { + debug b => _5; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 0_usize; + _4 = Lt(copy _3, const 2_usize); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _3) -> [success: bb1, unwind continue]; + } + + bb1: { + _2 = copy _1[_3]; + StorageDead(_3); + StorageLive(_5); + StorageLive(_6); + _6 = const 1_usize; + _7 = Lt(copy _6, const 2_usize); + assert(move _7, "index out of bounds: the length is {} but the index is {}", const 2_usize, copy _6) -> [success: bb2, unwind continue]; + } + + bb2: { + _5 = copy _1[_6]; + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = copy _2; + StorageLive(_10); + _10 = copy _2; + _8 = Mul(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = copy _5; + StorageLive(_13); + _13 = copy _5; + _11 = Mul(move _12, move _13); + StorageDead(_13); + StorageDead(_12); + _0 = Add(move _8, move _11); + StorageDead(_11); + StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff new file mode 100644 index 0000000000000..e9cb2c5817720 --- /dev/null +++ b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-abort.diff @@ -0,0 +1,71 @@ +- // MIR for `normN` before InstSimplify-after-simplifycfg ++ // MIR for `normN` after InstSimplify-after-simplifycfg + + fn normN(_1: [f32; N]) -> f32 { + debug x => _1; + let mut _0: f32; + let _2: f32; + let _3: usize; + let mut _4: bool; + let _6: usize; + let mut _7: bool; + let mut _8: f32; + let mut _9: f32; + let mut _10: f32; + let mut _11: f32; + let mut _12: f32; + let mut _13: f32; + scope 1 { + debug a => _2; + let _5: f32; + scope 2 { + debug b => _5; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 0_usize; + _4 = Lt(copy _3, const N); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const N, copy _3) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _2 = copy _1[_3]; + StorageDead(_3); + StorageLive(_5); + StorageLive(_6); + _6 = const 1_usize; + _7 = Lt(copy _6, const N); + assert(move _7, "index out of bounds: the length is {} but the index is {}", const N, copy _6) -> [success: bb2, unwind unreachable]; + } + + bb2: { + _5 = copy _1[_6]; + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = copy _2; + StorageLive(_10); + _10 = copy _2; + _8 = Mul(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = copy _5; + StorageLive(_13); + _13 = copy _5; + _11 = Mul(move _12, move _13); + StorageDead(_13); + StorageDead(_12); + _0 = Add(move _8, move _11); + StorageDead(_11); + StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff new file mode 100644 index 0000000000000..0ddc70f2003e8 --- /dev/null +++ b/tests/mir-opt/instsimplify/combine_array_len.normN.InstSimplify-after-simplifycfg.panic-unwind.diff @@ -0,0 +1,71 @@ +- // MIR for `normN` before InstSimplify-after-simplifycfg ++ // MIR for `normN` after InstSimplify-after-simplifycfg + + fn normN(_1: [f32; N]) -> f32 { + debug x => _1; + let mut _0: f32; + let _2: f32; + let _3: usize; + let mut _4: bool; + let _6: usize; + let mut _7: bool; + let mut _8: f32; + let mut _9: f32; + let mut _10: f32; + let mut _11: f32; + let mut _12: f32; + let mut _13: f32; + scope 1 { + debug a => _2; + let _5: f32; + scope 2 { + debug b => _5; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = const 0_usize; + _4 = Lt(copy _3, const N); + assert(move _4, "index out of bounds: the length is {} but the index is {}", const N, copy _3) -> [success: bb1, unwind continue]; + } + + bb1: { + _2 = copy _1[_3]; + StorageDead(_3); + StorageLive(_5); + StorageLive(_6); + _6 = const 1_usize; + _7 = Lt(copy _6, const N); + assert(move _7, "index out of bounds: the length is {} but the index is {}", const N, copy _6) -> [success: bb2, unwind continue]; + } + + bb2: { + _5 = copy _1[_6]; + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = copy _2; + StorageLive(_10); + _10 = copy _2; + _8 = Mul(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = copy _5; + StorageLive(_13); + _13 = copy _5; + _11 = Mul(move _12, move _13); + StorageDead(_13); + StorageDead(_12); + _0 = Add(move _8, move _11); + StorageDead(_11); + StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs new file mode 100644 index 0000000000000..1c4d42d3bbe82 --- /dev/null +++ b/tests/mir-opt/instsimplify/combine_array_len.rs @@ -0,0 +1,25 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +//@ test-mir-pass: InstSimplify-after-simplifycfg + +// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff +fn norm2(x: [f32; 2]) -> f32 { + // CHECK-LABEL: fn norm2( + // CHECK-NOT: PtrMetadata( + let a = x[0]; + let b = x[1]; + a * a + b * b +} + +// EMIT_MIR combine_array_len.normN.InstSimplify-after-simplifycfg.diff +fn normN(x: [f32; N]) -> f32 { + // CHECK-LABEL: fn normN( + // CHECK-NOT: PtrMetadata( + let a = x[0]; + let b = x[1]; + a * a + b * b +} + +fn main() { + assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0); + assert_eq!(normN([3.0, 4.0]), 5.0 * 5.0); +} diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 08dee3697e072..5cf36b9aebf2f 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -7,18 +7,16 @@ let _2: &[T]; let _3: &[T; 3]; let _4: [T; 3]; - let mut _5: usize; - let mut _6: bool; - let mut _10: !; + let mut _8: !; scope 1 { debug v => _2; + let _5: &T; + let _6: &T; let _7: &T; - let _8: &T; - let _9: &T; scope 2 { - debug v1 => _7; - debug v2 => _8; - debug v3 => _9; + debug v1 => _5; + debug v2 => _6; + debug v3 => _7; } } @@ -27,25 +25,23 @@ _4 = [copy _1, copy _1, copy _1]; _3 = &_4; _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit)); - nop; - nop; goto -> bb2; } bb1: { - _10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; + _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; } bb2: { + StorageLive(_5); + _5 = &(*_2)[0 of 3]; + StorageLive(_6); + _6 = &(*_2)[1 of 3]; StorageLive(_7); - _7 = &(*_2)[0 of 3]; - StorageLive(_8); - _8 = &(*_2)[1 of 3]; - StorageLive(_9); - _9 = &(*_2)[2 of 3]; - StorageDead(_9); - StorageDead(_8); + _7 = &(*_2)[2 of 3]; StorageDead(_7); + StorageDead(_6); + StorageDead(_5); StorageDead(_4); return; } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index aa44a2ad532be..0598a3aa3f19a 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -7,18 +7,16 @@ let _2: &[T]; let _3: &[T; 3]; let _4: [T; 3]; - let mut _5: usize; - let mut _6: bool; - let mut _10: !; + let mut _8: !; scope 1 { debug v => _2; + let _5: &T; + let _6: &T; let _7: &T; - let _8: &T; - let _9: &T; scope 2 { - debug v1 => _7; - debug v2 => _8; - debug v3 => _9; + debug v1 => _5; + debug v2 => _6; + debug v3 => _7; } } @@ -27,25 +25,23 @@ _4 = [copy _1, copy _1, copy _1]; _3 = &_4; _2 = copy _3 as &[T] (PointerCoercion(Unsize, Implicit)); - nop; - nop; goto -> bb2; } bb1: { - _10 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; + _8 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; } bb2: { + StorageLive(_5); + _5 = &(*_2)[0 of 3]; + StorageLive(_6); + _6 = &(*_2)[1 of 3]; StorageLive(_7); - _7 = &(*_2)[0 of 3]; - StorageLive(_8); - _8 = &(*_2)[1 of 3]; - StorageLive(_9); - _9 = &(*_2)[2 of 3]; - StorageDead(_9); - StorageDead(_8); + _7 = &(*_2)[2 of 3]; StorageDead(_7); + StorageDead(_6); + StorageDead(_5); StorageDead(_4); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff index 180a7db029794..714a12804e692 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff @@ -18,8 +18,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _4 = &_1; @@ -41,8 +40,7 @@ bb1: { StorageDead(_6); StorageDead(_5); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_7); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff index 180a7db029794..714a12804e692 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff @@ -18,8 +18,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _4 = &_1; @@ -41,8 +40,7 @@ bb1: { StorageDead(_6); StorageDead(_5); -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageDead(_7); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff index 49964f8b49e26..b236b22f067d8 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff @@ -17,8 +17,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _4 = &mut _1; @@ -38,8 +37,7 @@ bb1: { StorageDead(_6); StorageDead(_5); -- StorageDead(_2); -+ nop; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff index 49964f8b49e26..b236b22f067d8 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff @@ -17,8 +17,7 @@ } bb0: { -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); _4 = &mut _1; @@ -38,8 +37,7 @@ bb1: { StorageDead(_6); StorageDead(_5); -- StorageDead(_2); -+ nop; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff index 3da795b61f948..375b6096d88d8 100644 --- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff @@ -17,14 +17,15 @@ let mut _15: std::ops::RangeFull; let mut _16: usize; let mut _17: usize; - let mut _18: bool; - let _23: &&mut u8; - let _24: &mut u8; - let mut _25: debuginfo::T; + let mut _18: usize; + let mut _19: bool; + let _24: &&mut u8; + let _25: &mut u8; + let mut _26: debuginfo::T; scope 1 { debug ref_mut_u8 => _1; let _3: &u8; - let mut _28: &debuginfo::T; + let mut _29: &debuginfo::T; scope 2 { debug field => _3; let _5: &u8; @@ -32,22 +33,22 @@ - debug reborrow => _5; + debug reborrow => _1; let _9: &i32; - let _22: &&&mut u8; - let mut _27: &std::option::Option; + let _23: &&&mut u8; + let mut _28: &std::option::Option; scope 4 { debug variant_field => _9; } scope 5 { - debug constant_index => _19; - debug subslice => _20; - debug constant_index_from_end => _21; - let _19: &i32; - let _20: &[i32]; - let _21: &i32; - let mut _26: &[i32; 10]; + debug constant_index => _20; + debug subslice => _21; + debug constant_index_from_end => _22; + let _20: &i32; + let _21: &[i32]; + let _22: &i32; + let mut _27: &[i32; 10]; } scope 6 { - debug multiple_borrow => _22; + debug multiple_borrow => _23; } } } @@ -59,8 +60,8 @@ _2 = const 5_u8; _1 = &mut _2; StorageLive(_3); - _28 = const debuginfo::promoted[2]; - _3 = &((*_28).0: u8); + _29 = const debuginfo::promoted[2]; + _3 = &((*_29).0: u8); - StorageLive(_5); - _5 = &(*_1); - StorageLive(_6); @@ -76,8 +77,8 @@ bb2: { StorageLive(_9); - _27 = const debuginfo::promoted[1]; - _9 = &(((*_27) as Some).0: i32); + _28 = const debuginfo::promoted[1]; + _9 = &(((*_28) as Some).0: i32); - _6 = const (); StorageDead(_9); goto -> bb4; @@ -92,11 +93,11 @@ StorageDead(_7); - StorageDead(_6); - StorageLive(_10); -- StorageLive(_11); + StorageLive(_11); - StorageLive(_12); StorageLive(_13); - _26 = const debuginfo::promoted[0]; - _13 = &(*_26); + _27 = const debuginfo::promoted[0]; + _13 = &(*_27); StorageLive(_15); _15 = RangeFull; - _12 = <[i32; 10] as Index>::index(move _13, move _15) -> [return: bb5, unwind continue]; @@ -106,28 +107,28 @@ bb5: { StorageDead(_15); StorageDead(_13); -- _11 = &(*_12); -- _16 = Len((*_11)); -+ _16 = Len((*_12)); - _17 = const 3_usize; - _18 = Ge(move _16, move _17); - switchInt(move _18) -> [0: bb7, otherwise: bb6]; + _11 = &(*_12); + _17 = PtrMetadata(copy _11); + _16 = move _17; + _18 = const 3_usize; + _19 = Ge(move _16, move _18); + switchInt(move _19) -> [0: bb7, otherwise: bb6]; } bb6: { - StorageLive(_19); -- _19 = &(*_11)[1 of 3]; -+ _19 = &(*_12)[1 of 3]; StorageLive(_20); -- _20 = &(*_11)[2:-1]; -+ _20 = &(*_12)[2:-1]; +- _20 = &(*_11)[1 of 3]; ++ _20 = &(*_12)[1 of 3]; StorageLive(_21); -- _21 = &(*_11)[-1 of 3]; +- _21 = &(*_11)[2:-1]; ++ _21 = &(*_12)[2:-1]; + StorageLive(_22); +- _22 = &(*_11)[-1 of 3]; - _10 = const (); -+ _21 = &(*_12)[-1 of 3]; ++ _22 = &(*_12)[-1 of 3]; + StorageDead(_22); StorageDead(_21); StorageDead(_20); - StorageDead(_19); goto -> bb8; } @@ -138,21 +139,21 @@ bb8: { - StorageDead(_12); -- StorageDead(_11); + StorageDead(_11); - StorageDead(_10); - StorageLive(_22); StorageLive(_23); StorageLive(_24); StorageLive(_25); - _25 = T(const 6_u8); - _24 = &mut (_25.0: u8); + StorageLive(_26); + _26 = T(const 6_u8); + _25 = &mut (_26.0: u8); + _24 = &_25; _23 = &_24; - _22 = &_23; _0 = const (); + StorageDead(_26); StorageDead(_25); StorageDead(_24); StorageDead(_23); - StorageDead(_22); - StorageDead(_5); StorageDead(_3); StorageDead(_2);