Skip to content

Commit e489971

Browse files
committed
Fix def-use dominance check
A definition does not dominate a use in the same statement. For example in MIR generated for compound assignment x += a (when overflow checks are disabled).
1 parent c62665e commit e489971

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

compiler/rustc_codegen_ssa/src/mir/analyze.rs

+22-11
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
3636

3737
// Arguments get assigned to by means of the function being called
3838
for arg in mir.args_iter() {
39-
analyzer.assign(arg, mir::START_BLOCK.start_location());
39+
analyzer.assign(arg, DefLocation::Argument);
4040
}
4141

4242
// If there exists a local definition that dominates all uses of that local,
@@ -64,7 +64,22 @@ enum LocalKind {
6464
/// A scalar or a scalar pair local that is neither defined nor used.
6565
Unused,
6666
/// A scalar or a scalar pair local with a single definition that dominates all uses.
67-
SSA(mir::Location),
67+
SSA(DefLocation),
68+
}
69+
70+
#[derive(Copy, Clone, PartialEq, Eq)]
71+
enum DefLocation {
72+
Argument,
73+
Body(Location),
74+
}
75+
76+
impl DefLocation {
77+
fn dominates(self, location: Location, dominators: &Dominators<mir::BasicBlock>) -> bool {
78+
match self {
79+
DefLocation::Argument => true,
80+
DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators),
81+
}
82+
}
6883
}
6984

7085
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
@@ -74,17 +89,13 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
7489
}
7590

7691
impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
77-
fn assign(&mut self, local: mir::Local, location: Location) {
92+
fn assign(&mut self, local: mir::Local, location: DefLocation) {
7893
let kind = &mut self.locals[local];
7994
match *kind {
8095
LocalKind::ZST => {}
8196
LocalKind::Memory => {}
82-
LocalKind::Unused => {
83-
*kind = LocalKind::SSA(location);
84-
}
85-
LocalKind::SSA(_) => {
86-
*kind = LocalKind::Memory;
87-
}
97+
LocalKind::Unused => *kind = LocalKind::SSA(location),
98+
LocalKind::SSA(_) => *kind = LocalKind::Memory,
8899
}
89100
}
90101

@@ -166,7 +177,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
166177
debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
167178

168179
if let Some(local) = place.as_local() {
169-
self.assign(local, location);
180+
self.assign(local, DefLocation::Body(location));
170181
if self.locals[local] != LocalKind::Memory {
171182
let decl_span = self.fx.mir.local_decls[local].source_info.span;
172183
if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
@@ -189,7 +200,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
189200
match context {
190201
PlaceContext::MutatingUse(MutatingUseContext::Call)
191202
| PlaceContext::MutatingUse(MutatingUseContext::Yield) => {
192-
self.assign(local, location);
203+
self.assign(local, DefLocation::Body(location));
193204
}
194205

195206
PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}

tests/ui/mir/mir_codegen_ssa.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// build-pass
2+
// compile-flags: --crate-type=lib
3+
#![feature(custom_mir, core_intrinsics)]
4+
use std::intrinsics::mir::*;
5+
6+
#[custom_mir(dialect = "runtime", phase = "optimized")]
7+
pub fn f(a: u32) -> u32 {
8+
mir!(
9+
let x: u32;
10+
{
11+
// Previously code generation failed with ICE "use of .. before def ..." because the
12+
// definition of x was incorrectly identified as dominating the use of x located in the
13+
// same statement:
14+
x = x + a;
15+
RET = x;
16+
Return()
17+
}
18+
)
19+
}

0 commit comments

Comments
 (0)