[llvm] 892c71a - [StackSafety] Don't run datafow on allocas

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


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

URL: https://github.com/llvm/llvm-project/commit/892c71a5bb72cfcce1f0e94e3a0fd314d4606977
DIFF: https://github.com/llvm/llvm-project/commit/892c71a5bb72cfcce1f0e94e3a0fd314d4606977.diff

LOG: [StackSafety] Don't run datafow on allocas

We need to process only parameters. Allocas access can be calculated
afterwards.
Also don't create fake function for aliases and just resolve them on
initialization.

Added: 
    

Modified: 
    llvm/lib/Analysis/StackSafetyAnalysis.cpp
    llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/StackSafetyAnalysis.cpp b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
index e969639973a4..cdb952ba3278 100644
--- a/llvm/lib/Analysis/StackSafetyAnalysis.cpp
+++ b/llvm/lib/Analysis/StackSafetyAnalysis.cpp
@@ -137,31 +137,19 @@ ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) {
   return R;
 }
 
-/// Describes uses of allocas and parameters inside of a single function.
 struct FunctionInfo {
   SmallVector<UseInfo, 4> Allocas;
   SmallVector<UseInfo, 4> Params;
-  const GlobalValue *GV = nullptr;
   // TODO: describe return value as depending on one or more of its arguments.
 
   // StackSafetyDataFlowAnalysis counter stored here for faster access.
   int UpdateCount = 0;
 
-  FunctionInfo() = default;
-  FunctionInfo(const Function *F) : GV(F){};
-  explicit FunctionInfo(const GlobalAlias *A);
-
-  bool IsDSOLocal() const { return GV->isDSOLocal(); };
-
-  bool IsInterposable() const { return GV->isInterposable(); };
-
-  StringRef getName() const { return GV->getName(); }
-
   void print(raw_ostream &O, StringRef Name, const Function *F) const {
     // TODO: Consider 
diff erent printout format after
     // StackSafetyDataFlowAnalysis. Calls and parameters are irrelevant then.
-    O << "  @" << Name << (IsDSOLocal() ? "" : " dso_preemptable")
-      << (IsInterposable() ? " interposable" : "") << "\n";
+    O << "  @" << Name << ((F && F->isDSOLocal()) ? "" : " dso_preemptable")
+      << ((F && F->isInterposable()) ? " interposable" : "") << "\n";
 
     O << "    args uses:\n";
     size_t Pos = 0;
@@ -190,18 +178,6 @@ struct FunctionInfo {
   }
 };
 
-FunctionInfo::FunctionInfo(const GlobalAlias *A) : GV(A) {
-  unsigned PointerSize = A->getParent()->getDataLayout().getPointerSizeInBits();
-  const GlobalObject *Aliasee = A->getBaseObject();
-  const FunctionType *Type = cast<FunctionType>(Aliasee->getValueType());
-  // 'Forward' all parameters to this alias to the aliasee
-  for (unsigned ArgNo = 0; ArgNo < Type->getNumParams(); ArgNo++) {
-    Params.emplace_back(PointerSize);
-    UseInfo &US = Params.back();
-    US.Calls.emplace_back(Aliasee, ArgNo, ConstantRange(APInt(PointerSize, 0)));
-  }
-}
-
 } // namespace
 
 struct StackSafetyInfo::InfoTy {
@@ -404,7 +380,7 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, UseInfo &US) {
 }
 
 FunctionInfo StackSafetyLocalAnalysis::run() {
-  FunctionInfo Info(&F);
+  FunctionInfo Info;
   assert(!F.isDeclaration() &&
          "Can't run StackSafety on a function declaration");
 
@@ -433,15 +409,13 @@ class StackSafetyDataFlowAnalysis {
   using FunctionMap = std::map<const GlobalValue *, FunctionInfo>;
 
   FunctionMap Functions;
+  const ConstantRange UnknownRange;
+
   // Callee-to-Caller multimap.
   DenseMap<const GlobalValue *, SmallVector<const GlobalValue *, 4>> Callers;
   SetVector<const GlobalValue *> WorkList;
 
-  unsigned PointerSize = 0;
-  const ConstantRange UnknownRange;
 
-  ConstantRange getArgumentAccessRange(const GlobalValue *Callee,
-                                       unsigned ParamNo) const;
   bool updateOneUse(UseInfo &US, bool UpdateToFullSet);
   void updateOneNode(const GlobalValue *Callee, FunctionInfo &FS);
   void updateOneNode(const GlobalValue *Callee) {
@@ -456,25 +430,24 @@ 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:
-  StackSafetyDataFlowAnalysis(
-      Module &M, std::function<const FunctionInfo &(Function &)> FI);
-  GVToSSI run();
-};
+  explicit StackSafetyDataFlowAnalysis(FunctionMap Functions)
+      : Functions(std::move(Functions)),
+        UnknownRange(ConstantRange::getFull(findPointerWidth())) {}
 
-StackSafetyDataFlowAnalysis::StackSafetyDataFlowAnalysis(
-    Module &M, std::function<const FunctionInfo &(Function &)> FI)
-    : PointerSize(M.getDataLayout().getPointerSizeInBits()),
-      UnknownRange(PointerSize, true) {
-  // Without ThinLTO, run the local analysis for every function in the TU and
-  // then run the DFA.
-  for (auto &F : M.functions())
-    if (!F.isDeclaration())
-      Functions.emplace(&F, FI(F));
-  for (auto &A : M.aliases())
-    if (isa<Function>(A.getBaseObject()))
-      Functions.emplace(&A, FunctionInfo(&A));
-}
+  const FunctionMap &run();
+
+  // FIXME: Accept offset.
+  ConstantRange getArgumentAccessRange(const GlobalValue *Callee,
+                                       unsigned ParamNo) const;
+};
 
 ConstantRange
 StackSafetyDataFlowAnalysis::getArgumentAccessRange(const GlobalValue *Callee,
@@ -484,10 +457,6 @@ StackSafetyDataFlowAnalysis::getArgumentAccessRange(const GlobalValue *Callee,
   if (IT == Functions.end())
     return UnknownRange;
   const FunctionInfo &FS = IT->second;
-  // The definition of this symbol may not be the definition in this linkage
-  // unit.
-  if (!FS.IsDSOLocal() || FS.IsInterposable())
-    return UnknownRange;
   if (ParamNo >= FS.Params.size()) // possibly vararg
     return UnknownRange;
   return FS.Params[ParamNo].Range;
@@ -517,8 +486,6 @@ void StackSafetyDataFlowAnalysis::updateOneNode(const GlobalValue *Callee,
                                                 FunctionInfo &FS) {
   bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations;
   bool Changed = false;
-  for (auto &AS : FS.Allocas)
-    Changed |= updateOneUse(AS, UpdateToFullSet);
   for (auto &PS : FS.Params)
     Changed |= updateOneUse(PS, UpdateToFullSet);
 
@@ -542,9 +509,6 @@ void StackSafetyDataFlowAnalysis::runDataFlow() {
   for (auto &F : Functions) {
     Callees.clear();
     FunctionInfo &FS = F.second;
-    for (auto &AS : FS.Allocas)
-      for (auto &CS : AS.Calls)
-        Callees.push_back(CS.Callee);
     for (auto &PS : FS.Params)
       for (auto &CS : PS.Calls)
         Callees.push_back(CS.Callee);
@@ -573,14 +537,11 @@ void StackSafetyDataFlowAnalysis::verifyFixedPoint() {
 }
 #endif
 
-GVToSSI StackSafetyDataFlowAnalysis::run() {
+const StackSafetyDataFlowAnalysis::FunctionMap &
+StackSafetyDataFlowAnalysis::run() {
   runDataFlow();
   LLVM_DEBUG(verifyFixedPoint());
-
-  GVToSSI SSI;
-  for (auto &F : Functions)
-    SSI.emplace(F.first, makeSSI(F.second));
-  return SSI;
+  return Functions;
 }
 
 bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) {
@@ -608,6 +569,78 @@ bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) {
   return Changed;
 }
 
+const Function *FindCalleeInModule(const GlobalValue *GV) {
+  while (GV) {
+    if (GV->isInterposable() || !GV->isDSOLocal())
+      return nullptr;
+    if (const Function *F = dyn_cast<Function>(GV))
+      return F;
+    const GlobalAlias *A = dyn_cast<GlobalAlias>(GV);
+    if (!A)
+      return nullptr;
+    GV = A->getBaseObject();
+    if (GV == A)
+      return nullptr;
+  }
+  return nullptr;
+}
+
+void ResolveAllCalls(UseInfo &Use) {
+  ConstantRange FullSet(Use.Range.getBitWidth(), true);
+  for (auto &C : Use.Calls) {
+    const Function *F = FindCalleeInModule(C.Callee);
+    if (F) {
+      C.Callee = F;
+      continue;
+    }
+
+    return Use.updateRange(FullSet);
+  }
+}
+
+void ResolveAllCalls(SmallVectorImpl<UseInfo> &Values) {
+  for (auto &V : Values)
+    ResolveAllCalls(V);
+}
+
+GVToSSI createGlobalStackSafetyInfo(
+    std::map<const GlobalValue *, FunctionInfo> Functions) {
+  GVToSSI SSI;
+  if (Functions.empty())
+    return SSI;
+
+  // FIXME: Simplify printing and remove copying here.
+  auto Copy = Functions;
+
+  for (auto &FI : Copy)
+    ResolveAllCalls(FI.second.Params);
+
+  StackSafetyDataFlowAnalysis SSDFA(std::move(Copy));
+
+  for (auto &F : SSDFA.run()) {
+    auto FI = F.second;
+    size_t Pos = 0;
+    for (auto &A : FI.Allocas) {
+      ResolveAllCalls(A);
+      for (auto &C : A.Calls) {
+        ConstantRange R = SSDFA.getArgumentAccessRange(C.Callee, C.ParamNo);
+        A.updateRange(R.add(C.Offset));
+      }
+      // FIXME: This is needed only to preserve calls in print() results.
+      A.Calls = Functions[F.first].Allocas[Pos].Calls;
+      ++Pos;
+    }
+    Pos = 0;
+    for (auto &P : FI.Params) {
+      P.Calls = Functions[F.first].Params[Pos].Calls;
+      ++Pos;
+    }
+    SSI.emplace(F.first, makeSSI(std::move(FI)));
+  }
+
+  return SSI;
+}
+
 } // end anonymous namespace
 
 StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default;
@@ -636,10 +669,6 @@ void StackSafetyGlobalInfo::print(raw_ostream &O) const {
       O << "\n";
     }
   }
-  for (auto &A : M.aliases()) {
-    SSGI.find(&A)->second.print(O, A);
-    O << "\n";
-  }
 }
 
 LLVM_DUMP_METHOD void StackSafetyGlobalInfo::dump() const { print(dbgs()); }
@@ -689,11 +718,17 @@ StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
   FunctionAnalysisManager &FAM =
       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
 
-  StackSafetyDataFlowAnalysis SSDFA(
-      M, [&FAM](Function &F) -> const FunctionInfo & {
-        return FAM.getResult<StackSafetyAnalysis>(F).getInfo().Info;
-      });
-  return SSDFA.run();
+  // 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));
 }
 
 PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M,
@@ -729,14 +764,16 @@ void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage(
 }
 
 bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) {
-  StackSafetyDataFlowAnalysis SSDFA(
-      M, [this](Function &F) -> const FunctionInfo & {
-        return getAnalysis<StackSafetyInfoWrapperPass>(F)
-            .getResult()
-            .getInfo()
-            .Info;
-      });
-  SSGI = SSDFA.run();
+  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));
   return SSGI.setMetadata(M);
 }
 

diff  --git a/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll b/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
index d77e7a68925a..cfb6528e34e8 100644
--- a/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
+++ b/llvm/test/Analysis/StackSafetyAnalysis/ipa-alias.ll
@@ -95,39 +95,3 @@ entry:
 ; CHECK-NEXT: p[]: [0,1){{$}}
 ; CHECK-NEXT: allocas uses:
 ; CHECK-NOT: ]:
-
-; GLOBAL-LABEL: @InterposableAliasWrite1 interposable{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:
-
-; GLOBAL-LABEL: @PreemptableAliasWrite1 dso_preemptable{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:
-
-; GLOBAL-LABEL: @AliasToPreemptableAliasWrite1{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:
-
-; GLOBAL-LABEL: @AliasWrite1{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:
-
-; GLOBAL-LABEL: @BitcastAliasWrite1{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:
-
-; GLOBAL-LABEL: @AliasToBitcastAliasWrite1{{$}}
-; GLOBAL-NEXT: args uses:
-; GLOBAL-NEXT: <N/A>[]: [0,1), @Write1(arg0, [0,1)){{$}}
-; GLOBAL-NEXT: allocas uses:
-; GLOBAL-NOT: ]:


        


More information about the llvm-commits mailing list