mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[StackSafety] Lazy calculations
We are going to convert this into pure analysis, so processing will be delayed up to the first safety request.
This commit is contained in:
parent
56ccc916eb
commit
507fec3651
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
static char ID;
|
||||
|
||||
StackSafetyGlobalInfoWrapperPass();
|
||||
~StackSafetyGlobalInfoWrapperPass();
|
||||
|
||||
const StackSafetyGlobalInfo &getResult() const { return SSGI; }
|
||||
|
||||
|
@ -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(StackSafetyInfo &&) = default;
|
||||
StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;
|
||||
StackSafetyInfo::StackSafetyInfo() = default;
|
||||
|
||||
StackSafetyInfo::StackSafetyInfo(InfoTy Info)
|
||||
: Info(new InfoTy(std::move(Info))) {}
|
||||
StackSafetyInfo::StackSafetyInfo(Function *F,
|
||||
std::function<ScalarEvolution &()> GetSE)
|
||||
: F(F), GetSE(GetSE) {}
|
||||
|
||||
StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user