Skip to content

Commit 64cd13f

Browse files
committed
add test for GVN issue; cleanup in dataflow_const_prop
1 parent 1025a12 commit 64cd13f

File tree

5 files changed

+98
-7
lines changed

5 files changed

+98
-7
lines changed

compiler/rustc_const_eval/src/interpret/operand.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,12 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
260260
// This makes several assumptions about what layouts we will encounter; we match what
261261
// codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`).
262262
let inner_val: Immediate<_> = match (**self, self.layout.abi) {
263-
// if the entire value is uninit, then so is the field (can happen in ConstProp)
263+
// If the entire value is uninit, then so is the field (can happen in ConstProp).
264264
(Immediate::Uninit, _) => Immediate::Uninit,
265+
// If the field is uninhabited, we can forget the data (can happen in ConstProp).
266+
// `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
267+
// has an `Uninhabited` variant, which means this case is possible.
268+
_ if layout.abi.is_uninhabited() => Immediate::Uninit,
265269
// the field contains no information, can be left uninit
266270
// (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
267271
_ if layout.is_zst() => Immediate::Uninit,

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -403,12 +403,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
403403
operand,
404404
&mut |elem, op| match elem {
405405
TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(),
406-
TrackElem::Variant(idx) => {
407-
if op.layout.for_variant(&self.ecx, idx).abi.is_uninhabited() {
408-
return None;
409-
}
410-
self.ecx.project_downcast(op, idx).ok()
411-
}
406+
TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(),
412407
TrackElem::Discriminant => {
413408
let variant = self.ecx.read_discriminant(op).ok()?;
414409
let discr_value =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- // MIR for `f` before GVN
2+
+ // MIR for `f` after GVN
3+
4+
fn f() -> u32 {
5+
let mut _0: u32;
6+
let _1: u32;
7+
let mut _2: E;
8+
let mut _3: &U;
9+
let _4: U;
10+
scope 1 {
11+
debug i => _1;
12+
}
13+
scope 2 {
14+
let mut _5: &U;
15+
}
16+
17+
bb0: {
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
_5 = const _;
21+
_3 = &(*_5);
22+
_2 = ((*_3).1: E);
23+
StorageLive(_1);
24+
- _1 = ((_2 as A).1: u32);
25+
+ _1 = const 0_u32;
26+
StorageDead(_3);
27+
StorageDead(_2);
28+
- _0 = _1;
29+
+ _0 = const 0_u32;
30+
StorageDead(_1);
31+
return;
32+
}
33+
}
34+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- // MIR for `f` before GVN
2+
+ // MIR for `f` after GVN
3+
4+
fn f() -> u32 {
5+
let mut _0: u32;
6+
let _1: u32;
7+
let mut _2: E;
8+
let mut _3: &U;
9+
let _4: U;
10+
scope 1 {
11+
debug i => _1;
12+
}
13+
scope 2 {
14+
let mut _5: &U;
15+
}
16+
17+
bb0: {
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
_5 = const _;
21+
_3 = &(*_5);
22+
_2 = ((*_3).1: E);
23+
StorageLive(_1);
24+
- _1 = ((_2 as A).1: u32);
25+
+ _1 = const 0_u32;
26+
StorageDead(_3);
27+
StorageDead(_2);
28+
- _0 = _1;
29+
+ _0 = const 0_u32;
30+
StorageDead(_1);
31+
return;
32+
}
33+
}
34+

tests/mir-opt/gvn_uninhabited.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// unit-test: GVN
2+
// compile-flags: -O
3+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
4+
// skip-filecheck
5+
6+
#![feature(never_type)]
7+
8+
#[derive(Copy, Clone)]
9+
pub enum E {
10+
A(!, u32),
11+
}
12+
13+
pub union U {
14+
i: u32,
15+
e: E,
16+
}
17+
18+
// EMIT_MIR gvn_uninhabited.f.GVN.diff
19+
pub const fn f() -> u32 {
20+
let E::A(_, i) = unsafe { (&U { i: 0 }).e };
21+
i
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)