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