2021-03-17 01:30:37 +00:00
|
|
|
//! Removes assignments to ZST places.
|
|
|
|
|
2021-01-01 00:53:25 +00:00
|
|
|
use crate::MirPass;
|
2022-12-03 22:00:05 +00:00
|
|
|
use rustc_middle::mir::{Body, StatementKind};
|
2021-03-20 02:25:56 +00:00
|
|
|
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>) {
|
2021-09-15 00:00:00 +00:00
|
|
|
// Avoid query cycles (generators require optimized MIR for layout).
|
2023-02-07 08:29:48 +00:00
|
|
|
if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
|
2021-09-15 00:00:00 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-03-17 01:30:37 +00:00
|
|
|
let param_env = tcx.param_env(body.source.def_id());
|
2022-07-04 00:00:00 +00:00
|
|
|
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
|
|
|
|
{
|
2021-06-03 18:54:21 +00:00
|
|
|
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;
|
2021-06-03 18:54:21 +00:00
|
|
|
};
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 02:25:56 +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)
|
2022-11-26 21:51:55 +00:00
|
|
|
ty::Adt(..)
|
|
|
|
| ty::Array(..)
|
|
|
|
| ty::Closure(..)
|
|
|
|
| ty::Tuple(..)
|
|
|
|
| ty::Alias(ty::Opaque, ..) => true,
|
2021-03-20 02:25:56 +00:00
|
|
|
// definitely ZST
|
|
|
|
ty::FnDef(..) | ty::Never => true,
|
|
|
|
// unreachable or can't be ZST
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|