Simplify Candidate. · rust-lang/rust@1be2204 (original) (raw)

`@@ -164,8 +164,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {

`

164

164

``

165

165

`fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {

`

166

166

`let def_id = body.source.def_id();

`

167

``

`-

let mut candidates = FxIndexMap::default();

`

168

``

`-

let mut candidates_reverse = FxIndexMap::default();

`

``

167

`+

let mut candidates = Candidates::default();

`

169

168

`let mut write_info = WriteInfo::default();

`

170

169

`trace!(func = ?tcx.def_path_str(def_id));

`

171

170

``

`@@ -194,12 +193,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {

`

194

193

`loop {

`

195

194

`// PERF: Can we do something smarter than recalculating the candidates and liveness

`

196

195

`// results?

`

197

``

`-

let mut candidates = find_candidates(

`

198

``

`-

body,

`

199

``

`-

&borrowed,

`

200

``

`-

&mut candidates,

`

201

``

`-

&mut candidates_reverse,

`

202

``

`-

);

`

``

196

`+

candidates.reset_and_find(body, &borrowed);

`

203

197

`trace!(?candidates);

`

204

198

`dest_prop_mir_dump(tcx, body, &points, &live, round_count);

`

205

199

``

`@@ -256,8 +250,8 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {

`

256

250

`}

`

257

251

`}

`

258

252

``

259

``

`-

#[derive(Debug)]

`

260

``

`-

struct Candidates<'alloc> {

`

``

253

`+

#[derive(Debug, Default)]

`

``

254

`+

struct Candidates {

`

261

255

`/// The set of candidates we are considering in this optimization.

`

262

256

`///

`

263

257

`/// We will always merge the key into at most one of its values.

`

`@@ -272,11 +266,12 @@ struct Candidates<'alloc> {

`

272

266

`///

`

273

267

`` /// We will still report that we would like to merge _1 and _2 in an attempt to allow us to

``

274

268

`/// remove that assignment.

`

275

``

`-

c: &'alloc mut FxIndexMap<Local, Vec>,

`

``

269

`+

c: FxIndexMap<Local, Vec>,

`

``

270

+

276

271

`` /// A reverse index of the c set; if the c set contains a => Place { local: b, proj },

``

277

272

`` /// then this contains b => a.

``

278

273

`` // PERF: Possibly these should be SmallVecs?

``

279

``

`-

reverse: &'alloc mut FxIndexMap<Local, Vec>,

`

``

274

`+

reverse: FxIndexMap<Local, Vec>,

`

280

275

`}

`

281

276

``

282

277

`//////////////////////////////////////////////////////////

`

`@@ -349,19 +344,40 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {

`

349

344

`//

`

350

345

`// This section enforces bullet point 2

`

351

346

``

352

``

`-

struct FilterInformation<'a, 'alloc, 'tcx> {

`

``

347

`+

struct FilterInformation<'a, 'tcx> {

`

353

348

`body: &'a Body<'tcx>,

`

354

349

`points: &'a DenseLocationMap,

`

355

350

`live: &'a SparseIntervalMatrix<Local, PointIndex>,

`

356

``

`-

candidates: &'a mut Candidates<'alloc>,

`

``

351

`+

candidates: &'a mut Candidates,

`

357

352

`write_info: &'a mut WriteInfo,

`

358

353

`at: Location,

`

359

354

`}

`

360

355

``

361

356

`// We first implement some utility functions which we will expose removing candidates according to

`

362

357

`` // different needs. Throughout the liveness filtering, the candidates are only ever accessed

``

363

358

`// through these methods, and not directly.

`

364

``

`-

impl<'alloc> Candidates<'alloc> {

`

``

359

`+

impl Candidates {

`

``

360

`+

/// Collects the candidates for merging.

`

``

361

`+

///

`

``

362

`+

/// This is responsible for enforcing the first and third bullet point.

`

``

363

`+

fn reset_and_find<'tcx>(&mut self, body: &Body<'tcx>, borrowed: &BitSet) {

`

``

364

`+

self.c.clear();

`

``

365

`+

self.reverse.clear();

`

``

366

`+

let mut visitor = FindAssignments { body, candidates: &mut self.c, borrowed };

`

``

367

`+

visitor.visit_body(body);

`

``

368

`+

// Deduplicate candidates.

`

``

369

`+

for (_, cands) in self.c.iter_mut() {

`

``

370

`+

cands.sort();

`

``

371

`+

cands.dedup();

`

``

372

`+

}

`

``

373

`+

// Generate the reverse map.

`

``

374

`+

for (src, cands) in self.c.iter() {

`

``

375

`+

for dest in cands.iter().copied() {

`

``

376

`+

self.reverse.entry(dest).or_default().push(*src);

`

``

377

`+

}

`

``

378

`+

}

`

``

379

`+

}

`

``

380

+

365

381

`` /// Just Vec::retain, but the condition is inverted and we add debugging output

``

366

382

`fn vec_filter_candidates(

`

367

383

`src: Local,

`

`@@ -436,7 +452,7 @@ enum CandidateFilter {

`

436

452

`Remove,

`

437

453

`}

`

438

454

``

439

``

`-

impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> {

`

``

455

`+

impl<'a, 'tcx> FilterInformation<'a, 'tcx> {

`

440

456

`/// Filters the set of candidates to remove those that conflict.

`

441

457

`///

`

442

458

`/// The steps we take are exactly those that are outlined at the top of the file. For each

`

`@@ -455,7 +471,7 @@ impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> {

`

455

471

`/// statement/terminator to be live. We are additionally conservative by treating all written to

`

456

472

`/// locals as also being read from.

`

457

473

`fn filter_liveness(

`

458

``

`-

candidates: &mut Candidates<'alloc>,

`

``

474

`+

candidates: &mut Candidates,

`

459

475

`points: &DenseLocationMap,

`

460

476

`live: &SparseIntervalMatrix<Local, PointIndex>,

`

461

477

`write_info: &mut WriteInfo,

`

`@@ -725,40 +741,13 @@ fn places_to_candidate_pair<'tcx>(

`

725

741

`Some((a, b))

`

726

742

`}

`

727

743

``

728

``

`-

/// Collects the candidates for merging

`

729

``

`-

///

`

730

``

`-

/// This is responsible for enforcing the first and third bullet point.

`

731

``

`-

fn find_candidates<'alloc, 'tcx>(

`

732

``

`-

body: &Body<'tcx>,

`

733

``

`-

borrowed: &BitSet,

`

734

``

`-

candidates: &'alloc mut FxIndexMap<Local, Vec>,

`

735

``

`-

candidates_reverse: &'alloc mut FxIndexMap<Local, Vec>,

`

736

``

`-

) -> Candidates<'alloc> {

`

737

``

`-

candidates.clear();

`

738

``

`-

candidates_reverse.clear();

`

739

``

`-

let mut visitor = FindAssignments { body, candidates, borrowed };

`

740

``

`-

visitor.visit_body(body);

`

741

``

`-

// Deduplicate candidates

`

742

``

`-

for (_, cands) in candidates.iter_mut() {

`

743

``

`-

cands.sort();

`

744

``

`-

cands.dedup();

`

745

``

`-

}

`

746

``

`-

// Generate the reverse map

`

747

``

`-

for (src, cands) in candidates.iter() {

`

748

``

`-

for dest in cands.iter().copied() {

`

749

``

`-

candidates_reverse.entry(dest).or_default().push(*src);

`

750

``

`-

}

`

751

``

`-

}

`

752

``

`-

Candidates { c: candidates, reverse: candidates_reverse }

`

753

``

`-

}

`

754

``

-

755

``

`-

struct FindAssignments<'a, 'alloc, 'tcx> {

`

``

744

`+

struct FindAssignments<'a, 'tcx> {

`

756

745

`body: &'a Body<'tcx>,

`

757

``

`-

candidates: &'alloc mut FxIndexMap<Local, Vec>,

`

``

746

`+

candidates: &'a mut FxIndexMap<Local, Vec>,

`

758

747

`borrowed: &'a BitSet,

`

759

748

`}

`

760

749

``

761

``

`-

impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {

`

``

750

`+

impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {

`

762

751

`fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {

`

763

752

`if let StatementKind::Assign(box (

`

764

753

` lhs,

`