Skip to content

Commit 10967a1

Browse files
committed
Auto merge of rust-lang#88968 - tmiasko:start-block-no-predecessors, r=davidtwco
Start block is not allowed to have basic block predecessors * The MIR validator is extended to detect potential violations. * The start block has no predecessors after building MIR, so no changes are required there. * The SimplifyCfg could previously violate this requirement when collapsing goto chains, so transformation is disabled for the start block, which also substantially simplifies the implementation. * The LLVM function entry block also must not have basic block predecessors. Previously, to ensure that code generation had to perform necessary adjustments. This now became unnecessary. The motivation behind the change is to align with analogous requirement in LLVM, and to avoid potential latent bugs like the one reported in rust-lang#88043.
2 parents e20a4ec + f1f1c8f commit 10967a1

9 files changed

+84
-110
lines changed

Diff for: compiler/rustc_codegen_ssa/src/mir/mod.rs

+5-19
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
152152
}
153153

154154
let cleanup_kinds = analyze::cleanup_kinds(&mir);
155-
// Allocate a `Block` for every basic block, except
156-
// the start block, if nothing loops back to it.
157-
let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
158-
let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> =
159-
mir.basic_blocks()
160-
.indices()
161-
.map(|bb| {
162-
if bb == mir::START_BLOCK && !reentrant_start_block {
163-
Some(start_llbb)
164-
} else {
165-
None
166-
}
167-
})
168-
.collect();
155+
let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = mir
156+
.basic_blocks()
157+
.indices()
158+
.map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None })
159+
.collect();
169160

170161
let mut fx = FunctionCx {
171162
instance,
@@ -247,11 +238,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
247238
// Apply debuginfo to the newly allocated locals.
248239
fx.debug_introduce_locals(&mut bx);
249240

250-
// Branch to the START block, if it's not the entry block.
251-
if reentrant_start_block {
252-
bx.br(fx.llbb(mir::START_BLOCK));
253-
}
254-
255241
// Codegen the body of each block using reverse postorder
256242
// FIXME(eddyb) reuse RPO iterator between `analysis` and this.
257243
for (bb, _) in traversal::reverse_postorder(&mir) {

Diff for: compiler/rustc_const_eval/src/transform/validate.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::mir::visit::{PlaceContext, Visitor};
99
use rustc_middle::mir::{
1010
AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
1111
PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
12-
TerminatorKind,
12+
TerminatorKind, START_BLOCK,
1313
};
1414
use rustc_middle::ty::fold::BottomUpFolder;
1515
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
@@ -130,6 +130,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
130130
}
131131

132132
fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
133+
if bb == START_BLOCK {
134+
self.fail(location, "start block must not have predecessors")
135+
}
133136
if let Some(bb) = self.body.basic_blocks().get(bb) {
134137
let src = self.body.basic_blocks().get(location.block).unwrap();
135138
match (src.is_cleanup, bb.is_cleanup, edge_kind) {

Diff for: compiler/rustc_mir_transform/src/simplify.rs

-25
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
9595
pub fn simplify(mut self) {
9696
self.strip_nops();
9797

98-
let mut start = START_BLOCK;
99-
10098
// Vec of the blocks that should be merged. We store the indices here, instead of the
10199
// statements itself to avoid moving the (relatively) large statements twice.
102100
// We do not push the statements directly into the target block (`bb`) as that is slower
@@ -105,8 +103,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
105103
loop {
106104
let mut changed = false;
107105

108-
self.collapse_goto_chain(&mut start, &mut changed);
109-
110106
for bb in self.basic_blocks.indices() {
111107
if self.pred_count[bb] == 0 {
112108
continue;
@@ -149,27 +145,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
149145
break;
150146
}
151147
}
152-
153-
if start != START_BLOCK {
154-
debug_assert!(self.pred_count[START_BLOCK] == 0);
155-
self.basic_blocks.swap(START_BLOCK, start);
156-
self.pred_count.swap(START_BLOCK, start);
157-
158-
// pred_count == 1 if the start block has no predecessor _blocks_.
159-
if self.pred_count[START_BLOCK] > 1 {
160-
for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
161-
if self.pred_count[bb] == 0 {
162-
continue;
163-
}
164-
165-
for target in data.terminator_mut().successors_mut() {
166-
if *target == start {
167-
*target = START_BLOCK;
168-
}
169-
}
170-
}
171-
}
172-
}
173148
}
174149

175150
/// This function will return `None` if

Diff for: src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ digraph Cov_0_3 {
22
graph [fontname="Courier, monospace"];
33
node [fontname="Courier, monospace"];
44
edge [fontname="Courier, monospace"];
5-
bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/> 13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
6-
bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/> 12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb1 + 0) at 15:2-15:2<br/> 15:2-15:2: @3.Return: return</td></tr><tr><td align="left" balign="left">bb3: Return</td></tr></table>>];
7-
bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/> 11:12-11:17: @1.Call: _2 = bar() -&gt; [return: bb2, unwind: bb5]</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
8-
bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>];
9-
bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=<false>];
10-
bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<otherwise>];
5+
bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br/> 13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>];
6+
bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18<br/> 12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2<br/> 15:2-15:2: @4.Return: return</td></tr><tr><td align="left" balign="left">bb4: Return</td></tr></table>>];
7+
bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br/> 11:12-11:17: @2.Call: _2 = bar() -&gt; [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
8+
bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br/> </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
9+
bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
10+
bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
11+
bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
12+
bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
1113
}

Diff for: src/test/mir-opt/inline/inline_diverging.h.Inline.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
4848
+ StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
4949
+ _9 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
50-
+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22
50+
+ goto -> bb1; // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22
5151
}
5252

5353
bb1: {

Diff for: src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff

+17-12
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,43 @@
88
let mut _3: !; // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10
99

1010
bb0: {
11-
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
12-
falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
11+
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 10:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
12+
goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
1313
}
1414

1515
bb1: {
16+
+ Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:11:5 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
17+
falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
18+
}
19+
20+
bb2: {
1621
StorageLive(_2); // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
17-
_2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
22+
_2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
1823
// mir::Constant
1924
// + span: /the/src/instrument_coverage.rs:12:12: 12:15
2025
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
2126
}
2227

23-
bb2: {
24-
switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
28+
bb3: {
29+
switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
2530
}
2631

27-
bb3: {
28-
+ Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
29-
+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
32+
bb4: {
33+
+ Coverage::Expression(4294967293) = 4294967294 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
34+
+ Coverage::Expression(4294967294) = 4294967295 - 2 for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
3035
_0 = const (); // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
3136
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
3237
return; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
3338
}
3439

35-
bb4: {
36-
+ Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
40+
bb5: {
41+
+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
3742
_1 = const (); // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10
3843
StorageDead(_2); // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
39-
goto -> bb0; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
44+
goto -> bb1; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
4045
}
4146

42-
bb5 (cleanup): {
47+
bb6 (cleanup): {
4348
resume; // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2
4449
}
4550
}

Diff for: src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff

+19-15
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,44 @@
88
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
99

1010
bb0: {
11-
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
11+
goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
12+
}
13+
14+
bb1: {
15+
- goto -> bb2; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
1216
- }
1317
-
14-
- bb1: {
18+
- bb2: {
1519
StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
16-
- _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
17-
+ _2 = bar() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
20+
- _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
21+
+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
1822
// mir::Constant
1923
// + span: $DIR/simplify_cfg.rs:9:12: 9:15
2024
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
2125
}
2226

23-
- bb2: {
24-
- switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
25-
+ bb1: {
26-
+ switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
27-
}
28-
2927
- bb3: {
28+
- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
3029
+ bb2: {
30+
+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
31+
}
32+
33+
- bb4: {
34+
+ bb3: {
3135
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
3236
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
3337
return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
3438
}
3539

36-
- bb4: {
37-
+ bb3: {
40+
- bb5: {
41+
+ bb4: {
3842
_1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
3943
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
40-
goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
44+
goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
4145
}
4246

43-
- bb5 (cleanup): {
44-
+ bb4 (cleanup): {
47+
- bb6 (cleanup): {
48+
+ bb5 (cleanup): {
4549
resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
4650
}
4751
}

Diff for: src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff

+12-17
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,35 @@
88
let mut _3: !; // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
99

1010
bb0: {
11-
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
12-
+ falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
11+
goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
1312
}
1413

1514
bb1: {
1615
- falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
17-
- }
18-
-
19-
- bb2: {
16+
+ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
17+
}
18+
19+
bb2: {
2020
StorageLive(_2); // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
2121
- _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
22-
+ _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
22+
+ _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
2323
// mir::Constant
2424
// + span: $DIR/simplify_cfg.rs:9:12: 9:15
2525
// + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
2626
}
2727

28-
- bb3: {
29-
- switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
30-
+ bb2: {
31-
+ switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
28+
bb3: {
29+
switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
3230
}
3331

34-
- bb4: {
35-
+ bb3: {
32+
bb4: {
3633
_0 = const (); // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
3734
- goto -> bb10; // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
3835
+ StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
3936
+ return; // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
4037
}
4138

42-
- bb5: {
39+
bb5: {
4340
- goto -> bb8; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
4441
- }
4542
-
@@ -52,15 +49,13 @@
5249
- }
5350
-
5451
- bb8: {
55-
+ bb4: {
5652
_1 = const (); // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
5753
- goto -> bb9; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
5854
- }
5955
-
6056
- bb9: {
6157
StorageDead(_2); // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
62-
- goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
63-
+ goto -> bb0; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
58+
goto -> bb1; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
6459
}
6560

6661
- bb10: {
@@ -69,7 +64,7 @@
6964
- }
7065
-
7166
- bb11 (cleanup): {
72-
+ bb5 (cleanup): {
67+
+ bb6 (cleanup): {
7368
resume; // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
7469
}
7570
}

0 commit comments

Comments
 (0)