Allocate candidate vectors as we sort them
This commit is contained in:
parent
3d3b321c60
commit
8c3688cbb5
@ -1653,10 +1653,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
&'b mut [&'c mut Candidate<'pat, 'tcx>],
|
&'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||||
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
|
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
|
||||||
) {
|
) {
|
||||||
// For each of the N possible outcomes, create a (initially empty) vector of candidates.
|
// For each of the possible outcomes, collect vector of candidates that apply if the test
|
||||||
// Those are the candidates that apply if the test has that particular outcome.
|
// has that particular outcome.
|
||||||
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'pat, 'tcx>>> =
|
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default();
|
||||||
test.targets().into_iter().map(|branch| (branch, Vec::new())).collect();
|
|
||||||
|
|
||||||
let total_candidate_count = candidates.len();
|
let total_candidate_count = candidates.len();
|
||||||
|
|
||||||
@ -1668,7 +1667,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
let (candidate, rest) = candidates.split_first_mut().unwrap();
|
let (candidate, rest) = candidates.split_first_mut().unwrap();
|
||||||
target_candidates[&branch].push(candidate);
|
target_candidates.entry(branch).or_insert_with(Vec::new).push(candidate);
|
||||||
candidates = rest;
|
candidates = rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1809,31 +1808,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
otherwise_block
|
otherwise_block
|
||||||
};
|
};
|
||||||
|
|
||||||
// For each outcome of test, process the candidates that still
|
// For each outcome of test, process the candidates that still apply.
|
||||||
// apply. Collect a list of blocks where control flow will
|
|
||||||
// branch if one of the `target_candidate` sets is not
|
|
||||||
// exhaustive.
|
|
||||||
let target_blocks: FxIndexMap<_, _> = target_candidates
|
let target_blocks: FxIndexMap<_, _> = target_candidates
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(branch, mut candidates)| {
|
.map(|(branch, mut candidates)| {
|
||||||
if !candidates.is_empty() {
|
let candidate_start = self.cfg.start_new_block();
|
||||||
let candidate_start = self.cfg.start_new_block();
|
self.match_candidates(
|
||||||
self.match_candidates(
|
span,
|
||||||
span,
|
scrutinee_span,
|
||||||
scrutinee_span,
|
candidate_start,
|
||||||
candidate_start,
|
remainder_start,
|
||||||
remainder_start,
|
&mut *candidates,
|
||||||
&mut *candidates,
|
);
|
||||||
);
|
(branch, candidate_start)
|
||||||
(branch, candidate_start)
|
|
||||||
} else {
|
|
||||||
(branch, remainder_start)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Perform the test, branching to one of N blocks.
|
// Perform the test, branching to one of N blocks.
|
||||||
self.perform_test(span, scrutinee_span, start_block, &match_place, &test, target_blocks);
|
self.perform_test(
|
||||||
|
span,
|
||||||
|
scrutinee_span,
|
||||||
|
start_block,
|
||||||
|
remainder_start,
|
||||||
|
&match_place,
|
||||||
|
&test,
|
||||||
|
target_blocks,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine the fake borrows that are needed from a set of places that
|
/// Determine the fake borrows that are needed from a set of places that
|
||||||
|
@ -127,6 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
match_start_span: Span,
|
match_start_span: Span,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
|
otherwise_block: BasicBlock,
|
||||||
place_builder: &PlaceBuilder<'tcx>,
|
place_builder: &PlaceBuilder<'tcx>,
|
||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
|
target_blocks: FxIndexMap<TestBranch<'tcx>, BasicBlock>,
|
||||||
@ -134,14 +135,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let place = place_builder.to_place(self);
|
let place = place_builder.to_place(self);
|
||||||
let place_ty = place.ty(&self.local_decls, self.tcx);
|
let place_ty = place.ty(&self.local_decls, self.tcx);
|
||||||
debug!(?place, ?place_ty);
|
debug!(?place, ?place_ty);
|
||||||
let target_block = |branch| target_blocks[&branch];
|
let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block);
|
||||||
|
|
||||||
let source_info = self.source_info(test.span);
|
let source_info = self.source_info(test.span);
|
||||||
match test.kind {
|
match test.kind {
|
||||||
TestKind::Switch { adt_def, ref variants } => {
|
TestKind::Switch { adt_def, ref variants } => {
|
||||||
// Variants is a BitVec of indexes into adt_def.variants.
|
// Variants is a BitVec of indexes into adt_def.variants.
|
||||||
let num_enum_variants = adt_def.variants().len();
|
let num_enum_variants = adt_def.variants().len();
|
||||||
debug_assert_eq!(target_blocks.len(), num_enum_variants + 1);
|
|
||||||
let otherwise_block = target_block(TestBranch::Failure);
|
let otherwise_block = target_block(TestBranch::Failure);
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let switch_targets = SwitchTargets::new(
|
let switch_targets = SwitchTargets::new(
|
||||||
@ -185,7 +185,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
TestKind::SwitchInt { ref options } => {
|
TestKind::SwitchInt { ref options } => {
|
||||||
// The switch may be inexhaustive so we have a catch-all block
|
// The switch may be inexhaustive so we have a catch-all block
|
||||||
debug_assert_eq!(options.len() + 1, target_blocks.len());
|
|
||||||
let otherwise_block = target_block(TestBranch::Failure);
|
let otherwise_block = target_block(TestBranch::Failure);
|
||||||
let switch_targets = SwitchTargets::new(
|
let switch_targets = SwitchTargets::new(
|
||||||
options
|
options
|
||||||
@ -201,7 +200,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestKind::If => {
|
TestKind::If => {
|
||||||
debug_assert_eq!(target_blocks.len(), 2);
|
|
||||||
let success_block = target_block(TestBranch::Success);
|
let success_block = target_block(TestBranch::Success);
|
||||||
let fail_block = target_block(TestBranch::Failure);
|
let fail_block = target_block(TestBranch::Failure);
|
||||||
let terminator =
|
let terminator =
|
||||||
@ -211,7 +209,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
TestKind::Eq { value, ty } => {
|
TestKind::Eq { value, ty } => {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
debug_assert_eq!(target_blocks.len(), 2);
|
|
||||||
let success_block = target_block(TestBranch::Success);
|
let success_block = target_block(TestBranch::Success);
|
||||||
let fail_block = target_block(TestBranch::Failure);
|
let fail_block = target_block(TestBranch::Failure);
|
||||||
if let ty::Adt(def, _) = ty.kind()
|
if let ty::Adt(def, _) = ty.kind()
|
||||||
@ -290,7 +287,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestKind::Range(ref range) => {
|
TestKind::Range(ref range) => {
|
||||||
debug_assert_eq!(target_blocks.len(), 2);
|
|
||||||
let success = target_block(TestBranch::Success);
|
let success = target_block(TestBranch::Success);
|
||||||
let fail = target_block(TestBranch::Failure);
|
let fail = target_block(TestBranch::Failure);
|
||||||
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
||||||
@ -337,7 +333,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// expected = <N>
|
// expected = <N>
|
||||||
let expected = self.push_usize(block, source_info, len);
|
let expected = self.push_usize(block, source_info, len);
|
||||||
|
|
||||||
debug_assert_eq!(target_blocks.len(), 2);
|
|
||||||
let success_block = target_block(TestBranch::Success);
|
let success_block = target_block(TestBranch::Success);
|
||||||
let fail_block = target_block(TestBranch::Failure);
|
let fail_block = target_block(TestBranch::Failure);
|
||||||
// result = actual == expected OR result = actual < expected
|
// result = actual == expected OR result = actual < expected
|
||||||
@ -753,33 +748,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Test<'tcx> {
|
|
||||||
pub(super) fn targets(&self) -> Vec<TestBranch<'tcx>> {
|
|
||||||
match self.kind {
|
|
||||||
TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => {
|
|
||||||
vec![TestBranch::Success, TestBranch::Failure]
|
|
||||||
}
|
|
||||||
TestKind::Switch { adt_def, .. } => {
|
|
||||||
// While the switch that we generate doesn't test for all
|
|
||||||
// variants, we have a target for each variant and the
|
|
||||||
// otherwise case, and we make sure that all of the cases not
|
|
||||||
// specified have the same block.
|
|
||||||
adt_def
|
|
||||||
.variants()
|
|
||||||
.indices()
|
|
||||||
.map(|idx| TestBranch::Variant(idx))
|
|
||||||
.chain([TestBranch::Failure])
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
TestKind::SwitchInt { ref options } => options
|
|
||||||
.iter()
|
|
||||||
.map(|(val, bits)| TestBranch::Constant(*val, *bits))
|
|
||||||
.chain([TestBranch::Failure])
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_switch_ty(ty: Ty<'_>) -> bool {
|
fn is_switch_ty(ty: Ty<'_>) -> bool {
|
||||||
ty.is_integral() || ty.is_char()
|
ty.is_integral() || ty.is_char()
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ fn main() -> () {
|
|||||||
StorageLive(_3);
|
StorageLive(_3);
|
||||||
_3 = const true;
|
_3 = const true;
|
||||||
PlaceMention(_3);
|
PlaceMention(_3);
|
||||||
switchInt(_3) -> [0: bb6, otherwise: bb4];
|
switchInt(_3) -> [0: bb4, otherwise: bb6];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
@ -34,8 +34,7 @@ fn main() -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
_0 = const ();
|
falseEdge -> [real: bb8, imaginary: bb6];
|
||||||
goto -> bb13;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
@ -43,7 +42,8 @@ fn main() -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
falseEdge -> [real: bb8, imaginary: bb4];
|
_0 = const ();
|
||||||
|
goto -> bb13;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb7: {
|
bb7: {
|
||||||
|
@ -28,7 +28,7 @@ fn full_tested_match() -> () {
|
|||||||
_2 = Option::<i32>::Some(const 42_i32);
|
_2 = Option::<i32>::Some(const 42_i32);
|
||||||
PlaceMention(_2);
|
PlaceMention(_2);
|
||||||
_3 = discriminant(_2);
|
_3 = discriminant(_2);
|
||||||
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
|
switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
@ -37,20 +37,20 @@ fn full_tested_match() -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
_1 = (const 3_i32, const 3_i32);
|
falseEdge -> [real: bb7, imaginary: bb3];
|
||||||
goto -> bb13;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
goto -> bb1;
|
falseEdge -> [real: bb12, imaginary: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
falseEdge -> [real: bb7, imaginary: bb5];
|
goto -> bb1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
falseEdge -> [real: bb12, imaginary: bb2];
|
_1 = (const 3_i32, const 3_i32);
|
||||||
|
goto -> bb13;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
@ -91,7 +91,7 @@ fn full_tested_match() -> () {
|
|||||||
bb11: {
|
bb11: {
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
goto -> bb5;
|
goto -> bb3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb12: {
|
bb12: {
|
||||||
|
@ -28,7 +28,7 @@ fn full_tested_match2() -> () {
|
|||||||
_2 = Option::<i32>::Some(const 42_i32);
|
_2 = Option::<i32>::Some(const 42_i32);
|
||||||
PlaceMention(_2);
|
PlaceMention(_2);
|
||||||
_3 = discriminant(_2);
|
_3 = discriminant(_2);
|
||||||
switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1];
|
switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
@ -37,18 +37,10 @@ fn full_tested_match2() -> () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
falseEdge -> [real: bb12, imaginary: bb5];
|
falseEdge -> [real: bb7, imaginary: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
goto -> bb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb4: {
|
|
||||||
falseEdge -> [real: bb7, imaginary: bb2];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb5: {
|
|
||||||
StorageLive(_9);
|
StorageLive(_9);
|
||||||
_9 = ((_2 as Some).0: i32);
|
_9 = ((_2 as Some).0: i32);
|
||||||
StorageLive(_10);
|
StorageLive(_10);
|
||||||
@ -59,6 +51,14 @@ fn full_tested_match2() -> () {
|
|||||||
goto -> bb13;
|
goto -> bb13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
goto -> bb1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
falseEdge -> [real: bb12, imaginary: bb3];
|
||||||
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
goto -> bb1;
|
goto -> bb1;
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ fn full_tested_match2() -> () {
|
|||||||
bb11: {
|
bb11: {
|
||||||
StorageDead(_7);
|
StorageDead(_7);
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
falseEdge -> [real: bb5, imaginary: bb2];
|
falseEdge -> [real: bb3, imaginary: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb12: {
|
bb12: {
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_8 = discriminant((_3.0: std::option::Option<u32>));
|
_8 = discriminant((_3.0: std::option::Option<u32>));
|
||||||
- switchInt(move _8) -> [0: bb2, 1: bb3, otherwise: bb1];
|
- switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1];
|
||||||
+ StorageLive(_11);
|
+ StorageLive(_11);
|
||||||
+ _11 = discriminant((_3.1: std::option::Option<u32>));
|
+ _11 = discriminant((_3.1: std::option::Option<u32>));
|
||||||
+ StorageLive(_12);
|
+ StorageLive(_12);
|
||||||
@ -48,12 +48,12 @@
|
|||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
- _6 = discriminant((_3.1: std::option::Option<u32>));
|
- _6 = discriminant((_3.1: std::option::Option<u32>));
|
||||||
- switchInt(move _6) -> [0: bb5, otherwise: bb1];
|
- switchInt(move _6) -> [1: bb4, otherwise: bb1];
|
||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb3: {
|
- bb3: {
|
||||||
- _7 = discriminant((_3.1: std::option::Option<u32>));
|
- _7 = discriminant((_3.1: std::option::Option<u32>));
|
||||||
- switchInt(move _7) -> [1: bb4, otherwise: bb1];
|
- switchInt(move _7) -> [0: bb5, otherwise: bb1];
|
||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb4: {
|
- bb4: {
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
StorageDead(_5);
|
StorageDead(_5);
|
||||||
StorageDead(_4);
|
StorageDead(_4);
|
||||||
_8 = discriminant((_3.0: std::option::Option<u32>));
|
_8 = discriminant((_3.0: std::option::Option<u32>));
|
||||||
switchInt(move _8) -> [0: bb2, 1: bb4, otherwise: bb1];
|
switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
@ -45,17 +45,17 @@
|
|||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
_6 = discriminant((_3.1: std::option::Option<u32>));
|
_6 = discriminant((_3.1: std::option::Option<u32>));
|
||||||
switchInt(move _6) -> [0: bb3, 1: bb7, otherwise: bb1];
|
switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
_0 = const 3_u32;
|
_7 = discriminant((_3.1: std::option::Option<u32>));
|
||||||
goto -> bb8;
|
switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
_7 = discriminant((_3.1: std::option::Option<u32>));
|
_0 = const 3_u32;
|
||||||
switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb1];
|
goto -> bb8;
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user