Skip to content

Commit 0e6628d

Browse files
committed
[StackSafety] Lazy calculations
We are going to convert this into pure analysis, so processing will be delayed up to the first safety request.
1 parent 2622cfb commit 0e6628d

File tree

2 files changed

+105
-70
lines changed

2 files changed

+105
-70
lines changed

llvm/include/llvm/Analysis/StackSafetyAnalysis.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,48 @@
1919
namespace llvm {
2020

2121
class AllocaInst;
22+
class ScalarEvolution;
2223

2324
/// Interface to access stack safety analysis results for single function.
2425
class StackSafetyInfo {
2526
public:
2627
struct InfoTy;
2728

2829
private:
29-
std::unique_ptr<InfoTy> Info;
30+
Function *F = nullptr;
31+
std::function<ScalarEvolution &()> GetSE;
32+
mutable std::unique_ptr<InfoTy> Info;
3033

3134
public:
32-
StackSafetyInfo(InfoTy Info);
35+
StackSafetyInfo();
36+
StackSafetyInfo(Function *F, std::function<ScalarEvolution &()> GetSE);
3337
StackSafetyInfo(StackSafetyInfo &&);
3438
StackSafetyInfo &operator=(StackSafetyInfo &&);
3539
~StackSafetyInfo();
3640

37-
const InfoTy &getInfo() const { return *Info; }
41+
const InfoTy &getInfo() const;
3842

3943
// TODO: Add useful for client methods.
40-
void print(raw_ostream &O, const GlobalValue &F) const;
44+
void print(raw_ostream &O) const;
4145
};
4246

4347
class StackSafetyGlobalInfo {
4448
public:
45-
using GVToSSI = std::map<const GlobalValue *, StackSafetyInfo>;
49+
struct InfoTy;
4650

4751
private:
48-
GVToSSI SSGI;
52+
Module *M = nullptr;
53+
std::function<const StackSafetyInfo &(Function &F)> GetSSI;
54+
mutable std::unique_ptr<InfoTy> Info;
55+
const InfoTy &getInfo() const;
4956

5057
public:
51-
StackSafetyGlobalInfo() = default;
52-
StackSafetyGlobalInfo(GVToSSI SSGI) : SSGI(std::move(SSGI)) {}
58+
StackSafetyGlobalInfo();
59+
StackSafetyGlobalInfo(
60+
Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI);
61+
StackSafetyGlobalInfo(StackSafetyGlobalInfo &&);
62+
StackSafetyGlobalInfo &operator=(StackSafetyGlobalInfo &&);
63+
~StackSafetyGlobalInfo();
5364

5465
bool setMetadata(Module &M) const;
5566
void print(raw_ostream &O) const;
@@ -77,14 +88,13 @@ class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
7788

7889
/// StackSafetyInfo wrapper for the legacy pass manager
7990
class StackSafetyInfoWrapperPass : public FunctionPass {
80-
Optional<StackSafetyInfo> SSI;
81-
const Function *F = nullptr;
91+
StackSafetyInfo SSI;
8292

8393
public:
8494
static char ID;
8595
StackSafetyInfoWrapperPass();
8696

87-
const StackSafetyInfo &getResult() const { return *SSI; }
97+
const StackSafetyInfo &getResult() const { return SSI; }
8898

8999
void print(raw_ostream &O, const Module *M) const override;
90100
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -131,6 +141,7 @@ class StackSafetyGlobalInfoWrapperPass : public ModulePass {
131141
static char ID;
132142

133143
StackSafetyGlobalInfoWrapperPass();
144+
~StackSafetyGlobalInfoWrapperPass();
134145

135146
const StackSafetyGlobalInfo &getResult() const { return SSGI; }
136147

llvm/lib/Analysis/StackSafetyAnalysis.cpp

Lines changed: 83 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations",
3333

3434
namespace {
3535

36-
using GVToSSI = StackSafetyGlobalInfo::GVToSSI;
37-
3836
/// Rewrite an SCEV expression for a memory access address to an expression that
3937
/// represents offset from the given alloca.
4038
class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> {
@@ -178,15 +176,17 @@ struct FunctionInfo {
178176
}
179177
};
180178

179+
using GVToSSI = std::map<const GlobalValue *, FunctionInfo>;
180+
181181
} // namespace
182182

183183
struct StackSafetyInfo::InfoTy {
184184
FunctionInfo Info;
185185
};
186186

187-
StackSafetyInfo makeSSI(FunctionInfo Info) {
188-
return StackSafetyInfo(StackSafetyInfo::InfoTy{std::move(Info)});
189-
}
187+
struct StackSafetyGlobalInfo::InfoTy {
188+
GVToSSI Info;
189+
};
190190

191191
namespace {
192192

@@ -430,17 +430,10 @@ class StackSafetyDataFlowAnalysis {
430430
void verifyFixedPoint();
431431
#endif
432432

433-
uint32_t findPointerWidth() const {
434-
for (auto &F : Functions)
435-
for (auto &P : F.second.Params)
436-
return P.Range.getBitWidth();
437-
return 1;
438-
}
439-
440433
public:
441-
explicit StackSafetyDataFlowAnalysis(FunctionMap Functions)
434+
StackSafetyDataFlowAnalysis(uint32_t PointerBitWidth, FunctionMap Functions)
442435
: Functions(std::move(Functions)),
443-
UnknownRange(ConstantRange::getFull(findPointerWidth())) {}
436+
UnknownRange(ConstantRange::getFull(PointerBitWidth)) {}
444437

445438
const FunctionMap &run();
446439

@@ -560,7 +553,7 @@ bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) {
560553
auto Iter = SSGI.find(&F);
561554
if (Iter == SSGI.end())
562555
continue;
563-
const FunctionInfo &Summary = Iter->second.getInfo().Info;
556+
const FunctionInfo &Summary = Iter->second;
564557
size_t Pos = 0;
565558
for (auto &I : instructions(F)) {
566559
if (auto AI = dyn_cast<AllocaInst>(&I)) {
@@ -623,57 +616,103 @@ GVToSSI createGlobalStackSafetyInfo(
623616
for (auto &FI : Copy)
624617
ResolveAllCalls(FI.second.Params);
625618

626-
StackSafetyDataFlowAnalysis SSDFA(std::move(Copy));
619+
uint32_t PointerSize = Copy.begin()
620+
->first->getParent()
621+
->getDataLayout()
622+
.getMaxPointerSizeInBits();
623+
StackSafetyDataFlowAnalysis SSDFA(PointerSize, std::move(Copy));
627624

628625
for (auto &F : SSDFA.run()) {
629626
auto FI = F.second;
630627
size_t Pos = 0;
628+
auto &SrcF = Functions[F.first];
631629
for (auto &A : FI.Allocas) {
632630
ResolveAllCalls(A);
633631
for (auto &C : A.Calls) {
634632
A.updateRange(
635633
SSDFA.getArgumentAccessRange(C.Callee, C.ParamNo, C.Offset));
636634
}
637635
// FIXME: This is needed only to preserve calls in print() results.
638-
A.Calls = Functions[F.first].Allocas[Pos].Calls;
636+
A.Calls = SrcF.Allocas[Pos].Calls;
639637
++Pos;
640638
}
641639
Pos = 0;
642640
for (auto &P : FI.Params) {
643-
P.Calls = Functions[F.first].Params[Pos].Calls;
641+
P.Calls = SrcF.Params[Pos].Calls;
644642
++Pos;
645643
}
646-
SSI.emplace(F.first, makeSSI(std::move(FI)));
644+
SSI[F.first] = std::move(FI);
647645
}
648646

649647
return SSI;
650648
}
651649

652650
} // end anonymous namespace
653651

652+
StackSafetyInfo::StackSafetyInfo() = default;
653+
654+
StackSafetyInfo::StackSafetyInfo(Function *F,
655+
std::function<ScalarEvolution &()> GetSE)
656+
: F(F), GetSE(GetSE) {}
657+
654658
StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default;
655-
StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;
656659

657-
StackSafetyInfo::StackSafetyInfo(InfoTy Info)
658-
: Info(new InfoTy(std::move(Info))) {}
660+
StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;
659661

660662
StackSafetyInfo::~StackSafetyInfo() = default;
661663

662-
void StackSafetyInfo::print(raw_ostream &O, const GlobalValue &F) const {
663-
Info->Info.print(O, F.getName(), dyn_cast<Function>(&F));
664+
const StackSafetyInfo::InfoTy &StackSafetyInfo::getInfo() const {
665+
if (!Info) {
666+
StackSafetyLocalAnalysis SSLA(*F, GetSE());
667+
Info.reset(new InfoTy{SSLA.run()});
668+
}
669+
return *Info;
670+
}
671+
672+
void StackSafetyInfo::print(raw_ostream &O) const {
673+
getInfo().Info.print(O, F->getName(), dyn_cast<Function>(F));
674+
}
675+
676+
const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const {
677+
if (!Info) {
678+
std::map<const GlobalValue *, FunctionInfo> Functions;
679+
for (auto &F : M->functions()) {
680+
if (!F.isDeclaration()) {
681+
auto FI = GetSSI(F).getInfo().Info;
682+
Functions.emplace(&F, std::move(FI));
683+
}
684+
}
685+
Info.reset(new InfoTy{createGlobalStackSafetyInfo(std::move(Functions))});
686+
}
687+
return *Info;
664688
}
665689

690+
StackSafetyGlobalInfo::StackSafetyGlobalInfo() = default;
691+
692+
StackSafetyGlobalInfo::StackSafetyGlobalInfo(
693+
Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI)
694+
: M(M), GetSSI(GetSSI) {}
695+
696+
StackSafetyGlobalInfo::StackSafetyGlobalInfo(StackSafetyGlobalInfo &&) =
697+
default;
698+
699+
StackSafetyGlobalInfo &
700+
StackSafetyGlobalInfo::operator=(StackSafetyGlobalInfo &&) = default;
701+
702+
StackSafetyGlobalInfo::~StackSafetyGlobalInfo() = default;
703+
666704
bool StackSafetyGlobalInfo::setMetadata(Module &M) const {
667-
return setStackSafetyMetadata(M, SSGI);
705+
return setStackSafetyMetadata(M, getInfo().Info);
668706
}
669707

670708
void StackSafetyGlobalInfo::print(raw_ostream &O) const {
671-
if (SSGI.empty())
709+
auto &SSI = getInfo().Info;
710+
if (SSI.empty())
672711
return;
673-
const Module &M = *SSGI.begin()->first->getParent();
712+
const Module &M = *SSI.begin()->first->getParent();
674713
for (auto &F : M.functions()) {
675714
if (!F.isDeclaration()) {
676-
SSGI.find(&F)->second.print(O, F);
715+
SSI.find(&F)->second.print(O, F.getName(), &F);
677716
O << "\n";
678717
}
679718
}
@@ -685,14 +724,15 @@ AnalysisKey StackSafetyAnalysis::Key;
685724

686725
StackSafetyInfo StackSafetyAnalysis::run(Function &F,
687726
FunctionAnalysisManager &AM) {
688-
StackSafetyLocalAnalysis SSLA(F, AM.getResult<ScalarEvolutionAnalysis>(F));
689-
return makeSSI(SSLA.run());
727+
return StackSafetyInfo(&F, [&AM, &F]() -> ScalarEvolution & {
728+
return AM.getResult<ScalarEvolutionAnalysis>(F);
729+
});
690730
}
691731

692732
PreservedAnalyses StackSafetyPrinterPass::run(Function &F,
693733
FunctionAnalysisManager &AM) {
694734
OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n";
695-
AM.getResult<StackSafetyAnalysis>(F).print(OS, F);
735+
AM.getResult<StackSafetyAnalysis>(F).print(OS);
696736
return PreservedAnalyses::all();
697737
}
698738

@@ -703,19 +743,17 @@ StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) {
703743
}
704744

705745
void StackSafetyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
706-
AU.addRequired<ScalarEvolutionWrapperPass>();
746+
AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
707747
AU.setPreservesAll();
708748
}
709749

710750
void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const {
711-
SSI->print(O, *F);
751+
SSI.print(O);
712752
}
713753

714754
bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) {
715-
StackSafetyLocalAnalysis SSLA(
716-
F, getAnalysis<ScalarEvolutionWrapperPass>().getSE());
717-
SSI = makeSSI(SSLA.run());
718-
this->F = &F;
755+
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
756+
SSI = {&F, [SE]() -> ScalarEvolution & { return *SE; }};
719757
return false;
720758
}
721759

@@ -725,18 +763,9 @@ StackSafetyGlobalInfo
725763
StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
726764
FunctionAnalysisManager &FAM =
727765
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
728-
729-
// FIXME: Lookup Module Summary.
730-
std::map<const GlobalValue *, FunctionInfo> Functions;
731-
732-
for (auto &F : M.functions()) {
733-
if (!F.isDeclaration()) {
734-
auto FI = FAM.getResult<StackSafetyAnalysis>(F).getInfo().Info;
735-
Functions.emplace(&F, std::move(FI));
736-
}
737-
}
738-
739-
return createGlobalStackSafetyInfo(std::move(Functions));
766+
return {&M, [&FAM](Function &F) -> const StackSafetyInfo & {
767+
return FAM.getResult<StackSafetyAnalysis>(F);
768+
}};
740769
}
741770

742771
PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M,
@@ -761,6 +790,8 @@ StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass()
761790
*PassRegistry::getPassRegistry());
762791
}
763792

793+
StackSafetyGlobalInfoWrapperPass::~StackSafetyGlobalInfoWrapperPass() = default;
794+
764795
void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O,
765796
const Module *M) const {
766797
SSGI.print(O);
@@ -772,16 +803,9 @@ void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage(
772803
}
773804

774805
bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) {
775-
std::map<const GlobalValue *, FunctionInfo> Functions;
776-
for (auto &F : M.functions()) {
777-
if (!F.isDeclaration()) {
778-
auto FI =
779-
getAnalysis<StackSafetyInfoWrapperPass>(F).getResult().getInfo().Info;
780-
Functions.emplace(&F, std::move(FI));
781-
}
782-
}
783-
784-
SSGI = createGlobalStackSafetyInfo(std::move(Functions));
806+
SSGI = {&M, [this](Function &F) -> const StackSafetyInfo & {
807+
return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult();
808+
}};
785809
return SSGI.setMetadata(M);
786810
}
787811

0 commit comments

Comments
 (0)