@@ -108,55 +108,6 @@ static cl::opt<int> ColdCCRelFreq(
108108 " entry frequency, for a call site to be considered cold for enabling"
109109 " coldcc" ));
110110
111- // / Is this global variable possibly used by a leak checker as a root? If so,
112- // / we might not really want to eliminate the stores to it.
113- static bool isLeakCheckerRoot (GlobalVariable *GV) {
114- // A global variable is a root if it is a pointer, or could plausibly contain
115- // a pointer. There are two challenges; one is that we could have a struct
116- // the has an inner member which is a pointer. We recurse through the type to
117- // detect these (up to a point). The other is that we may actually be a union
118- // of a pointer and another type, and so our LLVM type is an integer which
119- // gets converted into a pointer, or our type is an [i8 x #] with a pointer
120- // potentially contained here.
121-
122- if (GV->hasPrivateLinkage ())
123- return false ;
124-
125- SmallVector<Type *, 4 > Types;
126- Types.push_back (GV->getValueType ());
127-
128- unsigned Limit = 20 ;
129- do {
130- Type *Ty = Types.pop_back_val ();
131- switch (Ty->getTypeID ()) {
132- default : break ;
133- case Type::PointerTyID:
134- return true ;
135- case Type::FixedVectorTyID:
136- case Type::ScalableVectorTyID:
137- if (cast<VectorType>(Ty)->getElementType ()->isPointerTy ())
138- return true ;
139- break ;
140- case Type::ArrayTyID:
141- Types.push_back (cast<ArrayType>(Ty)->getElementType ());
142- break ;
143- case Type::StructTyID: {
144- StructType *STy = cast<StructType>(Ty);
145- if (STy->isOpaque ()) return true ;
146- for (Type *InnerTy : STy->elements ()) {
147- if (isa<PointerType>(InnerTy)) return true ;
148- if (isa<StructType>(InnerTy) || isa<ArrayType>(InnerTy) ||
149- isa<VectorType>(InnerTy))
150- Types.push_back (InnerTy);
151- }
152- break ;
153- }
154- }
155- if (--Limit == 0 ) return true ;
156- } while (!Types.empty ());
157- return false ;
158- }
159-
160111// / Given a value that is stored to a global but never read, determine whether
161112// / it's safe to remove the store and the chain of computation that feeds the
162113// / store.
@@ -165,7 +116,7 @@ static bool IsSafeComputationToRemove(
165116 do {
166117 if (isa<Constant>(V))
167118 return true ;
168- if (! V->hasOneUse ( ))
119+ if (V->hasNUsesOrMore ( 1 ))
169120 return false ;
170121 if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
171122 isa<GlobalValue>(V))
@@ -187,90 +138,12 @@ static bool IsSafeComputationToRemove(
187138 } while (true );
188139}
189140
190- // / This GV is a pointer root. Loop over all users of the global and clean up
191- // / any that obviously don't assign the global a value that isn't dynamically
192- // / allocated.
193- static bool
194- CleanupPointerRootUsers (GlobalVariable *GV,
195- function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
196- // A brief explanation of leak checkers. The goal is to find bugs where
197- // pointers are forgotten, causing an accumulating growth in memory
198- // usage over time. The common strategy for leak checkers is to explicitly
199- // allow the memory pointed to by globals at exit. This is popular because it
200- // also solves another problem where the main thread of a C++ program may shut
201- // down before other threads that are still expecting to use those globals. To
202- // handle that case, we expect the program may create a singleton and never
203- // destroy it.
204-
205- bool Changed = false ;
206-
207- // If Dead[n].first is the only use of a malloc result, we can delete its
208- // chain of computation and the store to the global in Dead[n].second.
209- SmallVector<std::pair<Instruction *, Instruction *>, 32 > Dead;
210-
211- SmallVector<User *> Worklist (GV->users ());
212- // Constants can't be pointers to dynamically allocated memory.
213- while (!Worklist.empty ()) {
214- User *U = Worklist.pop_back_val ();
215- if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
216- Value *V = SI->getValueOperand ();
217- if (isa<Constant>(V)) {
218- Changed = true ;
219- SI->eraseFromParent ();
220- } else if (Instruction *I = dyn_cast<Instruction>(V)) {
221- if (I->hasOneUse ())
222- Dead.push_back (std::make_pair (I, SI));
223- }
224- } else if (MemSetInst *MSI = dyn_cast<MemSetInst>(U)) {
225- if (isa<Constant>(MSI->getValue ())) {
226- Changed = true ;
227- MSI->eraseFromParent ();
228- } else if (Instruction *I = dyn_cast<Instruction>(MSI->getValue ())) {
229- if (I->hasOneUse ())
230- Dead.push_back (std::make_pair (I, MSI));
231- }
232- } else if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(U)) {
233- GlobalVariable *MemSrc = dyn_cast<GlobalVariable>(MTI->getSource ());
234- if (MemSrc && MemSrc->isConstant ()) {
235- Changed = true ;
236- MTI->eraseFromParent ();
237- } else if (Instruction *I = dyn_cast<Instruction>(MTI->getSource ())) {
238- if (I->hasOneUse ())
239- Dead.push_back (std::make_pair (I, MTI));
240- }
241- } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
242- if (isa<GEPOperator>(CE))
243- append_range (Worklist, CE->users ());
244- }
245- }
246-
247- for (int i = 0 , e = Dead.size (); i != e; ++i) {
248- if (IsSafeComputationToRemove (Dead[i].first , GetTLI)) {
249- Dead[i].second ->eraseFromParent ();
250- Instruction *I = Dead[i].first ;
251- do {
252- if (isAllocationFn (I, GetTLI))
253- break ;
254- Instruction *J = dyn_cast<Instruction>(I->getOperand (0 ));
255- if (!J)
256- break ;
257- I->eraseFromParent ();
258- I = J;
259- } while (true );
260- I->eraseFromParent ();
261- Changed = true ;
262- }
263- }
264-
265- GV->removeDeadConstantUsers ();
266- return Changed;
267- }
268-
269141// / We just marked GV constant. Loop over all users of the global, cleaning up
270142// / the obvious ones. This is largely just a quick scan over the use list to
271143// / clean up the easy and obvious cruft. This returns true if it made a change.
272- static bool CleanupConstantGlobalUsers (GlobalVariable *GV,
273- const DataLayout &DL) {
144+ static bool CleanupConstantGlobalUsers (
145+ GlobalVariable *GV, const DataLayout &DL,
146+ function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
274147 Constant *Init = GV->getInitializer ();
275148 SmallVector<User *, 8 > WorkList (GV->users ());
276149 SmallPtrSet<User *, 8 > Visited;
@@ -320,11 +193,30 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
320193 }
321194 }
322195 } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
323- // Store must be unreachable or storing Init into the global.
324- EraseFromParent (SI);
325- } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U)) { // memset/cpy/mv
326- if (getUnderlyingObject (MI->getRawDest ()) == GV)
327- EraseFromParent (MI);
196+ auto *V = SI->getValueOperand ();
197+ if (isa<Constant>(V)) {
198+ EraseFromParent (SI);
199+ } else if (isa<Instruction>(V)) {
200+ EraseFromParent (SI);
201+ if (IsSafeComputationToRemove (V, GetTLI))
202+ RecursivelyDeleteTriviallyDeadInstructions (V);
203+ } else if (isa<Argument>(V)) {
204+ if (!V->getType ()->isPointerTy ())
205+ EraseFromParent (SI);
206+ }
207+ } else if (auto *MSI = dyn_cast<MemSetInst>(U)) { // memset/cpy/mv
208+ if (getUnderlyingObject (MSI->getRawDest ()) == GV)
209+ EraseFromParent (MSI);
210+ } else if (auto *MTI = dyn_cast<MemTransferInst>(U)) {
211+ auto *Src = MTI->getRawSource ();
212+ auto *Dst = MTI->getRawDest ();
213+ if (getUnderlyingObject (Dst) != GV)
214+ continue ;
215+ if (isa<Instruction, Operator>(Src)) {
216+ EraseFromParent (MTI);
217+ if (IsSafeComputationToRemove (Src, GetTLI))
218+ RecursivelyDeleteTriviallyDeadInstructions (Src);
219+ }
328220 } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
329221 if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
330222 append_range (WorkList, II->users ());
@@ -872,12 +764,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(
872764 // If we nuked all of the loads, then none of the stores are needed either,
873765 // nor is the global.
874766 if (AllNonStoreUsesGone) {
875- if (isLeakCheckerRoot (GV)) {
876- Changed |= CleanupPointerRootUsers (GV, GetTLI);
877- } else {
878- Changed = true ;
879- CleanupConstantGlobalUsers (GV, DL);
880- }
767+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI);
881768 if (GV->use_empty ()) {
882769 LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
883770 Changed = true ;
@@ -1491,15 +1378,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
14911378 // Delete it now.
14921379 if (!GS.IsLoaded ) {
14931380 LLVM_DEBUG (dbgs () << " GLOBAL NEVER LOADED: " << *GV << " \n " );
1494-
1495- if (isLeakCheckerRoot (GV)) {
1496- // Delete any constant stores to the global.
1497- Changed = CleanupPointerRootUsers (GV, GetTLI);
1498- } else {
1499- // Delete any stores we can find to the global. We may not be able to
1500- // make it completely dead though.
1501- Changed = CleanupConstantGlobalUsers (GV, DL);
1502- }
1381+ Changed = CleanupConstantGlobalUsers (GV, DL, GetTLI);
15031382
15041383 // If the global is dead now, delete it.
15051384 if (GV->use_empty ()) {
@@ -1523,7 +1402,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15231402 }
15241403
15251404 // Clean up any obviously simplifiable users now.
1526- Changed |= CleanupConstantGlobalUsers (GV, DL);
1405+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI );
15271406
15281407 // If the global is dead now, just nuke it.
15291408 if (GV->use_empty ()) {
@@ -1578,7 +1457,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15781457 }
15791458
15801459 // Clean up any obviously simplifiable users now.
1581- CleanupConstantGlobalUsers (GV, DL);
1460+ CleanupConstantGlobalUsers (GV, DL, GetTLI );
15821461
15831462 if (GV->use_empty ()) {
15841463 LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments