Rollup merge of #97079 - SparrowLii:successors, r=lcnr

Change `Successors` to `impl Iterator<Item = BasicBlock>`

This PR fixes the FIXME in `compiler\rustc_middle\src\mir\mod.rs`.
This can omit several `&`, `*` or `cloned` operations on Successros' generated elements
This commit is contained in:
Yuki Okushi 2022-05-17 19:01:32 +09:00 committed by GitHub
commit 70cd85f5e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 54 additions and 55 deletions

View file

@ -199,7 +199,7 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
// Add successor BBs to the work list, if necessary. // Add successor BBs to the work list, if necessary.
let bb_data = &self.body[bb]; let bb_data = &self.body[bb];
debug_assert!(hi == bb_data.statements.len()); debug_assert!(hi == bb_data.statements.len());
for &succ_bb in bb_data.terminator().successors() { for succ_bb in bb_data.terminator().successors() {
if !self.visited.insert(succ_bb) { if !self.visited.insert(succ_bb) {
if succ_bb == location.block && first_lo > 0 { if succ_bb == location.block && first_lo > 0 {
// `succ_bb` has been seen before. If it wasn't // `succ_bb` has been seen before. If it wasn't

View file

@ -467,7 +467,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
block block
.terminator() .terminator()
.successors() .successors()
.map(|bb| Location { statement_index: 0, block: *bb }) .map(|bb| Location { statement_index: 0, block: bb })
.filter(|s| visited_locations.insert(*s)) .filter(|s| visited_locations.insert(*s))
.map(|s| { .map(|s| {
if self.is_back_edge(location, s) { if self.is_back_edge(location, s) {
@ -526,7 +526,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} else { } else {
for bb in block.terminator().successors() { for bb in block.terminator().successors() {
let successor = Location { statement_index: 0, block: *bb }; let successor = Location { statement_index: 0, block: bb };
if !visited_locations.contains(&successor) if !visited_locations.contains(&successor)
&& self.find_loop_head_dfs(successor, loop_head, visited_locations) && self.find_loop_head_dfs(successor, loop_head, visited_locations)

View file

@ -67,8 +67,8 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
block_data block_data
.terminator() .terminator()
.successors() .successors()
.filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind()) .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind())
.map(|&bb| Location { statement_index: 0, block: bb }), .map(|bb| Location { statement_index: 0, block: bb }),
); );
} }
} }

View file

@ -108,7 +108,7 @@ fn populate_polonius_move_facts(
// We are at the terminator of an init that has a panic path, // We are at the terminator of an init that has a panic path,
// and where the init should not happen on panic // and where the init should not happen on panic
for &successor in block_data.terminator().successors() { for successor in block_data.terminator().successors() {
if body[successor].is_cleanup { if body[successor].is_cleanup {
continue; continue;
} }

View file

@ -328,7 +328,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
bb, data, result[bb], funclet bb, data, result[bb], funclet
); );
for &succ in data.terminator().successors() { for succ in data.terminator().successors() {
let kind = result[succ]; let kind = result[succ];
debug!("cleanup_kinds: propagating {:?} to {:?}/{:?}", funclet, succ, kind); debug!("cleanup_kinds: propagating {:?} to {:?}/{:?}", funclet, succ, kind);
match kind { match kind {

View file

@ -24,7 +24,7 @@ pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Grap
let terminator = body[source].terminator(); let terminator = body[source].terminator();
let labels = terminator.kind.fmt_successor_labels(); let labels = terminator.kind.fmt_successor_labels();
for (&target, label) in terminator.successors().zip(labels) { for (target, label) in terminator.successors().zip(labels) {
let src = node(def_id, source); let src = node(def_id, source);
let trg = node(def_id, target); let trg = node(def_id, target);
edges.push(Edge::new(src, trg, label.to_string())); edges.push(Edge::new(src, trg, label.to_string()));

View file

@ -1355,10 +1355,7 @@ pub enum InlineAsmOperand<'tcx> {
/// Type for MIR `Assert` terminator error messages. /// Type for MIR `Assert` terminator error messages.
pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>; pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
// FIXME: Change `Successors` to `impl Iterator<Item = BasicBlock>`. pub type Successors<'a> = impl Iterator<Item = BasicBlock> + 'a;
#[allow(rustc::pass_by_value)]
pub type Successors<'a> =
iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
pub type SuccessorsMut<'a> = pub type SuccessorsMut<'a> =
iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>; iter::Chain<option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
@ -3434,13 +3431,13 @@ impl<'tcx> graph::WithStartNode for Body<'tcx> {
impl<'tcx> graph::WithSuccessors for Body<'tcx> { impl<'tcx> graph::WithSuccessors for Body<'tcx> {
#[inline] #[inline]
fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter { fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
self.basic_blocks[node].terminator().successors().cloned() self.basic_blocks[node].terminator().successors()
} }
} }
impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
type Item = BasicBlock; type Item = BasicBlock;
type Iter = iter::Cloned<Successors<'b>>; type Iter = Successors<'b>;
} }
impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> { impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> {

View file

@ -166,9 +166,7 @@ impl<'tcx> MirPatch<'tcx> {
// get terminator's targets and apply the statement to all of them. // get terminator's targets and apply the statement to all of them.
if loc.statement_index > body[loc.block].statements.len() { if loc.statement_index > body[loc.block].statements.len() {
let term = body[loc.block].terminator(); let term = body[loc.block].terminator();
let successors = term.successors().clone(); for i in term.successors() {
for i in successors {
stmts_and_targets stmts_and_targets
.push((Statement { source_info, kind: stmt.clone() }, i.clone())); .push((Statement { source_info, kind: stmt.clone() }, i.clone()));
} }

View file

@ -43,7 +43,7 @@ impl PredecessorCache {
let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks); let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
for (bb, data) in basic_blocks.iter_enumerated() { for (bb, data) in basic_blocks.iter_enumerated() {
if let Some(term) = &data.terminator { if let Some(term) = &data.terminator {
for &succ in term.successors() { for succ in term.successors() {
preds[succ].push(bb); preds[succ].push(bb);
} }
} }

View file

@ -416,32 +416,36 @@ impl<'tcx> TerminatorKind<'tcx> {
| Return | Return
| Unreachable | Unreachable
| Call { destination: None, cleanup: None, .. } | Call { destination: None, cleanup: None, .. }
| InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]), | InlineAsm { destination: None, cleanup: None, .. } => {
Goto { target: ref t } None.into_iter().chain((&[]).into_iter().copied())
| Call { destination: None, cleanup: Some(ref t), .. }
| Call { destination: Some((_, ref t)), cleanup: None, .. }
| Yield { resume: ref t, drop: None, .. }
| DropAndReplace { target: ref t, unwind: None, .. }
| Drop { target: ref t, unwind: None, .. }
| Assert { target: ref t, cleanup: None, .. }
| FalseUnwind { real_target: ref t, unwind: None }
| InlineAsm { destination: Some(ref t), cleanup: None, .. }
| InlineAsm { destination: None, cleanup: Some(ref t), .. } => {
Some(t).into_iter().chain(&[])
} }
Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } Goto { target: t }
| Yield { resume: ref t, drop: Some(ref u), .. } | Call { destination: None, cleanup: Some(t), .. }
| DropAndReplace { target: ref t, unwind: Some(ref u), .. } | Call { destination: Some((_, t)), cleanup: None, .. }
| Drop { target: ref t, unwind: Some(ref u), .. } | Yield { resume: t, drop: None, .. }
| Assert { target: ref t, cleanup: Some(ref u), .. } | DropAndReplace { target: t, unwind: None, .. }
| FalseUnwind { real_target: ref t, unwind: Some(ref u) } | Drop { target: t, unwind: None, .. }
| InlineAsm { destination: Some(ref t), cleanup: Some(ref u), .. } => { | Assert { target: t, cleanup: None, .. }
Some(t).into_iter().chain(slice::from_ref(u)) | FalseUnwind { real_target: t, unwind: None }
| InlineAsm { destination: Some(t), cleanup: None, .. }
| InlineAsm { destination: None, cleanup: Some(t), .. } => {
Some(t).into_iter().chain((&[]).into_iter().copied())
} }
SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets), Call { destination: Some((_, t)), cleanup: Some(ref u), .. }
FalseEdge { ref real_target, ref imaginary_target } => { | Yield { resume: t, drop: Some(ref u), .. }
Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) | DropAndReplace { target: t, unwind: Some(ref u), .. }
| Drop { target: t, unwind: Some(ref u), .. }
| Assert { target: t, cleanup: Some(ref u), .. }
| FalseUnwind { real_target: t, unwind: Some(ref u) }
| InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => {
Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
} }
SwitchInt { ref targets, .. } => {
None.into_iter().chain(targets.targets.iter().copied())
}
FalseEdge { real_target, ref imaginary_target } => Some(real_target)
.into_iter()
.chain(slice::from_ref(imaginary_target).into_iter().copied()),
} }
} }

View file

@ -180,7 +180,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
// two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A] // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
loop { loop {
let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() { let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() {
if let Some(&bb) = iter.next() { if let Some(bb) = iter.next() {
bb bb
} else { } else {
break; break;

View file

@ -125,7 +125,7 @@ where
} }
fn target(&self, edge: &Self::Edge) -> Self::Node { fn target(&self, edge: &Self::Edge) -> Self::Node {
self.body[edge.source].terminator().successors().nth(edge.index).copied().unwrap() self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
} }
} }

View file

@ -701,7 +701,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>(
edge_labels.retain(|label| label != "unreachable"); edge_labels.retain(|label| label != "unreachable");
let edge_counters = from_terminator let edge_counters = from_terminator
.successors() .successors()
.map(|&successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb)); .map(|successor_bb| graphviz_data.get_edge_counter(from_bcb, successor_bb));
iter::zip(&edge_labels, edge_counters) iter::zip(&edge_labels, edge_counters)
.map(|(label, some_counter)| { .map(|(label, some_counter)| {
if let Some(counter) = some_counter { if let Some(counter) = some_counter {

View file

@ -484,17 +484,17 @@ fn bcb_filtered_successors<'a, 'tcx>(
body: &'tcx &'a mir::Body<'tcx>, body: &'tcx &'a mir::Body<'tcx>,
term_kind: &'tcx TerminatorKind<'tcx>, term_kind: &'tcx TerminatorKind<'tcx>,
) -> Box<dyn Iterator<Item = BasicBlock> + 'a> { ) -> Box<dyn Iterator<Item = BasicBlock> + 'a> {
let mut successors = term_kind.successors();
Box::new( Box::new(
match &term_kind { match &term_kind {
// SwitchInt successors are never unwind, and all of them should be traversed. // SwitchInt successors are never unwind, and all of them should be traversed.
TerminatorKind::SwitchInt { .. } => successors, TerminatorKind::SwitchInt { ref targets, .. } => {
None.into_iter().chain(targets.all_targets().into_iter().copied())
}
// For all other kinds, return only the first successor, if any, and ignore unwinds. // For all other kinds, return only the first successor, if any, and ignore unwinds.
// NOTE: `chain(&[])` is required to coerce the `option::iter` (from // NOTE: `chain(&[])` is required to coerce the `option::iter` (from
// `next().into_iter()`) into the `mir::Successors` aliased type. // `next().into_iter()`) into the `mir::Successors` aliased type.
_ => successors.next().into_iter().chain(&[]), _ => term_kind.successors().next().into_iter().chain((&[]).into_iter().copied()),
} }
.copied()
.filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable), .filter(move |&successor| body[successor].terminator().kind != TerminatorKind::Unreachable),
) )
} }

View file

@ -450,7 +450,7 @@ impl<'tcx> Inliner<'tcx> {
} }
if !is_drop { if !is_drop {
for &succ in term.successors() { for succ in term.successors() {
work_list.push(succ); work_list.push(succ);
} }
} }

View file

@ -65,7 +65,7 @@ impl RemoveNoopLandingPads {
| TerminatorKind::SwitchInt { .. } | TerminatorKind::SwitchInt { .. }
| TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => { | TerminatorKind::FalseUnwind { .. } => {
terminator.successors().all(|&succ| nop_landing_pads.contains(succ)) terminator.successors().all(|succ| nop_landing_pads.contains(succ))
} }
TerminatorKind::GeneratorDrop TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. } | TerminatorKind::Yield { .. }

View file

@ -81,7 +81,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
for (_, data) in traversal::preorder(body) { for (_, data) in traversal::preorder(body) {
if let Some(ref term) = data.terminator { if let Some(ref term) = data.terminator {
for &tgt in term.successors() { for tgt in term.successors() {
pred_count[tgt] += 1; pred_count[tgt] += 1;
} }
} }
@ -235,8 +235,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
}; };
let first_succ = { let first_succ = {
if let Some(&first_succ) = terminator.successors().next() { if let Some(first_succ) = terminator.successors().next() {
if terminator.successors().all(|s| *s == first_succ) { if terminator.successors().all(|s| s == first_succ) {
let count = terminator.successors().count(); let count = terminator.successors().count();
self.pred_count[first_succ] -= (count - 1) as u32; self.pred_count[first_succ] -= (count - 1) as u32;
first_succ first_succ

View file

@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
} }
// Give up on loops // Give up on loops
if terminator.successors().any(|s| *s == bb) { if terminator.successors().any(|s| s == bb) {
continue; continue;
} }
@ -440,7 +440,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
// Short-circuit // Short-circuit
if (usage.cloned_used && usage.clone_consumed_or_mutated) || if (usage.cloned_used && usage.clone_consumed_or_mutated) ||
// Give up on loops // Give up on loops
tdata.terminator().successors().any(|s| *s == bb) tdata.terminator().successors().any(|s| s == bb)
{ {
return CloneUsage { return CloneUsage {
cloned_used: true, cloned_used: true,