[llvm] 0e6628d - [StackSafety] Lazy calculations

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu May 28 13:33:18 PDT 2020


Author: Vitaly Buka
Date: 2020-05-28T13:32:57-07:00
New Revision: 0e6628d37f99b3baaab662b9d1fa9a1e39d3aeb8

URL: https://github.com/llvm/llvm-project/commit/0e6628d37f99b3baaab662b9d1fa9a1e39d3aeb8
DIFF: https://github.com/llvm/llvm-project/commit/0e6628d37f99b3baaab662b9d1fa9a1e39d3aeb8.diff

LOG: [StackSafety] Lazy calculations

We are going to convert this into pure analysis, so
processing will be delayed up to the first safety request.

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/StackSafetyAnalysis.h
    llvm/lib/Analysis/StackSafetyAnalysis.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h
index b5589611c8e2..246f44f19f47 100644
--- a/llvm/include/llvm/Analysis/StackSafetyAnalysis.h
+++ b/llvm/include/llvm/Analysis/StackSafetyAnalysis.h
@@ -19,6 +19,7 @@
 namespace llvm {
 
 class AllocaInst;
+class ScalarEvolution;
 
 /// Interface to access stack safety analysis results for single function.
 class StackSafetyInfo {
@@ -26,30 +27,40 @@ class StackSafetyInfo {
   struct InfoTy;
 
 private:
-  std::unique_ptr<InfoTy> Info;
+  Function *F = nullptr;
+  std::function<ScalarEvolution &()> GetSE;
+  mutable std::unique_ptr<InfoTy> Info;
 
 public:
-  StackSafetyInfo(InfoTy Info);
+  StackSafetyInfo();
+  StackSafetyInfo(Function *F, std::function<ScalarEvolution &()> GetSE);
   StackSafetyInfo(StackSafetyInfo &&);
   StackSafetyInfo &operator=(StackSafetyInfo &&);
   ~StackSafetyInfo();
 
-  const InfoTy &getInfo() const { return *Info; }
+  const InfoTy &getInfo() const;
 
   // TODO: Add useful for client methods.
-  void print(raw_ostream &O, const GlobalValue &F) const;
+  void print(raw_ostream &O) const;
 };
 
 class StackSafetyGlobalInfo {
 public:
-  using GVToSSI = std::map<const GlobalValue *, StackSafetyInfo>;
+  struct InfoTy;
 
 private:
-  GVToSSI SSGI;
+  Module *M = nullptr;
+  std::function<const StackSafetyInfo &(Function &F)> GetSSI;
+  mutable std::unique_ptr<InfoTy> Info;
+  const InfoTy &getInfo() const;
 
 public:
-  StackSafetyGlobalInfo() = default;
-  StackSafetyGlobalInfo(GVToSSI SSGI) : SSGI(std::move(SSGI)) {}
+  StackSafetyGlobalInfo();
+  StackSafetyGlobalInfo(
+      Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI);
+  StackSafetyGlobalInfo(StackSafetyGlobalInfo &&);
+  StackSafetyGlobalInfo &operator=(StackSafetyGlobalInfo &&);
+  ~StackSafetyGlobalInfo();
 
   bool setMetadata(Module &M) const;
   void print(raw_ostream &O) const;
@@ -77,14 +88,13 @@ class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
 
 /// StackSafetyInfo wrapper for the legacy pass manager
 class StackSafetyInfoWrapperPass : public FunctionPass {
-  Optional<StackSafetyInfo> SSI;
-  const Function *F = nullptr;
+  StackSafetyInfo SSI;
 
 public:
   static char ID;
   StackSafetyInfoWrapperPass();
 
-  const StackSafetyInfo &getResult() const { return *SSI; }
+  const StackSafetyInfo &getResult() const { return SSI; }
 
   void print(raw_ostream &O, const Module *M) const override;
   void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -131,6 +141,7 @@ class StackSafetyGlobalInfoWrapperPass : public ModulePass {
   static char ID;
 
   StackSafetyGlobalInfoWrapperPass();
+  ~StackSafetyGlobalInfoWrapperPass();
 
   const StackSafetyGlobalInfo &getResult() const { return SSGI; }
 

diff  --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
index 15ddea6a957c..2c8a5e33c847 100644
--- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp
+++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
@@ -33,8 +33,6 @@ static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations",
 
 namespace {
 
-using GVToSSI = StackSafetyGlobalInfo::GVToSSI;
-
 /// Rewrite an SCEV expression for a memory access address to an expression that
 /// represents offset from the given alloca.
 class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> {
@@ -178,15 +176,17 @@ struct FunctionInfo {
   }
 };
 
+using GVToSSI = std::map<const GlobalValue *, FunctionInfo>;
+
 } // namespace
 
 struct StackSafetyInfo::InfoTy {
   FunctionInfo Info;
 };
 
-StackSafetyInfo makeSSI(FunctionInfo Info) {
-  return StackSafetyInfo(StackSafetyInfo::InfoTy{std::move(Info)});
-}
+struct StackSafetyGlobalInfo::InfoTy {
+  GVToSSI Info;
+};
 
 namespace {
 
@@ -430,17 +430,10 @@ class StackSafetyDataFlowAnalysis {
   void verifyFixedPoint();
 #endif
 
-  uint32_t findPointerWidth() const {
-    for (auto &F : Functions)
-      for (auto &P : F.second.Params)
-        return P.Range.getBitWidth();
-    return 1;
-  }
-
 public:
-  explicit StackSafetyDataFlowAnalysis(FunctionMap Functions)
+  StackSafetyDataFlowAnalysis(uint32_t PointerBitWidth, FunctionMap Functions)
       : Functions(std::move(Functions)),
-        UnknownRange(ConstantRange::getFull(findPointerWidth())) {}
+        UnknownRange(ConstantRange::getFull(PointerBitWidth)) {}
 
   const FunctionMap &run();
 
@@ -560,7 +553,7 @@ bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) {
     auto Iter = SSGI.find(&F);
     if (Iter == SSGI.end())
       continue;
-    const FunctionInfo &Summary = Iter->second.getInfo().Info;
+    const FunctionInfo &Summary = Iter->second;
     size_t Pos = 0;
     for (auto &I : instructions(F)) {
       if (auto AI = dyn_cast<AllocaInst>(&I)) {
@@ -623,11 +616,16 @@ GVToSSI createGlobalStackSafetyInfo(
   for (auto &FI : Copy)
     ResolveAllCalls(FI.second.Params);
 
-  StackSafetyDataFlowAnalysis SSDFA(std::move(Copy));
+  uint32_t PointerSize = Copy.begin()
+                             ->first->getParent()
+                             ->getDataLayout()
+                             .getMaxPointerSizeInBits();
+  StackSafetyDataFlowAnalysis SSDFA(PointerSize, std::move(Copy));
 
   for (auto &F : SSDFA.run()) {
     auto FI = F.second;
     size_t Pos = 0;
+    auto &SrcF = Functions[F.first];
     for (auto &A : FI.Allocas) {
       ResolveAllCalls(A);
       for (auto &C : A.Calls) {
@@ -635,15 +633,15 @@ GVToSSI createGlobalStackSafetyInfo(
             SSDFA.getArgumentAccessRange(C.Callee, C.ParamNo, C.Offset));
       }
       // FIXME: This is needed only to preserve calls in print() results.
-      A.Calls = Functions[F.first].Allocas[Pos].Calls;
+      A.Calls = SrcF.Allocas[Pos].Calls;
       ++Pos;
     }
     Pos = 0;
     for (auto &P : FI.Params) {
-      P.Calls = Functions[F.first].Params[Pos].Calls;
+      P.Calls = SrcF.Params[Pos].Calls;
       ++Pos;
     }
-    SSI.emplace(F.first, makeSSI(std::move(FI)));
+    SSI[F.first] = std::move(FI);
   }
 
   return SSI;
@@ -651,29 +649,70 @@ GVToSSI createGlobalStackSafetyInfo(
 
 } // end anonymous namespace
 
+StackSafetyInfo::StackSafetyInfo() = default;
+
+StackSafetyInfo::StackSafetyInfo(Function *F,
+                                 std::function<ScalarEvolution &()> GetSE)
+    : F(F), GetSE(GetSE) {}
+
 StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default;
-StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;
 
-StackSafetyInfo::StackSafetyInfo(InfoTy Info)
-    : Info(new InfoTy(std::move(Info))) {}
+StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;
 
 StackSafetyInfo::~StackSafetyInfo() = default;
 
-void StackSafetyInfo::print(raw_ostream &O, const GlobalValue &F) const {
-  Info->Info.print(O, F.getName(), dyn_cast<Function>(&F));
+const StackSafetyInfo::InfoTy &StackSafetyInfo::getInfo() const {
+  if (!Info) {
+    StackSafetyLocalAnalysis SSLA(*F, GetSE());
+    Info.reset(new InfoTy{SSLA.run()});
+  }
+  return *Info;
+}
+
+void StackSafetyInfo::print(raw_ostream &O) const {
+  getInfo().Info.print(O, F->getName(), dyn_cast<Function>(F));
+}
+
+const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const {
+  if (!Info) {
+    std::map<const GlobalValue *, FunctionInfo> Functions;
+    for (auto &F : M->functions()) {
+      if (!F.isDeclaration()) {
+        auto FI = GetSSI(F).getInfo().Info;
+        Functions.emplace(&F, std::move(FI));
+      }
+    }
+    Info.reset(new InfoTy{createGlobalStackSafetyInfo(std::move(Functions))});
+  }
+  return *Info;
 }
 
+StackSafetyGlobalInfo::StackSafetyGlobalInfo() = default;
+
+StackSafetyGlobalInfo::StackSafetyGlobalInfo(
+    Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI)
+    : M(M), GetSSI(GetSSI) {}
+
+StackSafetyGlobalInfo::StackSafetyGlobalInfo(StackSafetyGlobalInfo &&) =
+    default;
+
+StackSafetyGlobalInfo &
+StackSafetyGlobalInfo::operator=(StackSafetyGlobalInfo &&) = default;
+
+StackSafetyGlobalInfo::~StackSafetyGlobalInfo() = default;
+
 bool StackSafetyGlobalInfo::setMetadata(Module &M) const {
-  return setStackSafetyMetadata(M, SSGI);
+  return setStackSafetyMetadata(M, getInfo().Info);
 }
 
 void StackSafetyGlobalInfo::print(raw_ostream &O) const {
-  if (SSGI.empty())
+  auto &SSI = getInfo().Info;
+  if (SSI.empty())
     return;
-  const Module &M = *SSGI.begin()->first->getParent();
+  const Module &M = *SSI.begin()->first->getParent();
   for (auto &F : M.functions()) {
     if (!F.isDeclaration()) {
-      SSGI.find(&F)->second.print(O, F);
+      SSI.find(&F)->second.print(O, F.getName(), &F);
       O << "\n";
     }
   }
@@ -685,14 +724,15 @@ AnalysisKey StackSafetyAnalysis::Key;
 
 StackSafetyInfo StackSafetyAnalysis::run(Function &F,
                                          FunctionAnalysisManager &AM) {
-  StackSafetyLocalAnalysis SSLA(F, AM.getResult<ScalarEvolutionAnalysis>(F));
-  return makeSSI(SSLA.run());
+  return StackSafetyInfo(&F, [&AM, &F]() -> ScalarEvolution & {
+    return AM.getResult<ScalarEvolutionAnalysis>(F);
+  });
 }
 
 PreservedAnalyses StackSafetyPrinterPass::run(Function &F,
                                               FunctionAnalysisManager &AM) {
   OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n";
-  AM.getResult<StackSafetyAnalysis>(F).print(OS, F);
+  AM.getResult<StackSafetyAnalysis>(F).print(OS);
   return PreservedAnalyses::all();
 }
 
@@ -703,19 +743,17 @@ StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) {
 }
 
 void StackSafetyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
-  AU.addRequired<ScalarEvolutionWrapperPass>();
+  AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
   AU.setPreservesAll();
 }
 
 void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const {
-  SSI->print(O, *F);
+  SSI.print(O);
 }
 
 bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) {
-  StackSafetyLocalAnalysis SSLA(
-      F, getAnalysis<ScalarEvolutionWrapperPass>().getSE());
-  SSI = makeSSI(SSLA.run());
-  this->F = &F;
+  auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
+  SSI = {&F, [SE]() -> ScalarEvolution & { return *SE; }};
   return false;
 }
 
@@ -725,18 +763,9 @@ StackSafetyGlobalInfo
 StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
   FunctionAnalysisManager &FAM =
       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
-
-  // FIXME: Lookup Module Summary.
-  std::map<const GlobalValue *, FunctionInfo> Functions;
-
-  for (auto &F : M.functions()) {
-    if (!F.isDeclaration()) {
-      auto FI = FAM.getResult<StackSafetyAnalysis>(F).getInfo().Info;
-      Functions.emplace(&F, std::move(FI));
-    }
-  }
-
-  return createGlobalStackSafetyInfo(std::move(Functions));
+  return {&M, [&FAM](Function &F) -> const StackSafetyInfo & {
+            return FAM.getResult<StackSafetyAnalysis>(F);
+          }};
 }
 
 PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M,
@@ -761,6 +790,8 @@ StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass()
       *PassRegistry::getPassRegistry());
 }
 
+StackSafetyGlobalInfoWrapperPass::~StackSafetyGlobalInfoWrapperPass() = default;
+
 void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O,
                                              const Module *M) const {
   SSGI.print(O);
@@ -772,16 +803,9 @@ void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage(
 }
 
 bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) {
-  std::map<const GlobalValue *, FunctionInfo> Functions;
-  for (auto &F : M.functions()) {
-    if (!F.isDeclaration()) {
-      auto FI =
-          getAnalysis<StackSafetyInfoWrapperPass>(F).getResult().getInfo().Info;
-      Functions.emplace(&F, std::move(FI));
-    }
-  }
-
-  SSGI = createGlobalStackSafetyInfo(std::move(Functions));
+  SSGI = {&M, [this](Function &F) -> const StackSafetyInfo & {
+            return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult();
+          }};
   return SSGI.setMetadata(M);
 }
 


        


More information about the llvm-commits mailing list