@@ -114,6 +114,55 @@ static cl::opt<int> ColdCCRelFreq(
114114 " entry frequency, for a call site to be considered cold for enabling "
115115 " coldcc" ));
116116
117+ // / Is this global variable possibly used by a leak checker as a root? If so,
118+ // / we might not really want to eliminate the stores to it.
119+ static bool isLeakCheckerRoot (GlobalVariable *GV) {
120+ // A global variable is a root if it is a pointer, or could plausibly contain
121+ // a pointer. There are two challenges; one is that we could have a struct
122+ // the has an inner member which is a pointer. We recurse through the type to
123+ // detect these (up to a point). The other is that we may actually be a union
124+ // of a pointer and another type, and so our LLVM type is an integer which
125+ // gets converted into a pointer, or our type is an [i8 x #] with a pointer
126+ // potentially contained here.
127+
128+ if (GV->hasPrivateLinkage ())
129+ return false ;
130+
131+ SmallVector<Type *, 4 > Types;
132+ Types.push_back (GV->getValueType ());
133+
134+ unsigned Limit = 20 ;
135+ do {
136+ Type *Ty = Types.pop_back_val ();
137+ switch (Ty->getTypeID ()) {
138+ default : break ;
139+ case Type::PointerTyID:
140+ return true ;
141+ case Type::FixedVectorTyID:
142+ case Type::ScalableVectorTyID:
143+ if (cast<VectorType>(Ty)->getElementType ()->isPointerTy ())
144+ return true ;
145+ break ;
146+ case Type::ArrayTyID:
147+ Types.push_back (cast<ArrayType>(Ty)->getElementType ());
148+ break ;
149+ case Type::StructTyID: {
150+ StructType *STy = cast<StructType>(Ty);
151+ if (STy->isOpaque ()) return true ;
152+ for (Type *InnerTy : STy->elements ()) {
153+ if (isa<PointerType>(InnerTy)) return true ;
154+ if (isa<StructType>(InnerTy) || isa<ArrayType>(InnerTy) ||
155+ isa<VectorType>(InnerTy))
156+ Types.push_back (InnerTy);
157+ }
158+ break ;
159+ }
160+ }
161+ if (--Limit == 0 ) return true ;
162+ } while (!Types.empty ());
163+ return false ;
164+ }
165+
117166// / Given a value that is stored to a global but never read, determine whether
118167// / it's safe to remove the store and the chain of computation that feeds the
119168// / store.
@@ -122,7 +171,7 @@ static bool IsSafeComputationToRemove(
122171 do {
123172 if (isa<Constant>(V))
124173 return true ;
125- if (V->hasNUsesOrMore ( 1 ))
174+ if (! V->hasOneUse ( ))
126175 return false ;
127176 if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
128177 isa<GlobalValue>(V))
@@ -144,12 +193,90 @@ static bool IsSafeComputationToRemove(
144193 } while (true );
145194}
146195
196+ // / This GV is a pointer root. Loop over all users of the global and clean up
197+ // / any that obviously don't assign the global a value that isn't dynamically
198+ // / allocated.
199+ static bool
200+ CleanupPointerRootUsers (GlobalVariable *GV,
201+ function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
202+ // A brief explanation of leak checkers. The goal is to find bugs where
203+ // pointers are forgotten, causing an accumulating growth in memory
204+ // usage over time. The common strategy for leak checkers is to explicitly
205+ // allow the memory pointed to by globals at exit. This is popular because it
206+ // also solves another problem where the main thread of a C++ program may shut
207+ // down before other threads that are still expecting to use those globals. To
208+ // handle that case, we expect the program may create a singleton and never
209+ // destroy it.
210+
211+ bool Changed = false ;
212+
213+ // If Dead[n].first is the only use of a malloc result, we can delete its
214+ // chain of computation and the store to the global in Dead[n].second.
215+ SmallVector<std::pair<Instruction *, Instruction *>, 32 > Dead;
216+
217+ SmallVector<User *> Worklist (GV->users ());
218+ // Constants can't be pointers to dynamically allocated memory.
219+ while (!Worklist.empty ()) {
220+ User *U = Worklist.pop_back_val ();
221+ if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
222+ Value *V = SI->getValueOperand ();
223+ if (isa<Constant>(V)) {
224+ Changed = true ;
225+ SI->eraseFromParent ();
226+ } else if (Instruction *I = dyn_cast<Instruction>(V)) {
227+ if (I->hasOneUse ())
228+ Dead.push_back (std::make_pair (I, SI));
229+ }
230+ } else if (MemSetInst *MSI = dyn_cast<MemSetInst>(U)) {
231+ if (isa<Constant>(MSI->getValue ())) {
232+ Changed = true ;
233+ MSI->eraseFromParent ();
234+ } else if (Instruction *I = dyn_cast<Instruction>(MSI->getValue ())) {
235+ if (I->hasOneUse ())
236+ Dead.push_back (std::make_pair (I, MSI));
237+ }
238+ } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(U)) {
239+ GlobalVariable *MemSrc = dyn_cast<GlobalVariable>(MTI->getSource ());
240+ if (MemSrc && MemSrc->isConstant ()) {
241+ Changed = true ;
242+ MTI->eraseFromParent ();
243+ } else if (Instruction *I = dyn_cast<Instruction>(MTI->getSource ())) {
244+ if (I->hasOneUse ())
245+ Dead.push_back (std::make_pair (I, MTI));
246+ }
247+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
248+ if (isa<GEPOperator>(CE))
249+ append_range (Worklist, CE->users ());
250+ }
251+ }
252+
253+ for (int i = 0 , e = Dead.size (); i != e; ++i) {
254+ if (IsSafeComputationToRemove (Dead[i].first , GetTLI)) {
255+ Dead[i].second ->eraseFromParent ();
256+ Instruction *I = Dead[i].first ;
257+ do {
258+ if (isAllocationFn (I, GetTLI))
259+ break ;
260+ Instruction *J = dyn_cast<Instruction>(I->getOperand (0 ));
261+ if (!J)
262+ break ;
263+ I->eraseFromParent ();
264+ I = J;
265+ } while (true );
266+ I->eraseFromParent ();
267+ Changed = true ;
268+ }
269+ }
270+
271+ GV->removeDeadConstantUsers ();
272+ return Changed;
273+ }
274+
147275// / We just marked GV constant. Loop over all users of the global, cleaning up
148276// / the obvious ones. This is largely just a quick scan over the use list to
149277// / clean up the easy and obvious cruft. This returns true if it made a change.
150- static bool CleanupConstantGlobalUsers (
151- GlobalVariable *GV, const DataLayout &DL,
152- function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
278+ static bool CleanupConstantGlobalUsers (GlobalVariable *GV,
279+ const DataLayout &DL) {
153280 Constant *Init = GV->getInitializer ();
154281 SmallVector<User *, 8 > WorkList (GV->users ());
155282 SmallPtrSet<User *, 8 > Visited;
@@ -199,30 +326,11 @@ static bool CleanupConstantGlobalUsers(
199326 }
200327 }
201328 } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
202- auto *V = SI->getValueOperand ();
203- if (isa<Constant>(V)) {
204- EraseFromParent (SI);
205- } else if (isa<Instruction>(V)) {
206- EraseFromParent (SI);
207- if (IsSafeComputationToRemove (V, GetTLI))
208- RecursivelyDeleteTriviallyDeadInstructions (V);
209- } else if (isa<Argument>(V)) {
210- if (!V->getType ()->isPointerTy ())
211- EraseFromParent (SI);
212- }
213- } else if (auto *MSI = dyn_cast<MemSetInst>(U)) { // memset/cpy/mv
214- if (getUnderlyingObject (MSI->getRawDest ()) == GV)
215- EraseFromParent (MSI);
216- } else if (auto *MTI = dyn_cast<MemTransferInst>(U)) {
217- auto *Src = MTI->getRawSource ();
218- auto *Dst = MTI->getRawDest ();
219- if (getUnderlyingObject (Dst) != GV)
220- continue ;
221- if (isa<Instruction, Operator>(Src)) {
222- EraseFromParent (MTI);
223- if (IsSafeComputationToRemove (Src, GetTLI))
224- RecursivelyDeleteTriviallyDeadInstructions (Src);
225- }
329+ // Store must be unreachable or storing Init into the global.
330+ EraseFromParent (SI);
331+ } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U)) { // memset/cpy/mv
332+ if (getUnderlyingObject (MI->getRawDest ()) == GV)
333+ EraseFromParent (MI);
226334 } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
227335 if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
228336 append_range (WorkList, II->users ());
@@ -770,7 +878,12 @@ static bool OptimizeAwayTrappingUsesOfLoads(
770878 // If we nuked all of the loads, then none of the stores are needed either,
771879 // nor is the global.
772880 if (AllNonStoreUsesGone) {
773- Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI);
881+ if (isLeakCheckerRoot (GV)) {
882+ Changed |= CleanupPointerRootUsers (GV, GetTLI);
883+ } else {
884+ Changed = true ;
885+ CleanupConstantGlobalUsers (GV, DL);
886+ }
774887 if (GV->use_empty ()) {
775888 LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
776889 Changed = true ;
@@ -1384,7 +1497,15 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
13841497 // Delete it now.
13851498 if (!GS.IsLoaded ) {
13861499 LLVM_DEBUG (dbgs () << " GLOBAL NEVER LOADED: " << *GV << " \n " );
1387- Changed = CleanupConstantGlobalUsers (GV, DL, GetTLI);
1500+
1501+ if (isLeakCheckerRoot (GV)) {
1502+ // Delete any constant stores to the global.
1503+ Changed = CleanupPointerRootUsers (GV, GetTLI);
1504+ } else {
1505+ // Delete any stores we can find to the global. We may not be able to
1506+ // make it completely dead though.
1507+ Changed = CleanupConstantGlobalUsers (GV, DL);
1508+ }
13881509
13891510 // If the global is dead now, delete it.
13901511 if (GV->use_empty ()) {
@@ -1408,7 +1529,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
14081529 }
14091530
14101531 // Clean up any obviously simplifiable users now.
1411- Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI );
1532+ Changed |= CleanupConstantGlobalUsers (GV, DL);
14121533
14131534 // If the global is dead now, just nuke it.
14141535 if (GV->use_empty ()) {
@@ -1463,7 +1584,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
14631584 }
14641585
14651586 // Clean up any obviously simplifiable users now.
1466- CleanupConstantGlobalUsers (GV, DL, GetTLI );
1587+ CleanupConstantGlobalUsers (GV, DL);
14671588
14681589 if (GV->use_empty ()) {
14691590 LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments