[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