@@ -114,55 +114,6 @@ static cl::opt<int> ColdCCRelFreq(
114
114
" entry frequency, for a call site to be considered cold for enabling "
115
115
" coldcc" ));
116
116
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
-
166
117
// / Given a value that is stored to a global but never read, determine whether
167
118
// / it's safe to remove the store and the chain of computation that feeds the
168
119
// / store.
@@ -171,7 +122,7 @@ static bool IsSafeComputationToRemove(
171
122
do {
172
123
if (isa<Constant>(V))
173
124
return true ;
174
- if (! V->hasOneUse ( ))
125
+ if (V->hasNUsesOrMore ( 1 ))
175
126
return false ;
176
127
if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
177
128
isa<GlobalValue>(V))
@@ -193,90 +144,12 @@ static bool IsSafeComputationToRemove(
193
144
} while (true );
194
145
}
195
146
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
-
275
147
// / We just marked GV constant. Loop over all users of the global, cleaning up
276
148
// / the obvious ones. This is largely just a quick scan over the use list to
277
149
// / 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) {
280
153
Constant *Init = GV->getInitializer ();
281
154
SmallVector<User *, 8 > WorkList (GV->users ());
282
155
SmallPtrSet<User *, 8 > Visited;
@@ -326,11 +199,30 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
326
199
}
327
200
}
328
201
} 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
+ }
334
226
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
335
227
if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
336
228
append_range (WorkList, II->users ());
@@ -878,12 +770,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(
878
770
// If we nuked all of the loads, then none of the stores are needed either,
879
771
// nor is the global.
880
772
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);
887
774
if (GV->use_empty ()) {
888
775
LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
889
776
Changed = true ;
@@ -1497,15 +1384,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1497
1384
// Delete it now.
1498
1385
if (!GS.IsLoaded ) {
1499
1386
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);
1509
1388
1510
1389
// If the global is dead now, delete it.
1511
1390
if (GV->use_empty ()) {
@@ -1529,7 +1408,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1529
1408
}
1530
1409
1531
1410
// Clean up any obviously simplifiable users now.
1532
- Changed |= CleanupConstantGlobalUsers (GV, DL);
1411
+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI );
1533
1412
1534
1413
// If the global is dead now, just nuke it.
1535
1414
if (GV->use_empty ()) {
@@ -1584,7 +1463,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1584
1463
}
1585
1464
1586
1465
// Clean up any obviously simplifiable users now.
1587
- CleanupConstantGlobalUsers (GV, DL);
1466
+ CleanupConstantGlobalUsers (GV, DL, GetTLI );
1588
1467
1589
1468
if (GV->use_empty ()) {
1590
1469
LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments