rust/compiler/rustc_mir_transform/src/remove_zsts.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

66 lines
2.2 KiB
Rust
Raw Normal View History

2021-03-17 01:30:37 +00:00
//! Removes assignments to ZST places.
use crate::MirPass;
use rustc_middle::mir::{Body, StatementKind};
use rustc_middle::ty::{self, Ty, TyCtxt};
2021-03-17 01:30:37 +00:00
pub struct RemoveZsts;
impl<'tcx> MirPass<'tcx> for RemoveZsts {
2021-12-02 17:17:32 +00:00
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
sess.mir_opt_level() > 0
}
2021-03-17 01:30:37 +00:00
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Avoid query cycles (generators require optimized MIR for layout).
if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
return;
}
2021-03-17 01:30:37 +00:00
let param_env = tcx.param_env(body.source.def_id());
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
let local_decls = &body.local_decls;
for block in basic_blocks {
2021-03-17 01:30:37 +00:00
for statement in block.statements.iter_mut() {
2022-04-05 21:14:59 +00:00
if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) =
statement.kind
{
let place_ty = place.ty(local_decls, tcx).ty;
if !maybe_zst(place_ty) {
continue;
}
2022-02-18 23:48:49 +00:00
let Ok(layout) = tcx.layout_of(param_env.and(place_ty)) else {
continue;
};
if !layout.is_zst() {
continue;
}
if tcx.consider_optimizing(|| {
format!(
"RemoveZsts - Place: {:?} SourceInfo: {:?}",
place, statement.source_info
)
}) {
statement.make_nop();
2021-03-17 01:30:37 +00:00
}
}
}
}
}
}
/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
fn maybe_zst(ty: Ty<'_>) -> bool {
match ty.kind() {
// maybe ZST (could be more precise)
ty::Adt(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Tuple(..)
| ty::Alias(ty::Opaque, ..) => true,
// definitely ZST
ty::FnDef(..) | ty::Never => true,
// unreachable or can't be ZST
_ => false,
}
}