@@ -114,55 +114,6 @@ 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-
166117// / Given a value that is stored to a global but never read, determine whether
167118// / it's safe to remove the store and the chain of computation that feeds the
168119// / store.
@@ -171,7 +122,7 @@ static bool IsSafeComputationToRemove(
171122 do {
172123 if (isa<Constant>(V))
173124 return true ;
174- if (! V->hasOneUse ( ))
125+ if (V->hasNUsesOrMore ( 1 ))
175126 return false ;
176127 if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
177128 isa<GlobalValue>(V))
@@ -193,90 +144,12 @@ static bool IsSafeComputationToRemove(
193144 } while (true );
194145}
195146
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-
275147// / We just marked GV constant. Loop over all users of the global, cleaning up
276148// / the obvious ones. This is largely just a quick scan over the use list to
277149// / clean up the easy and obvious cruft. This returns true if it made a change.
278- static bool CleanupConstantGlobalUsers (GlobalVariable *GV,
279- const DataLayout &DL) {
150+ static bool CleanupConstantGlobalUsers (
151+ GlobalVariable *GV, const DataLayout &DL,
152+ function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
280153 Constant *Init = GV->getInitializer ();
281154 SmallVector<User *, 8 > WorkList (GV->users ());
282155 SmallPtrSet<User *, 8 > Visited;
@@ -326,11 +199,30 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
326199 }
327200 }
328201 } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
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);
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+ }
334226 } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
335227 if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
336228 append_range (WorkList, II->users ());
@@ -878,12 +770,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(
878770 // If we nuked all of the loads, then none of the stores are needed either,
879771 // nor is the global.
880772 if (AllNonStoreUsesGone) {
881- if (isLeakCheckerRoot (GV)) {
882- Changed |= CleanupPointerRootUsers (GV, GetTLI);
883- } else {
884- Changed = true ;
885- CleanupConstantGlobalUsers (GV, DL);
886- }
773+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI);
887774 if (GV->use_empty ()) {
888775 LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
889776 Changed = true ;
@@ -1497,15 +1384,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
14971384 // Delete it now.
14981385 if (!GS.IsLoaded ) {
14991386 LLVM_DEBUG (dbgs () << " GLOBAL NEVER LOADED: " << *GV << " \n " );
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- }
1387+ Changed = CleanupConstantGlobalUsers (GV, DL, GetTLI);
15091388
15101389 // If the global is dead now, delete it.
15111390 if (GV->use_empty ()) {
@@ -1529,7 +1408,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15291408 }
15301409
15311410 // Clean up any obviously simplifiable users now.
1532- Changed |= CleanupConstantGlobalUsers (GV, DL);
1411+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI );
15331412
15341413 // If the global is dead now, just nuke it.
15351414 if (GV->use_empty ()) {
@@ -1584,7 +1463,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15841463 }
15851464
15861465 // Clean up any obviously simplifiable users now.
1587- CleanupConstantGlobalUsers (GV, DL);
1466+ CleanupConstantGlobalUsers (GV, DL, GetTLI );
15881467
15891468 if (GV->use_empty ()) {
15901469 LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments