Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 438955f

Browse files
committedSep 12, 2023
Auto merge of #115797 - cjgillot:const-prop-noclone, r=<try>
Do not clone the Body for ConstProp Based on #115748 for the `POST_MONO_CHECKS` flag.
2 parents e5fedce + d0cba3d commit 438955f

File tree

4 files changed

+111
-133
lines changed

4 files changed

+111
-133
lines changed
 

‎compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -749,10 +749,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
749749
self.stack_mut().push(frame);
750750

751751
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
752-
for ct in &body.required_consts {
753-
let span = ct.span;
754-
let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?;
755-
self.eval_mir_constant(&ct, Some(span), None)?;
752+
if M::POST_MONO_CHECKS {
753+
for ct in &body.required_consts {
754+
let span = ct.span;
755+
let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?;
756+
self.eval_mir_constant(&ct, Some(span), None)?;
757+
}
756758
}
757759

758760
// done

‎compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
130130
/// Should the machine panic on allocation failures?
131131
const PANIC_ON_ALLOC_FAIL: bool;
132132

133+
/// Should post-monomorphization checks be run when a stack frame is pushed?
134+
const POST_MONO_CHECKS: bool = true;
135+
133136
/// Whether memory accesses should be alignment-checked.
134137
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment;
135138

‎compiler/rustc_mir_transform/src/const_prop.rs

Lines changed: 37 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ use rustc_middle::mir::visit::{
1515
use rustc_middle::mir::*;
1616
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
1717
use rustc_middle::ty::{self, GenericArgs, Instance, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
18-
use rustc_span::{def_id::DefId, Span, DUMMY_SP};
18+
use rustc_span::{def_id::DefId, Span};
1919
use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
2020
use rustc_target::spec::abi::Abi as CallAbi;
2121

22+
use crate::dataflow_const_prop::Patch;
2223
use crate::MirPass;
2324
use rustc_const_eval::interpret::{
2425
self, compile_time_machine, AllocId, ConstAllocation, ConstValue, FnArg, Frame, ImmTy,
@@ -83,43 +84,32 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
8384
return;
8485
}
8586

86-
let is_generator = tcx.type_of(def_id.to_def_id()).instantiate_identity().is_generator();
8787
// FIXME(welseywiser) const prop doesn't work on generators because of query cycles
8888
// computing their layout.
89+
let is_generator = def_kind == DefKind::Generator;
8990
if is_generator {
9091
trace!("ConstProp skipped for generator {:?}", def_id);
9192
return;
9293
}
9394

9495
trace!("ConstProp starting for {:?}", def_id);
9596

96-
let dummy_body = &Body::new(
97-
body.source,
98-
(*body.basic_blocks).to_owned(),
99-
body.source_scopes.clone(),
100-
body.local_decls.clone(),
101-
Default::default(),
102-
body.arg_count,
103-
Default::default(),
104-
body.span,
105-
body.generator_kind(),
106-
body.tainted_by_errors,
107-
);
108-
10997
// FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
11098
// constants, instead of just checking for const-folding succeeding.
11199
// That would require a uniform one-def no-mutation analysis
112100
// and RPO (or recursing when needing the value of a local).
113-
let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx);
101+
let mut optimization_finder = ConstPropagator::new(body, tcx);
114102

115103
// Traverse the body in reverse post-order, to ensure that `FullConstProp` locals are
116104
// assigned before being read.
117-
let rpo = body.basic_blocks.reverse_postorder().to_vec();
118-
for bb in rpo {
119-
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
105+
for &bb in body.basic_blocks.reverse_postorder() {
106+
let data = &body.basic_blocks[bb];
120107
optimization_finder.visit_basic_block_data(bb, data);
121108
}
122109

110+
let mut patch = optimization_finder.patch;
111+
patch.visit_body_preserves_cfg(body);
112+
123113
trace!("ConstProp done for {:?}", def_id);
124114
}
125115
}
@@ -143,8 +133,11 @@ impl ConstPropMachine<'_, '_> {
143133

144134
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
145135
compile_time_machine!(<'mir, 'tcx>);
136+
146137
const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
147138

139+
const POST_MONO_CHECKS: bool = false; // this MIR is still generic!
140+
148141
type MemoryKind = !;
149142

150143
#[inline(always)]
@@ -299,6 +292,7 @@ struct ConstPropagator<'mir, 'tcx> {
299292
tcx: TyCtxt<'tcx>,
300293
param_env: ParamEnv<'tcx>,
301294
local_decls: &'mir IndexSlice<Local, LocalDecl<'tcx>>,
295+
patch: Patch<'tcx>,
302296
}
303297

304298
impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> {
@@ -332,11 +326,7 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
332326
}
333327

334328
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
335-
fn new(
336-
body: &Body<'tcx>,
337-
dummy_body: &'mir Body<'tcx>,
338-
tcx: TyCtxt<'tcx>,
339-
) -> ConstPropagator<'mir, 'tcx> {
329+
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
340330
let def_id = body.source.def_id();
341331
let args = &GenericArgs::identity_for_item(tcx, def_id);
342332
let param_env = tcx.param_env_reveal_all_normalized(def_id);
@@ -367,7 +357,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
367357

368358
ecx.push_stack_frame(
369359
Instance::new(def_id, args),
370-
dummy_body,
360+
body,
371361
&ret,
372362
StackPopCleanup::Root { cleanup: false },
373363
)
@@ -382,7 +372,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
382372
ecx.frame_mut().locals[local].make_live_uninit();
383373
}
384374

385-
ConstPropagator { ecx, tcx, param_env, local_decls: &dummy_body.local_decls }
375+
let patch = Patch::new(tcx);
376+
ConstPropagator { ecx, tcx, param_env, local_decls: &body.local_decls, patch }
386377
}
387378

388379
fn get_const(&self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
@@ -419,12 +410,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
419410
ecx.machine.written_only_inside_own_block_locals.remove(&local);
420411
}
421412

422-
fn propagate_operand(&mut self, operand: &mut Operand<'tcx>) {
423-
if let Some(place) = operand.place() && let Some(op) = self.replace_with_const(place) {
424-
*operand = op;
425-
}
426-
}
427-
428413
fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Option<()> {
429414
// Perform any special handling for specific Rvalue types.
430415
// Generally, checks here fall into one of two categories:
@@ -540,16 +525,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
540525
}
541526
}
542527

543-
/// Creates a new `Operand::Constant` from a `Scalar` value
544-
fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>) -> Operand<'tcx> {
545-
Operand::Constant(Box::new(Constant {
546-
span: DUMMY_SP,
547-
user_ty: None,
548-
literal: ConstantKind::from_scalar(self.tcx, scalar, ty),
549-
}))
550-
}
551-
552-
fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<Operand<'tcx>> {
528+
fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<ConstantKind<'tcx>> {
553529
// This will return None if the above `const_prop` invocation only "wrote" a
554530
// type whose creation requires no write. E.g. a generator whose initial state
555531
// consists solely of uninitialized memory (so it doesn't capture any locals).
@@ -565,7 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
565541
let Right(imm) = imm else { return None };
566542
match *imm {
567543
Immediate::Scalar(scalar) if scalar.try_to_int().is_ok() => {
568-
Some(self.operand_from_scalar(scalar, value.layout.ty))
544+
Some(ConstantKind::from_scalar(self.tcx, scalar, value.layout.ty))
569545
}
570546
Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
571547
let alloc = self
@@ -575,15 +551,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
575551
})
576552
.ok()?;
577553

578-
let literal = ConstantKind::Val(
554+
Some(ConstantKind::Val(
579555
ConstValue::ByRef { alloc, offset: Size::ZERO },
580556
value.layout.ty,
581-
);
582-
Some(Operand::Constant(Box::new(Constant {
583-
span: DUMMY_SP,
584-
user_ty: None,
585-
literal,
586-
})))
557+
))
587558
}
588559
// Scalars or scalar pairs that contain undef values are assumed to not have
589560
// successfully evaluated and are thus not propagated.
@@ -725,40 +696,29 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
725696
}
726697
}
727698

