diff options
| author | Chandler Carruth <chandlerc@gmail.com> | 2015-07-28 06:01:57 +0000 |
|---|---|---|
| committer | Chandler Carruth <chandlerc@gmail.com> | 2015-07-28 06:01:57 +0000 |
| commit | 786e6db1872ddb2c2dc4cc6c994b25084909a76b (patch) | |
| tree | 07fc4f7a4e98f9e2c0e361e8d2e195c3cfee7dd3 /llvm/lib/Analysis/IPA/GlobalsModRef.cpp | |
| parent | 13af03286e718f9542afaf8684ff7a82ab68a5f3 (diff) | |
| download | bcm5719-llvm-786e6db1872ddb2c2dc4cc6c994b25084909a76b.tar.gz bcm5719-llvm-786e6db1872ddb2c2dc4cc6c994b25084909a76b.zip | |
[GMR] Fix a long-standing bug in GlobalsModRef where it failed to clear
out the per-function modref data structures when functions were deleted
or when globals were deleted.
I don't actually know how the global deletion side of this bug hasn't
been hit before, but for the other it just-so-happens that functions
aren't likely to be deleted in the particular part of the LTO pipeline
where we currently enable GMR, so we got lucky.
With this patch, I can self-host with GMR enabled in the normal pass
pipeline!
I was a bit concerned about the compile-time impact of this chang, which
is part of what motivated my prior string of patches to make the
per-function datastructure very dense and fast to walk. With those
changes in place, I can't measure a significant compile time difference
(the difference is around 0.1% which is *way* below the noise) before
and after this patch when building a linked bitcode for all of Clang.
Differential Revision: http://reviews.llvm.org/D11453
llvm-svn: 243385
Diffstat (limited to 'llvm/lib/Analysis/IPA/GlobalsModRef.cpp')
| -rw-r--r-- | llvm/lib/Analysis/IPA/GlobalsModRef.cpp | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/IPA/GlobalsModRef.cpp b/llvm/lib/Analysis/IPA/GlobalsModRef.cpp index 2aad9313386..18a7233075e 100644 --- a/llvm/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/llvm/lib/Analysis/IPA/GlobalsModRef.cpp @@ -180,6 +180,13 @@ public: GlobalMRI = ModRefInfo(GlobalMRI | NewMRI); } + /// Clear a global's ModRef info. Should be used when a global is being + /// deleted. + void eraseModRefInfoForGlobal(const GlobalValue &GV) { + if (AlignedMap *P = Info.getPointer()) + P->Map.erase(&GV); + } + private: /// All of the information is encoded into a single pointer, with a three bit /// integer in the low three bits. The high bit provides a flag for when this @@ -215,11 +222,13 @@ class GlobalsModRef : public ModulePass, public AliasAnalysis { void deleted() override { Value *V = getValPtr(); + if (auto *F = dyn_cast<Function>(V)) + GMR.FunctionInfos.erase(F); + if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) { if (GMR.NonAddressTakenGlobals.erase(GV)) { // This global might be an indirect global. If so, remove it and - // remove - // any AllocRelatedValues for it. + // remove any AllocRelatedValues for it. if (GMR.IndirectGlobals.erase(GV)) { // Remove any entries in AllocsForIndirectGlobals for this global. for (auto I = GMR.AllocsForIndirectGlobals.begin(), @@ -228,6 +237,11 @@ class GlobalsModRef : public ModulePass, public AliasAnalysis { if (I->second == GV) GMR.AllocsForIndirectGlobals.erase(I); } + + // Scan the function info we have collected and remove this global + // from all of them. + for (auto &FIPair : GMR.FunctionInfos) + FIPair.second.eraseModRefInfoForGlobal(*GV); } } @@ -361,11 +375,13 @@ Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); } /// (really, their address passed to something nontrivial), record this fact, /// and record the functions that they are used directly in. void GlobalsModRef::AnalyzeGlobals(Module &M) { + SmallPtrSet<Function *, 64> TrackedFunctions; for (Function &F : M) if (F.hasLocalLinkage()) if (!AnalyzeUsesOfPointer(&F)) { // Remember that we are tracking this global. NonAddressTakenGlobals.insert(&F); + TrackedFunctions.insert(&F); Handles.emplace_front(*this, &F); Handles.front().I = Handles.begin(); ++NumNonAddrTakenFunctions; @@ -381,12 +397,22 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { Handles.emplace_front(*this, &GV); Handles.front().I = Handles.begin(); - for (Function *Reader : Readers) + for (Function *Reader : Readers) { + if (TrackedFunctions.insert(Reader).second) { + Handles.emplace_front(*this, Reader); + Handles.front().I = Handles.begin(); + } FunctionInfos[Reader].addModRefInfoForGlobal(GV, MRI_Ref); + } if (!GV.isConstant()) // No need to keep track of writers to constants - for (Function *Writer : Writers) + for (Function *Writer : Writers) { + if (TrackedFunctions.insert(Writer).second) { + Handles.emplace_front(*this, Writer); + Handles.front().I = Handles.begin(); + } FunctionInfos[Writer].addModRefInfoForGlobal(GV, MRI_Mod); + } ++NumNonAddrTakenGlobalVars; // If this global holds a pointer type, see if it is an indirect global. |

