[StackSafety,NFC] Convert to template internal stuff

It's going to be usefull for ThinLTO.
This commit is contained in:
Vitaly Buka 2020-06-02 02:51:35 -07:00
parent a019579fe5
commit 6e51a080f7
1 changed files with 54 additions and 50 deletions

View File

@ -58,9 +58,9 @@ public:
}; };
/// Describes use of address in as a function call argument. /// Describes use of address in as a function call argument.
struct CallInfo { template <typename CalleeTy> struct CallInfo {
/// Function being called. /// Function being called.
const GlobalValue *Callee = nullptr; const CalleeTy *Callee = nullptr;
/// Index of argument which pass address. /// Index of argument which pass address.
size_t ParamNo = 0; size_t ParamNo = 0;
// Offset range of address from base address (alloca or calling function // Offset range of address from base address (alloca or calling function
@ -68,25 +68,24 @@ struct CallInfo {
// Range should never set to empty-set, that is an invalid access range // Range should never set to empty-set, that is an invalid access range
// that can cause empty-set to be propagated with ConstantRange::add // that can cause empty-set to be propagated with ConstantRange::add
ConstantRange Offset; ConstantRange Offset;
CallInfo(const GlobalValue *Callee, size_t ParamNo, ConstantRange Offset) CallInfo(const CalleeTy *Callee, size_t ParamNo, ConstantRange Offset)
: Callee(Callee), ParamNo(ParamNo), Offset(Offset) {} : Callee(Callee), ParamNo(ParamNo), Offset(Offset) {}
StringRef getName() const { return Callee->getName(); }
}; };
raw_ostream &operator<<(raw_ostream &OS, const CallInfo &P) { template <typename CalleeTy>
return OS << "@" << P.getName() << "(arg" << P.ParamNo << ", " << P.Offset raw_ostream &operator<<(raw_ostream &OS, const CallInfo<CalleeTy> &P) {
<< ")"; return OS << "@" << P.Callee->getName() << "(arg" << P.ParamNo << ", "
<< P.Offset << ")";
} }
/// Describe uses of address (alloca or parameter) inside of the function. /// Describe uses of address (alloca or parameter) inside of the function.
struct UseInfo { template <typename CalleeTy> struct UseInfo {
// Access range if the address (alloca or parameters). // Access range if the address (alloca or parameters).
// It is allowed to be empty-set when there are no known accesses. // It is allowed to be empty-set when there are no known accesses.
ConstantRange Range; ConstantRange Range;
// List of calls which pass address as an argument. // List of calls which pass address as an argument.
SmallVector<CallInfo, 4> Calls; SmallVector<CallInfo<CalleeTy>, 4> Calls;
UseInfo(unsigned PointerSize) : Range{PointerSize, false} {} UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}
@ -97,7 +96,8 @@ struct UseInfo {
} }
}; };
raw_ostream &operator<<(raw_ostream &OS, const UseInfo &U) { template <typename CalleeTy>
raw_ostream &operator<<(raw_ostream &OS, const UseInfo<CalleeTy> &U) {
OS << U.Range; OS << U.Range;
for (auto &Call : U.Calls) for (auto &Call : U.Calls)
OS << ", " << Call; OS << ", " << Call;
@ -140,9 +140,9 @@ ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) {
return R; return R;
} }
struct FunctionInfo { template <typename CalleeTy> struct FunctionInfo {
std::map<const AllocaInst *, UseInfo> Allocas; std::map<const AllocaInst *, UseInfo<CalleeTy>> Allocas;
std::map<uint32_t, UseInfo> Params; std::map<uint32_t, UseInfo<CalleeTy>> Params;
// TODO: describe return value as depending on one or more of its arguments. // TODO: describe return value as depending on one or more of its arguments.
// StackSafetyDataFlowAnalysis counter stored here for faster access. // StackSafetyDataFlowAnalysis counter stored here for faster access.
@ -179,12 +179,12 @@ struct FunctionInfo {
} }
}; };
using GVToSSI = std::map<const GlobalValue *, FunctionInfo>; using GVToSSI = std::map<const GlobalValue *, FunctionInfo<GlobalValue>>;
} // namespace } // namespace
struct StackSafetyInfo::InfoTy { struct StackSafetyInfo::InfoTy {
FunctionInfo Info; FunctionInfo<GlobalValue> Info;
}; };
struct StackSafetyGlobalInfo::InfoTy { struct StackSafetyGlobalInfo::InfoTy {
@ -209,7 +209,7 @@ class StackSafetyLocalAnalysis {
ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U, ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U,
Value *Base); Value *Base);
bool analyzeAllUses(Value *Ptr, UseInfo &AS); bool analyzeAllUses(Value *Ptr, UseInfo<GlobalValue> &AS);
public: public:
StackSafetyLocalAnalysis(Function &F, ScalarEvolution &SE) StackSafetyLocalAnalysis(Function &F, ScalarEvolution &SE)
@ -218,7 +218,7 @@ public:
UnknownRange(PointerSize, true) {} UnknownRange(PointerSize, true) {}
// Run the transformation on the associated function. // Run the transformation on the associated function.
FunctionInfo run(); FunctionInfo<GlobalValue> run();
}; };
ConstantRange StackSafetyLocalAnalysis::offsetFrom(Value *Addr, Value *Base) { ConstantRange StackSafetyLocalAnalysis::offsetFrom(Value *Addr, Value *Base) {
@ -292,7 +292,8 @@ ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
/// The function analyzes all local uses of Ptr (alloca or argument) and /// The function analyzes all local uses of Ptr (alloca or argument) and
/// calculates local access range and all function calls where it was used. /// calculates local access range and all function calls where it was used.
bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, UseInfo &US) { bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr,
UseInfo<GlobalValue> &US) {
SmallPtrSet<const Value *, 16> Visited; SmallPtrSet<const Value *, 16> Visited;
SmallVector<const Value *, 8> WorkList; SmallVector<const Value *, 8> WorkList;
WorkList.push_back(Ptr); WorkList.push_back(Ptr);
@ -381,8 +382,8 @@ bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, UseInfo &US) {
return true; return true;
} }
FunctionInfo StackSafetyLocalAnalysis::run() { FunctionInfo<GlobalValue> StackSafetyLocalAnalysis::run() {
FunctionInfo Info; FunctionInfo<GlobalValue> Info;
assert(!F.isDeclaration() && assert(!F.isDeclaration() &&
"Can't run StackSafety on a function declaration"); "Can't run StackSafety on a function declaration");
@ -407,19 +408,19 @@ FunctionInfo StackSafetyLocalAnalysis::run() {
return Info; return Info;
} }
class StackSafetyDataFlowAnalysis { template <typename CalleeTy> class StackSafetyDataFlowAnalysis {
using FunctionMap = std::map<const GlobalValue *, FunctionInfo>; using FunctionMap = std::map<const CalleeTy *, FunctionInfo<CalleeTy>>;
FunctionMap Functions; FunctionMap Functions;
const ConstantRange UnknownRange; const ConstantRange UnknownRange;
// Callee-to-Caller multimap. // Callee-to-Caller multimap.
DenseMap<const GlobalValue *, SmallVector<const GlobalValue *, 4>> Callers; DenseMap<const CalleeTy *, SmallVector<const CalleeTy *, 4>> Callers;
SetVector<const GlobalValue *> WorkList; SetVector<const CalleeTy *> WorkList;
bool updateOneUse(UseInfo &US, bool UpdateToFullSet); bool updateOneUse(UseInfo<CalleeTy> &US, bool UpdateToFullSet);
void updateOneNode(const GlobalValue *Callee, FunctionInfo &FS); void updateOneNode(const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS);
void updateOneNode(const GlobalValue *Callee) { void updateOneNode(const CalleeTy *Callee) {
updateOneNode(Callee, Functions.find(Callee)->second); updateOneNode(Callee, Functions.find(Callee)->second);
} }
void updateAllNodes() { void updateAllNodes() {
@ -438,13 +439,13 @@ public:
const FunctionMap &run(); const FunctionMap &run();
ConstantRange getArgumentAccessRange(const GlobalValue *Callee, ConstantRange getArgumentAccessRange(const CalleeTy *Callee, unsigned ParamNo,
unsigned ParamNo,
const ConstantRange &Offsets) const; const ConstantRange &Offsets) const;
}; };
ConstantRange StackSafetyDataFlowAnalysis::getArgumentAccessRange( template <typename CalleeTy>
const GlobalValue *Callee, unsigned ParamNo, ConstantRange StackSafetyDataFlowAnalysis<CalleeTy>::getArgumentAccessRange(
const CalleeTy *Callee, unsigned ParamNo,
const ConstantRange &Offsets) const { const ConstantRange &Offsets) const {
auto FnIt = Functions.find(Callee); auto FnIt = Functions.find(Callee);
// Unknown callee (outside of LTO domain or an indirect call). // Unknown callee (outside of LTO domain or an indirect call).
@ -465,8 +466,9 @@ ConstantRange StackSafetyDataFlowAnalysis::getArgumentAccessRange(
return Access.add(Offsets); return Access.add(Offsets);
} }
bool StackSafetyDataFlowAnalysis::updateOneUse(UseInfo &US, template <typename CalleeTy>
bool UpdateToFullSet) { bool StackSafetyDataFlowAnalysis<CalleeTy>::updateOneUse(UseInfo<CalleeTy> &US,
bool UpdateToFullSet) {
bool Changed = false; bool Changed = false;
for (auto &CS : US.Calls) { for (auto &CS : US.Calls) {
assert(!CS.Offset.isEmptySet() && assert(!CS.Offset.isEmptySet() &&
@ -485,8 +487,9 @@ bool StackSafetyDataFlowAnalysis::updateOneUse(UseInfo &US,
return Changed; return Changed;
} }
void StackSafetyDataFlowAnalysis::updateOneNode(const GlobalValue *Callee, template <typename CalleeTy>
FunctionInfo &FS) { void StackSafetyDataFlowAnalysis<CalleeTy>::updateOneNode(
const CalleeTy *Callee, FunctionInfo<CalleeTy> &FS) {
bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations; bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations;
bool Changed = false; bool Changed = false;
for (auto &KV : FS.Params) for (auto &KV : FS.Params)
@ -504,14 +507,13 @@ void StackSafetyDataFlowAnalysis::updateOneNode(const GlobalValue *Callee,
} }
} }
void StackSafetyDataFlowAnalysis::runDataFlow() { template <typename CalleeTy>
Callers.clear(); void StackSafetyDataFlowAnalysis<CalleeTy>::runDataFlow() {
WorkList.clear(); SmallVector<const CalleeTy *, 16> Callees;
SmallVector<const GlobalValue *, 16> Callees;
for (auto &F : Functions) { for (auto &F : Functions) {
Callees.clear(); Callees.clear();
for (auto &KV : F.second.Params) auto &FS = F.second;
for (auto &KV : FS.Params)
for (auto &CS : KV.second.Calls) for (auto &CS : KV.second.Calls)
Callees.push_back(CS.Callee); Callees.push_back(CS.Callee);
@ -525,22 +527,24 @@ void StackSafetyDataFlowAnalysis::runDataFlow() {
updateAllNodes(); updateAllNodes();
while (!WorkList.empty()) { while (!WorkList.empty()) {
const GlobalValue *Callee = WorkList.back(); const CalleeTy *Callee = WorkList.back();
WorkList.pop_back(); WorkList.pop_back();
updateOneNode(Callee); updateOneNode(Callee);
} }
} }
#ifndef NDEBUG #ifndef NDEBUG
void StackSafetyDataFlowAnalysis::verifyFixedPoint() { template <typename ID>
void StackSafetyDataFlowAnalysis<ID>::verifyFixedPoint() {
WorkList.clear(); WorkList.clear();
updateAllNodes(); updateAllNodes();
assert(WorkList.empty()); assert(WorkList.empty());
} }
#endif #endif
const StackSafetyDataFlowAnalysis::FunctionMap & template <typename CalleeTy>
StackSafetyDataFlowAnalysis::run() { const typename StackSafetyDataFlowAnalysis<CalleeTy>::FunctionMap &
StackSafetyDataFlowAnalysis<CalleeTy>::run() {
runDataFlow(); runDataFlow();
LLVM_DEBUG(verifyFixedPoint()); LLVM_DEBUG(verifyFixedPoint());
return Functions; return Functions;
@ -562,7 +566,7 @@ const Function *findCalleeInModule(const GlobalValue *GV) {
return nullptr; return nullptr;
} }
void resolveAllCalls(UseInfo &Use) { template <typename CalleeTy> void resolveAllCalls(UseInfo<CalleeTy> &Use) {
ConstantRange FullSet(Use.Range.getBitWidth(), true); ConstantRange FullSet(Use.Range.getBitWidth(), true);
for (auto &C : Use.Calls) { for (auto &C : Use.Calls) {
const Function *F = findCalleeInModule(C.Callee); const Function *F = findCalleeInModule(C.Callee);
@ -576,7 +580,7 @@ void resolveAllCalls(UseInfo &Use) {
} }
GVToSSI createGlobalStackSafetyInfo( GVToSSI createGlobalStackSafetyInfo(
std::map<const GlobalValue *, FunctionInfo> Functions) { std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions) {
GVToSSI SSI; GVToSSI SSI;
if (Functions.empty()) if (Functions.empty())
return SSI; return SSI;
@ -592,7 +596,7 @@ GVToSSI createGlobalStackSafetyInfo(
->first->getParent() ->first->getParent()
->getDataLayout() ->getDataLayout()
.getMaxPointerSizeInBits(); .getMaxPointerSizeInBits();
StackSafetyDataFlowAnalysis SSDFA(PointerSize, std::move(Copy)); StackSafetyDataFlowAnalysis<GlobalValue> SSDFA(PointerSize, std::move(Copy));
for (auto &F : SSDFA.run()) { for (auto &F : SSDFA.run()) {
auto FI = F.second; auto FI = F.second;
@ -645,7 +649,7 @@ void StackSafetyInfo::print(raw_ostream &O) const {
const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const { const StackSafetyGlobalInfo::InfoTy &StackSafetyGlobalInfo::getInfo() const {
if (!Info) { if (!Info) {
std::map<const GlobalValue *, FunctionInfo> Functions; std::map<const GlobalValue *, FunctionInfo<GlobalValue>> Functions;
for (auto &F : M->functions()) { for (auto &F : M->functions()) {
if (!F.isDeclaration()) { if (!F.isDeclaration()) {
auto FI = GetSSI(F).getInfo().Info; auto FI = GetSSI(F).getInfo().Info;