728-
impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
729-
fn tcx(&self) -> TyCtxt<'tcx> {
730-
self.tcx
731-
}
732-
733-
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
699+
impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
700+
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
734701
self.super_operand(operand, location);
735-
self.propagate_operand(operand)
702+
if let Some(place) = operand.place() && let Some(value) = self.replace_with_const(place) {
703+
self.patch.before_effect.insert((location, place), value);
704+
}
736705
}
737706

738-
fn process_projection_elem(
707+
fn visit_projection_elem(
739708
&mut self,
709+
_: PlaceRef<'tcx>,
740710
elem: PlaceElem<'tcx>,
741-
_: Location,
742-
) -> Option<PlaceElem<'tcx>> {
711+
_: PlaceContext,
712+
location: Location,
713+
) {
743714
if let PlaceElem::Index(local) = elem
744-
&& let Some(value) = self.get_const(local.into())
745-
&& let Some(imm) = value.as_mplace_or_imm().right()
746-
&& let Immediate::Scalar(scalar) = *imm
747-
&& let Ok(offset) = scalar.to_target_usize(&self.tcx)
748-
&& let Some(min_length) = offset.checked_add(1)
715+
&& let Some(value) = self.replace_with_const(local.into())
749716
{
750-
Some(PlaceElem::ConstantIndex { offset, min_length, from_end: false })
751-
} else {
752-
None
717+
self.patch.before_effect.insert((location, local.into()), value);
753718
}
754719
}
755720

756-
fn visit_assign(
757-
&mut self,
758-
place: &mut Place<'tcx>,
759-
rvalue: &mut Rvalue<'tcx>,
760-
location: Location,
761-
) {
721+
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
762722
self.super_assign(place, rvalue, location);
763723

764724
let Some(()) = self.check_rvalue(rvalue) else { return };
@@ -775,7 +735,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
775735
{
776736
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
777737
} else if let Some(operand) = self.replace_with_const(*place) {
778-
*rvalue = Rvalue::Use(operand);
738+
self.patch.assignments.insert(location, operand);
779739
}
780740
} else {
781741
// Const prop failed, so erase the destination, ensuring that whatever happens
@@ -799,7 +759,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
799759
}
800760
}
801761

802-
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
762+
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
803763
trace!("visit_statement: {:?}", statement);
804764

805765
// We want to evaluate operands before any change to the assigned-to value,
@@ -843,7 +803,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
843803
}
844804
}
845805

846-
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
806+
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
847807
self.super_basic_block_data(block, data);
848808

849809
// We remove all Locals which are restricted in propagation to their containing blocks and

‎compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 65 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}
77
use rustc_data_structures::fx::FxHashMap;
88
use rustc_hir::def::DefKind;
99
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ConstValue, InterpResult, Scalar};
10-
use rustc_middle::mir::visit::{MutVisitor, NonMutatingUseContext, PlaceContext, Visitor};
10+
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
1111
use rustc_middle::mir::*;
1212
use rustc_middle::ty::layout::TyAndLayout;
13-
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
13+
use rustc_middle::ty::{self, Ty, TyCtxt};
1414
use rustc_mir_dataflow::value_analysis::{
1515
Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
1616
};
@@ -60,13 +60,10 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
6060
.in_scope(|| analysis.wrap().into_engine(tcx, body).iterate_to_fixpoint());
6161

6262
// Collect results and patch the body afterwards.
63-
let mut visitor = CollectAndPatch::new(tcx, &body.local_decls);
63+
let mut visitor = Collector::new(tcx, &body.local_decls);
6464
debug_span!("collect").in_scope(|| results.visit_reachable_with(body, &mut visitor));
65-
debug_span!("patch").in_scope(|| {
66-
for (block, bbdata) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
67-
visitor.visit_basic_block_data(block, bbdata);
68-
}
69-
})
65+
let mut patch = visitor.patch;
66+
debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body));
7067
}
7168
}
7269

@@ -517,41 +514,55 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
517514
}
518515
}
519516

