[clang] 64f7b2d - [clang][dataflow] Change `transfer` function to update lattice element in place.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 10 06:46:17 PST 2022


Author: Yitzhak Mandelbaum
Date: 2022-01-10T14:45:30Z
New Revision: 64f7b2d4bf92eeb8f753f46d2a9499688b07293a

URL: https://github.com/llvm/llvm-project/commit/64f7b2d4bf92eeb8f753f46d2a9499688b07293a
DIFF: https://github.com/llvm/llvm-project/commit/64f7b2d4bf92eeb8f753f46d2a9499688b07293a.diff

LOG: [clang][dataflow] Change `transfer` function to update lattice element in place.

Currently, the transfer function returns a new lattice element, which forces an
unnecessary copy on processing each CFG statement.

Differential Revision: https://reviews.llvm.org/D116834

Added: 
    

Modified: 
    clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
    clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
    clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
    clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
    clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
    clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
    clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
index a96ed0437a439..7402e42749ee2 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
@@ -39,9 +39,8 @@ namespace dataflow {
 ///  must provide the following public members:
 ///   * `LatticeT initialElement()` - returns a lattice element that models the
 ///     initial state of a basic block;
-///   * `LatticeT transfer(const Stmt *, const LatticeT &, Environment &)` -
-///     applies the analysis transfer function for a given statement and lattice
-///     element.
+///   * `void transfer(const Stmt *, LatticeT &, Environment &)` - applies the
+///     analysis transfer function for a given statement and lattice element.
 ///
 ///  `LatticeT` is a bounded join-semilattice that is used by `Derived` and must
 ///  provide the following public members:
@@ -79,11 +78,10 @@ class DataflowAnalysis : public TypeErasedDataflowAnalysis {
     return L1 == L2;
   }
 
-  TypeErasedLattice transferTypeErased(const Stmt *Stmt,
-                                       const TypeErasedLattice &E,
-                                       Environment &Env) final {
-    const Lattice &L = llvm::any_cast<const Lattice &>(E.Value);
-    return {static_cast<Derived *>(this)->transfer(Stmt, L, Env)};
+  void transferTypeErased(const Stmt *Stmt, TypeErasedLattice &E,
+                          Environment &Env) final {
+    Lattice &L = llvm::any_cast<Lattice &>(E.Value);
+    static_cast<Derived *>(this)->transfer(Stmt, L, Env);
   }
 
 private:

diff  --git a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
index 65875445a86b1..c0490140d0ce5 100644
--- a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
+++ b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h
@@ -64,9 +64,8 @@ class TypeErasedDataflowAnalysis {
 
   /// Applies the analysis transfer function for a given statement and
   /// type-erased lattice element.
-  virtual TypeErasedLattice transferTypeErased(const Stmt *,
-                                               const TypeErasedLattice &,
-                                               Environment &) = 0;
+  virtual void transferTypeErased(const Stmt *, TypeErasedLattice &,
+                                  Environment &) = 0;
 };
 
 /// Type-erased model of the program at a given program point.

diff  --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index deb73b5265ed7..0d7f3b31e6c48 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -123,7 +123,7 @@ TypeErasedDataflowAnalysisState transferBlock(
     assert(S != nullptr);
 
     transfer(*S, State.Env);
-    State.Lattice = Analysis.transferTypeErased(S, State.Lattice, State.Env);
+    Analysis.transferTypeErased(S, State.Lattice, State.Env);
 
     if (HandleTransferredStmt != nullptr)
       HandleTransferredStmt(CfgStmt.getValue(), State);

diff  --git a/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp b/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
index d5275b10e946e..972edcd22f009 100644
--- a/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/MultiVarConstantPropagationTest.cpp
@@ -132,8 +132,8 @@ class ConstantPropagationAnalysis
     return ConstantPropagationLattice::bottom();
   }
 
-  ConstantPropagationLattice
-  transfer(const Stmt *S, ConstantPropagationLattice Vars, Environment &Env) {
+  void transfer(const Stmt *S, ConstantPropagationLattice &Vars,
+                Environment &Env) {
     auto matcher =
         stmt(anyOf(declStmt(hasSingleDecl(
                        varDecl(decl().bind(kVar), hasType(isInteger()),
@@ -148,7 +148,7 @@ class ConstantPropagationAnalysis
     ASTContext &Context = getASTContext();
     auto Results = match(matcher, *S, Context);
     if (Results.empty())
-      return Vars;
+      return;
     const BoundNodes &Nodes = Results[0];
 
     const auto *Var = Nodes.getNodeAs<clang::VarDecl>(kVar);
@@ -165,10 +165,7 @@ class ConstantPropagationAnalysis
         // is (it is implementation defined), so we set it to top.
         Vars[Var] = ValueLattice::top();
       }
-      return Vars;
-    }
-
-    if (Nodes.getNodeAs<clang::Expr>(kJustAssignment)) {
+    } else if (Nodes.getNodeAs<clang::Expr>(kJustAssignment)) {
       const auto *E = Nodes.getNodeAs<clang::Expr>(kRHS);
       assert(E != nullptr);
 
@@ -176,18 +173,12 @@ class ConstantPropagationAnalysis
       Vars[Var] = (E->EvaluateAsInt(R, Context) && R.Val.isInt())
                       ? ValueLattice(R.Val.getInt().getExtValue())
                       : ValueLattice::top();
-      return Vars;
-    }
-
-    // Any assignment involving the expression itself resets the variable to
-    // "unknown". A more advanced analysis could try to evaluate the compound
-    // assignment. For example, `x += 0` need not invalidate `x`.
-    if (Nodes.getNodeAs<clang::Expr>(kAssignment)) {
+    } else if (Nodes.getNodeAs<clang::Expr>(kAssignment)) {
+      // Any assignment involving the expression itself resets the variable to
+      // "unknown". A more advanced analysis could try to evaluate the compound
+      // assignment. For example, `x += 0` need not invalidate `x`.
       Vars[Var] = ValueLattice::top();
-      return Vars;
     }
-
-    llvm_unreachable("expected at least one bound identifier");
   }
 };
 

diff  --git a/clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h b/clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
index eb045a24d2e4e..fc24a2b71421b 100644
--- a/clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
+++ b/clang/unittests/Analysis/FlowSensitive/NoopAnalysis.h
@@ -44,9 +44,7 @@ class NoopAnalysis : public DataflowAnalysis<NoopAnalysis, NoopLattice> {
 
   static NoopLattice initialElement() { return {}; }
 
-  NoopLattice transfer(const Stmt *S, const NoopLattice &E, Environment &Env) {
-    return {};
-  }
+  void transfer(const Stmt *S, NoopLattice &E, Environment &Env) {}
 };
 
 } // namespace dataflow

diff  --git a/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp b/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
index c2ba3b965004a..bb04ead6fac64 100644
--- a/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/SingleVarConstantPropagationTest.cpp
@@ -121,9 +121,8 @@ class ConstantPropagationAnalysis
     return ConstantPropagationLattice::bottom();
   }
 
-  ConstantPropagationLattice transfer(const Stmt *S,
-                                      const ConstantPropagationLattice &Element,
-                                      Environment &Env) {
+  void transfer(const Stmt *S, ConstantPropagationLattice &Element,
+                Environment &Env) {
     auto matcher = stmt(
         anyOf(declStmt(hasSingleDecl(varDecl(hasType(isInteger()),
                                              hasInitializer(expr().bind(kInit)))
@@ -137,7 +136,7 @@ class ConstantPropagationAnalysis
     ASTContext &Context = getASTContext();
     auto Results = match(matcher, *S, Context);
     if (Results.empty())
-      return Element;
+      return;
     const BoundNodes &Nodes = Results[0];
 
     const auto *Var = Nodes.getNodeAs<clang::VarDecl>(kVar);
@@ -145,30 +144,26 @@ class ConstantPropagationAnalysis
 
     if (const auto *E = Nodes.getNodeAs<clang::Expr>(kInit)) {
       Expr::EvalResult R;
-      if (E->EvaluateAsInt(R, Context) && R.Val.isInt())
-        return ConstantPropagationLattice{
-            {{Var, R.Val.getInt().getExtValue()}}};
-      return ConstantPropagationLattice::top();
-    }
-
-    if (Nodes.getNodeAs<clang::Expr>(kJustAssignment)) {
+      Element =
+          (E->EvaluateAsInt(R, Context) && R.Val.isInt())
+              ? ConstantPropagationLattice{{{Var,
+                                             R.Val.getInt().getExtValue()}}}
+              : ConstantPropagationLattice::top();
+    } else if (Nodes.getNodeAs<clang::Expr>(kJustAssignment)) {
       const auto *RHS = Nodes.getNodeAs<clang::Expr>(kRHS);
       assert(RHS != nullptr);
 
       Expr::EvalResult R;
-      if (RHS->EvaluateAsInt(R, Context) && R.Val.isInt())
-        return ConstantPropagationLattice{
-            {{Var, R.Val.getInt().getExtValue()}}};
-      return ConstantPropagationLattice::top();
-    }
-
-    // Any assignment involving the expression itself resets the variable to
-    // "unknown". A more advanced analysis could try to evaluate the compound
-    // assignment. For example, `x += 0` need not invalidate `x`.
-    if (Nodes.getNodeAs<clang::Expr>(kAssignment))
-      return ConstantPropagationLattice::top();
-
-    llvm_unreachable("expected at least one bound identifier");
+      Element =
+          (RHS->EvaluateAsInt(R, Context) && R.Val.isInt())
+              ? ConstantPropagationLattice{{{Var,
+                                             R.Val.getInt().getExtValue()}}}
+              : ConstantPropagationLattice::top();
+    } else if (Nodes.getNodeAs<clang::Expr>(kAssignment))
+      // Any assignment involving the expression itself resets the variable to
+      // "unknown". A more advanced analysis could try to evaluate the compound
+      // assignment. For example, `x += 0` need not invalidate `x`.
+      Element = ConstantPropagationLattice::top();
   }
 };
 

diff  --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index 77e48972a484b..5161bd517abea 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -113,9 +113,8 @@ class NonConvergingAnalysis
 
   static NonConvergingLattice initialElement() { return {0}; }
 
-  NonConvergingLattice transfer(const Stmt *S, const NonConvergingLattice &E,
-                                Environment &Env) {
-    return {E.State + 1};
+  void transfer(const Stmt *S, NonConvergingLattice &E, Environment &Env) {
+    ++E.State;
   }
 };
 
@@ -165,15 +164,12 @@ class FunctionCallAnalysis
 
   static FunctionCallLattice initialElement() { return {}; }
 
-  FunctionCallLattice transfer(const Stmt *S, const FunctionCallLattice &E,
-                               Environment &Env) {
-    FunctionCallLattice R = E;
+  void transfer(const Stmt *S, FunctionCallLattice &E, Environment &Env) {
     if (auto *C = dyn_cast<CallExpr>(S)) {
       if (auto *F = dyn_cast<FunctionDecl>(C->getCalleeDecl())) {
-        R.CalledFunctions.insert(F->getNameInfo().getAsString());
+        E.CalledFunctions.insert(F->getNameInfo().getAsString());
       }
     }
-    return R;
   }
 };
 


        


More information about the cfe-commits mailing list