@@ -108,55 +108,6 @@ static cl::opt<int> ColdCCRelFreq(
108
108
" entry frequency, for a call site to be considered cold for enabling"
109
109
" coldcc" ));
110
110
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
-
160
111
// / Given a value that is stored to a global but never read, determine whether
161
112
// / it's safe to remove the store and the chain of computation that feeds the
162
113
// / store.
@@ -165,7 +116,7 @@ static bool IsSafeComputationToRemove(
165
116
do {
166
117
if (isa<Constant>(V))
167
118
return true ;
168
- if (! V->hasOneUse ( ))
119
+ if (V->hasNUsesOrMore ( 1 ))
169
120
return false ;
170
121
if (isa<LoadInst>(V) || isa<InvokeInst>(V) || isa<Argument>(V) ||
171
122
isa<GlobalValue>(V))
@@ -187,90 +138,12 @@ static bool IsSafeComputationToRemove(
187
138
} while (true );
188
139
}
189
140
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
-
269
141
// / We just marked GV constant. Loop over all users of the global, cleaning up
270
142
// / the obvious ones. This is largely just a quick scan over the use list to
271
143
// / 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) {
274
147
Constant *Init = GV->getInitializer ();
275
148
SmallVector<User *, 8 > WorkList (GV->users ());
276
149
SmallPtrSet<User *, 8 > Visited;
@@ -320,11 +193,30 @@ static bool CleanupConstantGlobalUsers(GlobalVariable *GV,
320
193
}
321
194
}
322
195
} 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
+ }
328
220
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
329
221
if (II->getIntrinsicID () == Intrinsic::threadlocal_address)
330
222
append_range (WorkList, II->users ());
@@ -872,12 +764,7 @@ static bool OptimizeAwayTrappingUsesOfLoads(
872
764
// If we nuked all of the loads, then none of the stores are needed either,
873
765
// nor is the global.
874
766
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);
881
768
if (GV->use_empty ()) {
882
769
LLVM_DEBUG (dbgs () << " *** GLOBAL NOW DEAD!\n " );
883
770
Changed = true ;
@@ -1491,15 +1378,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1491
1378
// Delete it now.
1492
1379
if (!GS.IsLoaded ) {
1493
1380
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);
1503
1382
1504
1383
// If the global is dead now, delete it.
1505
1384
if (GV->use_empty ()) {
@@ -1523,7 +1402,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1523
1402
}
1524
1403
1525
1404
// Clean up any obviously simplifiable users now.
1526
- Changed |= CleanupConstantGlobalUsers (GV, DL);
1405
+ Changed |= CleanupConstantGlobalUsers (GV, DL, GetTLI );
1527
1406
1528
1407
// If the global is dead now, just nuke it.
1529
1408
if (GV->use_empty ()) {
@@ -1578,7 +1457,7 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS,
1578
1457
}
1579
1458
1580
1459
// Clean up any obviously simplifiable users now.
1581
- CleanupConstantGlobalUsers (GV, DL);
1460
+ CleanupConstantGlobalUsers (GV, DL, GetTLI );
1582
1461
1583
1462
if (GV->use_empty ()) {
1584
1463
LLVM_DEBUG (dbgs () << " *** Substituting initializer allowed us to "
0 commit comments