Create place and value indices on-demand.
This commit is contained in:
parent
051dd12f9e
commit
9415102fb4
5 changed files with 315 additions and 224 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use std::assert_matches::debug_assert_matches;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::ops::Range;
|
||||
|
||||
|
|
@ -350,32 +351,47 @@ pub struct Map<'tcx> {
|
|||
projections: FxHashMap<(PlaceIndex, TrackElem), PlaceIndex>,
|
||||
places: IndexVec<PlaceIndex, PlaceInfo<'tcx>>,
|
||||
value_count: usize,
|
||||
mode: PlaceCollectionMode,
|
||||
// The Range corresponds to a slice into `inner_values_buffer`.
|
||||
inner_values: IndexVec<PlaceIndex, Range<usize>>,
|
||||
inner_values_buffer: Vec<ValueIndex>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum PlaceCollectionMode {
|
||||
Full { value_limit: Option<usize> },
|
||||
OnDemand,
|
||||
}
|
||||
|
||||
impl<'tcx> Map<'tcx> {
|
||||
/// Returns a map that only tracks places whose type has scalar layout.
|
||||
///
|
||||
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
|
||||
/// chosen is an implementation detail and may not be relied upon (other than that their type
|
||||
/// are scalars).
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) -> Self {
|
||||
let capacity = 4 * body.local_decls.len() + value_limit.unwrap_or(body.local_decls.len());
|
||||
#[tracing::instrument(level = "trace", skip(tcx, body))]
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, mode: PlaceCollectionMode) -> Self {
|
||||
tracing::trace!(def_id=?body.source.def_id());
|
||||
let capacity = 4 * body.local_decls.len();
|
||||
let mut map = Self {
|
||||
locals: IndexVec::from_elem(None, &body.local_decls),
|
||||
projections: FxHashMap::default(),
|
||||
places: IndexVec::with_capacity(capacity),
|
||||
value_count: 0,
|
||||
inner_values: IndexVec::with_capacity(capacity),
|
||||
mode,
|
||||
inner_values: IndexVec::new(),
|
||||
inner_values_buffer: Vec::new(),
|
||||
};
|
||||
map.register_locals(tcx, body);
|
||||
map.collect_places(tcx, body);
|
||||
map.propagate_assignments(tcx, body);
|
||||
map.create_values(tcx, body, value_limit);
|
||||
map.trim_useless_places();
|
||||
match mode {
|
||||
PlaceCollectionMode::Full { value_limit } => {
|
||||
map.collect_places(tcx, body);
|
||||
map.propagate_assignments(tcx, body);
|
||||
map.create_values(tcx, body, value_limit);
|
||||
map.trim_useless_places();
|
||||
}
|
||||
PlaceCollectionMode::OnDemand => {}
|
||||
}
|
||||
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
|
||||
map
|
||||
}
|
||||
|
|
@ -427,12 +443,18 @@ impl<'tcx> Map<'tcx> {
|
|||
match rhs {
|
||||
Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs))
|
||||
| Rvalue::CopyForDeref(rhs) => {
|
||||
let Some(lhs) = self.register_place(tcx, body, *lhs) else { continue };
|
||||
let Some(rhs) = self.register_place(tcx, body, *rhs) else { continue };
|
||||
let Some(lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
|
||||
continue;
|
||||
};
|
||||
let Some(rhs) = self.register_place_and_discr(tcx, body, *rhs) else {
|
||||
continue;
|
||||
};
|
||||
assignments.insert((lhs, rhs));
|
||||
}
|
||||
Rvalue::Aggregate(kind, fields) => {
|
||||
let Some(mut lhs) = self.register_place(tcx, body, *lhs) else { continue };
|
||||
let Some(mut lhs) = self.register_place_and_discr(tcx, body, *lhs) else {
|
||||
continue;
|
||||
};
|
||||
match **kind {
|
||||
// Do not propagate unions.
|
||||
AggregateKind::Adt(_, _, _, _, Some(_)) => continue,
|
||||
|
|
@ -455,7 +477,7 @@ impl<'tcx> Map<'tcx> {
|
|||
}
|
||||
for (index, field) in fields.iter_enumerated() {
|
||||
if let Some(rhs) = field.place()
|
||||
&& let Some(rhs) = self.register_place(tcx, body, rhs)
|
||||
&& let Some(rhs) = self.register_place_and_discr(tcx, body, rhs)
|
||||
{
|
||||
let lhs = self.register_place_index(
|
||||
self.places[rhs].ty,
|
||||
|
|
@ -512,6 +534,7 @@ impl<'tcx> Map<'tcx> {
|
|||
/// Create values for places whose type have scalar layout.
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
|
||||
fn create_values(&mut self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, value_limit: Option<usize>) {
|
||||
debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
|
||||
let typing_env = body.typing_env(tcx);
|
||||
for place_info in self.places.iter_mut() {
|
||||
// The user requires a bound on the number of created values.
|
||||
|
|
@ -550,6 +573,7 @@ impl<'tcx> Map<'tcx> {
|
|||
/// Trim useless places.
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
fn trim_useless_places(&mut self) {
|
||||
debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
|
||||
for opt_place in self.locals.iter_mut() {
|
||||
if let Some(place) = *opt_place
|
||||
&& self.inner_values[place].is_empty()
|
||||
|
|
@ -562,7 +586,7 @@ impl<'tcx> Map<'tcx> {
|
|||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self), ret)]
|
||||
fn register_place_index(
|
||||
pub fn register_place_index(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
base: PlaceIndex,
|
||||
|
|
@ -576,49 +600,124 @@ impl<'tcx> Map<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, body))]
|
||||
fn register_place(
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
|
||||
pub fn register_place(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
place: Place<'tcx>,
|
||||
tail: Option<TrackElem>,
|
||||
) -> Option<PlaceIndex> {
|
||||
// Create a place for this projection.
|
||||
let mut place_index = self.locals[place.local]?;
|
||||
let mut ty = PlaceTy::from_ty(body.local_decls[place.local].ty);
|
||||
tracing::trace!(?place_index, ?ty);
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
self.register_place_index(tcx.types.usize, place_index, TrackElem::DerefLen);
|
||||
} else if ty.ty.is_enum() {
|
||||
let discriminant_ty = ty.ty.discriminant_ty(tcx);
|
||||
self.register_place_index(discriminant_ty, place_index, TrackElem::Discriminant);
|
||||
}
|
||||
|
||||
for proj in place.projection {
|
||||
let track_elem = proj.try_into().ok()?;
|
||||
ty = ty.projection_ty(tcx, proj);
|
||||
place_index = self.register_place_index(ty.ty, place_index, track_elem);
|
||||
tracing::trace!(?proj, ?place_index, ?ty);
|
||||
}
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
self.register_place_index(tcx.types.usize, place_index, TrackElem::DerefLen);
|
||||
} else if ty.ty.is_enum() {
|
||||
let discriminant_ty = ty.ty.discriminant_ty(tcx);
|
||||
self.register_place_index(discriminant_ty, place_index, TrackElem::Discriminant);
|
||||
}
|
||||
if let Some(tail) = tail {
|
||||
let ty = match tail {
|
||||
TrackElem::Discriminant => ty.ty.discriminant_ty(tcx),
|
||||
TrackElem::Variant(..) | TrackElem::Field(..) => todo!(),
|
||||
TrackElem::DerefLen => tcx.types.usize,
|
||||
};
|
||||
place_index = self.register_place_index(ty, place_index, tail);
|
||||
}
|
||||
|
||||
Some(place_index)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, body), ret)]
|
||||
fn register_place_and_discr(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
place: Place<'tcx>,
|
||||
) -> Option<PlaceIndex> {
|
||||
let place = self.register_place(tcx, body, place, None)?;
|
||||
let ty = self.places[place].ty;
|
||||
|
||||
if let ty::Ref(_, ref_ty, _) | ty::RawPtr(ref_ty, _) = ty.kind()
|
||||
&& let ty::Slice(..) = ref_ty.kind()
|
||||
{
|
||||
self.register_place_index(tcx.types.usize, place, TrackElem::DerefLen);
|
||||
} else if ty.is_enum() {
|
||||
let discriminant_ty = ty.discriminant_ty(tcx);
|
||||
self.register_place_index(discriminant_ty, place, TrackElem::Discriminant);
|
||||
}
|
||||
|
||||
Some(place)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, tcx, typing_env), ret)]
|
||||
pub fn register_value(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
place: PlaceIndex,
|
||||
) -> Option<ValueIndex> {
|
||||
let place_info = &mut self.places[place];
|
||||
if let Some(value) = place_info.value_index {
|
||||
return Some(value);
|
||||
}
|
||||
|
||||
if let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, place_info.ty) {
|
||||
place_info.ty = ty;
|
||||
}
|
||||
|
||||
// Allocate a value slot if it doesn't have one, and the user requested one.
|
||||
if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(place_info.ty))
|
||||
&& layout.backend_repr.is_scalar()
|
||||
{
|
||||
place_info.value_index = Some(self.value_count.into());
|
||||
self.value_count += 1;
|
||||
}
|
||||
|
||||
place_info.value_index
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, f))]
|
||||
pub fn register_copy_tree(
|
||||
&mut self,
|
||||
// Tree to copy.
|
||||
source: PlaceIndex,
|
||||
// Tree to build.
|
||||
target: PlaceIndex,
|
||||
f: &mut impl FnMut(ValueIndex, ValueIndex),
|
||||
) {
|
||||
if let Some(source_value) = self.places[source].value_index {
|
||||
let target_value = *self.places[target].value_index.get_or_insert_with(|| {
|
||||
let value_index = self.value_count.into();
|
||||
self.value_count += 1;
|
||||
value_index
|
||||
});
|
||||
f(source_value, target_value)
|
||||
}
|
||||
|
||||
// Iterate over `source` children and recurse.
|
||||
let mut source_child_iter = self.places[source].first_child;
|
||||
while let Some(source_child) = source_child_iter {
|
||||
source_child_iter = self.places[source_child].next_sibling;
|
||||
|
||||
// Try to find corresponding child and recurse. Reasoning is similar as above.
|
||||
let source_info = &self.places[source_child];
|
||||
let source_ty = source_info.ty;
|
||||
let source_elem = source_info.proj_elem.unwrap();
|
||||
let target_child = self.register_place_index(source_ty, target, source_elem);
|
||||
self.register_copy_tree(source_child, target_child, f);
|
||||
}
|
||||
}
|
||||
|
||||
/// Precompute the list of values inside `root` and store it inside
|
||||
/// as a slice within `inner_values_buffer`.
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
|
||||
debug_assert_matches!(self.mode, PlaceCollectionMode::Full { .. });
|
||||
let start = self.inner_values_buffer.len();
|
||||
if let Some(vi) = self.places[root].value_index {
|
||||
self.inner_values_buffer.push(vi);
|
||||
|
|
@ -649,7 +748,7 @@ impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
self.map.register_place(self.tcx, self.body, *place);
|
||||
self.map.register_place_and_discr(self.tcx, self.body, *place);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -724,6 +823,7 @@ impl<'tcx> Map<'tcx> {
|
|||
///
|
||||
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
|
||||
/// as such.
|
||||
#[tracing::instrument(level = "trace", skip(self, f))]
|
||||
pub fn for_each_aliasing_place(
|
||||
&self,
|
||||
place: PlaceRef<'_>,
|
||||
|
|
@ -758,6 +858,7 @@ impl<'tcx> Map<'tcx> {
|
|||
}
|
||||
|
||||
/// Invoke the given function on all the descendants of the given place, except one branch.
|
||||
#[tracing::instrument(level = "trace", skip(self, f))]
|
||||
fn for_each_variant_sibling(
|
||||
&self,
|
||||
parent: PlaceIndex,
|
||||
|
|
@ -784,9 +885,22 @@ impl<'tcx> Map<'tcx> {
|
|||
}
|
||||
|
||||
/// Invoke a function on each value in the given place and all descendants.
|
||||
#[tracing::instrument(level = "trace", skip(self, f))]
|
||||
fn for_each_value_inside(&self, root: PlaceIndex, f: &mut impl FnMut(ValueIndex)) {
|
||||
for &v in self.values_inside(root) {
|
||||
f(v)
|
||||
if let Some(range) = self.inner_values.get(root) {
|
||||
// Optimized path: we have cached the inner values.
|
||||
let values = &self.inner_values_buffer[range.clone()];
|
||||
for &v in values {
|
||||
f(v)
|
||||
}
|
||||
} else {
|
||||
if let Some(root) = self.places[root].value_index {
|
||||
f(root)
|
||||
}
|
||||
|
||||
for child in self.children(root) {
|
||||
self.for_each_value_inside(child, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -799,7 +913,9 @@ impl<'tcx> Map<'tcx> {
|
|||
f: &mut impl FnMut(PlaceIndex, &O),
|
||||
) {
|
||||
// Fast path is there is nothing to do.
|
||||
if self.inner_values[root].is_empty() {
|
||||
if let Some(value_range) = self.inner_values.get(root)
|
||||
&& value_range.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||
use rustc_mir_dataflow::fmt::DebugWithContext;
|
||||
use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
|
||||
use rustc_mir_dataflow::value_analysis::{
|
||||
Map, PlaceIndex, State, TrackElem, ValueOrPlace, debug_with_context,
|
||||
Map, PlaceCollectionMode, PlaceIndex, State, TrackElem, ValueOrPlace, debug_with_context,
|
||||
};
|
||||
use rustc_mir_dataflow::{Analysis, ResultsVisitor, visit_reachable_results};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
|
@ -55,10 +55,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
|
|||
// `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of
|
||||
// map nodes is strongly correlated to the number of tracked places, this becomes more or
|
||||
// less `O(n)` if we place a constant limit on the number of tracked places.
|
||||
let place_limit = if tcx.sess.mir_opt_level() < 4 { Some(PLACE_LIMIT) } else { None };
|
||||
let value_limit = if tcx.sess.mir_opt_level() < 4 { Some(PLACE_LIMIT) } else { None };
|
||||
|
||||
// Decide which places to track during the analysis.
|
||||
let map = Map::new(tcx, body, place_limit);
|
||||
let map = Map::new(tcx, body, PlaceCollectionMode::Full { value_limit });
|
||||
|
||||
// Perform the actual dataflow analysis.
|
||||
let const_ = debug_span!("analyze")
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ use rustc_middle::mir::interpret::Scalar;
|
|||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, ScalarInt, TyCtxt};
|
||||
use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, TrackElem, ValueIndex};
|
||||
use rustc_mir_dataflow::value_analysis::{
|
||||
Map, PlaceCollectionMode, PlaceIndex, TrackElem, ValueIndex,
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
|
@ -71,7 +73,6 @@ use crate::cost_checker::CostChecker;
|
|||
pub(super) struct JumpThreading;
|
||||
|
||||
const MAX_COST: u8 = 100;
|
||||
const MAX_PLACES: usize = 100;
|
||||
|
||||
impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
||||
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
|
||||
|
|
@ -95,7 +96,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
|||
typing_env,
|
||||
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
|
||||
body,
|
||||
map: Map::new(tcx, body, Some(MAX_PLACES)),
|
||||
map: Map::new(tcx, body, PlaceCollectionMode::OnDemand),
|
||||
maybe_loop_headers: loops::maybe_loop_headers(body),
|
||||
entry_states: IndexVec::from_elem(ConditionSet::default(), &body.basic_blocks),
|
||||
};
|
||||
|
|
@ -273,6 +274,19 @@ impl ConditionSet {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
||||
fn place(&mut self, place: Place<'tcx>, tail: Option<TrackElem>) -> Option<PlaceIndex> {
|
||||
self.map.register_place(self.tcx, self.body, place, tail)
|
||||
}
|
||||
|
||||
fn value(&mut self, place: PlaceIndex) -> Option<ValueIndex> {
|
||||
self.map.register_value(self.tcx, self.typing_env, place)
|
||||
}
|
||||
|
||||
fn place_value(&mut self, place: Place<'tcx>, tail: Option<TrackElem>) -> Option<ValueIndex> {
|
||||
let place = self.place(place, tail)?;
|
||||
self.value(place)
|
||||
}
|
||||
|
||||
/// Construct the condition set for `bb` from the terminator, without executing its effect.
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn populate_from_outgoing_edges(&mut self, bb: BasicBlock) -> ConditionSet {
|
||||
|
|
@ -397,7 +411,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
|
||||
#[instrument(level = "trace", skip(self, state))]
|
||||
fn process_immediate(&mut self, lhs: PlaceIndex, rhs: ImmTy<'tcx>, state: &mut ConditionSet) {
|
||||
if let Some(lhs) = self.map.value(lhs)
|
||||
if let Some(lhs) = self.value(lhs)
|
||||
&& let Immediate::Scalar(Scalar::Int(int)) = *rhs
|
||||
{
|
||||
state.fulfill_matches(lhs, int)
|
||||
|
|
@ -412,10 +426,6 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
constant: OpTy<'tcx>,
|
||||
state: &mut ConditionSet,
|
||||
) {
|
||||
let values_inside = self.map.values_inside(lhs);
|
||||
if !state.active.iter().any(|&(_, cond)| values_inside.contains(&cond.place)) {
|
||||
return;
|
||||
}
|
||||
self.map.for_each_projection_value(
|
||||
lhs,
|
||||
constant,
|
||||
|
|
@ -450,9 +460,13 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
#[instrument(level = "trace", skip(self, state))]
|
||||
fn process_copy(&mut self, lhs: PlaceIndex, rhs: PlaceIndex, state: &mut ConditionSet) {
|
||||
let mut renames = FxHashMap::default();
|
||||
self.map.for_each_value_pair(rhs, lhs, &mut |rhs, lhs| {
|
||||
renames.insert(lhs, rhs);
|
||||
});
|
||||
self.map.register_copy_tree(
|
||||
lhs, // tree to copy
|
||||
rhs, // tree to build
|
||||
&mut |lhs, rhs| {
|
||||
renames.insert(lhs, rhs);
|
||||
},
|
||||
);
|
||||
state.for_each_mut(|c| {
|
||||
if let Some(rhs) = renames.get(&c.place) {
|
||||
c.place = *rhs
|
||||
|
|
@ -474,7 +488,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
}
|
||||
// Transfer the conditions on the copied rhs.
|
||||
Operand::Move(rhs) | Operand::Copy(rhs) => {
|
||||
let Some(rhs) = self.map.find(rhs.as_ref()) else { return };
|
||||
let Some(rhs) = self.place(*rhs, None) else { return };
|
||||
self.process_copy(lhs, rhs, state)
|
||||
}
|
||||
}
|
||||
|
|
@ -487,12 +501,12 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
rvalue: &Rvalue<'tcx>,
|
||||
state: &mut ConditionSet,
|
||||
) {
|
||||
let Some(lhs) = self.map.find(lhs_place.as_ref()) else { return };
|
||||
let Some(lhs) = self.place(*lhs_place, None) else { return };
|
||||
match rvalue {
|
||||
Rvalue::Use(operand) => self.process_operand(lhs, operand, state),
|
||||
// Transfer the conditions on the copy rhs.
|
||||
Rvalue::Discriminant(rhs) => {
|
||||
let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return };
|
||||
let Some(rhs) = self.place(*rhs, Some(TrackElem::Discriminant)) else { return };
|
||||
self.process_copy(lhs, rhs, state)
|
||||
}
|
||||
// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
|
||||
|
|
@ -502,33 +516,37 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
// Do not support unions.
|
||||
AggregateKind::Adt(.., Some(_)) => return,
|
||||
AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => {
|
||||
if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant)
|
||||
&& let Some(discr_value) = self
|
||||
.ecx
|
||||
.discriminant_for_variant(agg_ty, *variant_index)
|
||||
.discard_err()
|
||||
let discr_ty = agg_ty.discriminant_ty(self.tcx);
|
||||
let discr_target =
|
||||
self.map.register_place_index(discr_ty, lhs, TrackElem::Discriminant);
|
||||
if let Some(discr_value) =
|
||||
self.ecx.discriminant_for_variant(agg_ty, *variant_index).discard_err()
|
||||
{
|
||||
self.process_immediate(discr_target, discr_value, state);
|
||||
}
|
||||
if let Some(idx) = self.map.apply(lhs, TrackElem::Variant(*variant_index)) {
|
||||
idx
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
self.map.register_place_index(
|
||||
agg_ty,
|
||||
lhs,
|
||||
TrackElem::Variant(*variant_index),
|
||||
)
|
||||
}
|
||||
_ => lhs,
|
||||
};
|
||||
for (field_index, operand) in operands.iter_enumerated() {
|
||||
if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) {
|
||||
self.process_operand(field, operand, state);
|
||||
}
|
||||
let operand_ty = operand.ty(self.body, self.tcx);
|
||||
let field = self.map.register_place_index(
|
||||
operand_ty,
|
||||
lhs,
|
||||
TrackElem::Field(field_index),
|
||||
);
|
||||
self.process_operand(field, operand, state);
|
||||
}
|
||||
}
|
||||
// Transfer the conditions on the copy rhs, after inverting the value of the condition.
|
||||
Rvalue::UnaryOp(UnOp::Not, Operand::Move(operand) | Operand::Copy(operand)) => {
|
||||
let layout = self.ecx.layout_of(operand.ty(self.body, self.tcx).ty).unwrap();
|
||||
let Some(lhs) = self.map.value(lhs) else { return };
|
||||
let Some(operand) = self.map.find_value(operand.as_ref()) else { return };
|
||||
let Some(lhs) = self.value(lhs) else { return };
|
||||
let Some(operand) = self.place_value(*operand, None) else { return };
|
||||
state.retain_mut(|mut c| {
|
||||
if c.place == lhs {
|
||||
let value = self
|
||||
|
|
@ -562,8 +580,8 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
// Avoid handling them, though this could be extended in the future.
|
||||
return;
|
||||
}
|
||||
let Some(lhs) = self.map.value(lhs) else { return };
|
||||
let Some(operand) = self.map.find_value(operand.as_ref()) else { return };
|
||||
let Some(lhs) = self.value(lhs) else { return };
|
||||
let Some(operand) = self.place_value(*operand, None) else { return };
|
||||
let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
|
||||
else {
|
||||
return;
|
||||
|
|
@ -592,7 +610,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
// If we expect `discriminant(place) ?= A`,
|
||||
// we have an opportunity if `variant_index ?= A`.
|
||||
StatementKind::SetDiscriminant { box place, variant_index } => {
|
||||
let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return };
|
||||
let Some(discr_target) = self.place(*place, Some(TrackElem::Discriminant)) else {
|
||||
return;
|
||||
};
|
||||
let enum_ty = place.ty(self.body, self.tcx).ty;
|
||||
// `SetDiscriminant` guarantees that the discriminant is now `variant_index`.
|
||||
// Even if the discriminant write does nothing due to niches, it is UB to set the
|
||||
|
|
@ -608,7 +628,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(
|
||||
Operand::Copy(place) | Operand::Move(place),
|
||||
)) => {
|
||||
let Some(place) = self.map.find_value(place.as_ref()) else { return };
|
||||
let Some(place) = self.place_value(*place, None) else { return };
|
||||
state.fulfill_matches(place, ScalarInt::TRUE);
|
||||
}
|
||||
StatementKind::Assign(box (lhs_place, rhs)) => {
|
||||
|
|
@ -665,7 +685,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
|
|||
state: &mut ConditionSet,
|
||||
) {
|
||||
let Some(discr) = discr.place() else { return };
|
||||
let Some(discr_idx) = self.map.find_value(discr.as_ref()) else { return };
|
||||
let Some(discr_idx) = self.place_value(discr, None) else { return };
|
||||
|
||||
let discr_ty = discr.ty(self.body, self.tcx).ty;
|
||||
let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return };
|
||||
|
|
|
|||
|
|
@ -69,24 +69,22 @@ Number of file 0 mappings: 61
|
|||
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
|
||||
Highest counter ID seen: c1
|
||||
|
||||
Function name: closure::main::{closure#0}
|
||||
Raw bytes (51): 0x[01, 01, 01, 01, 05, 09, 01, 28, 05, 00, 06, 01, 01, 0d, 00, 1a, 01, 00, 1d, 00, 1e, 01, 01, 0c, 00, 14, 05, 00, 15, 02, 0a, 02, 02, 09, 00, 0a, 01, 01, 09, 00, 17, 01, 00, 18, 00, 20, 01, 01, 05, 00, 06]
|
||||
Function name: closure::main::{closure#0} (unused)
|
||||
Raw bytes (49): 0x[01, 01, 00, 09, 00, 28, 05, 00, 06, 00, 01, 0d, 00, 1a, 00, 00, 1d, 00, 1e, 00, 01, 0c, 00, 14, 00, 00, 15, 02, 0a, 00, 02, 09, 00, 0a, 00, 01, 09, 00, 17, 00, 00, 18, 00, 20, 00, 01, 05, 00, 06]
|
||||
Number of files: 1
|
||||
- file 0 => $DIR/closure.rs
|
||||
Number of expressions: 1
|
||||
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 9
|
||||
- Code(Counter(0)) at (prev + 40, 5) to (start + 0, 6)
|
||||
- Code(Counter(0)) at (prev + 1, 13) to (start + 0, 26)
|
||||
- Code(Counter(0)) at (prev + 0, 29) to (start + 0, 30)
|
||||
- Code(Counter(0)) at (prev + 1, 12) to (start + 0, 20)
|
||||
- Code(Counter(1)) at (prev + 0, 21) to (start + 2, 10)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10)
|
||||
= (c0 - c1)
|
||||
- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 23)
|
||||
- Code(Counter(0)) at (prev + 0, 24) to (start + 0, 32)
|
||||
- Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6)
|
||||
Highest counter ID seen: c1
|
||||
- Code(Zero) at (prev + 40, 5) to (start + 0, 6)
|
||||
- Code(Zero) at (prev + 1, 13) to (start + 0, 26)
|
||||
- Code(Zero) at (prev + 0, 29) to (start + 0, 30)
|
||||
- Code(Zero) at (prev + 1, 12) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 21) to (start + 2, 10)
|
||||
- Code(Zero) at (prev + 2, 9) to (start + 0, 10)
|
||||
- Code(Zero) at (prev + 1, 9) to (start + 0, 23)
|
||||
- Code(Zero) at (prev + 0, 24) to (start + 0, 32)
|
||||
- Code(Zero) at (prev + 1, 5) to (start + 0, 6)
|
||||
Highest counter ID seen: (none)
|
||||
|
||||
Function name: closure::main::{closure#10} (unused)
|
||||
Raw bytes (20): 0x[01, 01, 00, 03, 00, 9b, 01, 07, 00, 08, 00, 00, 09, 00, 11, 00, 00, 20, 00, 21]
|
||||
|
|
|
|||
|
|
@ -92,71 +92,28 @@ Number of file 0 mappings: 14
|
|||
Highest counter ID seen: c1
|
||||
|
||||
Function name: try_error_result::test2
|
||||
Raw bytes (443): 0x[01, 01, 3d, 09, 0d, 09, 57, 0d, 15, 09, 57, 0d, 15, 09, 57, 0d, 15, 09, 4f, 53, 1d, 57, 19, 0d, 15, 09, 57, 0d, 15, 09, 57, 0d, 15, 09, 53, 57, 19, 0d, 15, 09, 4f, 53, 1d, 57, 19, 0d, 15, 41, 6b, 21, 25, 41, 21, 41, 6b, 21, 25, 05, 8f, 01, 93, 01, 2d, 09, 29, 05, 09, 05, 09, 05, 93, 01, 09, 29, 05, 8f, 01, 93, 01, 2d, 09, 29, 45, a7, 01, 31, 35, 45, 31, 45, a7, 01, 31, 35, 49, bb, 01, 39, 3d, 49, 39, 49, bb, 01, 39, 3d, 11, 05, c7, 01, 05, cb, 01, 3d, cf, 01, 39, d3, 01, 35, d7, 01, 31, db, 01, 2d, df, 01, 29, e3, 01, 25, e7, 01, 21, eb, 01, 1d, ef, 01, 19, f3, 01, 15, 11, 0d, 39, 01, 3d, 01, 00, 1d, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 1a, 01, 01, 09, 01, 12, 01, 01, 15, 00, 17, 01, 05, 09, 00, 0e, 05, 02, 09, 01, 11, 05, 04, 0d, 00, 1a, 09, 02, 0d, 00, 13, 09, 00, 14, 00, 1f, 0d, 00, 2f, 00, 30, 02, 00, 31, 00, 35, 02, 00, 45, 00, 4f, 02, 00, 50, 00, 62, 02, 01, 0d, 00, 13, 02, 02, 11, 00, 1c, 15, 01, 11, 00, 12, 36, 02, 11, 00, 15, 36, 02, 11, 00, 1b, 36, 01, 15, 00, 27, 4a, 02, 11, 00, 14, 36, 00, 17, 00, 1d, 36, 00, 1e, 00, 29, 19, 00, 41, 00, 42, 3e, 00, 43, 00, 47, 1d, 00, 5f, 00, 60, 4a, 01, 0d, 00, 17, 66, 01, 11, 00, 14, 41, 00, 17, 00, 1d, 41, 00, 1e, 00, 29, 21, 00, 41, 00, 42, 62, 00, 43, 00, 47, 25, 00, 60, 00, 61, 66, 01, 0d, 00, 17, 8a, 01, 04, 11, 00, 14, 7e, 00, 17, 00, 1d, 7e, 00, 1e, 00, 29, 29, 00, 42, 00, 43, 82, 01, 00, 44, 00, 48, 2d, 00, 61, 00, 62, 8a, 01, 01, 0d, 00, 17, a2, 01, 01, 11, 00, 14, 45, 00, 17, 00, 1d, 45, 01, 12, 00, 1d, 31, 00, 36, 00, 37, 9e, 01, 01, 12, 00, 16, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 17, b6, 01, 01, 11, 00, 14, 49, 00, 17, 00, 1d, 49, 01, 12, 00, 1d, 39, 01, 11, 00, 12, b2, 01, 01, 12, 00, 16, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 17, be, 01, 03, 05, 00, 0b, c2, 01, 01, 01, 00, 02]
|
||||
Raw bytes (325): 0x[01, 01, 12, 07, 09, 01, 05, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 01, 09, 05, 39, 01, 3d, 01, 00, 1d, 01, 01, 09, 00, 0f, 01, 00, 12, 00, 1a, 01, 01, 09, 01, 12, 01, 01, 15, 00, 17, 01, 05, 09, 00, 0e, 05, 02, 09, 01, 11, 05, 04, 0d, 00, 1a, 02, 02, 0d, 00, 13, 02, 00, 14, 00, 1f, 00, 00, 2f, 00, 30, 02, 00, 31, 00, 35, 02, 00, 45, 00, 4f, 02, 00, 50, 00, 62, 02, 01, 0d, 00, 13, 02, 02, 11, 00, 1c, 00, 01, 11, 00, 12, 02, 02, 11, 00, 15, 02, 02, 11, 00, 1b, 02, 01, 15, 00, 27, 00, 02, 11, 00, 14, 02, 00, 17, 00, 1d, 02, 00, 1e, 00, 29, 02, 00, 41, 00, 42, 00, 00, 43, 00, 47, 00, 00, 5f, 00, 60, 00, 01, 0d, 00, 17, 00, 01, 11, 00, 14, 00, 00, 17, 00, 1d, 00, 00, 1e, 00, 29, 00, 00, 41, 00, 42, 00, 00, 43, 00, 47, 00, 00, 60, 00, 61, 00, 01, 0d, 00, 17, 42, 04, 11, 00, 14, 42, 00, 17, 00, 1d, 42, 00, 1e, 00, 29, 00, 00, 42, 00, 43, 42, 00, 44, 00, 48, 00, 00, 61, 00, 62, 42, 01, 0d, 00, 17, 42, 01, 11, 00, 14, 42, 00, 17, 00, 1d, 42, 01, 12, 00, 1d, 00, 00, 36, 00, 37, 42, 01, 12, 00, 16, 00, 00, 2f, 00, 30, 42, 01, 0d, 00, 17, 42, 01, 11, 00, 14, 42, 00, 17, 00, 1d, 42, 01, 12, 00, 1d, 00, 01, 11, 00, 12, 42, 01, 12, 00, 16, 00, 01, 11, 00, 12, 42, 02, 0d, 00, 17, 46, 03, 05, 00, 0b, 01, 01, 01, 00, 02]
|
||||
Number of files: 1
|
||||
- file 0 => $DIR/try_error_result.rs
|
||||
Number of expressions: 61
|
||||
- expression 0 operands: lhs = Counter(2), rhs = Counter(3)
|
||||
- expression 1 operands: lhs = Counter(2), rhs = Expression(21, Add)
|
||||
- expression 2 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 3 operands: lhs = Counter(2), rhs = Expression(21, Add)
|
||||
- expression 4 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 5 operands: lhs = Counter(2), rhs = Expression(21, Add)
|
||||
- expression 6 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 7 operands: lhs = Counter(2), rhs = Expression(19, Add)
|
||||
- expression 8 operands: lhs = Expression(20, Add), rhs = Counter(7)
|
||||
- expression 9 operands: lhs = Expression(21, Add), rhs = Counter(6)
|
||||
- expression 10 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 11 operands: lhs = Counter(2), rhs = Expression(21, Add)
|
||||
- expression 12 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 13 operands: lhs = Counter(2), rhs = Expression(21, Add)
|
||||
- expression 14 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 15 operands: lhs = Counter(2), rhs = Expression(20, Add)
|
||||
- expression 16 operands: lhs = Expression(21, Add), rhs = Counter(6)
|
||||
- expression 17 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 18 operands: lhs = Counter(2), rhs = Expression(19, Add)
|
||||
- expression 19 operands: lhs = Expression(20, Add), rhs = Counter(7)
|
||||
- expression 20 operands: lhs = Expression(21, Add), rhs = Counter(6)
|
||||
- expression 21 operands: lhs = Counter(3), rhs = Counter(5)
|
||||
- expression 22 operands: lhs = Counter(16), rhs = Expression(26, Add)
|
||||
- expression 23 operands: lhs = Counter(8), rhs = Counter(9)
|
||||
- expression 24 operands: lhs = Counter(16), rhs = Counter(8)
|
||||
- expression 25 operands: lhs = Counter(16), rhs = Expression(26, Add)
|
||||
- expression 26 operands: lhs = Counter(8), rhs = Counter(9)
|
||||
- expression 27 operands: lhs = Counter(1), rhs = Expression(35, Add)
|
||||
- expression 28 operands: lhs = Expression(36, Add), rhs = Counter(11)
|
||||
- expression 29 operands: lhs = Counter(2), rhs = Counter(10)
|
||||
- expression 30 operands: lhs = Counter(1), rhs = Counter(2)
|
||||
- expression 31 operands: lhs = Counter(1), rhs = Counter(2)
|
||||
- expression 32 operands: lhs = Counter(1), rhs = Expression(36, Add)
|
||||
- expression 33 operands: lhs = Counter(2), rhs = Counter(10)
|
||||
- expression 34 operands: lhs = Counter(1), rhs = Expression(35, Add)
|
||||
- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(11)
|
||||
- expression 36 operands: lhs = Counter(2), rhs = Counter(10)
|
||||
- expression 37 operands: lhs = Counter(17), rhs = Expression(41, Add)
|
||||
- expression 38 operands: lhs = Counter(12), rhs = Counter(13)
|
||||
- expression 39 operands: lhs = Counter(17), rhs = Counter(12)
|
||||
- expression 40 operands: lhs = Counter(17), rhs = Expression(41, Add)
|
||||
- expression 41 operands: lhs = Counter(12), rhs = Counter(13)
|
||||
- expression 42 operands: lhs = Counter(18), rhs = Expression(46, Add)
|
||||
- expression 43 operands: lhs = Counter(14), rhs = Counter(15)
|
||||
- expression 44 operands: lhs = Counter(18), rhs = Counter(14)
|
||||
- expression 45 operands: lhs = Counter(18), rhs = Expression(46, Add)
|
||||
- expression 46 operands: lhs = Counter(14), rhs = Counter(15)
|
||||
- expression 47 operands: lhs = Counter(4), rhs = Counter(1)
|
||||
- expression 48 operands: lhs = Expression(49, Add), rhs = Counter(1)
|
||||
- expression 49 operands: lhs = Expression(50, Add), rhs = Counter(15)
|
||||
- expression 50 operands: lhs = Expression(51, Add), rhs = Counter(14)
|
||||
- expression 51 operands: lhs = Expression(52, Add), rhs = Counter(13)
|
||||
- expression 52 operands: lhs = Expression(53, Add), rhs = Counter(12)
|
||||
- expression 53 operands: lhs = Expression(54, Add), rhs = Counter(11)
|
||||
- expression 54 operands: lhs = Expression(55, Add), rhs = Counter(10)
|
||||
- expression 55 operands: lhs = Expression(56, Add), rhs = Counter(9)
|
||||
- expression 56 operands: lhs = Expression(57, Add), rhs = Counter(8)
|
||||
- expression 57 operands: lhs = Expression(58, Add), rhs = Counter(7)
|
||||
- expression 58 operands: lhs = Expression(59, Add), rhs = Counter(6)
|
||||
- expression 59 operands: lhs = Expression(60, Add), rhs = Counter(5)
|
||||
- expression 60 operands: lhs = Counter(4), rhs = Counter(3)
|
||||
Number of expressions: 18
|
||||
- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(2)
|
||||
- expression 1 operands: lhs = Counter(0), rhs = Counter(1)
|
||||
- expression 2 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 3 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 4 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 5 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 6 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 7 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 8 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 9 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 10 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 11 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 12 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 13 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 14 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 15 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 16 operands: lhs = Counter(2), rhs = Counter(0)
|
||||
- expression 17 operands: lhs = Counter(2), rhs = Counter(1)
|
||||
Number of file 0 mappings: 57
|
||||
- Code(Counter(0)) at (prev + 61, 1) to (start + 0, 29)
|
||||
- Code(Counter(0)) at (prev + 1, 9) to (start + 0, 15)
|
||||
|
|
@ -166,83 +123,83 @@ Number of file 0 mappings: 57
|
|||
- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 14)
|
||||
- Code(Counter(1)) at (prev + 2, 9) to (start + 1, 17)
|
||||
- Code(Counter(1)) at (prev + 4, 13) to (start + 0, 26)
|
||||
- Code(Counter(2)) at (prev + 2, 13) to (start + 0, 19)
|
||||
- Code(Counter(2)) at (prev + 0, 20) to (start + 0, 31)
|
||||
- Code(Counter(3)) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 20) to (start + 0, 31)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Zero) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 49) to (start + 0, 53)
|
||||
= (c2 - c3)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 69) to (start + 0, 79)
|
||||
= (c2 - c3)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 80) to (start + 0, 98)
|
||||
= (c2 - c3)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 1, 13) to (start + 0, 19)
|
||||
= (c2 - c3)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 28)
|
||||
= (c2 - c3)
|
||||
- Code(Counter(5)) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(13, Sub)) at (prev + 2, 17) to (start + 0, 21)
|
||||
= (c2 - (c3 + c5))
|
||||
- Code(Expression(13, Sub)) at (prev + 2, 17) to (start + 0, 27)
|
||||
= (c2 - (c3 + c5))
|
||||
- Code(Expression(13, Sub)) at (prev + 1, 21) to (start + 0, 39)
|
||||
= (c2 - (c3 + c5))
|
||||
- Code(Expression(18, Sub)) at (prev + 2, 17) to (start + 0, 20)
|
||||
= (c2 - (((c3 + c5) + c6) + c7))
|
||||
- Code(Expression(13, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= (c2 - (c3 + c5))
|
||||
- Code(Expression(13, Sub)) at (prev + 0, 30) to (start + 0, 41)
|
||||
= (c2 - (c3 + c5))
|
||||
- Code(Counter(6)) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Expression(15, Sub)) at (prev + 0, 67) to (start + 0, 71)
|
||||
= (c2 - ((c3 + c5) + c6))
|
||||
- Code(Counter(7)) at (prev + 0, 95) to (start + 0, 96)
|
||||
- Code(Expression(18, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c2 - (((c3 + c5) + c6) + c7))
|
||||
- Code(Expression(25, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= (c16 - (c8 + c9))
|
||||
- Code(Counter(16)) at (prev + 0, 23) to (start + 0, 29)
|
||||
- Code(Counter(16)) at (prev + 0, 30) to (start + 0, 41)
|
||||
- Code(Counter(8)) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Expression(24, Sub)) at (prev + 0, 67) to (start + 0, 71)
|
||||
= (c16 - c8)
|
||||
- Code(Counter(9)) at (prev + 0, 96) to (start + 0, 97)
|
||||
- Code(Expression(25, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c16 - (c8 + c9))
|
||||
- Code(Expression(34, Sub)) at (prev + 4, 17) to (start + 0, 20)
|
||||
= (c1 - ((c2 + c10) + c11))
|
||||
- Code(Expression(31, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= (c1 - c2)
|
||||
- Code(Expression(31, Sub)) at (prev + 0, 30) to (start + 0, 41)
|
||||
= (c1 - c2)
|
||||
- Code(Counter(10)) at (prev + 0, 66) to (start + 0, 67)
|
||||
- Code(Expression(32, Sub)) at (prev + 0, 68) to (start + 0, 72)
|
||||
= (c1 - (c2 + c10))
|
||||
- Code(Counter(11)) at (prev + 0, 97) to (start + 0, 98)
|
||||
- Code(Expression(34, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c1 - ((c2 + c10) + c11))
|
||||
- Code(Expression(40, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= (c17 - (c12 + c13))
|
||||
- Code(Counter(17)) at (prev + 0, 23) to (start + 0, 29)
|
||||
- Code(Counter(17)) at (prev + 1, 18) to (start + 0, 29)
|
||||
- Code(Counter(12)) at (prev + 0, 54) to (start + 0, 55)
|
||||
- Code(Expression(39, Sub)) at (prev + 1, 18) to (start + 0, 22)
|
||||
= (c17 - c12)
|
||||
- Code(Counter(13)) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(40, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c17 - (c12 + c13))
|
||||
- Code(Expression(45, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= (c18 - (c14 + c15))
|
||||
- Code(Counter(18)) at (prev + 0, 23) to (start + 0, 29)
|
||||
- Code(Counter(18)) at (prev + 1, 18) to (start + 0, 29)
|
||||
- Code(Counter(14)) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(44, Sub)) at (prev + 1, 18) to (start + 0, 22)
|
||||
= (c18 - c14)
|
||||
- Code(Counter(15)) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(45, Sub)) at (prev + 2, 13) to (start + 0, 23)
|
||||
= (c18 - (c14 + c15))
|
||||
- Code(Expression(47, Sub)) at (prev + 3, 5) to (start + 0, 11)
|
||||
= (c4 - c1)
|
||||
- Code(Expression(48, Sub)) at (prev + 1, 1) to (start + 0, 2)
|
||||
= (((((((((((((c4 + c3) + c5) + c6) + c7) + c8) + c9) + c10) + c11) + c12) + c13) + c14) + c15) - c1)
|
||||
Highest counter ID seen: c18
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 21)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 27)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 1, 21) to (start + 0, 39)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Zero) at (prev + 2, 17) to (start + 0, 20)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 30) to (start + 0, 41)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Expression(0, Sub)) at (prev + 0, 65) to (start + 0, 66)
|
||||
= ((c0 + c1) - c2)
|
||||
- Code(Zero) at (prev + 0, 67) to (start + 0, 71)
|
||||
- Code(Zero) at (prev + 0, 95) to (start + 0, 96)
|
||||
- Code(Zero) at (prev + 1, 13) to (start + 0, 23)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 20)
|
||||
- Code(Zero) at (prev + 0, 23) to (start + 0, 29)
|
||||
- Code(Zero) at (prev + 0, 30) to (start + 0, 41)
|
||||
- Code(Zero) at (prev + 0, 65) to (start + 0, 66)
|
||||
- Code(Zero) at (prev + 0, 67) to (start + 0, 71)
|
||||
- Code(Zero) at (prev + 0, 96) to (start + 0, 97)
|
||||
- Code(Zero) at (prev + 1, 13) to (start + 0, 23)
|
||||
- Code(Expression(16, Sub)) at (prev + 4, 17) to (start + 0, 20)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 30) to (start + 0, 41)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 0, 66) to (start + 0, 67)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 68) to (start + 0, 72)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 0, 97) to (start + 0, 98)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 18) to (start + 0, 29)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 0, 54) to (start + 0, 55)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 18) to (start + 0, 22)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 0, 47) to (start + 0, 48)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 13) to (start + 0, 23)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 17) to (start + 0, 20)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 0, 23) to (start + 0, 29)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 18) to (start + 0, 29)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(16, Sub)) at (prev + 1, 18) to (start + 0, 22)
|
||||
= (c2 - c0)
|
||||
- Code(Zero) at (prev + 1, 17) to (start + 0, 18)
|
||||
- Code(Expression(16, Sub)) at (prev + 2, 13) to (start + 0, 23)
|
||||
= (c2 - c0)
|
||||
- Code(Expression(17, Sub)) at (prev + 3, 5) to (start + 0, 11)
|
||||
= (c2 - c1)
|
||||
- Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2)
|
||||
Highest counter ID seen: c1
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue