Skip to content

Commit 68b433a

Browse files
committed
Lighten up const_prop_lint, reusing const_prop
1 parent 2f320a2 commit 68b433a

File tree

2 files changed

+19
-222
lines changed

2 files changed

+19
-222
lines changed

compiler/rustc_mir_transform/src/const_prop.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,18 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
155155
}
156156
}
157157

158-
struct ConstPropMachine<'mir, 'tcx> {
158+
pub struct ConstPropMachine<'mir, 'tcx> {
159159
/// The virtual call stack.
160160
stack: Vec<Frame<'mir, 'tcx>>,
161161
/// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
162-
written_only_inside_own_block_locals: FxHashSet<Local>,
162+
pub written_only_inside_own_block_locals: FxHashSet<Local>,
163163
/// Locals that need to be cleared after every block terminates.
164-
only_propagate_inside_block_locals: BitSet<Local>,
165-
can_const_prop: IndexVec<Local, ConstPropMode>,
164+
pub only_propagate_inside_block_locals: BitSet<Local>,
165+
pub can_const_prop: IndexVec<Local, ConstPropMode>,
166166
}
167167

168168
impl ConstPropMachine<'_, '_> {
169-
fn new(
169+
pub fn new(
170170
only_propagate_inside_block_locals: BitSet<Local>,
171171
can_const_prop: IndexVec<Local, ConstPropMode>,
172172
) -> Self {
@@ -816,7 +816,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
816816

817817
/// The mode that `ConstProp` is allowed to run in for a given `Local`.
818818
#[derive(Clone, Copy, Debug, PartialEq)]
819-
enum ConstPropMode {
819+
pub enum ConstPropMode {
820820
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
821821
FullConstProp,
822822
/// The `Local` can only be propagated into and from its own block.

compiler/rustc_mir_transform/src/const_prop_lint.rs

+13-216
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
//! Propagates constants for early reporting of statically known
22
//! assertion failures
33
4-
use std::cell::Cell;
5-
6-
use rustc_ast::Mutability;
7-
use rustc_data_structures::fx::FxHashSet;
4+
use crate::const_prop::ConstPropMachine;
5+
use crate::const_prop::ConstPropMode;
6+
use crate::MirLint;
7+
use rustc_const_eval::const_eval::ConstEvalErr;
8+
use rustc_const_eval::interpret::{
9+
self, InterpCx, InterpResult, LocalState, LocalValue, MemoryKind, OpTy, Scalar,
10+
ScalarMaybeUninit, StackPopCleanup,
11+
};
812
use rustc_hir::def::DefKind;
913
use rustc_hir::HirId;
1014
use rustc_index::bit_set::BitSet;
1115
use rustc_index::vec::IndexVec;
1216
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
1317
use rustc_middle::mir::{
14-
AssertKind, BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind,
15-
Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
16-
StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
18+
AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind, Location,
19+
Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind,
20+
Terminator, TerminatorKind, UnOp, RETURN_PLACE,
1721
};
1822
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
1923
use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -22,42 +26,15 @@ use rustc_middle::ty::{
2226
TypeVisitable,
2327
};
2428
use rustc_session::lint;
25-
use rustc_span::{def_id::DefId, Span};
29+
use rustc_span::Span;
2630
use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
27-
use rustc_target::spec::abi::Abi as CallAbi;
2831
use rustc_trait_selection::traits;
29-
30-
use crate::MirLint;
31-
use rustc_const_eval::const_eval::ConstEvalErr;
32-
use rustc_const_eval::interpret::{
33-
self, compile_time_machine, AllocId, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
34-
LocalState, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
35-
StackPopCleanup, StackPopUnwind,
36-
};
32+
use std::cell::Cell;
3733

3834
/// The maximum number of bytes that we'll allocate space for a local or the return value.
3935
/// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
4036
/// Severely regress performance.
4137
const MAX_ALLOC_LIMIT: u64 = 1024;
42-
43-
/// Macro for machine-specific `InterpError` without allocation.
44-
/// (These will never be shown to the user, but they help diagnose ICEs.)
45-
macro_rules! throw_machine_stop_str {
46-
($($tt:tt)*) => {{
47-
// We make a new local type for it. The type itself does not carry any information,
48-
// but its vtable (for the `MachineStopType` trait) does.
49-
struct Zst;
50-
// Printing this type shows the desired string.
51-
impl std::fmt::Display for Zst {
52-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53-
write!(f, $($tt)*)
54-
}
55-
}
56-
impl rustc_middle::mir::interpret::MachineStopType for Zst {}
57-
throw_machine_stop!(Zst)
58-
}};
59-
}
60-
6138
pub struct ConstProp;
6239

6340
impl<'tcx> MirLint<'tcx> for ConstProp {
@@ -151,172 +128,6 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
151128
}
152129
}
153130

154-
struct ConstPropMachine<'mir, 'tcx> {
155-
/// The virtual call stack.
156-
stack: Vec<Frame<'mir, 'tcx>>,
157-
/// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
158-
written_only_inside_own_block_locals: FxHashSet<Local>,
159-
/// Locals that need to be cleared after every block terminates.
160-
only_propagate_inside_block_locals: BitSet<Local>,
161-
can_const_prop: IndexVec<Local, ConstPropMode>,
162-
}
163-
164-
impl ConstPropMachine<'_, '_> {
165-
fn new(
166-
only_propagate_inside_block_locals: BitSet<Local>,
167-
can_const_prop: IndexVec<Local, ConstPropMode>,
168-
) -> Self {
169-
Self {
170-
stack: Vec::new(),
171-
written_only_inside_own_block_locals: Default::default(),
172-
only_propagate_inside_block_locals,
173-
can_const_prop,
174-
}
175-
}
176-
}
177-
178-
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
179-
compile_time_machine!(<'mir, 'tcx>);
180-
const PANIC_ON_ALLOC_FAIL: bool = true; // all allocations are small (see `MAX_ALLOC_LIMIT`)
181-
182-
type MemoryKind = !;
183-
184-
fn load_mir(
185-
_ecx: &InterpCx<'mir, 'tcx, Self>,
186-
_instance: ty::InstanceDef<'tcx>,
187-
) -> InterpResult<'tcx, &'tcx Body<'tcx>> {
188-
throw_machine_stop_str!("calling functions isn't supported in ConstProp")
189-
}
190-
191-
fn find_mir_or_eval_fn(
192-
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
193-
_instance: ty::Instance<'tcx>,
194-
_abi: CallAbi,
195-
_args: &[OpTy<'tcx>],
196-
_destination: &PlaceTy<'tcx>,
197-
_target: Option<BasicBlock>,
198-
_unwind: StackPopUnwind,
199-
) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
200-
Ok(None)
201-
}
202-
203-
fn call_intrinsic(
204-
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
205-
_instance: ty::Instance<'tcx>,
206-
_args: &[OpTy<'tcx>],
207-
_destination: &PlaceTy<'tcx>,
208-
_target: Option<BasicBlock>,
209-
_unwind: StackPopUnwind,
210-
) -> InterpResult<'tcx> {
211-
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
212-
}
213-
214-
fn assert_panic(
215-
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
216-
_msg: &rustc_middle::mir::AssertMessage<'tcx>,
217-
_unwind: Option<rustc_middle::mir::BasicBlock>,
218-
) -> InterpResult<'tcx> {
219-
bug!("panics terminators are not evaluated in ConstProp")
220-
}
221-
222-
fn binary_ptr_op(
223-
_ecx: &InterpCx<'mir, 'tcx, Self>,
224-
_bin_op: BinOp,
225-
_left: &ImmTy<'tcx>,
226-
_right: &ImmTy<'tcx>,
227-
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
228-
// We can't do this because aliasing of memory can differ between const eval and llvm
229-
throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp")
230-
}
231-
232-
fn access_local<'a>(
233-
frame: &'a Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
234-
local: Local,
235-
) -> InterpResult<'tcx, &'a interpret::Operand<Self::Provenance>> {
236-
let l = &frame.locals[local];
237-
238-
if matches!(
239-
l.value,
240-
LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit))
241-
) {
242-
// For us "uninit" means "we don't know its value, might be initiailized or not".
243-
// So stop here.
244-
throw_machine_stop_str!("tried to access a local with unknown value")
245-
}
246-
247-
l.access()
248-
}
249-
250-
fn access_local_mut<'a>(
251-
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
252-
frame: usize,
253-
local: Local,
254-
) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::Provenance>> {
255-
if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation {
256-
throw_machine_stop_str!("tried to write to a local that is marked as not propagatable")
257-
}
258-
if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) {
259-
trace!(
260-
"mutating local {:?} which is restricted to its block. \
261-
Will remove it from const-prop after block is finished.",
262-
local
263-
);
264-
ecx.machine.written_only_inside_own_block_locals.insert(local);
265-
}
266-
ecx.machine.stack[frame].locals[local].access_mut()
267-
}
268-
269-
fn before_access_global(
270-
_tcx: TyCtxt<'tcx>,
271-
_machine: &Self,
272-
_alloc_id: AllocId,
273-
alloc: ConstAllocation<'tcx, Self::Provenance, Self::AllocExtra>,
274-
_static_def_id: Option<DefId>,
275-
is_write: bool,
276-
) -> InterpResult<'tcx> {
277-
if is_write {
278-
throw_machine_stop_str!("can't write to global");
279-
}
280-
// If the static allocation is mutable, then we can't const prop it as its content
281-
// might be different at runtime.
282-
if alloc.inner().mutability == Mutability::Mut {
283-
throw_machine_stop_str!("can't access mutable globals in ConstProp");
284-
}
285-
286-
Ok(())
287-
}
288-
289-
#[inline(always)]
290-
fn expose_ptr(
291-
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
292-
_ptr: Pointer<AllocId>,
293-
) -> InterpResult<'tcx> {
294-
throw_machine_stop_str!("exposing pointers isn't supported in ConstProp")
295-
}
296-
297-
#[inline(always)]
298-
fn init_frame_extra(
299-
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
300-
frame: Frame<'mir, 'tcx>,
301-
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
302-
Ok(frame)
303-
}
304-
305-
#[inline(always)]
306-
fn stack<'a>(
307-
ecx: &'a InterpCx<'mir, 'tcx, Self>,
308-
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
309-
&ecx.machine.stack
310-
}
311-
312-
#[inline(always)]
313-
fn stack_mut<'a>(
314-
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
315-
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
316-
&mut ecx.machine.stack
317-
}
318-
}
319-
320131
/// Finds optimization opportunities on the MIR.
321132
struct ConstPropagator<'mir, 'tcx> {
322133
ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
@@ -711,20 +522,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
711522
}
712523
}
713524

714-
/// The mode that `ConstProp` is allowed to run in for a given `Local`.
715-
#[derive(Clone, Copy, Debug, PartialEq)]
716-
enum ConstPropMode {
717-
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
718-
FullConstProp,
719-
/// The `Local` can only be propagated into and from its own block.
720-
OnlyInsideOwnBlock,
721-
/// The `Local` can be propagated into but reads cannot be propagated.
722-
OnlyPropagateInto,
723-
/// The `Local` cannot be part of propagation at all. Any statement
724-
/// referencing it either for reading or writing will not get propagated.
725-
NoPropagation,
726-
}
727-
728525
struct CanConstProp {
729526
can_const_prop: IndexVec<Local, ConstPropMode>,
730527
// False at the beginning. Once set, no more assignments are allowed to that local.

0 commit comments

Comments
 (0)