From 89576cea3ff721821ce288d9c9aa338a6aed97e7 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 28 Jul 2015 06:01:57 +0000 Subject: [PATCH] [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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243385 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/IPA/GlobalsModRef.cpp | 34 ++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index 2aad9313386..18a7233075e 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/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(V)) + GMR.FunctionInfos.erase(F); + if (GlobalValue *GV = dyn_cast(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 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.