Const prop doesn't need a stack anymore
This commit is contained in:
parent
0294a0de09
commit
89e6a67310
2 changed files with 22 additions and 44 deletions
|
@ -49,24 +49,18 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{
|
||||||
throw_machine_stop!(Zst)
|
throw_machine_stop!(Zst)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
pub(crate) struct ConstPropMachine<'mir, 'tcx> {
|
pub(crate) struct ConstPropMachine {
|
||||||
/// The virtual call stack.
|
|
||||||
stack: Vec<Frame<'mir, 'tcx>>,
|
|
||||||
pub written_only_inside_own_block_locals: FxHashSet<Local>,
|
pub written_only_inside_own_block_locals: FxHashSet<Local>,
|
||||||
pub can_const_prop: IndexVec<Local, ConstPropMode>,
|
pub can_const_prop: IndexVec<Local, ConstPropMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstPropMachine<'_, '_> {
|
impl ConstPropMachine {
|
||||||
pub fn new(can_const_prop: IndexVec<Local, ConstPropMode>) -> Self {
|
pub fn new(can_const_prop: IndexVec<Local, ConstPropMode>) -> Self {
|
||||||
Self {
|
Self { written_only_inside_own_block_locals: Default::default(), can_const_prop }
|
||||||
stack: Vec::new(),
|
|
||||||
written_only_inside_own_block_locals: Default::default(),
|
|
||||||
can_const_prop,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
|
impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
compile_time_machine!(<'mir, 'tcx>);
|
compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
|
||||||
const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
|
const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
|
||||||
|
@ -192,16 +186,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn stack<'a>(
|
fn stack<'a>(
|
||||||
ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
_ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||||
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||||
&ecx.machine.stack
|
&[]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn stack_mut<'a>(
|
fn stack_mut<'a>(
|
||||||
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||||
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||||
&mut ecx.machine.stack
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use rustc_const_eval::interpret::{ImmTy, MPlaceTy, Projectable};
|
use rustc_const_eval::interpret::{ImmTy, Projectable};
|
||||||
use rustc_const_eval::interpret::{InterpCx, InterpResult, OpTy, Scalar, StackPopCleanup};
|
use rustc_const_eval::interpret::{InterpCx, InterpResult, OpTy, Scalar};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
|
@ -12,10 +12,7 @@ use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_middle::mir::visit::Visitor;
|
use rustc_middle::mir::visit::Visitor;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||||
use rustc_middle::ty::GenericArgs;
|
use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_middle::ty::{
|
|
||||||
self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
|
|
||||||
};
|
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
|
use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx};
|
||||||
|
|
||||||
|
@ -72,12 +69,13 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint {
|
||||||
|
|
||||||
/// Finds optimization opportunities on the MIR.
|
/// Finds optimization opportunities on the MIR.
|
||||||
struct ConstPropagator<'mir, 'tcx> {
|
struct ConstPropagator<'mir, 'tcx> {
|
||||||
ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
|
ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
worklist: Vec<BasicBlock>,
|
worklist: Vec<BasicBlock>,
|
||||||
visited_blocks: BitSet<BasicBlock>,
|
visited_blocks: BitSet<BasicBlock>,
|
||||||
locals: IndexVec<Local, Value<'tcx>>,
|
locals: IndexVec<Local, Value<'tcx>>,
|
||||||
|
body: &'mir Body<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -180,27 +178,16 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
|
||||||
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
|
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
|
||||||
let def_id = body.source.def_id();
|
let def_id = body.source.def_id();
|
||||||
let args = &GenericArgs::identity_for_item(tcx, def_id);
|
|
||||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||||
|
|
||||||
let can_const_prop = CanConstProp::check(tcx, param_env, body);
|
let can_const_prop = CanConstProp::check(tcx, param_env, body);
|
||||||
let mut ecx = InterpCx::new(
|
let ecx = InterpCx::new(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.def_span(def_id),
|
tcx.def_span(def_id),
|
||||||
param_env,
|
param_env,
|
||||||
ConstPropMachine::new(can_const_prop),
|
ConstPropMachine::new(can_const_prop),
|
||||||
);
|
);
|
||||||
|
|
||||||
let ret = MPlaceTy::fake_alloc_zst(ecx.layout_of(tcx.types.unit).unwrap()).into();
|
|
||||||
|
|
||||||
ecx.push_stack_frame(
|
|
||||||
Instance::new(def_id, args),
|
|
||||||
body,
|
|
||||||
&ret,
|
|
||||||
StackPopCleanup::Root { cleanup: false },
|
|
||||||
)
|
|
||||||
.expect("failed to push initial stack frame");
|
|
||||||
|
|
||||||
ConstPropagator {
|
ConstPropagator {
|
||||||
ecx,
|
ecx,
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -208,15 +195,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
worklist: vec![START_BLOCK],
|
worklist: vec![START_BLOCK],
|
||||||
visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
|
visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
|
||||||
locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()),
|
locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()),
|
||||||
|
body,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn body(&self) -> &'mir Body<'tcx> {
|
|
||||||
self.ecx.frame().body
|
|
||||||
}
|
|
||||||
|
|
||||||
fn local_decls(&self) -> &'mir LocalDecls<'tcx> {
|
fn local_decls(&self) -> &'mir LocalDecls<'tcx> {
|
||||||
&self.body().local_decls
|
&self.body.local_decls
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_const(&self, place: Place<'tcx>) -> Option<&Value<'tcx>> {
|
fn get_const(&self, place: Place<'tcx>) -> Option<&Value<'tcx>> {
|
||||||
|
@ -243,7 +227,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
|
fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
|
||||||
source_info.scope.lint_root(&self.body().source_scopes)
|
source_info.scope.lint_root(&self.body.source_scopes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
|
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
|
||||||
|
@ -332,7 +316,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
// `AssertKind` only has an `OverflowNeg` variant, so make sure that is
|
// `AssertKind` only has an `OverflowNeg` variant, so make sure that is
|
||||||
// appropriate to use.
|
// appropriate to use.
|
||||||
assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
|
assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
|
||||||
let source_info = self.body().source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
self.report_assert_as_lint(
|
self.report_assert_as_lint(
|
||||||
source_info,
|
source_info,
|
||||||
AssertLint::ArithmeticOverflow(
|
AssertLint::ArithmeticOverflow(
|
||||||
|
@ -370,7 +354,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
let r_bits = r.to_scalar().to_bits(right_size).ok();
|
let r_bits = r.to_scalar().to_bits(right_size).ok();
|
||||||
if r_bits.is_some_and(|b| b >= left_size.bits() as u128) {
|
if r_bits.is_some_and(|b| b >= left_size.bits() as u128) {
|
||||||
debug!("check_binary_op: reporting assert for {:?}", location);
|
debug!("check_binary_op: reporting assert for {:?}", location);
|
||||||
let source_info = self.body().source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
let panic = AssertKind::Overflow(
|
let panic = AssertKind::Overflow(
|
||||||
op,
|
op,
|
||||||
match l {
|
match l {
|
||||||
|
@ -398,7 +382,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
let (_res, overflow) = this.ecx.overflowing_binary_op(op, &l, &r)?;
|
let (_res, overflow) = this.ecx.overflowing_binary_op(op, &l, &r)?;
|
||||||
Ok(overflow)
|
Ok(overflow)
|
||||||
})? {
|
})? {
|
||||||
let source_info = self.body().source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
self.report_assert_as_lint(
|
self.report_assert_as_lint(
|
||||||
source_info,
|
source_info,
|
||||||
AssertLint::ArithmeticOverflow(
|
AssertLint::ArithmeticOverflow(
|
||||||
|
@ -545,7 +529,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
// Need proper const propagator for these.
|
// Need proper const propagator for these.
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let source_info = self.body().source_info(location);
|
let source_info = self.body.source_info(location);
|
||||||
self.report_assert_as_lint(
|
self.report_assert_as_lint(
|
||||||
source_info,
|
source_info,
|
||||||
AssertLint::UnconditionalPanic(source_info.span, msg),
|
AssertLint::UnconditionalPanic(source_info.span, msg),
|
||||||
|
@ -579,7 +563,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
use rustc_middle::mir::Rvalue::*;
|
use rustc_middle::mir::Rvalue::*;
|
||||||
let layout = self.use_ecx(|this| this.ecx.eval_place(*dest))?.layout;
|
let layout = self.ecx.layout_of(dest.ty(self.body, self.tcx).ty).ok()?;
|
||||||
trace!(?layout);
|
trace!(?layout);
|
||||||
|
|
||||||
let val: Value<'_> = match *rvalue {
|
let val: Value<'_> = match *rvalue {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue