Skip to content

Commit 9e3f091

Browse files
committed
Replace ZST operands and debuginfo by constants.
1 parent cf8d98b commit 9e3f091

15 files changed

+219
-106
lines changed
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()).subst_identity().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

+2-8
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 {
@@ -52,10 +50,6 @@
5250
+ // + literal: Const { ty: E, val: Value(Scalar(0x00000004)) }
5351
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
5452
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
55-
StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
56-
StorageLive(_7); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
57-
StorageDead(_7); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
58-
StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
5953
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
6054
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
6155
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
_2 = InvalidChar { int: const 1114113_u32 }; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
40+
_1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
41+
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
42+
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
43+
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
44+
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
45+
_5 = InvalidTag { int: const 4_u32 }; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
46+
_4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
47+
_3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
48+
StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60
49+
StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61
50+
StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
51+
StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
52+
StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
53+
_8 = NoVariants { int: const 0_u32 }; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
54+
- _7 = (_8.1: Empty); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
55+
- _6 = [move _7]; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
56+
+ nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
57+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
58+
StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
59+
StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75
60+
StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
61+
- _0 = const (); // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
62+
+ nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
63+
StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
64+
StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
65+
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
66+
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
67+
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
68+
}
69+
}
70+

tests/mir-opt/const_prop/invalid_constant.rs

+1
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/const_prop/issue_66971.main.ConstProp.diff

+1-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@
55
let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11
66
let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
77
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
8-
let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
98

109
bb0: {
1110
StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
1211
StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
13-
StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
14-
_2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
15-
StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22
12+
_2 = (const (), const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
1613
_1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
1714
// mir::Constant
1815
// + span: $DIR/issue_66971.rs:17:5: 17:11

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

+1-1
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

+3-2
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

+3-2
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

+3-2
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)