Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[LifetimeSafety] Support bidirectional dataflow analysis#148967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

usx95
Copy link
Contributor

@usx95usx95 commentedJul 15, 2025
edited
Loading

Generalize the dataflow analysis to support both forward and backward analyses.

Some program analyses would be expressed as backward dataflow problems (like liveness analysis). This change enables the framework to support both forward analyses (like the loan propagation analysis) and backward analyses with the same infrastructure.

@usx95usx95 changed the titleadd-backward-analysis-capability[LifetimeSafety] Support bidirectional dataflow analysisJul 15, 2025
@usx95usx95force-pushed theusers/usx95/07-15-add-backward-analysis-capability branch from601cd16 tob109b6aCompareJuly 15, 2025 21:32
@usx95usx95 marked this pull request as ready for reviewJuly 15, 2025 21:48
@usx95usx95 requested review fromymand,Xazax-hun andjvoung and removed request forymand andXazax-hunJuly 15, 2025 21:48
@llvmbotllvmbot added clangClang issues not falling into any other category clang:analysis labelsJul 15, 2025
@usx95usx95 requested a review fromXazax-hunJuly 15, 2025 21:48
@llvmbot
Copy link
Member

llvmbot commentedJul 15, 2025
edited
Loading

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Utkarsh Saxena (usx95)

Changes

Generalize the dataflow analysis to support both forward and backward analyses.

Some program analyses would be expressed as backward dataflow problems (like liveness analysis). This change enables the framework to support both forward analyses (like the loan propagation analysis) and backward analyses with the same infrastructure.


Full diff:https://github.com/llvm/llvm-project/pull/148967.diff

1 Files Affected:

  • (modified) clang/lib/Analysis/LifetimeSafety.cpp (+59-51)
diff --git a/clang/lib/Analysis/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety.cppindex 0e013ec23e776..f9a7093987896 100644--- a/clang/lib/Analysis/LifetimeSafety.cpp+++ b/clang/lib/Analysis/LifetimeSafety.cpp@@ -499,13 +499,16 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> { // ========================================================================= // //                         Generic Dataflow Analysis // ========================================================================= //-/// A generic, policy-based driver for forward dataflow analyses. It combines++enum class Direction { Forward, Backward };++/// A generic, policy-based driver for dataflow analyses. It combines /// the dataflow runner and the transferer logic into a single class hierarchy. /// /// The derived class is expected to provide: /// - A `Lattice` type. /// - `StringRef getAnalysisName() const`-/// - `Lattice getInitialState();` The initial state at the function entry.+/// - `Lattice getInitialState();` The initial state of the analysis. /// - `Lattice join(Lattice, Lattice);` Merges states from multiple CFG paths. /// - `Lattice transfer(Lattice, const FactType&);` Defines how a single ///   lifetime-relevant `Fact` transforms the lattice state. Only overloads@@ -514,18 +517,21 @@ class FactGenerator : public ConstStmtVisitor<FactGenerator> { /// \tparam Derived The CRTP derived class that implements the specific /// analysis. /// \tparam LatticeType The dataflow lattice used by the analysis.-/// TODO: Maybe use the dataflow framework! The framework might need changes-/// to support the current comparison done at block-entry.-template <typename Derived, typename LatticeType> class DataflowAnalysis {+/// \tparam Dir The direction of the analysis (Forward or Backward).+template <typename Derived, typename LatticeType, Direction Dir>+class DataflowAnalysis { public:   using Lattice = LatticeType;+  using Base = DataflowAnalysis<Derived, LatticeType, Dir>;  private:   const CFG &Cfg;   AnalysisDeclContext &AC;-  llvm::DenseMap<const CFGBlock *, Lattice> BlockEntryStates;-  llvm::DenseMap<const CFGBlock *, Lattice> BlockExitStates;+  llvm::DenseMap<const CFGBlock *, Lattice> InStates;+  llvm::DenseMap<const CFGBlock *, Lattice> OutStates;++  static constexpr bool isForward() { return Dir == Direction::Forward; }  protected:   FactManager &AllFacts;@@ -539,75 +545,76 @@ template <typename Derived, typename LatticeType> class DataflowAnalysis {     Derived &D = static_cast<Derived &>(*this);     llvm::TimeTraceScope Time(D.getAnalysisName());-    ForwardDataflowWorklist Worklist(Cfg, AC);-    const CFGBlock *Entry = &Cfg.getEntry();-    BlockEntryStates[Entry] = D.getInitialState();-    Worklist.enqueueBlock(Entry);-    llvm::SmallBitVector Visited;-    Visited.resize(Cfg.getNumBlockIDs() + 1);--    while (const CFGBlock *B = Worklist.dequeue()) {-      Lattice EntryState = getEntryState(B);-      Lattice ExitState = transferBlock(B, EntryState);-      BlockExitStates[B] = ExitState;-      Visited.set(B->getBlockID());+    using Worklist =+        std::conditional_t<Dir == Direction::Forward, ForwardDataflowWorklist,+                           BackwardDataflowWorklist>;+    Worklist W(Cfg, AC);++    const CFGBlock *Start = isForward() ? &Cfg.getEntry() : &Cfg.getExit();+    InStates[Start] = D.getInitialState();+    W.enqueueBlock(Start);-      for (const CFGBlock *Successor : B->succs()) {-        Lattice OldSuccEntryState = getEntryState(Successor);-        Lattice NewSuccEntryState = D.join(OldSuccEntryState, ExitState);+    llvm::SmallBitVector Visited(Cfg.getNumBlockIDs() + 1);-        // Enqueue the successor if its entry state has changed or if we have+    while (const CFGBlock *B = W.dequeue()) {+      Lattice StateIn = getInState(B);+      Lattice StateOut = transferBlock(B, StateIn);+      OutStates[B] = StateOut;+      Visited.set(B->getBlockID());+      for (const CFGBlock *AdjacentB : isForward() ? B->succs() : B->preds()) {+        Lattice OldInState = getInState(AdjacentB);+        Lattice NewInState = D.join(OldInState, StateOut);+        // Enqueue the adjacent block if its in-state has changed or if we have         // never visited it.-        if (!Visited.test(Successor->getBlockID()) ||-            NewSuccEntryState != OldSuccEntryState) {-          BlockEntryStates[Successor] = NewSuccEntryState;-          Worklist.enqueueBlock(Successor);+        if (!Visited.test(AdjacentB->getBlockID()) ||+            NewInState != OldInState) {+          InStates[AdjacentB] = NewInState;+          W.enqueueBlock(AdjacentB);         }       }     }   }-  Lattice getEntryState(const CFGBlock *B) const {-    return BlockEntryStates.lookup(B);-  }+  Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); }-  Lattice getExitState(const CFGBlock *B) const {-    return BlockExitStates.lookup(B);-  }+  Lattice getOutStates(const CFGBlock *B) const { return OutStates.lookup(B); }    void dump() const {     const Derived *D = static_cast<const Derived *>(this);     llvm::dbgs() << "==========================================\n";     llvm::dbgs() << D->getAnalysisName() << " results:\n";     llvm::dbgs() << "==========================================\n";-    const CFGBlock &B = Cfg.getExit();-    getExitState(&B).dump(llvm::dbgs());+    const CFGBlock &B = isForward() ? Cfg.getExit() : Cfg.getEntry();+    getOutStates(&B).dump(llvm::dbgs());   }-private:-  /// Computes the exit state of a block by applying all its facts sequentially-  /// to a given entry state.+  /// Computes the state at one end of a block by applying all its facts+  /// sequentially to a given state from the other end.   /// TODO: We might need to store intermediate states per-fact in the block for   /// later analysis.-  Lattice transferBlock(const CFGBlock *Block, Lattice EntryState) {-    Lattice BlockState = EntryState;-    for (const Fact *F : AllFacts.getFacts(Block)) {-      BlockState = transferFact(BlockState, F);-    }-    return BlockState;+  Lattice transferBlock(const CFGBlock *Block, Lattice State) {+    auto Facts = AllFacts.getFacts(Block);+    if constexpr (isForward())+      for (const Fact *F : Facts)+        State = transferFact(State, F);+    else+      for (const Fact *F : llvm::reverse(Facts))+        State = transferFact(State, F);+    return State;   }    Lattice transferFact(Lattice In, const Fact *F) {-    Derived *d = static_cast<Derived *>(this);+    assert(F);+    Derived *D = static_cast<Derived *>(this);     switch (F->getKind()) {     case Fact::Kind::Issue:-      return d->transfer(In, *F->getAs<IssueFact>());+      return D->transfer(In, *F->getAs<IssueFact>());     case Fact::Kind::Expire:-      return d->transfer(In, *F->getAs<ExpireFact>());+      return D->transfer(In, *F->getAs<ExpireFact>());     case Fact::Kind::AssignOrigin:-      return d->transfer(In, *F->getAs<AssignOriginFact>());+      return D->transfer(In, *F->getAs<AssignOriginFact>());     case Fact::Kind::ReturnOfOrigin:-      return d->transfer(In, *F->getAs<ReturnOfOriginFact>());+      return D->transfer(In, *F->getAs<ReturnOfOriginFact>());     }     llvm_unreachable("Unknown fact kind");   }@@ -715,7 +722,8 @@ struct LoanPropagationLattice {  /// The analysis that tracks which loans belong to which origins. class LoanPropagationAnalysis-    : public DataflowAnalysis<LoanPropagationAnalysis, LoanPropagationLattice> {+    : public DataflowAnalysis<LoanPropagationAnalysis, LoanPropagationLattice,+                              Direction::Forward> {    LifetimeFactory &Factory;@@ -724,7 +732,7 @@ class LoanPropagationAnalysis                           LifetimeFactory &Factory)       : DataflowAnalysis(C, AC, F), Factory(Factory) {}-  using DataflowAnalysis<LoanPropagationAnalysis, Lattice>::transfer;+  using Base::transfer;    StringRef getAnalysisName() const { return "LoanPropagation"; }

@usx95usx95force-pushed theusers/usx95/07-15-add-backward-analysis-capability branch 2 times, most recently from7502ee5 to9475733CompareJuly 15, 2025 22:20
@usx95usx95force-pushed theusers/usx95/lifetime-safety-liveness branch from7b26a72 to839eb25CompareJuly 15, 2025 22:20
@usx95usx95 moved this toIn Progress inLifetime Safety in ClangJul 15, 2025
@usx95usx95force-pushed theusers/usx95/07-15-add-backward-analysis-capability branch from9475733 to7762a38CompareJuly 16, 2025 14:08
@usx95Graphite App
Copy link
ContributorAuthor

usx95 commentedJul 16, 2025
edited
Loading

Merge activity

  • Jul 16, 2:12 PM UTC: A user started a stack merge that includes this pull request viaGraphite.
  • Jul 16, 2:20 PM UTC:Graphite rebased this pull request as part of a merge.
  • Jul 16, 2:23 PM UTC:Graphite rebased this pull request as part of a merge.
  • Jul 16, 2:25 PM UTC:@usx95 merged this pull request withGraphite.

@usx95usx95force-pushed theusers/usx95/lifetime-safety-liveness branch 2 times, most recently from954ba85 toa8d93c9CompareJuly 16, 2025 14:17
Base automatically changed fromusers/usx95/lifetime-safety-liveness tomainJuly 16, 2025 14:19
@usx95usx95force-pushed theusers/usx95/07-15-add-backward-analysis-capability branch from7762a38 to4a23369CompareJuly 16, 2025 14:20
@usx95usx95force-pushed theusers/usx95/07-15-add-backward-analysis-capability branch from4a23369 tob76c916CompareJuly 16, 2025 14:22
@usx95usx95 merged commitf7fc36d intomainJul 16, 2025
7 of 9 checks passed
@usx95usx95 deleted the users/usx95/07-15-add-backward-analysis-capability branchJuly 16, 2025 14:25
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@Xazax-hunXazax-hunXazax-hun approved these changes

@ymandymandymand approved these changes

@jvoungjvoungAwaiting requested review from jvoung

Assignees
No one assigned
Labels
clang:analysisclangClang issues not falling into any other category
Projects
Status: Done
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@usx95@llvmbot@Xazax-hun@ymand

[8]ページ先頭

©2009-2025 Movatter.jp