@@ -185,78 +185,12 @@ static bool isSafeComputationToRemove(
185185 } while (true );
186186}
187187
188- /* *
189- * Cleans up pointer root users of a global variable.
190- *
191- * This function iterates over all users of the global variable and collects
192- * all stores and memtransfer instructions. It then erases all writes and
193- * removes computation chains if they are safe to remove. Finally, it removes
194- * dead constant users of the global variable.
195- *
196- * @param GV The global variable to clean up.
197- * @param GetTLI A function reference to obtain the TargetLibraryInfo for a
198- * given function.
199- * @return True if any changes were made, false otherwise.
200- */
201- static bool
202- cleanupPointerRootUsers (GlobalVariable *GV,
203- function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
204- // A brief explanation of leak checkers. The goal is to find bugs where
205- // pointers are forgotten, causing an accumulating growth in memory
206- // usage over time. The common strategy for leak checkers is to explicitly
207- // allow the memory pointed to by globals at exit. This is popular because it
208- // also solves another problem where the main thread of a C++ program may shut
209- // down before other threads that are still expecting to use those globals. To
210- // handle that case, we expect the program may create a singleton and never
211- // destroy it.
212-
213- bool Changed = false ;
214-
215- // Iterate over all users of the global and collect all
216- // stores, memtransfer and memset instructions.
217- SmallVector<std::pair<Instruction *, Value *>> Writes;
218- SmallVector<User *> Worklist (GV->users ());
219- while (!Worklist.empty ()) {
220- User *U = Worklist.pop_back_val ();
221- if (auto *SI = dyn_cast<StoreInst>(U)) {
222- Writes.push_back ({SI, SI->getValueOperand ()});
223- } else if (auto *CE = dyn_cast<ConstantExpr>(U)) {
224- if (isa<GEPOperator>(CE)) {
225- append_range (Worklist, CE->users ());
226- }
227- } else if (auto *MTI = dyn_cast<MemTransferInst>(U)) {
228- if (MTI->getRawDest () == GV) {
229- Writes.push_back ({MTI, MTI->getSource ()});
230- }
231- } else if (auto *MSI = dyn_cast<MemSetInst>(U)) {
232- if (MSI->getRawDest () == GV) {
233- Writes.push_back ({MSI, MSI->getValue ()});
234- }
235- }
236- }
237-
238- // Finally, erase all writes and remove computation chains if they are safe
239- // to remove.
240- for (auto [WriteInst, V] : Writes) {
241- if (isa<Constant>(V) || isa<Instruction>(V))
242- WriteInst->eraseFromParent ();
243-
244- if (auto *Inst = dyn_cast<Instruction>(V)) {
245- if (isSafeComputationToRemove (V, GetTLI))
246- RecursivelyDeleteTriviallyDeadInstructions (V);
247- Changed = true ;
248- }
249- }
250-
251- GV->removeDeadConstantUsers ();
252- return Changed;
253- }
254-
255188// / We just marked GV constant. Loop over all users of the global, cleaning up
256189// / the obvious ones. This is largely just a quick scan over the use list to
257190// / clean up the easy and obvious cruft. This returns true if it made a change.
258- static bool CleanupConstantGlobalUsers (GlobalVariable *GV,
259- const DataLayout &DL) {
191+ static bool cleanupConstantGlobalUsers (GlobalVariable *GV,
192+ const DataLayout &DL,
193+ function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
260194 Constant *Init = GV->getInitializer ();
261195 SmallVector<User *, 8 > WorkList (GV->users ());
262196 SmallPtrSet<User *, 8 > Visited;
@@ -306,11 +240,30 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
306240 }
307241 }
308242 } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
309- // Store must be unreachable or storing Init into the global.
310- EraseFromParent (SI);
311- } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(U)) { // memset/cpy/mv
312- if (getUnderlyingObject (MI->getRawDest ()) == GV)
313- EraseFromParent (MI);
243+ auto *V = SI->getValueOperand ();
244+ if (isa<Constant>(V)) {
245+ EraseFromParent (SI);
246+ } else if (isa<Instruction>(V)) {
247+ EraseFromParent (SI);
248+ if (isSafeComputationToRemove (V, GetTLI))
249+ RecursivelyDeleteTriviallyDeadInstructions (V);
250+ } else if (isa<Argument>(V)) {
251+ if (!V->getType ()->isPointerTy ())
252+ EraseFromParent (SI);
253+ }
254+ } else if (auto *MSI = dyn_cast<MemSetInst>(U)) { // memset/cpy/mv
255+ if (getUnderlyingObject (MSI->getRawDest ()) == GV)
256+ EraseFromParent (MSI);
257+ } else if (auto *MTI = dyn_cast<MemTransferInst>(U)) {
258+ auto *Src = MTI->getRawSource ();
259+ auto *Dst = MTI->getRawDest ();
260+ if (getUnderlyingObject (Dst) != GV)
261+ continue ;
262+ if (isa<Instruction, Operator>(Src)) {
263+ EraseFromParent (MTI);
264+ if (isSafeComputationToRemove (Src, GetTLI))
265+ RecursivelyDeleteTriviallyDeadInstructions (Src);
266+ }
314267 } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
315268 if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
316269 append_range (WorkList, II->users ());
@@ -857,12 +810,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(
857810 // If we nuked all of the loads, then none of the stores are needed either,
858811 // nor is the global.
859812 if (AllNonStoreUsesGone) {
860- if (isLeakCheckerRoot (GV)) {
861- Changed |= cleanupPointerRootUsers (GV, GetTLI);
862- } else {
863- Changed = true ;
864- CleanupConstantGlobalUsers (GV, DL);
865- }
813+ Changed |= cleanupConstantGlobalUsers (GV, DL, GetTLI);
866814 if (GV->use_empty ()) {
867815 LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
868816 Changed = true ;
@@ -1481,15 +1429,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
14811429 // Delete it now.
14821430 if (!GS.IsLoaded ) {
14831431 LLVM_DEBUG (dbgs () << " GLOBAL NEVER LOADED: " << *GV << " \n " );
1484-
1485- if (isLeakCheckerRoot (GV)) {
1486- // Delete any constant stores to the global.
1487- Changed = cleanupPointerRootUsers (GV, GetTLI);
1488- } else {
1489- // Delete any stores we can find to the global. We may not be able to
1490- // make it completely dead though.
1491- Changed = CleanupConstantGlobalUsers (GV, DL);
1492- }
1432+ Changed = cleanupConstantGlobalUsers (GV, DL, GetTLI);
14931433
14941434 // If the global is dead now, delete it.
14951435 if (GV->use_empty ()) {
@@ -1513,7 +1453,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15131453 }
15141454
15151455 // Clean up any obviously simplifiable users now.
1516- Changed |= CleanupConstantGlobalUsers (GV, DL);
1456+ Changed |= cleanupConstantGlobalUsers (GV, DL, GetTLI );
15171457
15181458 // If the global is dead now, just nuke it.
15191459 if (GV->use_empty ()) {
@@ -1568,7 +1508,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
15681508 }
15691509
15701510 // Clean up any obviously simplifiable users now.
1571- CleanupConstantGlobalUsers (GV, DL);
1511+ cleanupConstantGlobalUsers (GV, DL, GetTLI );
15721512
15731513 if (GV->use_empty ()) {
15741514 LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments