18
18
19
19
#include " mlir/IR/Operation.h"
20
20
#include " mlir/Support/StorageUniquer.h"
21
+ #include " llvm/ADT/EquivalenceClasses.h"
21
22
#include " llvm/ADT/Hashing.h"
22
23
#include " llvm/ADT/SetVector.h"
23
24
#include " llvm/Support/Compiler.h"
@@ -265,6 +266,14 @@ struct LatticeAnchor
265
266
// / Forward declaration of the data-flow analysis class.
266
267
class DataFlowAnalysis ;
267
268
269
+ } // namespace mlir
270
+
271
+ template <>
272
+ struct llvm ::DenseMapInfo<mlir::LatticeAnchor>
273
+ : public llvm::DenseMapInfo<mlir::LatticeAnchor::ParentTy> {};
274
+
275
+ namespace mlir {
276
+
268
277
// ===----------------------------------------------------------------------===//
269
278
// DataFlowConfig
270
279
// ===----------------------------------------------------------------------===//
@@ -332,7 +341,9 @@ class DataFlowSolver {
332
341
// / does not exist.
333
342
template <typename StateT, typename AnchorT>
334
343
const StateT *lookupState (AnchorT anchor) const {
335
- const auto &mapIt = analysisStates.find (LatticeAnchor (anchor));
344
+ LatticeAnchor latticeAnchor =
345
+ getLeaderAnchorOrSelf<StateT>(LatticeAnchor (anchor));
346
+ const auto &mapIt = analysisStates.find (latticeAnchor);
336
347
if (mapIt == analysisStates.end ())
337
348
return nullptr ;
338
349
auto it = mapIt->second .find (TypeID::get<StateT>());
@@ -344,12 +355,34 @@ class DataFlowSolver {
344
355
// / Erase any analysis state associated with the given lattice anchor.
345
356
template <typename AnchorT>
346
357
void eraseState (AnchorT anchor) {
347
- LatticeAnchor la (anchor);
348
- analysisStates.erase (LatticeAnchor (anchor));
358
+ LatticeAnchor latticeAnchor (anchor);
359
+
360
+ // Update equivalentAnchorMap.
361
+ for (auto &&[TypeId, eqClass] : equivalentAnchorMap) {
362
+ if (!eqClass.contains (latticeAnchor)) {
363
+ continue ;
364
+ }
365
+ llvm::EquivalenceClasses<LatticeAnchor>::member_iterator leaderIt =
366
+ eqClass.findLeader (latticeAnchor);
367
+
368
+ // Update analysis states with new leader if needed.
369
+ if (*leaderIt == latticeAnchor && ++leaderIt != eqClass.member_end ()) {
370
+ analysisStates[*leaderIt][TypeId] =
371
+ std::move (analysisStates[latticeAnchor][TypeId]);
372
+ }
373
+
374
+ eqClass.erase (latticeAnchor);
375
+ }
376
+
377
+ // Update analysis states.
378
+ analysisStates.erase (latticeAnchor);
349
379
}
350
380
351
- // Erase all analysis states
352
- void eraseAllStates () { analysisStates.clear (); }
381
+ // / Erase all analysis states.
382
+ void eraseAllStates () {
383
+ analysisStates.clear ();
384
+ equivalentAnchorMap.clear ();
385
+ }
353
386
354
387
// / Get a uniqued lattice anchor instance. If one is not present, it is
355
388
// / created with the provided arguments.
@@ -399,6 +432,20 @@ class DataFlowSolver {
399
432
template <typename StateT, typename AnchorT>
400
433
StateT *getOrCreateState (AnchorT anchor);
401
434
435
+ // / Get leader lattice anchor in equivalence lattice anchor group, return
436
+ // / input lattice anchor if input not found in equivalece lattice anchor
437
+ // / group.
438
+ template <typename StateT>
439
+ LatticeAnchor getLeaderAnchorOrSelf (LatticeAnchor latticeAnchor) const ;
440
+
441
+ // / Union input anchors under the given state.
442
+ template <typename StateT, typename AnchorT>
443
+ void unionLatticeAnchors (AnchorT anchor, AnchorT other);
444
+
445
+ // / Return given lattice is equivalent on given state.
446
+ template <typename StateT>
447
+ bool isEquivalent (LatticeAnchor lhs, LatticeAnchor rhs) const ;
448
+
402
449
// / Propagate an update to an analysis state if it changed by pushing
403
450
// / dependent work items to the back of the queue.
404
451
// / This should only be used when DataFlowSolver is running.
@@ -429,10 +476,15 @@ class DataFlowSolver {
429
476
430
477
// / A type-erased map of lattice anchors to associated analysis states for
431
478
// / first-class lattice anchors.
432
- DenseMap<LatticeAnchor, DenseMap<TypeID, std::unique_ptr<AnalysisState>>,
433
- DenseMapInfo<LatticeAnchor::ParentTy>>
479
+ DenseMap<LatticeAnchor, DenseMap<TypeID, std::unique_ptr<AnalysisState>>>
434
480
analysisStates;
435
481
482
+ // / A map of Ananlysis state type to the equivalent lattice anchors.
483
+ // / Lattice anchors are considered equivalent under a certain analysis state
484
+ // / type if and only if, the analysis states pointed to by these lattice
485
+ // / anchors necessarily contain identical value.
486
+ DenseMap<TypeID, llvm::EquivalenceClasses<LatticeAnchor>> equivalentAnchorMap;
487
+
436
488
// / Allow the base child analysis class to access the internals of the solver.
437
489
friend class DataFlowAnalysis ;
438
490
};
@@ -564,6 +616,14 @@ class DataFlowAnalysis {
564
616
// / will provide a value for then.
565
617
virtual LogicalResult visit (ProgramPoint *point) = 0;
566
618
619
+ // / Initialize lattice anchor equivalence class from the provided top-level
620
+ // / operation.
621
+ // /
622
+ // / This function will union lattice anchor to same equivalent class if the
623
+ // / analysis can determine the lattice content of lattice anchor is
624
+ // / necessarily identical under the corrensponding lattice type.
625
+ virtual void initializeEquivalentLatticeAnchor (Operation *top) { return ; }
626
+
567
627
protected:
568
628
// / Create a dependency between the given analysis state and lattice anchor
569
629
// / on this analysis.
@@ -584,6 +644,12 @@ class DataFlowAnalysis {
584
644
return solver.getLatticeAnchor <AnchorT>(std::forward<Args>(args)...);
585
645
}
586
646
647
+ // / Union input anchors under the given state.
648
+ template <typename StateT, typename AnchorT>
649
+ void unionLatticeAnchors (AnchorT anchor, AnchorT other) {
650
+ return solver.unionLatticeAnchors <StateT>(anchor, other);
651
+ }
652
+
587
653
// / Get the analysis state associated with the lattice anchor. The returned
588
654
// / state is expected to be "write-only", and any updates need to be
589
655
// / propagated by `propagateIfChanged`.
@@ -598,7 +664,9 @@ class DataFlowAnalysis {
598
664
template <typename StateT, typename AnchorT>
599
665
const StateT *getOrCreateFor (ProgramPoint *dependent, AnchorT anchor) {
600
666
StateT *state = getOrCreate<StateT>(anchor);
601
- addDependency (state, dependent);
667
+ if (!solver.isEquivalent <StateT>(LatticeAnchor (anchor),
668
+ LatticeAnchor (dependent)))
669
+ addDependency (state, dependent);
602
670
return state;
603
671
}
604
672
@@ -644,10 +712,29 @@ AnalysisT *DataFlowSolver::load(Args &&...args) {
644
712
return static_cast <AnalysisT *>(childAnalyses.back ().get ());
645
713
}
646
714
715
+ template <typename StateT>
716
+ LatticeAnchor
717
+ DataFlowSolver::getLeaderAnchorOrSelf (LatticeAnchor latticeAnchor) const {
718
+ if (!equivalentAnchorMap.contains (TypeID::get<StateT>())) {
719
+ return latticeAnchor;
720
+ }
721
+ const llvm::EquivalenceClasses<LatticeAnchor> &eqClass =
722
+ equivalentAnchorMap.at (TypeID::get<StateT>());
723
+ llvm::EquivalenceClasses<LatticeAnchor>::member_iterator leaderIt =
724
+ eqClass.findLeader (latticeAnchor);
725
+ if (leaderIt != eqClass.member_end ()) {
726
+ return *leaderIt;
727
+ }
728
+ return latticeAnchor;
729
+ }
730
+
647
731
template <typename StateT, typename AnchorT>
648
732
StateT *DataFlowSolver::getOrCreateState (AnchorT anchor) {
733
+ // Replace to leader anchor if found.
734
+ LatticeAnchor latticeAnchor (anchor);
735
+ latticeAnchor = getLeaderAnchorOrSelf<StateT>(latticeAnchor);
649
736
std::unique_ptr<AnalysisState> &state =
650
- analysisStates[LatticeAnchor (anchor) ][TypeID::get<StateT>()];
737
+ analysisStates[latticeAnchor ][TypeID::get<StateT>()];
651
738
if (!state) {
652
739
state = std::unique_ptr<StateT>(new StateT (anchor));
653
740
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
@@ -657,6 +744,25 @@ StateT *DataFlowSolver::getOrCreateState(AnchorT anchor) {
657
744
return static_cast <StateT *>(state.get ());
658
745
}
659
746
747
+ template <typename StateT>
748
+ bool DataFlowSolver::isEquivalent (LatticeAnchor lhs, LatticeAnchor rhs) const {
749
+ if (!equivalentAnchorMap.contains (TypeID::get<StateT>())) {
750
+ return false ;
751
+ }
752
+ const llvm::EquivalenceClasses<LatticeAnchor> &eqClass =
753
+ equivalentAnchorMap.at (TypeID::get<StateT>());
754
+ if (!eqClass.contains (lhs) || !eqClass.contains (rhs))
755
+ return false ;
756
+ return eqClass.isEquivalent (lhs, rhs);
757
+ }
758
+
759
+ template <typename StateT, typename AnchorT>
760
+ void DataFlowSolver::unionLatticeAnchors (AnchorT anchor, AnchorT other) {
761
+ llvm::EquivalenceClasses<LatticeAnchor> &eqClass =
762
+ equivalentAnchorMap[TypeID::get<StateT>()];
763
+ eqClass.unionSets (LatticeAnchor (anchor), LatticeAnchor (other));
764
+ }
765
+
660
766
inline raw_ostream &operator <<(raw_ostream &os, const AnalysisState &state) {
661
767
state.print (os);
662
768
return os;
0 commit comments