1
Fork 0

rustc_mir_build: use IndexMap in TestKind::SwitchInt

This commit is contained in:
Josh Stone 2020-08-07 20:49:51 -07:00
parent c61f1c8bfa
commit 4efc7e92fa
2 changed files with 17 additions and 23 deletions

View file

@ -11,7 +11,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
use crate::thir::{self, *}; use crate::thir::{self, *};
use rustc_data_structures::{ use rustc_data_structures::{
fx::{FxHashMap, FxHashSet}, fx::{FxHashSet, FxIndexMap},
stack::ensure_sufficient_stack, stack::ensure_sufficient_stack,
}; };
use rustc_hir::HirId; use rustc_hir::HirId;
@ -817,9 +817,7 @@ enum TestKind<'tcx> {
/// ///
/// For `bool` we always generate two edges, one for `true` and one for /// For `bool` we always generate two edges, one for `true` and one for
/// `false`. /// `false`.
options: Vec<u128>, options: FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
/// Reverse map used to ensure that the values in `options` are unique.
indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
}, },
/// Test for equality with value, possibly after an unsizing coercion to /// Test for equality with value, possibly after an unsizing coercion to
@ -1396,14 +1394,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// may want to add cases based on the candidates that are // may want to add cases based on the candidates that are
// available // available
match test.kind { match test.kind {
TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => { TestKind::SwitchInt { switch_ty, ref mut options } => {
for candidate in candidates.iter() { for candidate in candidates.iter() {
if !self.add_cases_to_switch( if !self.add_cases_to_switch(
&match_place, &match_place,
candidate, candidate,
switch_ty, switch_ty,
options, options,
indices,
) { ) {
break; break;
} }

View file

@ -9,7 +9,7 @@ use crate::build::matches::{Candidate, MatchPair, Test, TestKind};
use crate::build::Builder; use crate::build::Builder;
use crate::thir::pattern::compare_const_vals; use crate::thir::pattern::compare_const_vals;
use crate::thir::*; use crate::thir::*;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::RangeEnd; use rustc_hir::RangeEnd;
use rustc_index::bit_set::BitSet; use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -44,8 +44,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// these maps are empty to start; cases are // these maps are empty to start; cases are
// added below in add_cases_to_switch // added below in add_cases_to_switch
options: vec![], options: Default::default(),
indices: Default::default(),
}, },
} }
} }
@ -83,8 +82,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
test_place: &Place<'tcx>, test_place: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>, candidate: &Candidate<'pat, 'tcx>,
switch_ty: Ty<'tcx>, switch_ty: Ty<'tcx>,
options: &mut Vec<u128>, options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>,
) -> bool { ) -> bool {
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
Some(match_pair) => match_pair, Some(match_pair) => match_pair,
@ -95,9 +93,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
match *match_pair.pattern.kind { match *match_pair.pattern.kind {
PatKind::Constant { value } => { PatKind::Constant { value } => {
indices.entry(value).or_insert_with(|| { options.entry(value).or_insert_with(|| {
options.push(value.eval_bits(self.hir.tcx(), self.hir.param_env, switch_ty)); value.eval_bits(self.hir.tcx(), self.hir.param_env, switch_ty)
options.len() - 1
}); });
true true
} }
@ -106,7 +103,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
PatKind::Range(range) => { PatKind::Range(range) => {
// Check that none of the switch values are in the range. // Check that none of the switch values are in the range.
self.values_not_contained_in_range(range, indices).unwrap_or(false) self.values_not_contained_in_range(range, options).unwrap_or(false)
} }
PatKind::Slice { .. } PatKind::Slice { .. }
| PatKind::Array { .. } | PatKind::Array { .. }
@ -216,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
); );
} }
TestKind::SwitchInt { switch_ty, ref options, indices: _ } => { TestKind::SwitchInt { switch_ty, ref options } => {
let target_blocks = make_target_blocks(self); let target_blocks = make_target_blocks(self);
let terminator = if switch_ty.kind == ty::Bool { let terminator = if switch_ty.kind == ty::Bool {
assert!(!options.is_empty() && options.len() <= 2); assert!(!options.is_empty() && options.len() <= 2);
@ -236,7 +233,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::SwitchInt { TerminatorKind::SwitchInt {
discr: Operand::Copy(place), discr: Operand::Copy(place),
switch_ty, switch_ty,
values: options.clone().into(), values: options.values().copied().collect(),
targets: target_blocks, targets: target_blocks,
} }
}; };
@ -532,20 +529,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// FIXME(#29623) we could use PatKind::Range to rule // FIXME(#29623) we could use PatKind::Range to rule
// things out here, in some cases. // things out here, in some cases.
( (
&TestKind::SwitchInt { switch_ty: _, options: _, ref indices }, &TestKind::SwitchInt { switch_ty: _, ref options },
&PatKind::Constant { ref value }, &PatKind::Constant { ref value },
) if is_switch_ty(match_pair.pattern.ty) => { ) if is_switch_ty(match_pair.pattern.ty) => {
let index = indices[value]; let index = options.get_index_of(value).unwrap();
self.candidate_without_match_pair(match_pair_index, candidate); self.candidate_without_match_pair(match_pair_index, candidate);
Some(index) Some(index)
} }
( (
&TestKind::SwitchInt { switch_ty: _, ref options, ref indices }, &TestKind::SwitchInt { switch_ty: _, ref options },
&PatKind::Range(range), &PatKind::Range(range),
) => { ) => {
let not_contained = let not_contained =
self.values_not_contained_in_range(range, indices).unwrap_or(false); self.values_not_contained_in_range(range, options).unwrap_or(false);
if not_contained { if not_contained {
// No switch values are contained in the pattern range, // No switch values are contained in the pattern range,
@ -777,9 +774,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn values_not_contained_in_range( fn values_not_contained_in_range(
&self, &self,
range: PatRange<'tcx>, range: PatRange<'tcx>,
indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, options: &FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
) -> Option<bool> { ) -> Option<bool> {
for &val in indices.keys() { for &val in options.keys() {
if self.const_range_contains(range, val)? { if self.const_range_contains(range, val)? {
return Some(false); return Some(false);
} }