Optimize redundant_clone

by using a static data structure to track transitive relations.
This commit is contained in:
mi_sawa 2022-02-12 02:24:32 +09:00
parent 57b3c4b90f
commit 6daa6d5ffe

View file

@ -3,7 +3,7 @@ use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth};
use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
use if_chain::if_chain;
use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{def_id, Body, FnDecl, HirId};
@ -512,7 +512,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
/// possible borrowers of `a`.
struct PossibleBorrowerVisitor<'a, 'tcx> {
possible_borrower: TransitiveRelation<mir::Local>,
possible_borrower: TransitiveRelation,
body: &'a mir::Body<'tcx>,
cx: &'a LateContext<'tcx>,
possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
@ -543,18 +543,10 @@ impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
continue;
}
let borrowers = self.possible_borrower.reachable_from(&row);
let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
borrowers.remove(mir::Local::from_usize(0));
if !borrowers.is_empty() {
let mut bs = HybridBitSet::new_empty(self.body.local_decls.len());
for &c in borrowers {
if c != mir::Local::from_usize(0) {
bs.insert(c);
}
}
if !bs.is_empty() {
map.insert(row, bs);
}
map.insert(row, borrowers);
}
}
@ -644,7 +636,7 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
/// For exampel, `_1 = &mut _2` generate _1: {_2,...}
/// Known Problems: not sure all borrowed are tracked
struct PossibleOriginVisitor<'a, 'tcx> {
possible_origin: TransitiveRelation<mir::Local>,
possible_origin: TransitiveRelation,
body: &'a mir::Body<'tcx>,
}
@ -663,18 +655,10 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
continue;
}
let borrowers = self.possible_origin.reachable_from(&row);
let mut borrowers = self.possible_origin.reachable_from(row, self.body.local_decls.len());
borrowers.remove(mir::Local::from_usize(0));
if !borrowers.is_empty() {
let mut bs = HybridBitSet::new_empty(self.body.local_decls.len());
for &c in borrowers {
if c != mir::Local::from_usize(0) {
bs.insert(c);
}
}
if !bs.is_empty() {
map.insert(row, bs);
}
map.insert(row, borrowers);
}
}
map
@ -766,3 +750,30 @@ impl PossibleBorrowerMap<'_, '_> {
self.maybe_live.contains(local)
}
}
#[derive(Default)]
struct TransitiveRelation {
relations: FxHashMap<mir::Local, Vec<mir::Local>>,
}
impl TransitiveRelation {
fn add(&mut self, a: mir::Local, b: mir::Local) {
self.relations.entry(a).or_default().push(b);
}
fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> {
let mut seen = HybridBitSet::new_empty(domain_size);
seen.insert(a);
let mut stack = vec![a];
while let Some(u) = stack.pop() {
if let Some(edges) = self.relations.get(&u) {
for &v in edges {
if seen.insert(v) {
stack.push(v);
}
}
}
}
seen.remove(a);
seen
}
}