Skip to content

Commit

Permalink
Rollup merge of rust-lang#107270 - cjgillot:remove-zst, r=oli-obk
Browse files Browse the repository at this point in the history
Replace ZST operands and debuginfo by constants.

This is work that ConstProp will not have to do.
Split from rust-lang#107267
  • Loading branch information
matthiaskrgr authored Jan 26, 2023
2 parents ca7a610 + 49f4399 commit 71fa6ef
Show file tree
Hide file tree
Showing 29 changed files with 304 additions and 183 deletions.
132 changes: 103 additions & 29 deletions compiler/rustc_mir_transform/src/remove_zsts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Removes assignments to ZST places.
//! Removes operations on ZST places, and convert ZST operands to constants.

use crate::MirPass;
use rustc_middle::mir::{Body, StatementKind};
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};

pub struct RemoveZsts;
Expand All @@ -16,38 +18,24 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
if tcx.type_of(body.source.def_id()).is_generator() {
return;
}
let param_env = tcx.param_env(body.source.def_id());
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let local_decls = &body.local_decls;
for block in basic_blocks {
for statement in block.statements.iter_mut() {
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;
}
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();
}
}
}
let mut replacer = Replacer { tcx, param_env, local_decls };
for var_debug_info in &mut body.var_debug_info {
replacer.visit_var_debug_info(var_debug_info);
}
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
replacer.visit_basic_block_data(bb, data);
}
}
}

struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
}

/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
fn maybe_zst(ty: Ty<'_>) -> bool {
match ty.kind() {
Expand All @@ -63,3 +51,89 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
_ => false,
}
}

impl<'tcx> Replacer<'_, 'tcx> {
fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool {
if !maybe_zst(ty) {
return false;
}
let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else {
return false;
};
layout.is_zst()
}

fn make_zst(&self, ty: Ty<'tcx>) -> Constant<'tcx> {
debug_assert!(self.known_to_be_zst(ty));
Constant {
span: rustc_span::DUMMY_SP,
user_ty: None,
literal: ConstantKind::Val(ConstValue::ZeroSized, ty),
}
}
}

impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
match var_debug_info.value {
VarDebugInfoContents::Const(_) => {}
VarDebugInfoContents::Place(place) => {
let place_ty = place.ty(self.local_decls, self.tcx).ty;
if self.known_to_be_zst(place_ty) {
var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(place_ty))
}
}
VarDebugInfoContents::Composite { ty, fragments: _ } => {
if self.known_to_be_zst(ty) {
var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(ty))
}
}
}
}

fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
if let Operand::Constant(_) = operand {
return;
}
let op_ty = operand.ty(self.local_decls, self.tcx);
if self.known_to_be_zst(op_ty)
&& self.tcx.consider_optimizing(|| {
format!("RemoveZsts - Operand: {:?} Location: {:?}", operand, loc)
})
{
*operand = Operand::Constant(Box::new(self.make_zst(op_ty)))
}
}

fn visit_statement(&mut self, statement: &mut Statement<'tcx>, loc: Location) {
let place_for_ty = match statement.kind {
StatementKind::Assign(box (place, ref rvalue)) => {
rvalue.is_safe_to_remove().then_some(place)
}
StatementKind::Deinit(box place)
| StatementKind::SetDiscriminant { box place, variant_index: _ }
| StatementKind::AscribeUserType(box (place, _), _)
| StatementKind::Retag(_, box place)
| StatementKind::FakeRead(box (_, place)) => Some(place),
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
Some(local.into())
}
StatementKind::Coverage(_) | StatementKind::Intrinsic(_) | StatementKind::Nop => None,
};
if let Some(place_for_ty) = place_for_ty
&& let ty = place_for_ty.ty(self.local_decls, self.tcx).ty
&& self.known_to_be_zst(ty)
&& self.tcx.consider_optimizing(|| {
format!("RemoveZsts - Place: {:?} SourceInfo: {:?}", place_for_ty, statement.source_info)
})
{
statement.make_nop();
} else {
self.super_statement(statement, loc);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
}

bb1: {
StorageLive(_2); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
_2 = begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/std/src/panic.rs:LL:COL
Expand Down
14 changes: 4 additions & 10 deletions tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@
let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
scope 3 {
debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21
let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
scope 5 {
debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
let _7: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
debug _enum_without_variants => const [ZeroSized: Empty]; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
scope 7 {
debug _non_utf8_str => _7; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
debug _non_utf8_str => const Str::<"���">; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
}
}
scope 6 {
Expand Down Expand Up @@ -46,18 +44,14 @@
- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
+ // mir::Constant
+ // + span: $DIR/invalid_constant.rs:28:34: 28:57
+ // + span: $DIR/invalid_constant.rs:29:34: 29:57
+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) }
+ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
+ // mir::Constant
+ // + span: $DIR/invalid_constant.rs:28:24: 28:60
+ // + span: $DIR/invalid_constant.rs:29:24: 29:60
+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) }
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
StorageLive(_7); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
StorageDead(_7); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
Expand Down
79 changes: 79 additions & 0 deletions tests/mir-opt/const_prop/invalid_constant.main.RemoveZsts.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
- // MIR for `main` before RemoveZsts
+ // MIR for `main` after RemoveZsts

fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:+0:11: +0:11
let _1: char; // in scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63
let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59
let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55
let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73
let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65
scope 1 {
debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22
let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
scope 3 {
debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21
let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
scope 5 {
- debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
+ debug _enum_without_variants => const [ZeroSized: Empty]; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
scope 7 {
- debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
+ debug _non_utf8_str => const Str::<"���">; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
}
}
scope 6 {
}
}
scope 4 {
}
}
scope 2 {
}

bb0: {
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
(_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
_1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
(_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
_4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
_3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
- StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
- StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
(_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
- _7 = (_8.1: Empty); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
- _6 = [move _7]; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
- StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
+ nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75
- StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
- _0 = const (); // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
- StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
- StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
+ nop; // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
+ nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
+ nop; // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
+ nop; // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
}
}

1 change: 1 addition & 0 deletions tests/mir-opt/const_prop/invalid_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum E { A, B, C }
#[derive(Copy, Clone)]
enum Empty {}

// EMIT_MIR invalid_constant.main.RemoveZsts.diff
// EMIT_MIR invalid_constant.main.ConstProp.diff
fn main() {
// An invalid char.
Expand Down
2 changes: 0 additions & 2 deletions tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22

bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
(_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
Expand All @@ -20,7 +19,6 @@

bb1: {
StorageDead(_2); // scope 0 at $DIR/issue_66971.rs:+1:22: +1:23
StorageDead(_1); // scope 0 at $DIR/issue_66971.rs:+1:23: +1:24
return; // scope 0 at $DIR/issue_66971.rs:+2:2: +2:2
}
}
Expand Down
2 changes: 0 additions & 2 deletions tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
let mut _3: (u8, u8); // in scope 0 at $DIR/issue_67019.rs:+1:11: +1:17

bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
Expand All @@ -26,7 +25,6 @@

bb1: {
StorageDead(_2); // scope 0 at $DIR/issue_67019.rs:+1:19: +1:20
StorageDead(_1); // scope 0 at $DIR/issue_67019.rs:+1:20: +1:21
return; // scope 0 at $DIR/issue_67019.rs:+2:2: +2:2
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10
_1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14
StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
Expand All @@ -26,7 +25,6 @@

bb1: {
StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15
StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16
StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2
return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
(_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
(_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
Expand All @@ -27,7 +26,6 @@

bb1: {
StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
}
Expand Down
Loading

0 comments on commit 71fa6ef

Please sign in to comment.