520-
struct CollectAndPatch<'tcx, 'locals> {
517+
pub(crate) struct Patch<'tcx> {
521518
tcx: TyCtxt<'tcx>,
522-
local_decls: &'locals LocalDecls<'tcx>,
523519

524520
/// For a given MIR location, this stores the values of the operands used by that location. In
525521
/// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are
526522
/// properly captured. (This may become UB soon, but it is currently emitted even by safe code.)
527-
before_effect: FxHashMap<(Location, Place<'tcx>), ScalarInt>,
523+
pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), ConstantKind<'tcx>>,
528524

529525
/// Stores the assigned values for assignments where the Rvalue is constant.
530-
assignments: FxHashMap<Location, ScalarInt>,
526+
pub(crate) assignments: FxHashMap<Location, ConstantKind<'tcx>>,
531527
}
532528

533-
impl<'tcx, 'locals> CollectAndPatch<'tcx, 'locals> {
534-
fn new(tcx: TyCtxt<'tcx>, local_decls: &'locals LocalDecls<'tcx>) -> Self {
535-
Self {
536-
tcx,
537-
local_decls,
538-
before_effect: FxHashMap::default(),
539-
assignments: FxHashMap::default(),
540-
}
529+
impl<'tcx> Patch<'tcx> {
530+
pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self {
531+
Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() }
541532
}
542533

543-
fn make_operand(&self, scalar: ScalarInt, ty: Ty<'tcx>) -> Operand<'tcx> {
544-
Operand::Constant(Box::new(Constant {
545-
span: DUMMY_SP,
546-
user_ty: None,
547-
literal: ConstantKind::Val(ConstValue::Scalar(scalar.into()), ty),
548-
}))
534+
fn make_operand(&self, literal: ConstantKind<'tcx>) -> Operand<'tcx> {
535+
Operand::Constant(Box::new(Constant { span: DUMMY_SP, user_ty: None, literal }))
536+
}
537+
}
538+
539+
struct Collector<'tcx, 'locals> {
540+
patch: Patch<'tcx>,
541+
local_decls: &'locals LocalDecls<'tcx>,
542+
}
543+
544+
impl<'tcx, 'locals> Collector<'tcx, 'locals> {
545+
pub(crate) fn new(tcx: TyCtxt<'tcx>, local_decls: &'locals LocalDecls<'tcx>) -> Self {
546+
Self { patch: Patch::new(tcx), local_decls }
547+
}
548+
549+
fn try_make_constant(
550+
&self,
551+
place: Place<'tcx>,
552+
state: &State<FlatSet<Scalar>>,
553+
map: &Map,
554+
) -> Option<ConstantKind<'tcx>> {
555+
let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else {
556+
return None;
557+
};
558+
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
559+
Some(ConstantKind::Val(ConstValue::Scalar(value.into()), ty))
549560
}
550561
}
551562

552563
impl<'mir, 'tcx>
553564
ResultsVisitor<'mir, 'tcx, Results<'tcx, ValueAnalysisWrapper<ConstAnalysis<'_, 'tcx>>>>
554-
for CollectAndPatch<'tcx, '_>
565+
for Collector<'tcx, '_>
555566
{
556567
type FlowState = State<FlatSet<Scalar>>;
557568

@@ -583,10 +594,8 @@ impl<'mir, 'tcx>
583594
// Don't overwrite the assignment if it already uses a constant (to keep the span).
584595
}
585596
StatementKind::Assign(box (place, _)) => {
586-
if let FlatSet::Elem(Scalar::Int(value)) =
587-
state.get(place.as_ref(), &results.analysis.0.map)
588-
{
589-
self.assignments.insert(location, value);
597+
if let Some(value) = self.try_make_constant(place, state, &results.analysis.0.map) {
598+
self.patch.assignments.insert(location, value);
590599
}
591600
}
592601
_ => (),
@@ -605,7 +614,7 @@ impl<'mir, 'tcx>
605614
}
606615
}
607616

608-
impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx, '_> {
617+
impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> {
609618
fn tcx(&self) -> TyCtxt<'tcx> {
610619
self.tcx
611620
}
@@ -614,8 +623,7 @@ impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx, '_> {
614623
if let Some(value) = self.assignments.get(&location) {
615624
match &mut statement.kind {
616625
StatementKind::Assign(box (_, rvalue)) => {
617-
let ty = rvalue.ty(self.local_decls, self.tcx);
618-
*rvalue = Rvalue::Use(self.make_operand(*value, ty));
626+
*rvalue = Rvalue::Use(self.make_operand(*value));
619627
}
620628
_ => bug!("found assignment info for non-assign statement"),
621629
}
@@ -628,8 +636,7 @@ impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx, '_> {
628636
match operand {
629637
Operand::Copy(place) | Operand::Move(place) => {
630638
if let Some(value) = self.before_effect.get(&(location, *place)) {
631-
let ty = place.ty(self.local_decls, self.tcx).ty;
632-
*operand = self.make_operand(*value, ty);
639+
*operand = self.make_operand(*value);
633640
} else if !place.projection.is_empty() {
634641
self.super_operand(operand, location)
635642
}
@@ -643,11 +650,11 @@ impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx, '_> {
643650
elem: PlaceElem<'tcx>,
644651
location: Location,
645652
) -> Option<PlaceElem<'tcx>> {
646-
if let PlaceElem::Index(local) = elem
647-
&& let Some(value) = self.before_effect.get(&(location, local.into()))
648-
&& let Ok(offset) = value.try_to_target_usize(self.tcx)
649-
&& let Some(min_length) = offset.checked_add(1)
650-
{
653+
if let PlaceElem::Index(local) = elem {
654+
let offset = self.before_effect.get(&(location, local.into()))?;
655+
let offset = offset.try_to_scalar()?;
656+
let offset = offset.to_target_usize(&self.tcx).ok()?;
657+
let min_length = offset.checked_add(1)?;
651658
Some(PlaceElem::ConstantIndex { offset, min_length, from_end: false })
652659
} else {
653660
None
@@ -657,29 +664,35 @@ impl<'tcx> MutVisitor<'tcx> for CollectAndPatch<'tcx, '_> {
657664

658665
struct OperandCollector<'tcx, 'map, 'locals, 'a> {
659666
state: &'a State<FlatSet<Scalar>>,
660-
visitor: &'a mut CollectAndPatch<'tcx, 'locals>,
667+
visitor: &'a mut Collector<'tcx, 'locals>,
661668
map: &'map Map,
662669
}
663670

664671
impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
672+
fn visit_projection_elem(
673+
&mut self,
674+
_: PlaceRef<'tcx>,
675+
elem: PlaceElem<'tcx>,
676+
_: PlaceContext,
677+
location: Location,
678+
) {
679+
if let PlaceElem::Index(local) = elem
680+
&& let Some(value) = self.visitor.try_make_constant(local.into(), self.state, self.map)
681+
{
682+
self.visitor.patch.before_effect.insert((location, local.into()), value);
683+
}
684+
}
685+
665686
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
666687
if let Some(place) = operand.place() {
667-
if let FlatSet::Elem(Scalar::Int(value)) = self.state.get(place.as_ref(), self.map) {
668-
self.visitor.before_effect.insert((location, place), value);
688+
if let Some(value) = self.visitor.try_make_constant(place, self.state, self.map) {
689+
self.visitor.patch.before_effect.insert((location, place), value);
669690
} else if !place.projection.is_empty() {
670691
// Try to propagate into `Index` projections.
671692
self.super_operand(operand, location)
672693
}
673694
}
674695
}
675-
676-
fn visit_local(&mut self, local: Local, ctxt: PlaceContext, location: Location) {
677-
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy | NonMutatingUseContext::Move) = ctxt
678-
&& let FlatSet::Elem(Scalar::Int(value)) = self.state.get(local.into(), self.map)
679-
{
680-
self.visitor.before_effect.insert((location, local.into()), value);
681-
}
682-
}
683696
}
684697

685698
struct DummyMachine;

0 commit comments

Comments
 (0)
Please sign in to comment.