Skip to content

Commit c23e3b1

Browse files
committed
fixup! simplifycfg: Preserve debuginfos when merging bbs
Move all debuginfos to the last basic block if each bb has only one predecessor.
1 parent 7a04335 commit c23e3b1

File tree

3 files changed

+99
-14
lines changed

3 files changed

+99
-14
lines changed

compiler/rustc_mir_transform/src/simplify.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,9 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
158158
let mut terminator =
159159
self.basic_blocks[bb].terminator.take().expect("invalid terminator state");
160160

161-
let identical_succ = terminator.identical_successor();
162161
terminator.successors_mut(|successor| {
163162
self.collapse_goto_chain(successor, &mut changed);
164163
});
165-
if changed && let Some(identical_succ) = identical_succ {
166-
// Add debugging information from the goto chain only when all successors are identical,
167-
// otherwise, we may provide misleading debugging information within a branch.
168-
let mut succ_debuginfos =
169-
self.basic_blocks[identical_succ].after_last_stmt_debuginfos.clone();
170-
self.basic_blocks[bb].after_last_stmt_debuginfos.append(&mut succ_debuginfos);
171-
}
172164

173165
let mut inner_changed = true;
174166
merged_blocks.clear();
@@ -236,28 +228,36 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
236228
// goto chains. We should probably benchmark different sizes.
237229
let mut terminators: SmallVec<[_; 1]> = Default::default();
238230
let mut current = *start;
231+
// If each successor has only one predecessor, it's a trivial goto chain.
232+
// We can move all debuginfos to the last basic block.
233+
let mut trivial_goto_chain = true;
239234
while let Some(terminator) = self.take_terminator_if_simple_goto(current) {
240235
let Terminator { kind: TerminatorKind::Goto { target }, .. } = terminator else {
241236
unreachable!();
242237
};
238+
trivial_goto_chain &= self.pred_count[target] == 1;
243239
terminators.push((current, terminator));
244240
current = target;
245241
}
246242
let last = current;
247243
*changed |= *start != last;
248244
*start = last;
249-
let mut succ = last;
250245
while let Some((current, mut terminator)) = terminators.pop() {
251246
let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator
252247
else {
253248
unreachable!();
254249
};
255-
if *target != last {
256-
let mut succ_debuginfos =
257-
self.basic_blocks[succ].after_last_stmt_debuginfos.clone();
258-
self.basic_blocks[current].after_last_stmt_debuginfos.extend(&mut succ_debuginfos);
250+
if trivial_goto_chain {
251+
let mut pred_debuginfos =
252+
std::mem::take(&mut self.basic_blocks[current].after_last_stmt_debuginfos);
253+
let debuginfos = if let Some(stmt) = self.basic_blocks[last].statements.first_mut()
254+
{
255+
&mut stmt.debuginfos
256+
} else {
257+
&mut self.basic_blocks[last].after_last_stmt_debuginfos
258+
};
259+
debuginfos.prepend(&mut pred_debuginfos);
259260
}
260-
succ = current;
261261
*changed |= *target != last;
262262
*target = last;
263263
debug!("collapsing goto chain from {:?} to {:?}", current, target);
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
- // MIR for `preserve_debuginfo_3` before SimplifyCfg-final
2+
+ // MIR for `preserve_debuginfo_3` after SimplifyCfg-final
3+
4+
fn preserve_debuginfo_3(_1: &Foo, _2: bool) -> i32 {
5+
debug foo_a => _3;
6+
debug foo_b => _4;
7+
debug foo_c => _5;
8+
let mut _0: i32;
9+
let mut _3: &i32;
10+
let mut _4: &i64;
11+
let mut _5: &i32;
12+
13+
bb0: {
14+
- switchInt(copy _2) -> [1: bb1, otherwise: bb2];
15+
+ switchInt(copy _2) -> [1: bb2, otherwise: bb1];
16+
}
17+
18+
bb1: {
19+
- // DBG: _3 = &((*_1).0: i32);
20+
- goto -> bb3;
21+
- }
22+
-
23+
- bb2: {
24+
// DBG: _4 = &((*_1).1: i64);
25+
_0 = copy ((*_1).2: i32);
26+
return;
27+
}
28+
29+
- bb3: {
30+
+ bb2: {
31+
+ // DBG: _3 = &((*_1).0: i32);
32+
// DBG: _5 = &((*_1).2: i32);
33+
_0 = copy ((*_1).0: i32);
34+
return;
35+
}
36+
}
37+

tests/mir-opt/debuginfo/simplifycfg.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,54 @@ pub fn preserve_debuginfo_2(foo: &Foo) -> i32 {
119119
}
120120
}
121121

122+
// EMIT_MIR simplifycfg.preserve_debuginfo_3.SimplifyCfg-final.diff
123+
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
124+
pub fn preserve_debuginfo_3(foo: &Foo, c: bool) -> i32 {
125+
// CHECK-LABEL: fn preserve_debuginfo_3
126+
// CHECK: debug foo_a => [[foo_a:_[0-9]+]];
127+
// CHECK: debug foo_b => [[foo_b:_[0-9]+]];
128+
// CHECK: debug foo_c => [[foo_c:_[0-9]+]];
129+
// CHECK: bb0: {
130+
// CHECK-NEXT: switchInt(copy _2) -> [1: bb2, otherwise: bb1];
131+
// CHECK: bb1: {
132+
// CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64)
133+
// CHECK-NEXT: _0 = copy ((*_1).2: i32);
134+
// CHECK-NEXT: return;
135+
// CHECK: bb2: {
136+
// CHECK-NEXT: DBG: [[foo_a]] = &((*_1).0: i32)
137+
// CHECK-NEXT: DBG: [[foo_c]] = &((*_1).2: i32)
138+
// CHECK-NEXT: _0 = copy ((*_1).0: i32);
139+
// CHECK-NEXT: return;
140+
mir! {
141+
let _foo_a: &i32;
142+
let _foo_b: &i64;
143+
let _foo_c: &i32;
144+
debug foo_a => _foo_a;
145+
debug foo_b => _foo_b;
146+
debug foo_c => _foo_c;
147+
{
148+
match c {
149+
true => tmp,
150+
_ => ret,
151+
}
152+
}
153+
tmp = {
154+
_foo_a = &(*foo).a;
155+
Goto(ret_1)
156+
}
157+
ret = {
158+
_foo_b = &(*foo).b;
159+
RET = (*foo).c;
160+
Return()
161+
}
162+
ret_1 = {
163+
_foo_c = &(*foo).c;
164+
RET = (*foo).a;
165+
Return()
166+
}
167+
}
168+
}
169+
122170
// EMIT_MIR simplifycfg.preserve_debuginfo_identical_succs.SimplifyCfg-final.diff
123171
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
124172
pub fn preserve_debuginfo_identical_succs(foo: &Foo, c: bool) -> i32 {

0 commit comments

Comments
 (0)