mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
Auto merge of #115796 - cjgillot:const-prop-rvalue, r=oli-obk
Generate aggregate constants in DataflowConstProp.
This commit is contained in:
commit
df871fbf05
@ -2,13 +2,13 @@
|
||||
//!
|
||||
//! Currently, this pass only propagates scalar values.
|
||||
|
||||
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable};
|
||||
use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar};
|
||||
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_mir_dataflow::value_analysis::{
|
||||
Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
|
||||
@ -16,8 +16,9 @@ use rustc_mir_dataflow::value_analysis::{
|
||||
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
|
||||
|
||||
use crate::const_prop::throw_machine_stop_str;
|
||||
use crate::MirPass;
|
||||
|
||||
// These constants are somewhat random guesses and have not been optimized.
|
||||
@ -553,18 +554,153 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
|
||||
|
||||
fn try_make_constant(
|
||||
&self,
|
||||
ecx: &mut InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
place: Place<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
) -> Option<Const<'tcx>> {
|
||||
let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else {
|
||||
return None;
|
||||
};
|
||||
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
|
||||
Some(Const::Val(ConstValue::Scalar(value.into()), ty))
|
||||
let layout = ecx.layout_of(ty).ok()?;
|
||||
|
||||
if layout.is_zst() {
|
||||
return Some(Const::zero_sized(ty));
|
||||
}
|
||||
|
||||
if layout.is_unsized() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let place = map.find(place.as_ref())?;
|
||||
if layout.abi.is_scalar()
|
||||
&& let Some(value) = propagatable_scalar(place, state, map)
|
||||
{
|
||||
return Some(Const::Val(ConstValue::Scalar(value), ty));
|
||||
}
|
||||
|
||||
if matches!(layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
|
||||
let alloc_id = ecx
|
||||
.intern_with_temp_alloc(layout, |ecx, dest| {
|
||||
try_write_constant(ecx, dest, place, ty, state, map)
|
||||
})
|
||||
.ok()?;
|
||||
return Some(Const::Val(ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ty));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn propagatable_scalar(
|
||||
place: PlaceIndex,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
) -> Option<Scalar> {
|
||||
if let FlatSet::Elem(value) = state.get_idx(place, map) && value.try_to_int().is_ok() {
|
||||
// Do not attempt to propagate pointers, as we may fail to preserve their identity.
|
||||
Some(value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(ecx, state, map))]
|
||||
fn try_write_constant<'tcx>(
|
||||
ecx: &mut InterpCx<'_, 'tcx, DummyMachine>,
|
||||
dest: &PlaceTy<'tcx>,
|
||||
place: PlaceIndex,
|
||||
ty: Ty<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
) -> InterpResult<'tcx> {
|
||||
let layout = ecx.layout_of(ty)?;
|
||||
|
||||
// Fast path for ZSTs.
|
||||
if layout.is_zst() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Fast path for scalars.
|
||||
if layout.abi.is_scalar()
|
||||
&& let Some(value) = propagatable_scalar(place, state, map)
|
||||
{
|
||||
return ecx.write_immediate(Immediate::Scalar(value), dest);
|
||||
}
|
||||
|
||||
match ty.kind() {
|
||||
// ZSTs. Nothing to do.
|
||||
ty::FnDef(..) => {}
|
||||
|
||||
// Those are scalars, must be handled above.
|
||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"),
|
||||
|
||||
ty::Tuple(elem_tys) => {
|
||||
for (i, elem) in elem_tys.iter().enumerate() {
|
||||
let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else {
|
||||
throw_machine_stop_str!("missing field in tuple")
|
||||
};
|
||||
let field_dest = ecx.project_field(dest, i)?;
|
||||
try_write_constant(ecx, &field_dest, field, elem, state, map)?;
|
||||
}
|
||||
}
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
if def.is_union() {
|
||||
throw_machine_stop_str!("cannot propagate unions")
|
||||
}
|
||||
|
||||
let (variant_idx, variant_def, variant_place, variant_dest) = if def.is_enum() {
|
||||
let Some(discr) = map.apply(place, TrackElem::Discriminant) else {
|
||||
throw_machine_stop_str!("missing discriminant for enum")
|
||||
};
|
||||
let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else {
|
||||
throw_machine_stop_str!("discriminant with provenance")
|
||||
};
|
||||
let discr_bits = discr.assert_bits(discr.size());
|
||||
let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else {
|
||||
throw_machine_stop_str!("illegal discriminant for enum")
|
||||
};
|
||||
let Some(variant_place) = map.apply(place, TrackElem::Variant(variant)) else {
|
||||
throw_machine_stop_str!("missing variant for enum")
|
||||
};
|
||||
let variant_dest = ecx.project_downcast(dest, variant)?;
|
||||
(variant, def.variant(variant), variant_place, variant_dest)
|
||||
} else {
|
||||
(FIRST_VARIANT, def.non_enum_variant(), place, dest.clone())
|
||||
};
|
||||
|
||||
for (i, field) in variant_def.fields.iter_enumerated() {
|
||||
let ty = field.ty(*ecx.tcx, args);
|
||||
let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else {
|
||||
throw_machine_stop_str!("missing field in ADT")
|
||||
};
|
||||
let field_dest = ecx.project_field(&variant_dest, i.as_usize())?;
|
||||
try_write_constant(ecx, &field_dest, field, ty, state, map)?;
|
||||
}
|
||||
ecx.write_discriminant(variant_idx, dest)?;
|
||||
}
|
||||
|
||||
// Unsupported for now.
|
||||
ty::Array(_, _)
|
||||
|
||||
// Do not attempt to support indirection in constants.
|
||||
| ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_)
|
||||
|
||||
| ty::Never
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Coroutine(..)
|
||||
| ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"),
|
||||
|
||||
ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx>
|
||||
ResultsVisitor<'mir, 'tcx, Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>>
|
||||
for Collector<'tcx, '_>
|
||||
@ -580,8 +716,13 @@ impl<'mir, 'tcx>
|
||||
) {
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (_, rvalue)) => {
|
||||
OperandCollector { state, visitor: self, map: &results.analysis.0.map }
|
||||
.visit_rvalue(rvalue, location);
|
||||
OperandCollector {
|
||||
state,
|
||||
visitor: self,
|
||||
ecx: &mut results.analysis.0.ecx,
|
||||
map: &results.analysis.0.map,
|
||||
}
|
||||
.visit_rvalue(rvalue, location);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
@ -599,7 +740,12 @@ impl<'mir, 'tcx>
|
||||
// Don't overwrite the assignment if it already uses a constant (to keep the span).
|
||||
}
|
||||
StatementKind::Assign(box (place, _)) => {
|
||||
if let Some(value) = self.try_make_constant(place, state, &results.analysis.0.map) {
|
||||
if let Some(value) = self.try_make_constant(
|
||||
&mut results.analysis.0.ecx,
|
||||
place,
|
||||
state,
|
||||
&results.analysis.0.map,
|
||||
) {
|
||||
self.patch.assignments.insert(location, value);
|
||||
}
|
||||
}
|
||||
@ -614,8 +760,13 @@ impl<'mir, 'tcx>
|
||||
terminator: &'mir Terminator<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
OperandCollector { state, visitor: self, map: &results.analysis.0.map }
|
||||
.visit_terminator(terminator, location);
|
||||
OperandCollector {
|
||||
state,
|
||||
visitor: self,
|
||||
ecx: &mut results.analysis.0.ecx,
|
||||
map: &results.analysis.0.map,
|
||||
}
|
||||
.visit_terminator(terminator, location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -670,6 +821,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> {
|
||||
struct OperandCollector<'tcx, 'map, 'locals, 'a> {
|
||||
state: &'a State<FlatSet<Scalar>>,
|
||||
visitor: &'a mut Collector<'tcx, 'locals>,
|
||||
ecx: &'map mut InterpCx<'tcx, 'tcx, DummyMachine>,
|
||||
map: &'map Map,
|
||||
}
|
||||
|
||||
@ -682,7 +834,7 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
|
||||
location: Location,
|
||||
) {
|
||||
if let PlaceElem::Index(local) = elem
|
||||
&& let Some(value) = self.visitor.try_make_constant(local.into(), self.state, self.map)
|
||||
&& let Some(value) = self.visitor.try_make_constant(self.ecx, local.into(), self.state, self.map)
|
||||
{
|
||||
self.visitor.patch.before_effect.insert((location, local.into()), value);
|
||||
}
|
||||
@ -690,7 +842,9 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
|
||||
|
||||
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
|
||||
if let Some(place) = operand.place() {
|
||||
if let Some(value) = self.visitor.try_make_constant(place, self.state, self.map) {
|
||||
if let Some(value) =
|
||||
self.visitor.try_make_constant(self.ecx, place, self.state, self.map)
|
||||
{
|
||||
self.visitor.patch.before_effect.insert((location, place), value);
|
||||
} else if !place.projection.is_empty() {
|
||||
// Try to propagate into `Index` projections.
|
||||
@ -713,7 +867,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
|
||||
}
|
||||
|
||||
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool {
|
||||
unimplemented!()
|
||||
false
|
||||
}
|
||||
|
||||
fn before_access_global(
|
||||
@ -725,13 +879,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
|
||||
is_write: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
if is_write {
|
||||
crate::const_prop::throw_machine_stop_str!("can't write to global");
|
||||
throw_machine_stop_str!("can't write to global");
|
||||
}
|
||||
|
||||
// If the static allocation is mutable, then we can't const prop it as its content
|
||||
// might be different at runtime.
|
||||
if alloc.inner().mutability.is_mut() {
|
||||
crate::const_prop::throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
||||
throw_machine_stop_str!("can't access mutable globals in ConstProp");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -781,7 +935,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
|
||||
_left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
|
||||
_right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>,
|
||||
) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> {
|
||||
crate::const_prop::throw_machine_stop_str!("can't do pointer arithmetic");
|
||||
throw_machine_stop_str!("can't do pointer arithmetic");
|
||||
}
|
||||
|
||||
fn expose_ptr(
|
||||
|
@ -41,7 +41,8 @@
|
||||
+ debug ((f: (bool, bool, u32)).2: u32) => const 123_u32;
|
||||
let _10: std::option::Option<u16>;
|
||||
scope 7 {
|
||||
debug o => _10;
|
||||
- debug o => _10;
|
||||
+ debug o => const Option::<u16>::Some(99_u16);
|
||||
let _17: u32;
|
||||
let _18: u32;
|
||||
scope 8 {
|
||||
@ -81,7 +82,7 @@
|
||||
_15 = const false;
|
||||
_16 = const 123_u32;
|
||||
StorageLive(_10);
|
||||
_10 = Option::<u16>::Some(const 99_u16);
|
||||
_10 = const Option::<u16>::Some(99_u16);
|
||||
_17 = const 32_u32;
|
||||
_18 = const 32_u32;
|
||||
StorageLive(_11);
|
||||
@ -97,3 +98,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
ALLOC0 (size: 4, align: 2) {
|
||||
01 00 63 00 │ ..c.
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
- _6 = CheckedAdd(_4, _5);
|
||||
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable];
|
||||
+ _5 = const 2_i32;
|
||||
+ _6 = CheckedAdd(const 1_i32, const 2_i32);
|
||||
+ _6 = const (3_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
- _10 = CheckedAdd(_9, const 1_i32);
|
||||
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable];
|
||||
+ _9 = const i32::MAX;
|
||||
+ _10 = CheckedAdd(const i32::MAX, const 1_i32);
|
||||
+ _10 = const (i32::MIN, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind unreachable];
|
||||
}
|
||||
|
||||
@ -76,5 +76,13 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 00 00 00 80 01 __ __ __ │ .....░░░
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 8, align: 4) {
|
||||
+ 03 00 00 00 00 __ __ __ │ .....░░░
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
- _6 = CheckedAdd(_4, _5);
|
||||
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue];
|
||||
+ _5 = const 2_i32;
|
||||
+ _6 = CheckedAdd(const 1_i32, const 2_i32);
|
||||
+ _6 = const (3_i32, false);
|
||||
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
- _10 = CheckedAdd(_9, const 1_i32);
|
||||
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue];
|
||||
+ _9 = const i32::MAX;
|
||||
+ _10 = CheckedAdd(const i32::MAX, const 1_i32);
|
||||
+ _10 = const (i32::MIN, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind continue];
|
||||
}
|
||||
|
||||
@ -76,5 +76,13 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 00 00 00 80 01 __ __ __ │ .....░░░
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 8, align: 4) {
|
||||
+ 03 00 00 00 00 __ __ __ │ .....░░░
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// skip-filecheck
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
// unit-test: DataflowConstProp
|
||||
// compile-flags: -Coverflow-checks=on
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
// EMIT_MIR checked.main.DataflowConstProp.diff
|
||||
#[allow(arithmetic_overflow)]
|
||||
|
@ -23,7 +23,8 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = E::V1(const 0_i32);
|
||||
- _1 = E::V1(const 0_i32);
|
||||
+ _1 = const E::V1(0_i32);
|
||||
StorageLive(_2);
|
||||
- _3 = discriminant(_1);
|
||||
- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2];
|
||||
@ -59,5 +60,9 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = E::V1(const 0_i32);
|
||||
- _1 = E::V1(const 0_i32);
|
||||
+ _1 = const E::V1(0_i32);
|
||||
StorageLive(_2);
|
||||
- _3 = discriminant(_1);
|
||||
- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2];
|
||||
@ -59,5 +60,9 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,8 @@
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = const {ALLOC1: &E};
|
||||
_1 = (*_2);
|
||||
- _1 = (*_2);
|
||||
+ _1 = const E::V1(0_i32);
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
- _4 = discriminant(_1);
|
||||
@ -110,6 +111,10 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) {
|
||||
+ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
ALLOC2 (static: RC, size: 4, align: 4) {
|
||||
|
@ -44,7 +44,8 @@
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = const {ALLOC1: &E};
|
||||
_1 = (*_2);
|
||||
- _1 = (*_2);
|
||||
+ _1 = const E::V1(0_i32);
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
- _4 = discriminant(_1);
|
||||
@ -110,6 +111,10 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) {
|
||||
+ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
ALLOC2 (static: RC, size: 8, align: 8) {
|
||||
|
@ -23,7 +23,7 @@
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
|
||||
+ _4 = CheckedAdd(const u8::MAX, const 1_u8);
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
@ -37,5 +37,9 @@
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 2, align: 1) {
|
||||
+ 00 01 │ ..
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
StorageLive(_4);
|
||||
- _4 = CheckedAdd(_2, _3);
|
||||
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
|
||||
+ _4 = CheckedAdd(const u8::MAX, const 1_u8);
|
||||
+ _4 = const (0_u8, true);
|
||||
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];
|
||||
}
|
||||
|
||||
@ -37,5 +37,9 @@
|
||||
_0 = const ();
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 2, align: 1) {
|
||||
+ 00 01 │ ..
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = I32(const 0_i32);
|
||||
- _1 = I32(const 0_i32);
|
||||
+ _1 = const I32(0_i32);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
@ -31,12 +32,20 @@
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
- _2 = I32(move _3);
|
||||
+ _2 = I32(const 0_i32);
|
||||
+ _2 = const I32(0_i32);
|
||||
StorageDead(_3);
|
||||
_0 = const ();
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 4, align: 4) {
|
||||
+ 00 00 00 00 │ ....
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 4, align: 4) {
|
||||
+ 00 00 00 00 │ ....
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,24 @@
|
||||
let mut _3: i32;
|
||||
let mut _5: i32;
|
||||
let mut _6: i32;
|
||||
let mut _11: BigStruct;
|
||||
let mut _16: &&BigStruct;
|
||||
let mut _17: &BigStruct;
|
||||
let mut _18: &BigStruct;
|
||||
let mut _19: &BigStruct;
|
||||
let mut _20: &BigStruct;
|
||||
let mut _21: &BigStruct;
|
||||
let mut _10: SmallStruct;
|
||||
let mut _14: &&SmallStruct;
|
||||
let mut _16: f32;
|
||||
let mut _17: std::option::Option<S>;
|
||||
let mut _18: &[f32];
|
||||
let mut _22: BigStruct;
|
||||
let mut _26: &&BigStruct;
|
||||
let mut _28: f32;
|
||||
let mut _29: std::option::Option<S>;
|
||||
let mut _30: &[f32];
|
||||
let mut _31: &SmallStruct;
|
||||
let mut _32: &SmallStruct;
|
||||
let mut _33: &SmallStruct;
|
||||
let mut _34: &SmallStruct;
|
||||
let mut _35: &BigStruct;
|
||||
let mut _36: &BigStruct;
|
||||
let mut _37: &BigStruct;
|
||||
let mut _38: &BigStruct;
|
||||
scope 1 {
|
||||
debug s => _1;
|
||||
let _2: i32;
|
||||
@ -22,24 +33,44 @@
|
||||
let _4: i32;
|
||||
scope 3 {
|
||||
debug b => _4;
|
||||
let _7: S;
|
||||
let _8: u8;
|
||||
let _9: f32;
|
||||
let _10: S;
|
||||
let _7: f32;
|
||||
let _8: std::option::Option<S>;
|
||||
let _9: &[f32];
|
||||
scope 4 {
|
||||
debug a => _7;
|
||||
debug b => _8;
|
||||
debug c => _9;
|
||||
debug d => _10;
|
||||
let _12: S;
|
||||
let _13: u8;
|
||||
let _14: f32;
|
||||
let _15: S;
|
||||
let _11: f32;
|
||||
let _12: std::option::Option<S>;
|
||||
let _13: &[f32];
|
||||
scope 5 {
|
||||
debug a => _12;
|
||||
debug b => _13;
|
||||
debug c => _14;
|
||||
debug d => _15;
|
||||
debug a => _11;
|
||||
debug b => _12;
|
||||
debug c => _13;
|
||||
let _15: SmallStruct;
|
||||
scope 6 {
|
||||
debug ss => _15;
|
||||
let _19: f32;
|
||||
let _20: std::option::Option<S>;
|
||||
let _21: &[f32];
|
||||
scope 7 {
|
||||
debug a => _19;
|
||||
debug b => _20;
|
||||
debug c => _21;
|
||||
let _23: f32;
|
||||
let _24: std::option::Option<S>;
|
||||
let _25: &[f32];
|
||||
scope 8 {
|
||||
debug a => _23;
|
||||
debug b => _24;
|
||||
debug c => _25;
|
||||
let _27: BigStruct;
|
||||
scope 9 {
|
||||
debug bs => _27;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,7 +79,8 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = S(const 1_i32);
|
||||
- _1 = S(const 1_i32);
|
||||
+ _1 = const S(1_i32);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
- _3 = (_1.0: i32);
|
||||
@ -68,47 +100,95 @@
|
||||
+ _4 = const 6_i32;
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageLive(_11);
|
||||
_11 = const _;
|
||||
StorageLive(_7);
|
||||
- _7 = (_11.0: S);
|
||||
+ _7 = const S(1_i32);
|
||||
StorageLive(_8);
|
||||
- _8 = (_11.1: u8);
|
||||
+ _8 = const 5_u8;
|
||||
StorageLive(_9);
|
||||
- _9 = (_11.2: f32);
|
||||
+ _9 = const 7f32;
|
||||
StorageLive(_10);
|
||||
- _10 = (_11.3: S);
|
||||
+ _10 = const S(13_i32);
|
||||
StorageDead(_11);
|
||||
StorageLive(_16);
|
||||
_16 = const {ALLOC1: &&BigStruct};
|
||||
_17 = deref_copy (*_16);
|
||||
StorageLive(_12);
|
||||
_18 = deref_copy (*_16);
|
||||
- _12 = ((*_18).0: S);
|
||||
+ _12 = const S(1_i32);
|
||||
StorageLive(_13);
|
||||
_19 = deref_copy (*_16);
|
||||
- _13 = ((*_19).1: u8);
|
||||
+ _13 = const 5_u8;
|
||||
_10 = const _;
|
||||
StorageLive(_7);
|
||||
- _7 = (_10.0: f32);
|
||||
+ _7 = const 4f32;
|
||||
StorageLive(_8);
|
||||
- _8 = (_10.1: std::option::Option<S>);
|
||||
+ _8 = const Option::<S>::Some(S(1_i32));
|
||||
StorageLive(_9);
|
||||
_9 = (_10.2: &[f32]);
|
||||
StorageDead(_10);
|
||||
StorageLive(_14);
|
||||
_20 = deref_copy (*_16);
|
||||
- _14 = ((*_20).2: f32);
|
||||
+ _14 = const 7f32;
|
||||
StorageLive(_15);
|
||||
_21 = deref_copy (*_16);
|
||||
- _15 = ((*_21).3: S);
|
||||
+ _15 = const S(13_i32);
|
||||
StorageDead(_16);
|
||||
_0 = const ();
|
||||
StorageDead(_15);
|
||||
_14 = const {ALLOC4: &&SmallStruct};
|
||||
_31 = deref_copy (*_14);
|
||||
StorageLive(_11);
|
||||
_32 = deref_copy (*_14);
|
||||
- _11 = ((*_32).0: f32);
|
||||
+ _11 = const 9f32;
|
||||
StorageLive(_12);
|
||||
_33 = deref_copy (*_14);
|
||||
_12 = ((*_33).1: std::option::Option<S>);
|
||||
StorageLive(_13);
|
||||
_34 = deref_copy (*_14);
|
||||
_13 = ((*_34).2: &[f32]);
|
||||
StorageDead(_14);
|
||||
StorageLive(_15);
|
||||
StorageLive(_16);
|
||||
- _16 = _11;
|
||||
+ _16 = const 9f32;
|
||||
StorageLive(_17);
|
||||
_17 = _12;
|
||||
StorageLive(_18);
|
||||
_18 = _13;
|
||||
- _15 = SmallStruct(move _16, move _17, move _18);
|
||||
+ _15 = SmallStruct(const 9f32, move _17, move _18);
|
||||
StorageDead(_18);
|
||||
StorageDead(_17);
|
||||
StorageDead(_16);
|
||||
StorageLive(_22);
|
||||
_22 = const _;
|
||||
StorageLive(_19);
|
||||
- _19 = (_22.0: f32);
|
||||
+ _19 = const 25f32;
|
||||
StorageLive(_20);
|
||||
_20 = (_22.1: std::option::Option<S>);
|
||||
StorageLive(_21);
|
||||
_21 = (_22.2: &[f32]);
|
||||
StorageDead(_22);
|
||||
StorageLive(_26);
|
||||
_26 = const {ALLOC5: &&BigStruct};
|
||||
_35 = deref_copy (*_26);
|
||||
StorageLive(_23);
|
||||
_36 = deref_copy (*_26);
|
||||
- _23 = ((*_36).0: f32);
|
||||
+ _23 = const 82f32;
|
||||
StorageLive(_24);
|
||||
_37 = deref_copy (*_26);
|
||||
- _24 = ((*_37).1: std::option::Option<S>);
|
||||
+ _24 = const Option::<S>::Some(S(35_i32));
|
||||
StorageLive(_25);
|
||||
_38 = deref_copy (*_26);
|
||||
_25 = ((*_38).2: &[f32]);
|
||||
StorageDead(_26);
|
||||
StorageLive(_27);
|
||||
StorageLive(_28);
|
||||
- _28 = _23;
|
||||
+ _28 = const 82f32;
|
||||
StorageLive(_29);
|
||||
- _29 = _24;
|
||||
+ _29 = const Option::<S>::Some(S(35_i32));
|
||||
StorageLive(_30);
|
||||
_30 = _25;
|
||||
- _27 = BigStruct(move _28, move _29, move _30);
|
||||
+ _27 = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move _30);
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
_0 = const ();
|
||||
StorageDead(_27);
|
||||
StorageDead(_25);
|
||||
StorageDead(_24);
|
||||
StorageDead(_23);
|
||||
StorageDead(_21);
|
||||
StorageDead(_20);
|
||||
StorageDead(_19);
|
||||
StorageDead(_15);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
StorageDead(_10);
|
||||
StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
@ -117,13 +197,51 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC6 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC7 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC8 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC9 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 01 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC10 (size: 4, align: 4) {
|
||||
+ 01 00 00 00 │ ....
|
||||
}
|
||||
|
||||
ALLOC1 (static: STAT, size: 4, align: 4) {
|
||||
ALLOC5 (static: BIG_STAT, size: 4, align: 4) {
|
||||
╾ALLOC0╼ │ ╾──╼
|
||||
}
|
||||
|
||||
ALLOC0 (size: 16, align: 4) {
|
||||
01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░
|
||||
ALLOC0 (size: 20, align: 4) {
|
||||
0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼....
|
||||
0x10 │ 00 00 a4 42 │ ...B
|
||||
}
|
||||
|
||||
ALLOC1 (size: 8, align: 4) {
|
||||
00 00 34 42 00 00 90 42 │ ..4B...B
|
||||
}
|
||||
|
||||
ALLOC4 (static: SMALL_STAT, size: 4, align: 4) {
|
||||
╾ALLOC2╼ │ ╾──╼
|
||||
}
|
||||
|
||||
ALLOC2 (size: 20, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 10 41 │ ...A
|
||||
}
|
||||
|
||||
ALLOC3 (size: 4, align: 4) {
|
||||
00 00 50 41 │ ..PA
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,24 @@
|
||||
let mut _3: i32;
|
||||
let mut _5: i32;
|
||||
let mut _6: i32;
|
||||
let mut _11: BigStruct;
|
||||
let mut _16: &&BigStruct;
|
||||
let mut _17: &BigStruct;
|
||||
let mut _18: &BigStruct;
|
||||
let mut _19: &BigStruct;
|
||||
let mut _20: &BigStruct;
|
||||
let mut _21: &BigStruct;
|
||||
let mut _10: SmallStruct;
|
||||
let mut _14: &&SmallStruct;
|
||||
let mut _16: f32;
|
||||
let mut _17: std::option::Option<S>;
|
||||
let mut _18: &[f32];
|
||||
let mut _22: BigStruct;
|
||||
let mut _26: &&BigStruct;
|
||||
let mut _28: f32;
|
||||
let mut _29: std::option::Option<S>;
|
||||
let mut _30: &[f32];
|
||||
let mut _31: &SmallStruct;
|
||||
let mut _32: &SmallStruct;
|
||||
let mut _33: &SmallStruct;
|
||||
let mut _34: &SmallStruct;
|
||||
let mut _35: &BigStruct;
|
||||
let mut _36: &BigStruct;
|
||||
let mut _37: &BigStruct;
|
||||
let mut _38: &BigStruct;
|
||||
scope 1 {
|
||||
debug s => _1;
|
||||
let _2: i32;
|
||||
@ -22,24 +33,44 @@
|
||||
let _4: i32;
|
||||
scope 3 {
|
||||
debug b => _4;
|
||||
let _7: S;
|
||||
let _8: u8;
|
||||
let _9: f32;
|
||||
let _10: S;
|
||||
let _7: f32;
|
||||
let _8: std::option::Option<S>;
|
||||
let _9: &[f32];
|
||||
scope 4 {
|
||||
debug a => _7;
|
||||
debug b => _8;
|
||||
debug c => _9;
|
||||
debug d => _10;
|
||||
let _12: S;
|
||||
let _13: u8;
|
||||
let _14: f32;
|
||||
let _15: S;
|
||||
let _11: f32;
|
||||
let _12: std::option::Option<S>;
|
||||
let _13: &[f32];
|
||||
scope 5 {
|
||||
debug a => _12;
|
||||
debug b => _13;
|
||||
debug c => _14;
|
||||
debug d => _15;
|
||||
debug a => _11;
|
||||
debug b => _12;
|
||||
debug c => _13;
|
||||
let _15: SmallStruct;
|
||||
scope 6 {
|
||||
debug ss => _15;
|
||||
let _19: f32;
|
||||
let _20: std::option::Option<S>;
|
||||
let _21: &[f32];
|
||||
scope 7 {
|
||||
debug a => _19;
|
||||
debug b => _20;
|
||||
debug c => _21;
|
||||
let _23: f32;
|
||||
let _24: std::option::Option<S>;
|
||||
let _25: &[f32];
|
||||
scope 8 {
|
||||
debug a => _23;
|
||||
debug b => _24;
|
||||
debug c => _25;
|
||||
let _27: BigStruct;
|
||||
scope 9 {
|
||||
debug bs => _27;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,7 +79,8 @@
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = S(const 1_i32);
|
||||
- _1 = S(const 1_i32);
|
||||
+ _1 = const S(1_i32);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
- _3 = (_1.0: i32);
|
||||
@ -68,47 +100,95 @@
|
||||
+ _4 = const 6_i32;
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
StorageLive(_11);
|
||||
_11 = const _;
|
||||
StorageLive(_7);
|
||||
- _7 = (_11.0: S);
|
||||
+ _7 = const S(1_i32);
|
||||
StorageLive(_8);
|
||||
- _8 = (_11.1: u8);
|
||||
+ _8 = const 5_u8;
|
||||
StorageLive(_9);
|
||||
- _9 = (_11.2: f32);
|
||||
+ _9 = const 7f32;
|
||||
StorageLive(_10);
|
||||
- _10 = (_11.3: S);
|
||||
+ _10 = const S(13_i32);
|
||||
StorageDead(_11);
|
||||
StorageLive(_16);
|
||||
_16 = const {ALLOC1: &&BigStruct};
|
||||
_17 = deref_copy (*_16);
|
||||
StorageLive(_12);
|
||||
_18 = deref_copy (*_16);
|
||||
- _12 = ((*_18).0: S);
|
||||
+ _12 = const S(1_i32);
|
||||
StorageLive(_13);
|
||||
_19 = deref_copy (*_16);
|
||||
- _13 = ((*_19).1: u8);
|
||||
+ _13 = const 5_u8;
|
||||
_10 = const _;
|
||||
StorageLive(_7);
|
||||
- _7 = (_10.0: f32);
|
||||
+ _7 = const 4f32;
|
||||
StorageLive(_8);
|
||||
- _8 = (_10.1: std::option::Option<S>);
|
||||
+ _8 = const Option::<S>::Some(S(1_i32));
|
||||
StorageLive(_9);
|
||||
_9 = (_10.2: &[f32]);
|
||||
StorageDead(_10);
|
||||
StorageLive(_14);
|
||||
_20 = deref_copy (*_16);
|
||||
- _14 = ((*_20).2: f32);
|
||||
+ _14 = const 7f32;
|
||||
StorageLive(_15);
|
||||
_21 = deref_copy (*_16);
|
||||
- _15 = ((*_21).3: S);
|
||||
+ _15 = const S(13_i32);
|
||||
StorageDead(_16);
|
||||
_0 = const ();
|
||||
StorageDead(_15);
|
||||
_14 = const {ALLOC4: &&SmallStruct};
|
||||
_31 = deref_copy (*_14);
|
||||
StorageLive(_11);
|
||||
_32 = deref_copy (*_14);
|
||||
- _11 = ((*_32).0: f32);
|
||||
+ _11 = const 9f32;
|
||||
StorageLive(_12);
|
||||
_33 = deref_copy (*_14);
|
||||
_12 = ((*_33).1: std::option::Option<S>);
|
||||
StorageLive(_13);
|
||||
_34 = deref_copy (*_14);
|
||||
_13 = ((*_34).2: &[f32]);
|
||||
StorageDead(_14);
|
||||
StorageLive(_15);
|
||||
StorageLive(_16);
|
||||
- _16 = _11;
|
||||
+ _16 = const 9f32;
|
||||
StorageLive(_17);
|
||||
_17 = _12;
|
||||
StorageLive(_18);
|
||||
_18 = _13;
|
||||
- _15 = SmallStruct(move _16, move _17, move _18);
|
||||
+ _15 = SmallStruct(const 9f32, move _17, move _18);
|
||||
StorageDead(_18);
|
||||
StorageDead(_17);
|
||||
StorageDead(_16);
|
||||
StorageLive(_22);
|
||||
_22 = const _;
|
||||
StorageLive(_19);
|
||||
- _19 = (_22.0: f32);
|
||||
+ _19 = const 25f32;
|
||||
StorageLive(_20);
|
||||
_20 = (_22.1: std::option::Option<S>);
|
||||
StorageLive(_21);
|
||||
_21 = (_22.2: &[f32]);
|
||||
StorageDead(_22);
|
||||
StorageLive(_26);
|
||||
_26 = const {ALLOC5: &&BigStruct};
|
||||
_35 = deref_copy (*_26);
|
||||
StorageLive(_23);
|
||||
_36 = deref_copy (*_26);
|
||||
- _23 = ((*_36).0: f32);
|
||||
+ _23 = const 82f32;
|
||||
StorageLive(_24);
|
||||
_37 = deref_copy (*_26);
|
||||
- _24 = ((*_37).1: std::option::Option<S>);
|
||||
+ _24 = const Option::<S>::Some(S(35_i32));
|
||||
StorageLive(_25);
|
||||
_38 = deref_copy (*_26);
|
||||
_25 = ((*_38).2: &[f32]);
|
||||
StorageDead(_26);
|
||||
StorageLive(_27);
|
||||
StorageLive(_28);
|
||||
- _28 = _23;
|
||||
+ _28 = const 82f32;
|
||||
StorageLive(_29);
|
||||
- _29 = _24;
|
||||
+ _29 = const Option::<S>::Some(S(35_i32));
|
||||
StorageLive(_30);
|
||||
_30 = _25;
|
||||
- _27 = BigStruct(move _28, move _29, move _30);
|
||||
+ _27 = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move _30);
|
||||
StorageDead(_30);
|
||||
StorageDead(_29);
|
||||
StorageDead(_28);
|
||||
_0 = const ();
|
||||
StorageDead(_27);
|
||||
StorageDead(_25);
|
||||
StorageDead(_24);
|
||||
StorageDead(_23);
|
||||
StorageDead(_21);
|
||||
StorageDead(_20);
|
||||
StorageDead(_19);
|
||||
StorageDead(_15);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
StorageDead(_10);
|
||||
StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageDead(_7);
|
||||
@ -117,13 +197,51 @@
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC6 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC7 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC8 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 23 00 00 00 │ ....#...
|
||||
+ }
|
||||
+
|
||||
+ ALLOC9 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 01 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC10 (size: 4, align: 4) {
|
||||
+ 01 00 00 00 │ ....
|
||||
}
|
||||
|
||||
ALLOC1 (static: STAT, size: 8, align: 8) {
|
||||
ALLOC5 (static: BIG_STAT, size: 8, align: 8) {
|
||||
╾ALLOC0╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
ALLOC0 (size: 16, align: 4) {
|
||||
01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░
|
||||
ALLOC0 (size: 32, align: 8) {
|
||||
0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼
|
||||
0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░
|
||||
}
|
||||
|
||||
ALLOC1 (size: 8, align: 4) {
|
||||
00 00 34 42 00 00 90 42 │ ..4B...B
|
||||
}
|
||||
|
||||
ALLOC4 (static: SMALL_STAT, size: 8, align: 8) {
|
||||
╾ALLOC2╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
ALLOC2 (size: 32, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼
|
||||
0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░
|
||||
}
|
||||
|
||||
ALLOC3 (size: 4, align: 4) {
|
||||
00 00 50 41 │ ..PA
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,10 @@
|
||||
struct S(i32);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct BigStruct(S, u8, f32, S);
|
||||
struct SmallStruct(f32, Option<S>, &'static [f32]);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct BigStruct(f32, Option<S>, &'static [f32]);
|
||||
|
||||
// EMIT_MIR struct.main.DataflowConstProp.diff
|
||||
fn main() {
|
||||
@ -15,9 +18,21 @@ fn main() {
|
||||
s.0 = 3;
|
||||
let b = a + s.0;
|
||||
|
||||
const VAL: BigStruct = BigStruct(S(1), 5, 7., S(13));
|
||||
let BigStruct(a, b, c, d) = VAL;
|
||||
const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]);
|
||||
let SmallStruct(a, b, c) = SMALL_VAL;
|
||||
|
||||
static STAT: &BigStruct = &BigStruct(S(1), 5, 7., S(13));
|
||||
let BigStruct(a, b, c, d) = *STAT;
|
||||
static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]);
|
||||
let SmallStruct(a, b, c) = *SMALL_STAT;
|
||||
|
||||
let ss = SmallStruct(a, b, c);
|
||||
|
||||
const BIG_VAL: BigStruct = BigStruct(25., None, &[]);
|
||||
let BigStruct(a, b, c) = BIG_VAL;
|
||||
|
||||
static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]);
|
||||
let BigStruct(a, b, c) = *BIG_STAT;
|
||||
|
||||
// We arbitrarily limit the size of synthetized values to 4 pointers.
|
||||
// `BigStruct` can be read, but we will keep a MIR aggregate for this.
|
||||
let bs = BigStruct(a, b, c);
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ pub unsafe fn undef_union_as_integer() -> u32 {
|
||||
// EMIT_MIR transmute.unreachable_direct.DataflowConstProp.diff
|
||||
pub unsafe fn unreachable_direct() -> ! {
|
||||
// CHECK-LABEL: fn unreachable_direct(
|
||||
// CHECK: [[unit:_.*]] = ();
|
||||
// CHECK: move [[unit]] as Never (Transmute);
|
||||
// CHECK: = const ();
|
||||
// CHECK: = const ZeroSized: Never;
|
||||
let x: Never = unsafe { transmute(()) };
|
||||
match x {}
|
||||
}
|
||||
|
@ -11,8 +11,10 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = ();
|
||||
_1 = Union32 { value: move _2 };
|
||||
- _2 = ();
|
||||
- _1 = Union32 { value: move _2 };
|
||||
+ _2 = const ();
|
||||
+ _1 = Union32 { value: const () };
|
||||
StorageDead(_2);
|
||||
_0 = move _1 as u32 (Transmute);
|
||||
StorageDead(_1);
|
||||
|
@ -11,8 +11,10 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = ();
|
||||
_1 = Union32 { value: move _2 };
|
||||
- _2 = ();
|
||||
- _1 = Union32 { value: move _2 };
|
||||
+ _2 = const ();
|
||||
+ _1 = Union32 { value: const () };
|
||||
StorageDead(_2);
|
||||
_0 = move _1 as u32 (Transmute);
|
||||
StorageDead(_1);
|
||||
|
@ -14,8 +14,10 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = ();
|
||||
_1 = move _2 as Never (Transmute);
|
||||
- _2 = ();
|
||||
- _1 = move _2 as Never (Transmute);
|
||||
+ _2 = const ();
|
||||
+ _1 = const ZeroSized: Never;
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,10 @@
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
_2 = ();
|
||||
_1 = move _2 as Never (Transmute);
|
||||
- _2 = ();
|
||||
- _1 = move _2 as Never (Transmute);
|
||||
+ _2 = const ();
|
||||
+ _1 = const ZeroSized: Never;
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
let mut _8: i32;
|
||||
let mut _9: i32;
|
||||
let mut _10: i32;
|
||||
let mut _12: i32;
|
||||
let mut _13: (i32, i32);
|
||||
let mut _14: i32;
|
||||
scope 1 {
|
||||
debug a => _1;
|
||||
let _2: i32;
|
||||
@ -19,13 +22,18 @@
|
||||
let _6: i32;
|
||||
scope 3 {
|
||||
debug c => _6;
|
||||
let _11: (i32, (i32, i32), i32);
|
||||
scope 4 {
|
||||
debug d => _11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
_1 = (const 1_i32, const 2_i32);
|
||||
- _1 = (const 1_i32, const 2_i32);
|
||||
+ _1 = const (1_i32, 2_i32);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
@ -41,7 +49,8 @@
|
||||
- _2 = Add(move _3, const 3_i32);
|
||||
+ _2 = const 6_i32;
|
||||
StorageDead(_3);
|
||||
_1 = (const 2_i32, const 3_i32);
|
||||
- _1 = (const 2_i32, const 3_i32);
|
||||
+ _1 = const (2_i32, 3_i32);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
@ -61,11 +70,43 @@
|
||||
+ _6 = const 11_i32;
|
||||
StorageDead(_10);
|
||||
StorageDead(_7);
|
||||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
- _12 = _2;
|
||||
+ _12 = const 6_i32;
|
||||
StorageLive(_13);
|
||||
- _13 = _1;
|
||||
+ _13 = const (2_i32, 3_i32);
|
||||
StorageLive(_14);
|
||||
- _14 = _6;
|
||||
- _11 = (move _12, move _13, move _14);
|
||||
+ _14 = const 11_i32;
|
||||
+ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
_0 = const ();
|
||||
StorageDead(_11);
|
||||
StorageDead(_6);
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC2 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 02 00 00 00 │ ........
|
||||
}
|
||||
|
@ -0,0 +1,112 @@
|
||||
- // MIR for `main` before DataflowConstProp
|
||||
+ // MIR for `main` after DataflowConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let mut _1: (i32, i32);
|
||||
let mut _3: i32;
|
||||
let mut _4: i32;
|
||||
let mut _5: i32;
|
||||
let mut _7: i32;
|
||||
let mut _8: i32;
|
||||
let mut _9: i32;
|
||||
let mut _10: i32;
|
||||
let mut _12: i32;
|
||||
let mut _13: (i32, i32);
|
||||
let mut _14: i32;
|
||||
scope 1 {
|
||||
debug a => _1;
|
||||
let _2: i32;
|
||||
scope 2 {
|
||||
debug b => _2;
|
||||
let _6: i32;
|
||||
scope 3 {
|
||||
debug c => _6;
|
||||
let _11: (i32, (i32, i32), i32);
|
||||
scope 4 {
|
||||
debug d => _11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
- _1 = (const 1_i32, const 2_i32);
|
||||
+ _1 = const (1_i32, 2_i32);
|
||||
StorageLive(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
- _4 = (_1.0: i32);
|
||||
+ _4 = const 1_i32;
|
||||
StorageLive(_5);
|
||||
- _5 = (_1.1: i32);
|
||||
- _3 = Add(move _4, move _5);
|
||||
+ _5 = const 2_i32;
|
||||
+ _3 = const 3_i32;
|
||||
StorageDead(_5);
|
||||
StorageDead(_4);
|
||||
- _2 = Add(move _3, const 3_i32);
|
||||
+ _2 = const 6_i32;
|
||||
StorageDead(_3);
|
||||
- _1 = (const 2_i32, const 3_i32);
|
||||
+ _1 = const (2_i32, 3_i32);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
- _8 = (_1.0: i32);
|
||||
+ _8 = const 2_i32;
|
||||
StorageLive(_9);
|
||||
- _9 = (_1.1: i32);
|
||||
- _7 = Add(move _8, move _9);
|
||||
+ _9 = const 3_i32;
|
||||
+ _7 = const 5_i32;
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
StorageLive(_10);
|
||||
- _10 = _2;
|
||||
- _6 = Add(move _7, move _10);
|
||||
+ _10 = const 6_i32;
|
||||
+ _6 = const 11_i32;
|
||||
StorageDead(_10);
|
||||
StorageDead(_7);
|
||||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
- _12 = _2;
|
||||
+ _12 = const 6_i32;
|
||||
StorageLive(_13);
|
||||
- _13 = _1;
|
||||
+ _13 = const (2_i32, 3_i32);
|
||||
StorageLive(_14);
|
||||
- _14 = _6;
|
||||
- _11 = (move _12, move _13, move _14);
|
||||
+ _14 = const 11_i32;
|
||||
+ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32);
|
||||
StorageDead(_14);
|
||||
StorageDead(_13);
|
||||
StorageDead(_12);
|
||||
_0 = const ();
|
||||
StorageDead(_11);
|
||||
StorageDead(_6);
|
||||
StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ ALLOC0 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC1 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC2 (size: 8, align: 4) {
|
||||
+ 02 00 00 00 03 00 00 00 │ ........
|
||||
+ }
|
||||
+
|
||||
+ ALLOC3 (size: 8, align: 4) {
|
||||
+ 01 00 00 00 02 00 00 00 │ ........
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
// skip-filecheck
|
||||
// unit-test: DataflowConstProp
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
|
||||
// EMIT_MIR tuple.main.DataflowConstProp.diff
|
||||
fn main() {
|
||||
@ -7,4 +8,6 @@ fn main() {
|
||||
let b = a.0 + a.1 + 3;
|
||||
a = (2, 3);
|
||||
let c = a.0 + a.1 + b;
|
||||
|
||||
let d = (b, a, c);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user