Embed simplification into VnState.
This commit is contained in:
parent
3311536740
commit
5f9d64d72f
9 changed files with 136 additions and 101 deletions
|
@ -86,7 +86,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
// Clone dominators as we need them while mutating the body.
|
// Clone dominators as we need them while mutating the body.
|
||||||
let dominators = body.basic_blocks.dominators().clone();
|
let dominators = body.basic_blocks.dominators().clone();
|
||||||
|
|
||||||
let mut state = VnState::new(tcx, param_env, &body.local_decls);
|
let mut state = VnState::new(tcx, param_env, &ssa, &dominators, &body.local_decls);
|
||||||
for arg in body.args_iter() {
|
for arg in body.args_iter() {
|
||||||
if ssa.is_ssa(arg) {
|
if ssa.is_ssa(arg) {
|
||||||
let value = state.new_opaque().unwrap();
|
let value = state.new_opaque().unwrap();
|
||||||
|
@ -94,38 +94,29 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (local, rvalue, _) in ssa.assignments(body) {
|
ssa.for_each_assignment_mut(&mut body.basic_blocks, |local, rvalue, location| {
|
||||||
let value = state.insert_rvalue(rvalue).or_else(|| state.new_opaque()).unwrap();
|
let value = state.simplify_rvalue(rvalue, location).or_else(|| state.new_opaque()).unwrap();
|
||||||
// FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as
|
// FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as
|
||||||
// reusable if we have an exact type match.
|
// reusable if we have an exact type match.
|
||||||
if state.local_decls[local].ty == rvalue.ty(state.local_decls, tcx) {
|
if state.local_decls[local].ty == rvalue.ty(state.local_decls, tcx) {
|
||||||
state.assign(local, value);
|
state.assign(local, value);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Stop creating opaques during replacement as it is useless.
|
// Stop creating opaques during replacement as it is useless.
|
||||||
state.next_opaque = None;
|
state.next_opaque = None;
|
||||||
|
|
||||||
let mut any_replacement = false;
|
|
||||||
let mut replacer = Replacer {
|
|
||||||
tcx,
|
|
||||||
ssa,
|
|
||||||
dominators,
|
|
||||||
state,
|
|
||||||
reused_locals: BitSet::new_empty(body.local_decls.len()),
|
|
||||||
any_replacement: &mut any_replacement,
|
|
||||||
};
|
|
||||||
|
|
||||||
let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
|
let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec();
|
||||||
for bb in reverse_postorder {
|
for bb in reverse_postorder {
|
||||||
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
|
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
|
||||||
replacer.visit_basic_block_data(bb, data);
|
state.visit_basic_block_data(bb, data);
|
||||||
}
|
}
|
||||||
|
let any_replacement = state.any_replacement;
|
||||||
|
|
||||||
// For each local that is reused (`y` above), we remove its storage statements do avoid any
|
// For each local that is reused (`y` above), we remove its storage statements do avoid any
|
||||||
// difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
|
// difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage
|
||||||
// statements.
|
// statements.
|
||||||
StorageRemover { tcx, reused_locals: replacer.reused_locals }.visit_body_preserves_cfg(body);
|
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
|
||||||
|
|
||||||
if any_replacement {
|
if any_replacement {
|
||||||
crate::simplify::remove_unused_definitions(body);
|
crate::simplify::remove_unused_definitions(body);
|
||||||
|
@ -189,12 +180,18 @@ struct VnState<'body, 'tcx> {
|
||||||
/// Counter to generate different values.
|
/// Counter to generate different values.
|
||||||
/// This is an option to stop creating opaques during replacement.
|
/// This is an option to stop creating opaques during replacement.
|
||||||
next_opaque: Option<usize>,
|
next_opaque: Option<usize>,
|
||||||
|
ssa: &'body SsaLocals,
|
||||||
|
dominators: &'body Dominators<BasicBlock>,
|
||||||
|
reused_locals: BitSet<Local>,
|
||||||
|
any_replacement: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'body, 'tcx> VnState<'body, 'tcx> {
|
impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
ssa: &'body SsaLocals,
|
||||||
|
dominators: &'body Dominators<BasicBlock>,
|
||||||
local_decls: &'body LocalDecls<'tcx>,
|
local_decls: &'body LocalDecls<'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
VnState {
|
VnState {
|
||||||
|
@ -205,6 +202,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
rev_locals: FxHashMap::default(),
|
rev_locals: FxHashMap::default(),
|
||||||
values: FxIndexSet::default(),
|
values: FxIndexSet::default(),
|
||||||
next_opaque: Some(0),
|
next_opaque: Some(0),
|
||||||
|
ssa,
|
||||||
|
dominators,
|
||||||
|
reused_locals: BitSet::new_empty(local_decls.len()),
|
||||||
|
any_replacement: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,10 +253,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
|
|
||||||
/// Represent the *value* which would be read from `place`.
|
/// Represent the *value* which would be read from `place`.
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn insert_place(&mut self, place: Place<'tcx>) -> Option<VnIndex> {
|
fn simplify_place(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
|
||||||
|
// Another place that holds the same value.
|
||||||
|
let mut place_ref = place.as_ref();
|
||||||
let mut value = self.locals[place.local]?;
|
let mut value = self.locals[place.local]?;
|
||||||
|
|
||||||
for (index, proj) in place.projection.iter().enumerate() {
|
for (index, proj) in place.projection.iter().enumerate() {
|
||||||
|
if let Some(local) = self.try_as_local(value, location) {
|
||||||
|
place_ref = PlaceRef { local, projection: &place.projection[index..] };
|
||||||
|
}
|
||||||
|
|
||||||
let proj = match proj {
|
let proj = match proj {
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
let ty = Place::ty_from(
|
let ty = Place::ty_from(
|
||||||
|
@ -293,31 +300,65 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
value = self.insert(Value::Projection(value, proj));
|
value = self.insert(Value::Projection(value, proj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(local) = self.try_as_local(value, location)
|
||||||
|
&& local != place.local
|
||||||
|
{
|
||||||
|
*place = local.into();
|
||||||
|
self.reused_locals.insert(local);
|
||||||
|
self.any_replacement = true;
|
||||||
|
} else if place_ref.local != place.local
|
||||||
|
|| place_ref.projection.len() < place.projection.len()
|
||||||
|
{
|
||||||
|
*place = place_ref.project_deeper(&[], self.tcx);
|
||||||
|
self.reused_locals.insert(place_ref.local);
|
||||||
|
self.any_replacement = true;
|
||||||
|
}
|
||||||
|
|
||||||
Some(value)
|
Some(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn insert_operand(&mut self, operand: &Operand<'tcx>) -> Option<VnIndex> {
|
fn simplify_operand(
|
||||||
|
&mut self,
|
||||||
|
operand: &mut Operand<'tcx>,
|
||||||
|
location: Location,
|
||||||
|
) -> Option<VnIndex> {
|
||||||
match *operand {
|
match *operand {
|
||||||
Operand::Constant(ref constant) => Some(self.insert(Value::Constant(constant.const_))),
|
Operand::Constant(ref constant) => Some(self.insert(Value::Constant(constant.const_))),
|
||||||
Operand::Copy(place) | Operand::Move(place) => self.insert_place(place),
|
Operand::Copy(ref mut place) | Operand::Move(ref mut place) => {
|
||||||
|
let value = self.simplify_place(place, location)?;
|
||||||
|
if let Some(const_) = self.try_as_constant(value) {
|
||||||
|
*operand = Operand::Constant(Box::new(const_));
|
||||||
|
self.any_replacement = true;
|
||||||
|
}
|
||||||
|
Some(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
fn insert_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Option<VnIndex> {
|
fn simplify_rvalue(
|
||||||
|
&mut self,
|
||||||
|
rvalue: &mut Rvalue<'tcx>,
|
||||||
|
location: Location,
|
||||||
|
) -> Option<VnIndex> {
|
||||||
let value = match *rvalue {
|
let value = match *rvalue {
|
||||||
// Forward values.
|
// Forward values.
|
||||||
Rvalue::Use(ref operand) => return self.insert_operand(operand),
|
Rvalue::Use(ref mut operand) => return self.simplify_operand(operand, location),
|
||||||
Rvalue::CopyForDeref(place) => return self.insert_operand(&Operand::Copy(place)),
|
Rvalue::CopyForDeref(place) => {
|
||||||
|
let mut operand = Operand::Copy(place);
|
||||||
|
let val = self.simplify_operand(&mut operand, location);
|
||||||
|
*rvalue = Rvalue::Use(operand);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
// Roots.
|
// Roots.
|
||||||
Rvalue::Repeat(ref op, amount) => {
|
Rvalue::Repeat(ref mut op, amount) => {
|
||||||
let op = self.insert_operand(op)?;
|
let op = self.simplify_operand(op, location)?;
|
||||||
Value::Repeat(op, amount)
|
Value::Repeat(op, amount)
|
||||||
}
|
}
|
||||||
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
|
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
|
||||||
Rvalue::Aggregate(box ref kind, ref fields) => {
|
Rvalue::Aggregate(box ref kind, ref mut fields) => {
|
||||||
let variant_index = match *kind {
|
let variant_index = match *kind {
|
||||||
AggregateKind::Array(..)
|
AggregateKind::Array(..)
|
||||||
| AggregateKind::Tuple
|
| AggregateKind::Tuple
|
||||||
|
@ -328,8 +369,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
|
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
|
||||||
};
|
};
|
||||||
let fields: Option<Vec<_>> = fields
|
let fields: Option<Vec<_>> = fields
|
||||||
.iter()
|
.iter_mut()
|
||||||
.map(|op| self.insert_operand(op).or_else(|| self.new_opaque()))
|
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
|
||||||
.collect();
|
.collect();
|
||||||
let ty = rvalue.ty(self.local_decls, self.tcx);
|
let ty = rvalue.ty(self.local_decls, self.tcx);
|
||||||
Value::Aggregate(ty, variant_index, fields?)
|
Value::Aggregate(ty, variant_index, fields?)
|
||||||
|
@ -337,31 +378,31 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
Rvalue::Ref(.., place) | Rvalue::AddressOf(_, place) => return self.new_pointer(place),
|
Rvalue::Ref(.., place) | Rvalue::AddressOf(_, place) => return self.new_pointer(place),
|
||||||
|
|
||||||
// Operations.
|
// Operations.
|
||||||
Rvalue::Len(place) => {
|
Rvalue::Len(ref mut place) => {
|
||||||
let place = self.insert_place(place)?;
|
let place = self.simplify_place(place, location)?;
|
||||||
Value::Len(place)
|
Value::Len(place)
|
||||||
}
|
}
|
||||||
Rvalue::Cast(kind, ref value, to) => {
|
Rvalue::Cast(kind, ref mut value, to) => {
|
||||||
let from = value.ty(self.local_decls, self.tcx);
|
let from = value.ty(self.local_decls, self.tcx);
|
||||||
let value = self.insert_operand(value)?;
|
let value = self.simplify_operand(value, location)?;
|
||||||
Value::Cast { kind, value, from, to }
|
Value::Cast { kind, value, from, to }
|
||||||
}
|
}
|
||||||
Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => {
|
Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
|
||||||
let lhs = self.insert_operand(lhs)?;
|
let lhs = self.simplify_operand(lhs, location);
|
||||||
let rhs = self.insert_operand(rhs)?;
|
let rhs = self.simplify_operand(rhs, location);
|
||||||
Value::BinaryOp(op, lhs, rhs)
|
Value::BinaryOp(op, lhs?, rhs?)
|
||||||
}
|
}
|
||||||
Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs)) => {
|
Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => {
|
||||||
let lhs = self.insert_operand(lhs)?;
|
let lhs = self.simplify_operand(lhs, location);
|
||||||
let rhs = self.insert_operand(rhs)?;
|
let rhs = self.simplify_operand(rhs, location);
|
||||||
Value::CheckedBinaryOp(op, lhs, rhs)
|
Value::CheckedBinaryOp(op, lhs?, rhs?)
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(op, ref arg) => {
|
Rvalue::UnaryOp(op, ref mut arg) => {
|
||||||
let arg = self.insert_operand(arg)?;
|
let arg = self.simplify_operand(arg, location)?;
|
||||||
Value::UnaryOp(op, arg)
|
Value::UnaryOp(op, arg)
|
||||||
}
|
}
|
||||||
Rvalue::Discriminant(place) => {
|
Rvalue::Discriminant(ref mut place) => {
|
||||||
let place = self.insert_place(place)?;
|
let place = self.simplify_place(place, location)?;
|
||||||
Value::Discriminant(place)
|
Value::Discriminant(place)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,22 +414,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Replacer<'a, 'tcx> {
|
impl<'tcx> VnState<'_, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
ssa: SsaLocals,
|
|
||||||
dominators: Dominators<BasicBlock>,
|
|
||||||
state: VnState<'a, 'tcx>,
|
|
||||||
/// Set of locals that are reused, and for which we should remove storage statements to avoid a
|
|
||||||
/// use-after-StorageDead.
|
|
||||||
reused_locals: BitSet<Local>,
|
|
||||||
any_replacement: &'a mut bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Replacer<'_, 'tcx> {
|
|
||||||
/// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
|
/// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
|
||||||
fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> {
|
fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> {
|
||||||
if let Value::Constant(const_) = self.state.get(index) {
|
if let Value::Constant(const_) = *self.get(index) {
|
||||||
Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_: const_.clone() })
|
Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_ })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -397,50 +427,37 @@ impl<'tcx> Replacer<'_, 'tcx> {
|
||||||
/// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
|
/// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`,
|
||||||
/// return it.
|
/// return it.
|
||||||
fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> {
|
fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> {
|
||||||
let other = self.state.rev_locals.get(&index)?;
|
let other = self.rev_locals.get(&index)?;
|
||||||
other
|
other
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.find(|&other| self.ssa.assignment_dominates(&self.dominators, other, loc))
|
.find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
|
impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
|
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
|
||||||
if let Some(place) = operand.place()
|
self.simplify_operand(operand, location);
|
||||||
&& let Some(value) = self.state.insert_place(place)
|
|
||||||
{
|
|
||||||
if let Some(const_) = self.try_as_constant(value) {
|
|
||||||
*operand = Operand::Constant(Box::new(const_));
|
|
||||||
*self.any_replacement = true;
|
|
||||||
} else if let Some(local) = self.try_as_local(value, location)
|
|
||||||
&& *operand != Operand::Move(local.into())
|
|
||||||
{
|
|
||||||
*operand = Operand::Copy(local.into());
|
|
||||||
self.reused_locals.insert(local);
|
|
||||||
*self.any_replacement = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
|
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) {
|
||||||
self.super_statement(stmt, location);
|
self.super_statement(stmt, location);
|
||||||
if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
|
if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind
|
||||||
&& let Some(value) = self.state.insert_rvalue(rvalue)
|
&& let Some(value) = self.simplify_rvalue(rvalue, location)
|
||||||
{
|
{
|
||||||
if let Some(const_) = self.try_as_constant(value) {
|
if let Some(const_) = self.try_as_constant(value) {
|
||||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)));
|
*rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)));
|
||||||
*self.any_replacement = true;
|
self.any_replacement = true;
|
||||||
} else if let Some(local) = self.try_as_local(value, location)
|
} else if let Some(local) = self.try_as_local(value, location)
|
||||||
&& *rvalue != Rvalue::Use(Operand::Move(local.into()))
|
&& *rvalue != Rvalue::Use(Operand::Move(local.into()))
|
||||||
{
|
{
|
||||||
*rvalue = Rvalue::Use(Operand::Copy(local.into()));
|
*rvalue = Rvalue::Use(Operand::Copy(local.into()));
|
||||||
self.reused_locals.insert(local);
|
self.reused_locals.insert(local);
|
||||||
*self.any_replacement = true;
|
self.any_replacement = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,24 @@ impl SsaLocals {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn for_each_assignment_mut<'tcx>(
|
||||||
|
&self,
|
||||||
|
basic_blocks: &mut BasicBlocks<'tcx>,
|
||||||
|
mut f: impl FnMut(Local, &mut Rvalue<'tcx>, Location),
|
||||||
|
) {
|
||||||
|
for &local in &self.assignment_order {
|
||||||
|
if let Set1::One(LocationExtended::Plain(loc)) = self.assignments[local] {
|
||||||
|
// `loc` must point to a direct assignment to `local`.
|
||||||
|
let bbs = basic_blocks.as_mut_preserves_cfg();
|
||||||
|
let bb = &mut bbs[loc.block];
|
||||||
|
let stmt = &mut bb.statements[loc.statement_index];
|
||||||
|
let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { bug!() };
|
||||||
|
assert_eq!(target.as_local(), Some(local));
|
||||||
|
f(local, rvalue, loc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute the equivalence classes for locals, based on copy statements.
|
/// Compute the equivalence classes for locals, based on copy statements.
|
||||||
///
|
///
|
||||||
/// The returned vector maps each local to the one it copies. In the following case:
|
/// The returned vector maps each local to the one it copies. In the following case:
|
||||||
|
|
|
@ -104,11 +104,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_1);
|
- StorageLive(_1);
|
||||||
_1 = const 1_i64;
|
_1 = const 1_i64;
|
||||||
StorageLive(_2);
|
- StorageLive(_2);
|
||||||
_2 = const 1_u64;
|
_2 = const 1_u64;
|
||||||
StorageLive(_3);
|
- StorageLive(_3);
|
||||||
_3 = const 1f64;
|
_3 = const 1f64;
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
|
@ -492,9 +492,9 @@
|
||||||
- StorageDead(_90);
|
- StorageDead(_90);
|
||||||
StorageDead(_89);
|
StorageDead(_89);
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
StorageDead(_3);
|
- StorageDead(_3);
|
||||||
StorageDead(_2);
|
- StorageDead(_2);
|
||||||
StorageDead(_1);
|
- StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,11 +104,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_1);
|
- StorageLive(_1);
|
||||||
_1 = const 1_i64;
|
_1 = const 1_i64;
|
||||||
StorageLive(_2);
|
- StorageLive(_2);
|
||||||
_2 = const 1_u64;
|
_2 = const 1_u64;
|
||||||
StorageLive(_3);
|
- StorageLive(_3);
|
||||||
_3 = const 1f64;
|
_3 = const 1f64;
|
||||||
StorageLive(_4);
|
StorageLive(_4);
|
||||||
StorageLive(_5);
|
StorageLive(_5);
|
||||||
|
@ -492,9 +492,9 @@
|
||||||
- StorageDead(_90);
|
- StorageDead(_90);
|
||||||
StorageDead(_89);
|
StorageDead(_89);
|
||||||
_0 = const ();
|
_0 = const ();
|
||||||
StorageDead(_3);
|
- StorageDead(_3);
|
||||||
StorageDead(_2);
|
- StorageDead(_2);
|
||||||
StorageDead(_1);
|
- StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,20 +420,20 @@
|
||||||
StorageDead(_52);
|
StorageDead(_52);
|
||||||
StorageLive(_55);
|
StorageLive(_55);
|
||||||
- StorageLive(_56);
|
- StorageLive(_56);
|
||||||
StorageLive(_57);
|
- StorageLive(_57);
|
||||||
- StorageLive(_58);
|
- StorageLive(_58);
|
||||||
- _58 = _1;
|
- _58 = _1;
|
||||||
- _57 = S::<u64>(move _58);
|
- _57 = S::<u64>(move _58);
|
||||||
- StorageDead(_58);
|
- StorageDead(_58);
|
||||||
+ _57 = _53;
|
- _56 = (_57.0: u64);
|
||||||
_56 = (_57.0: u64);
|
|
||||||
- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind unreachable];
|
- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind unreachable];
|
||||||
|
+ _56 = (_53.0: u64);
|
||||||
+ _55 = opaque::<u64>(_56) -> [return: bb16, unwind unreachable];
|
+ _55 = opaque::<u64>(_56) -> [return: bb16, unwind unreachable];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb16: {
|
bb16: {
|
||||||
- StorageDead(_56);
|
- StorageDead(_56);
|
||||||
StorageDead(_57);
|
- StorageDead(_57);
|
||||||
StorageDead(_55);
|
StorageDead(_55);
|
||||||
StorageLive(_59);
|
StorageLive(_59);
|
||||||
StorageLive(_60);
|
StorageLive(_60);
|
||||||
|
|
|
@ -420,20 +420,20 @@
|
||||||
StorageDead(_52);
|
StorageDead(_52);
|
||||||
StorageLive(_55);
|
StorageLive(_55);
|
||||||
- StorageLive(_56);
|
- StorageLive(_56);
|
||||||
StorageLive(_57);
|
- StorageLive(_57);
|
||||||
- StorageLive(_58);
|
- StorageLive(_58);
|
||||||
- _58 = _1;
|
- _58 = _1;
|
||||||
- _57 = S::<u64>(move _58);
|
- _57 = S::<u64>(move _58);
|
||||||
- StorageDead(_58);
|
- StorageDead(_58);
|
||||||
+ _57 = _53;
|
- _56 = (_57.0: u64);
|
||||||
_56 = (_57.0: u64);
|
|
||||||
- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind continue];
|
- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind continue];
|
||||||
|
+ _56 = (_53.0: u64);
|
||||||
+ _55 = opaque::<u64>(_56) -> [return: bb16, unwind continue];
|
+ _55 = opaque::<u64>(_56) -> [return: bb16, unwind continue];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb16: {
|
bb16: {
|
||||||
- StorageDead(_56);
|
- StorageDead(_56);
|
||||||
StorageDead(_57);
|
- StorageDead(_57);
|
||||||
StorageDead(_55);
|
StorageDead(_55);
|
||||||
StorageLive(_59);
|
StorageLive(_59);
|
||||||
StorageLive(_60);
|
StorageLive(_60);
|
||||||
|
|
|
@ -42,10 +42,10 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = move (_7.0: i32);
|
_9 = move (_7.0: i32);
|
||||||
StorageLive(_11);
|
StorageLive(_11);
|
||||||
_10 = deref_copy ((*_6).0: &i32);
|
_10 = ((*_6).0: &i32);
|
||||||
_11 = (*_10);
|
_11 = (*_10);
|
||||||
StorageLive(_13);
|
StorageLive(_13);
|
||||||
_12 = deref_copy ((*_6).1: &T);
|
_12 = ((*_6).1: &T);
|
||||||
_13 = (*_12);
|
_13 = (*_12);
|
||||||
_0 = (move _11, move _13);
|
_0 = (move _11, move _13);
|
||||||
StorageDead(_13);
|
StorageDead(_13);
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
+ StorageDead(_3);
|
+ StorageDead(_3);
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = const false;
|
+ _5 = const false;
|
||||||
+ _6 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
|
+ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
|
||||||
+ _7 = discriminant((*_6));
|
+ _7 = discriminant((*_6));
|
||||||
+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
|
+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9];
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
- _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
|
- _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5];
|
||||||
+ StorageLive(_5);
|
+ StorageLive(_5);
|
||||||
+ _5 = const false;
|
+ _5 = const false;
|
||||||
+ _6 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
|
+ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8});
|
||||||
+ _7 = discriminant((*_6));
|
+ _7 = discriminant((*_6));
|
||||||
+ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
|
+ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue