Skip to content

Commit b3dc088

Browse files
committed
Allocate candidate vectors as we sort them
1 parent 0c9b5e2 commit b3dc088

7 files changed

+56
-88
lines changed

compiler/rustc_mir_build/src/build/matches/mod.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -1676,10 +1676,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16761676
&'b mut [&'c mut Candidate<'pat, 'tcx>],
16771677
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
16781678
) {
1679-
// For each of the N possible outcomes, create a (initially empty) vector of candidates.
1680-
// Those are the candidates that apply if the test has that particular outcome.
1681-
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'pat, 'tcx>>> =
1682-
test.targets().into_iter().map(|branch| (branch, Vec::new())).collect();
1679+
// For each of the possible outcomes, collect vector of candidates that apply if the test
1680+
// has that particular outcome.
1681+
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default();
16831682

16841683
let total_candidate_count = candidates.len();
16851684

@@ -1691,7 +1690,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16911690
break;
16921691
};
16931692
let (candidate, rest) = candidates.split_first_mut().unwrap();
1694-
target_candidates[&branch].push(candidate);
1693+
target_candidates.entry(branch).or_insert_with(Vec::new).push(candidate);
16951694
candidates = rest;
16961695
}
16971696

@@ -1832,31 +1831,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18321831
otherwise_block
18331832
};
18341833

1835-
// For each outcome of test, process the candidates that still
1836-
// apply. Collect a list of blocks where control flow will
1837-
// branch if one of the `target_candidate` sets is not
1838-
// exhaustive.
1834+
// For each outcome of test, process the candidates that still apply.
18391835
let target_blocks: FxIndexMap<_, _> = target_candidates
18401836
.into_iter()
18411837
.map(|(branch, mut candidates)| {
1842-
if !candidates.is_empty() {
1843-
let candidate_start = self.cfg.start_new_block();
1844-
self.match_candidates(
1845-
span,
1846-
scrutinee_span,
1847-
candidate_start,
1848-
remainder_start,
1849-
&mut *candidates,
1850-
);
1851-
(branch, candidate_start)
1852-
} else {
1853-
(branch, remainder_start)
1854-
}
1838+
let candidate_start = self.cfg.start_new_block();
1839+
self.match_candidates(
1840+
span,
1841+
scrutinee_span,
1842+
candidate_start,
1843+
remainder_start,
1844+
&mut *candidates,
1845+
);
1846+
(branch, candidate_start)
18551847
})
18561848
.collect();
18571849

18581850
// Perform the test, branching to one of N blocks.
1859-
self.perform_test(span, scrutinee_span, start_block, &match_place, &test, target_blocks);
1851+
self.perform_test(
1852+
span,
1853+
scrutinee_span,
1854+
start_block,
1855+
remainder_start,
1856+
&match_place,
1857+
&test,
1858+
target_blocks,
1859+
);
18601860
}
18611861

18621862
/// Determine the fake borrows that are needed from a set of places that

compiler/rustc_mir_build/src/build/matches/test.rs

+2-34
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
127127
match_start_span: Span,
128128
scrutinee_span: Span,
129129
block: BasicBlock,
130+
otherwise_block: BasicBlock,
130131
place_builder: &PlaceBuilder<'tcx>,
131132
test: &Test<'tcx>,
132133
target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
133134
) {
134135
let place = place_builder.to_place(self);
135136
let place_ty = place.ty(&self.local_decls, self.tcx);
136137
debug!(?place, ?place_ty);
137-
let target_block = |branch| target_blocks[&branch];
138+
let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block);
138139

139140
let source_info = self.source_info(test.span);
140141
match test.kind {
141142
TestKind::Switch { adt_def, ref variants } => {
142143
// Variants is a BitVec of indexes into adt_def.variants.
143144
let num_enum_variants = adt_def.variants().len();
144-
debug_assert_eq!(target_blocks.len(), num_enum_variants + 1);
145145
let otherwise_block = target_block(TestBranch::Failure);
146146
let tcx = self.tcx;
147147
let switch_targets = SwitchTargets::new(
@@ -185,7 +185,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
185185

186186
TestKind::SwitchInt { ref options } => {
187187
// The switch may be inexhaustive so we have a catch-all block
188-
debug_assert_eq!(options.len() + 1, target_blocks.len());
189188
let otherwise_block = target_block(TestBranch::Failure);
190189
let switch_targets = SwitchTargets::new(
191190
options
@@ -201,7 +200,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
201200
}
202201

203202
TestKind::If => {
204-
debug_assert_eq!(target_blocks.len(), 2);
205203
let success_block = target_block(TestBranch::Success);
206204
let fail_block = target_block(TestBranch::Failure);
207205
let terminator =
@@ -211,7 +209,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
211209

212210
TestKind::Eq { value, ty } => {
213211
let tcx = self.tcx;
214-
debug_assert_eq!(target_blocks.len(), 2);
215212
let success_block = target_block(TestBranch::Success);
216213
let fail_block = target_block(TestBranch::Failure);
217214
if let ty::Adt(def, _) = ty.kind()
@@ -290,7 +287,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
290287
}
291288

292289
TestKind::Range(ref range) => {
293-
debug_assert_eq!(target_blocks.len(), 2);
294290
let success = target_block(TestBranch::Success);
295291
let fail = target_block(TestBranch::Failure);
296292
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
@@ -337,7 +333,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
337333
// expected = <N>
338334
let expected = self.push_usize(block, source_info, len);
339335

340-
debug_assert_eq!(target_blocks.len(), 2);
341336
let success_block = target_block(TestBranch::Success);
342337
let fail_block = target_block(TestBranch::Failure);
343338
// result = actual == expected OR result = actual < expected
@@ -753,33 +748,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
753748
}
754749
}
755750

756-
impl<'tcx> Test<'tcx> {
757-
pub(super) fn targets(&self) -> Vec<TestBranch<'tcx>> {
758-
match self.kind {
759-
TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => {
760-
vec![TestBranch::Success, TestBranch::Failure]
761-
}
762-
TestKind::Switch { adt_def, .. } => {
763-
// While the switch that we generate doesn't test for all
764-
// variants, we have a target for each variant and the
765-
// otherwise case, and we make sure that all of the cases not
766-
// specified have the same block.
767-
adt_def
768-
.variants()
769-
.indices()
770-
.map(|idx| TestBranch::Variant(idx))
771-
.chain([TestBranch::Failure])
772-
.collect()
773-
}
774-
TestKind::SwitchInt { ref options } => options
775-
.iter()
776-
.map(|(val, bits)| TestBranch::Constant(*val, *bits))
777-
.chain([TestBranch::Failure])
778-
.collect(),
779-
}
780-
}
781-
}
782-
783751
fn is_switch_ty(ty: Ty<'_>) -> bool {
784752
ty.is_integral() || ty.is_char()
785753
}

tests/mir-opt/building/issue_49232.main.built.after.mir

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn main() -> () {
2525
StorageLive(_3);
2626
_3 = const true;
2727
PlaceMention(_3);
28-
switchInt(_3) -> [0: bb6, otherwise: bb4];
28+
switchInt(_3) -> [0: bb4, otherwise: bb6];
2929
}
3030

3131
bb3: {
@@ -34,16 +34,16 @@ fn main() -> () {
3434
}
3535

3636
bb4: {
37-
_0 = const ();
38-
goto -> bb13;
37+
falseEdge -> [real: bb8, imaginary: bb6];
3938
}
4039

4140
bb5: {
4241
goto -> bb3;
4342
}
4443

4544
bb6: {
46-
falseEdge -> [real: bb8, imaginary: bb4];
45+
_0 = const ();
46+
goto -> bb13;
4747
}
4848

4949
bb7: {

tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir

+7-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn full_tested_match() -> () {
2828
_2 = Option::<i32>::Some(const 42_i32);
2929
PlaceMention(_2);
3030
_3 = discriminant(_2);
31-
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
31+
switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
3232
}
3333

3434
bb1: {
@@ -37,20 +37,20 @@ fn full_tested_match() -> () {
3737
}
3838

3939
bb2: {
40-
_1 = (const 3_i32, const 3_i32);
41-
goto -> bb13;
40+
falseEdge -> [real: bb7, imaginary: bb3];
4241
}
4342

4443
bb3: {
45-
goto -> bb1;
44+
falseEdge -> [real: bb12, imaginary: bb5];
4645
}
4746

4847
bb4: {
49-
falseEdge -> [real: bb7, imaginary: bb5];
48+
goto -> bb1;
5049
}
5150

5251
bb5: {
53-
falseEdge -> [real: bb12, imaginary: bb2];
52+
_1 = (const 3_i32, const 3_i32);
53+
goto -> bb13;
5454
}
5555

5656
bb6: {
@@ -91,7 +91,7 @@ fn full_tested_match() -> () {
9191
bb11: {
9292
StorageDead(_7);
9393
StorageDead(_6);
94-
goto -> bb5;
94+
goto -> bb3;
9595
}
9696

9797
bb12: {

tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir

+11-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn full_tested_match2() -> () {
2828
_2 = Option::<i32>::Some(const 42_i32);
2929
PlaceMention(_2);
3030
_3 = discriminant(_2);
31-
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
31+
switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
3232
}
3333

3434
bb1: {
@@ -37,18 +37,10 @@ fn full_tested_match2() -> () {
3737
}
3838

3939
bb2: {
40-
falseEdge -> [real: bb12, imaginary: bb5];
40+
falseEdge -> [real: bb7, imaginary: bb5];
4141
}
4242

4343
bb3: {
44-
goto -> bb1;
45-
}
46-
47-
bb4: {
48-
falseEdge -> [real: bb7, imaginary: bb2];
49-
}
50-
51-
bb5: {
5244
StorageLive(_9);
5345
_9 = ((_2 as Some).0: i32);
5446
StorageLive(_10);
@@ -59,6 +51,14 @@ fn full_tested_match2() -> () {
5951
goto -> bb13;
6052
}
6153

54+
bb4: {
55+
goto -> bb1;
56+
}
57+
58+
bb5: {
59+
falseEdge -> [real: bb12, imaginary: bb3];
60+
}
61+
6262
bb6: {
6363
goto -> bb1;
6464
}
@@ -97,7 +97,7 @@ fn full_tested_match2() -> () {
9797
bb11: {
9898
StorageDead(_7);
9999
StorageDead(_6);
100-
falseEdge -> [real: bb5, imaginary: bb2];
100+
falseEdge -> [real: bb3, imaginary: bb5];
101101
}
102102

103103
bb12: {

tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
StorageDead(_5);
3131
StorageDead(_4);
3232
_8 = discriminant((_3.0: std::option::Option<u32>));
33-
- switchInt(move _8) -> [0: bb2, 1: bb3, otherwise: bb1];
33+
- switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1];
3434
+ StorageLive(_11);
3535
+ _11 = discriminant((_3.1: std::option::Option<u32>));
3636
+ StorageLive(_12);
@@ -48,12 +48,12 @@
4848

4949
bb2: {
5050
- _6 = discriminant((_3.1: std::option::Option<u32>));
51-
- switchInt(move _6) -> [0: bb5, otherwise: bb1];
51+
- switchInt(move _6) -> [1: bb4, otherwise: bb1];
5252
- }
5353
-
5454
- bb3: {
5555
- _7 = discriminant((_3.1: std::option::Option<u32>));
56-
- switchInt(move _7) -> [1: bb4, otherwise: bb1];
56+
- switchInt(move _7) -> [0: bb5, otherwise: bb1];
5757
- }
5858
-
5959
- bb4: {

tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
StorageDead(_5);
3737
StorageDead(_4);
3838
_8 = discriminant((_3.0: std::option::Option<u32>));
39-
switchInt(move _8) -> [0: bb2, 1: bb4, otherwise: bb1];
39+
switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1];
4040
}
4141

4242
bb1: {
@@ -45,17 +45,17 @@
4545

4646
bb2: {
4747
_6 = discriminant((_3.1: std::option::Option<u32>));
48-
switchInt(move _6) -> [0: bb3, 1: bb7, otherwise: bb1];
48+
switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
4949
}
5050

5151
bb3: {
52-
_0 = const 3_u32;
53-
goto -> bb8;
52+
_7 = discriminant((_3.1: std::option::Option<u32>));
53+
switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1];
5454
}
5555

5656
bb4: {
57-
_7 = discriminant((_3.1: std::option::Option<u32>));
58-
switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb1];
57+
_0 = const 3_u32;
58+
goto -> bb8;
5959
}
6060

6161
bb5: {

0 commit comments

Comments
 (0)