Skip to content

Commit 9c2336a

Browse files
authored
Rollup merge of rust-lang#107270 - cjgillot:remove-zst, r=oli-obk
Replace ZST operands and debuginfo by constants. This is work that ConstProp will not have to do. Split from rust-lang#107267
2 parents 85fed83 + 49f4399 commit 9c2336a

29 files changed

+304
-183
lines changed
+103-29
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
//! Removes assignments to ZST places.
1+
//! Removes operations on ZST places, and convert ZST operands to constants.
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,89 @@ fn maybe_zst(ty: Ty<'_>) -> bool {
6351
_ => false,
6452
}
6553
}
54+
55+
impl<'tcx> Replacer<'_, 'tcx> {
56+
fn known_to_be_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.known_to_be_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.known_to_be_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.known_to_be_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.known_to_be_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+
let place_for_ty = match statement.kind {
114+
StatementKind::Assign(box (place, ref rvalue)) => {
115+
rvalue.is_safe_to_remove().then_some(place)
116+
}
117+
StatementKind::Deinit(box place)
118+
| StatementKind::SetDiscriminant { box place, variant_index: _ }
119+
| StatementKind::AscribeUserType(box (place, _), _)
120+
| StatementKind::Retag(_, box place)
121+
| StatementKind::FakeRead(box (_, place)) => Some(place),
122+
StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
123+
Some(local.into())
124+
}
125+
StatementKind::Coverage(_) | StatementKind::Intrinsic(_) | StatementKind::Nop => None,
126+
};
127+
if let Some(place_for_ty) = place_for_ty
128+
&& let ty = place_for_ty.ty(self.local_decls, self.tcx).ty
129+
&& self.known_to_be_zst(ty)
130+
&& self.tcx.consider_optimizing(|| {
131+
format!("RemoveZsts - Place: {:?} SourceInfo: {:?}", place_for_ty, statement.source_info)
132+
})
133+
{
134+
statement.make_nop();
135+
} else {
136+
self.super_statement(statement, loc);
137+
}
138+
}
139+
}

tests/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
}
1515

1616
bb1: {
17-
StorageLive(_2); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
1817
_2 = begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL
1918
// mir::Constant
2019
// + span: $SRC_DIR/std/src/panic.rs:LL:COL

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

+4-10
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31
55+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73
56+
StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
57+
Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
58+
(_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65
59+
- _7 = (_8.1: Empty); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
60+
- _6 = [move _7]; // 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+
+ nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71
63+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74
64+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74
65+
StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75
66+
- StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
67+
- _0 = const (); // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
68+
- StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
69+
- StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
70+
+ nop; // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22
71+
+ nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2
72+
+ nop; // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2
73+
+ nop; // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2
74+
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2
75+
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2
76+
return; // scope 0 at $DIR/invalid_constant.rs:+27:2: +27:2
77+
}
78+
}
79+

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

-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
88

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

2120
bb1: {
2221
StorageDead(_2); // scope 0 at $DIR/issue_66971.rs:+1:22: +1:23
23-
StorageDead(_1); // scope 0 at $DIR/issue_66971.rs:+1:23: +1:24
2422
return; // scope 0 at $DIR/issue_66971.rs:+2:2: +2:2
2523
}
2624
}

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

-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
let mut _3: (u8, u8); // in scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
99

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

2726
bb1: {
2827
StorageDead(_2); // scope 0 at $DIR/issue_67019.rs:+1:19: +1:20
29-
StorageDead(_1); // scope 0 at $DIR/issue_67019.rs:+1:20: +1:21
3028
return; // scope 0 at $DIR/issue_67019.rs:+2:2: +2:2
3129
}
3230
}

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

-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
bb0: {
1414
StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10
1515
_1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14
16-
StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
1716
StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
1817
- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
1918
- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
@@ -26,7 +25,6 @@
2625

2726
bb1: {
2827
StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15
29-
StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16
3028
StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2
3129
return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2
3230
}

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

-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
1616
(_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
1717
(_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
18-
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
1918
StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
2019
- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
2120
+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
@@ -27,7 +26,6 @@
2726

2827
bb1: {
2928
StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
30-
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
3129
StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
3230
return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
3331
}

0 commit comments

Comments
 (0)