Skip to content

Commit 114eb2d

Browse files
committed
Replace ZST operands and debuginfo by constants.
1 parent 2a17174 commit 114eb2d

12 files changed

+220
-99
lines changed
Lines changed: 93 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Removes assignments to ZST places.
22
33
use crate::MirPass;
4-
use rustc_middle::mir::{Body, StatementKind};
4+
use rustc_middle::mir::interpret::ConstValue;
5+
use rustc_middle::mir::visit::*;
6+
use rustc_middle::mir::*;
57
use rustc_middle::ty::{self, Ty, TyCtxt};
68

79
pub struct RemoveZsts;
@@ -16,38 +18,24 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
1618
if tcx.type_of(body.source.def_id()).is_generator() {
1719
return;
1820
}
19-
let param_env = tcx.param_env(body.source.def_id());
20-
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
21+
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
2122
let local_decls = &body.local_decls;
22-
for block in basic_blocks {
23-
for statement in block.statements.iter_mut() {
24-
if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) =
25-
statement.kind
26-
{
27-
let place_ty = place.ty(local_decls, tcx).ty;
28-
if !maybe_zst(place_ty) {
29-
continue;
30-
}
31-
let Ok(layout) = tcx.layout_of(param_env.and(place_ty)) else {
32-
continue;
33-
};
34-
if !layout.is_zst() {
35-
continue;
36-
}
37-
if tcx.consider_optimizing(|| {
38-
format!(
39-
"RemoveZsts - Place: {:?} SourceInfo: {:?}",
40-
place, statement.source_info
41-
)
42-
}) {
43-
statement.make_nop();
44-
}
45-
}
46-
}
23+
let mut replacer = Replacer { tcx, param_env, local_decls };
24+
for var_debug_info in &mut body.var_debug_info {
25+
replacer.visit_var_debug_info(var_debug_info);
26+
}
27+
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
28+
replacer.visit_basic_block_data(bb, data);
4729
}
4830
}
4931
}
5032

33+
struct Replacer<'a, 'tcx> {
34+
tcx: TyCtxt<'tcx>,
35+
param_env: ty::ParamEnv<'tcx>,
36+
local_decls: &'a LocalDecls<'tcx>,
37+
}
38+
5139
/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
5240
fn maybe_zst(ty: Ty<'_>) -> bool {
5341
match ty.kind() {
@@ -63,3 +51,80 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
6351
_ => false,
6452
}
6553
}
54+
55+
impl<'tcx> Replacer<'_, 'tcx> {
56+
fn is_zst(&self, ty: Ty<'tcx>) -> bool {
57+
if !maybe_zst(ty) {
58+
return false;
59+
}
60+
let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else {
61+
return false;
62+
};
63+
layout.is_zst()
64+
}
65+
66+
fn make_zst(&self, ty: Ty<'tcx>) -> Constant<'tcx> {
67+
debug_assert!(self.is_zst(ty));
68+
Constant {
69+
span: rustc_span::DUMMY_SP,
70+
user_ty: None,
71+
literal: ConstantKind::Val(ConstValue::ZeroSized, ty),
72+
}
73+
}
74+
}
75+
76+
impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
77+
fn tcx(&self) -> TyCtxt<'tcx> {
78+
self.tcx
79+
}
80+
81+
fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
82+
match var_debug_info.value {
83+
VarDebugInfoContents::Const(_) => {}
84+
VarDebugInfoContents::Place(place) => {
85+
let place_ty = place.ty(self.local_decls, self.tcx).ty;
86+
if self.is_zst(place_ty) {
87+
var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(place_ty))
88+
}
89+
}
90+
VarDebugInfoContents::Composite { ty, fragments: _ } => {
91+
if self.is_zst(ty) {
92+
var_debug_info.value = VarDebugInfoContents::Const(self.make_zst(ty))
93+
}
94+
}
95+
}
96+
}
97+
98+
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
99+
if let Operand::Constant(_) = operand {
100+
return;
101+
}
102+
let op_ty = operand.ty(self.local_decls, self.tcx);
103+
if self.is_zst(op_ty)
104+
&& self.tcx.consider_optimizing(|| {
105+
format!("RemoveZsts - Operand: {:?} Location: {:?}", operand, loc)
106+
})
107+
{
108+
*operand = Operand::Constant(Box::new(self.make_zst(op_ty)))
109+
}
110+
}
111+
112+
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, loc: Location) {
113+
if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) =
114+
statement.kind
115+
{
116+
let place_ty = place.ty(self.local_decls, self.tcx).ty;
117+
if self.is_zst(place_ty)
118+
&& self.tcx.consider_optimizing(|| {
119+
format!(
120+
"RemoveZsts - Place: {:?} SourceInfo: {:?}",
121+
place, statement.source_info
122+
)
123+
})
124+
{
125+
statement.make_nop();
126+
}
127+
}
128+
self.super_statement(statement, loc);
129+
}
130+
}

tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@
1212
let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
1313
scope 3 {
1414
debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21
15-
let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
1615
scope 5 {
17-
debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
18-
let _7: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
16+
debug _enum_without_variants => const [ZeroSized: Empty]; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
1917
scope 7 {
20-
debug _non_utf8_str => _7; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
18+
debug _non_utf8_str => const Str::<"���">; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
2119
}
2220
}
2321
scope 6 {
@@ -46,18 +44,14 @@
4644
- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
4745
+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
4846
+ // mir::Constant
49-
+ // + span: $DIR/invalid_constant.rs:28:34: 28:57
47+
+ // + span: $DIR/invalid_constant.rs:29:34: 29:57
5048
+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) }
5149
+ _3 = [const Scalar(0x00000004): E]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
5250
+ // mir::Constant
53-
+ // + span: $DIR/invalid_constant.rs:28:24: 28:60
51+
+ // + span: $DIR/invalid_constant.rs:29:24: 29:60
5452
+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) }
5553
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
5654
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
57-
StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
58-
StorageLive(_7); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
59-
StorageDead(_7); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
60-
StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
6155
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
6256
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
6357
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
- // MIR for `main` before RemoveZsts
2+
+ // MIR for `main` after RemoveZsts
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:+0:11: +0:11
6+
let _1: char; // in scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
7+
let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63
8+
let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59
9+
let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55
10+
let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73
11+
let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65
12+
scope 1 {
13+
debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22
14+
let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
15+
scope 3 {
16+
debug _invalid_tag => _3; // in scope 3 at $DIR/invalid_constant.rs:+13:9: +13:21
17+
let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
18+
scope 5 {
19+
- debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
20+
+ debug _enum_without_variants => const [ZeroSized: Empty]; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31
21+
let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
22+
scope 7 {
23+
- debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
24+
+ debug _non_utf8_str => const Str::<"���">; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22
25+
}
26+
}
27+
scope 6 {
28+
}
29+
}
30+
scope 4 {
31+
}
32+
}
33+
scope 2 {
34+
}
35+
36+
bb0: {
37+
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
38+
StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
39+
Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
40+
(_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
41+
_1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
42+
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
43+
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
44+
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
45+
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
46+
Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
47+
(_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
48+
_4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
49+
_3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
50+
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
51+
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
52+
StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
53+
StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
54+
StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
55+
Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
56+
(_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
57+
- _7 = (_8.1: Empty); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
58+
- _6 = [move _7]; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
59+
+ nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
60+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
61+
StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
62+
StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75
63+
StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
64+
- _0 = const (); // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
65+
+ nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
66+
StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
67+
StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
68+
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
69+
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
70+
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
71+
}
72+
}
73+

tests/mir-opt/const_prop/invalid_constant.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum E { A, B, C }
1111
#[derive(Copy, Clone)]
1212
enum Empty {}
1313

14+
// EMIT_MIR invalid_constant.main.RemoveZsts.diff
1415
// EMIT_MIR invalid_constant.main.ConstProp.diff
1516
fn main() {
1617
// An invalid char.

tests/mir-opt/inline/asm_unwind.main.Inline.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
+ scope 1 (inlined foo) { // at $DIR/asm_unwind.rs:21:5: 21:10
88
+ let _2: D; // in scope 1 at $DIR/asm_unwind.rs:15:9: 15:11
99
+ scope 2 {
10-
+ debug _d => _2; // in scope 2 at $DIR/asm_unwind.rs:15:9: 15:11
10+
+ debug _d => const D; // in scope 2 at $DIR/asm_unwind.rs:15:9: 15:11
1111
+ scope 3 {
1212
+ }
1313
+ }

tests/mir-opt/inline/cycle.g.Inline.diff

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:8: +0:8
66
let _1: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:12
77
+ let mut _2: fn() {main}; // in scope 0 at $DIR/cycle.rs:+1:5: +1:12
8+
+ let mut _5: (); // in scope 0 at $DIR/cycle.rs:6:5: 6:8
89
+ scope 1 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
910
+ debug g => _2; // in scope 1 at $DIR/cycle.rs:5:6: 5:7
1011
+ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
1112
+ let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6
12-
+ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
1313
+ scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
1414
+ }
1515
+ }
@@ -29,6 +29,7 @@
2929
+ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6
3030
+ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6
3131
+ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
32+
+ _5 = const (); // scope 1 at $DIR/cycle.rs:6:5: 6:8
3233
+ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
3334
}
3435

@@ -48,7 +49,7 @@
4849
+ }
4950
+
5051
+ bb4: {
51-
+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
52+
+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
5253
+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
5354
+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
5455
+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2

tests/mir-opt/inline/cycle.main.Inline.diff

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:11: +0:11
66
let _1: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:9
77
+ let mut _2: fn() {g}; // in scope 0 at $DIR/cycle.rs:+1:5: +1:9
8+
+ let mut _5: (); // in scope 0 at $DIR/cycle.rs:6:5: 6:8
89
+ scope 1 (inlined f::<fn() {g}>) { // at $DIR/cycle.rs:17:5: 17:9
910
+ debug g => _2; // in scope 1 at $DIR/cycle.rs:5:6: 5:7
1011
+ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
1112
+ let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6
12-
+ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8
1313
+ scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8
1414
+ }
1515
+ }
@@ -29,6 +29,7 @@
2929
+ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6
3030
+ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6
3131
+ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
32+
+ _5 = const (); // scope 1 at $DIR/cycle.rs:6:5: 6:8
3233
+ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
3334
}
3435

@@ -48,7 +49,7 @@
4849
+ }
4950
+
5051
+ bb4: {
51-
+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8
52+
+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8
5253
+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8
5354
+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9
5455
+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2

tests/mir-opt/inline/inline_cycle.two.Inline.diff

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
66
let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
77
+ let mut _2: fn() {f}; // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
8+
+ let mut _4: (); // in scope 0 at $DIR/inline_cycle.rs:54:5: 54:8
89
+ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:49:5: 49:12
910
+ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23
1011
+ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
11-
+ let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
1212
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8
1313
+ }
1414
+ }
@@ -26,11 +26,12 @@
2626
// + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
2727
+ StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
2828
+ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
29+
+ _4 = const (); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
2930
+ _3 = move _2() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
3031
}
3132

3233
bb1: {
33-
+ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8
34+
+ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
3435
+ StorageDead(_3); // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9
3536
+ StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
3637
StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13

0 commit comments

Comments
 (0)