mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-23 14:25:07 +00:00
[GMR] Make the collection of readers and writers of globals much more
efficient, NFC. Previously, we built up vectors of function pointers to track readers and writers. The primary problem here is that we would add the same function to this vector every time we found an instruction that reads or writes to the pointer. This could be a *lot* of redudant function pointers. Instead of doing that, we can use a SmallPtrSet. This does more than just reduce the size of the list of readers or writers. We walk the entire lists of each and do a map lookup for each one. By having sets, we will only do one map lookup per reader or writer function. But only one user of the pointer analyzer actually needs this information, so we can also skip accumulating it (and doing a lot of heap allocations) for all the other pointer analysis. This is particularly useful because there are very many more pointers in some of the other cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242950 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -236,8 +236,9 @@ private:
|
|||||||
|
|
||||||
void AnalyzeGlobals(Module &M);
|
void AnalyzeGlobals(Module &M);
|
||||||
void AnalyzeCallGraph(CallGraph &CG, Module &M);
|
void AnalyzeCallGraph(CallGraph &CG, Module &M);
|
||||||
bool AnalyzeUsesOfPointer(Value *V, std::vector<Function *> &Readers,
|
bool AnalyzeUsesOfPointer(Value *V,
|
||||||
std::vector<Function *> &Writers,
|
SmallPtrSetImpl<Function *> *Readers = nullptr,
|
||||||
|
SmallPtrSetImpl<Function *> *Writers = nullptr,
|
||||||
GlobalValue *OkayStoreDest = nullptr);
|
GlobalValue *OkayStoreDest = nullptr);
|
||||||
bool AnalyzeIndirectGlobalMemory(GlobalValue *GV);
|
bool AnalyzeIndirectGlobalMemory(GlobalValue *GV);
|
||||||
};
|
};
|
||||||
@@ -259,23 +260,21 @@ Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); }
|
|||||||
/// (really, their address passed to something nontrivial), record this fact,
|
/// (really, their address passed to something nontrivial), record this fact,
|
||||||
/// and record the functions that they are used directly in.
|
/// and record the functions that they are used directly in.
|
||||||
void GlobalsModRef::AnalyzeGlobals(Module &M) {
|
void GlobalsModRef::AnalyzeGlobals(Module &M) {
|
||||||
std::vector<Function *> Readers, Writers;
|
|
||||||
for (Function &F : M)
|
for (Function &F : M)
|
||||||
if (F.hasLocalLinkage()) {
|
if (F.hasLocalLinkage())
|
||||||
if (!AnalyzeUsesOfPointer(&F, Readers, Writers)) {
|
if (!AnalyzeUsesOfPointer(&F)) {
|
||||||
// Remember that we are tracking this global.
|
// Remember that we are tracking this global.
|
||||||
NonAddressTakenGlobals.insert(&F);
|
NonAddressTakenGlobals.insert(&F);
|
||||||
Handles.emplace_front(*this, &F);
|
Handles.emplace_front(*this, &F);
|
||||||
Handles.front().I = Handles.begin();
|
Handles.front().I = Handles.begin();
|
||||||
++NumNonAddrTakenFunctions;
|
++NumNonAddrTakenFunctions;
|
||||||
}
|
}
|
||||||
Readers.clear();
|
|
||||||
Writers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SmallPtrSet<Function *, 64> Readers, Writers;
|
||||||
for (GlobalVariable &GV : M.globals())
|
for (GlobalVariable &GV : M.globals())
|
||||||
if (GV.hasLocalLinkage()) {
|
if (GV.hasLocalLinkage()) {
|
||||||
if (!AnalyzeUsesOfPointer(&GV, Readers, Writers)) {
|
if (!AnalyzeUsesOfPointer(&GV, &Readers,
|
||||||
|
GV.isConstant() ? nullptr : &Writers)) {
|
||||||
// Remember that we are tracking this global, and the mod/ref fns
|
// Remember that we are tracking this global, and the mod/ref fns
|
||||||
NonAddressTakenGlobals.insert(&GV);
|
NonAddressTakenGlobals.insert(&GV);
|
||||||
Handles.emplace_front(*this, &GV);
|
Handles.emplace_front(*this, &GV);
|
||||||
@@ -306,8 +305,8 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) {
|
|||||||
///
|
///
|
||||||
/// If OkayStoreDest is non-null, stores into this global are allowed.
|
/// If OkayStoreDest is non-null, stores into this global are allowed.
|
||||||
bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||||
std::vector<Function *> &Readers,
|
SmallPtrSetImpl<Function *> *Readers,
|
||||||
std::vector<Function *> &Writers,
|
SmallPtrSetImpl<Function *> *Writers,
|
||||||
GlobalValue *OkayStoreDest) {
|
GlobalValue *OkayStoreDest) {
|
||||||
if (!V->getType()->isPointerTy())
|
if (!V->getType()->isPointerTy())
|
||||||
return true;
|
return true;
|
||||||
@@ -315,10 +314,12 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
|||||||
for (Use &U : V->uses()) {
|
for (Use &U : V->uses()) {
|
||||||
User *I = U.getUser();
|
User *I = U.getUser();
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
||||||
Readers.push_back(LI->getParent()->getParent());
|
if (Readers)
|
||||||
|
Readers->insert(LI->getParent()->getParent());
|
||||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
|
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
|
||||||
if (V == SI->getOperand(1)) {
|
if (V == SI->getOperand(1)) {
|
||||||
Writers.push_back(SI->getParent()->getParent());
|
if (Writers)
|
||||||
|
Writers->insert(SI->getParent()->getParent());
|
||||||
} else if (SI->getOperand(1) != OkayStoreDest) {
|
} else if (SI->getOperand(1) != OkayStoreDest) {
|
||||||
return true; // Storing the pointer
|
return true; // Storing the pointer
|
||||||
}
|
}
|
||||||
@@ -333,10 +334,12 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
|||||||
// passing into the function.
|
// passing into the function.
|
||||||
if (!CS.isCallee(&U)) {
|
if (!CS.isCallee(&U)) {
|
||||||
// Detect calls to free.
|
// Detect calls to free.
|
||||||
if (isFreeCall(I, TLI))
|
if (isFreeCall(I, TLI)) {
|
||||||
Writers.push_back(CS->getParent()->getParent());
|
if (Writers)
|
||||||
else
|
Writers->insert(CS->getParent()->getParent());
|
||||||
|
} else {
|
||||||
return true; // Argument of an unknown call.
|
return true; // Argument of an unknown call.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
|
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
|
||||||
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
||||||
@@ -368,8 +371,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
|||||||
// The pointer loaded from the global can only be used in simple ways:
|
// The pointer loaded from the global can only be used in simple ways:
|
||||||
// we allow addressing of it and loading storing to it. We do *not* allow
|
// we allow addressing of it and loading storing to it. We do *not* allow
|
||||||
// storing the loaded pointer somewhere else or passing to a function.
|
// storing the loaded pointer somewhere else or passing to a function.
|
||||||
std::vector<Function *> ReadersWriters;
|
if (AnalyzeUsesOfPointer(LI))
|
||||||
if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters))
|
|
||||||
return false; // Loaded pointer escapes.
|
return false; // Loaded pointer escapes.
|
||||||
// TODO: Could try some IP mod/ref of the loaded pointer.
|
// TODO: Could try some IP mod/ref of the loaded pointer.
|
||||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
|
} else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
|
||||||
@@ -390,8 +392,8 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
|||||||
|
|
||||||
// Analyze all uses of the allocation. If any of them are used in a
|
// Analyze all uses of the allocation. If any of them are used in a
|
||||||
// non-simple way (e.g. stored to another global) bail out.
|
// non-simple way (e.g. stored to another global) bail out.
|
||||||
std::vector<Function *> ReadersWriters;
|
if (AnalyzeUsesOfPointer(Ptr, /*Readers*/ nullptr, /*Writers*/ nullptr,
|
||||||
if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV))
|
GV))
|
||||||
return false; // Loaded pointer escapes.
|
return false; // Loaded pointer escapes.
|
||||||
|
|
||||||
// Remember that this allocation is related to the indirect global.
|
// Remember that this allocation is related to the indirect global.
|
||||||
|
Reference in New Issue
Block a user