forked from OSchip/llvm-project
[StackSafety,NFC] Convert to template internal stuff
It's going to be usefull for ThinLTO.
This commit is contained in:
parent
a019579fe5
commit
6e51a080f7
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue