@@ -243,10 +243,11 @@ class PointerReplacer {
243
243
void replacePointer (Value *V);
244
244
245
245
private:
246
+ bool collectUsersRecursive (Instruction &I);
246
247
void replace (Instruction *I);
247
- Value *getReplacement (Value *V) const { return WorkMap. lookup (V); }
248
+ Value *getReplacement (Value *I);
248
249
bool isAvailable (Instruction *I) const {
249
- return I == &Root || UsersToReplace .contains (I);
250
+ return I == &Root || Worklist .contains (I);
250
251
}
251
252
252
253
bool isEqualOrValidAddrSpaceCast (const Instruction *I,
@@ -258,7 +259,8 @@ class PointerReplacer {
258
259
return (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
259
260
}
260
261
261
- SmallSetVector<Instruction *, 32 > UsersToReplace;
262
+ SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
263
+ SmallSetVector<Instruction *, 4 > Worklist;
262
264
MapVector<Value *, Value *> WorkMap;
263
265
InstCombinerImpl &IC;
264
266
Instruction &Root;
@@ -267,119 +269,80 @@ class PointerReplacer {
267
269
} // end anonymous namespace
268
270
269
271
bool PointerReplacer::collectUsers () {
270
- SmallVector<Instruction *> Worklist;
271
- SmallSetVector<Instruction *, 32 > ValuesToRevisit;
272
-
273
- auto PushUsersToWorklist = [&](Instruction *Inst) {
274
- for (auto *U : Inst->users ())
275
- if (auto *I = dyn_cast<Instruction>(U))
276
- if (!isAvailable (I) && !ValuesToRevisit.contains (I))
277
- Worklist.emplace_back (I);
278
- };
272
+ if (!collectUsersRecursive (Root))
273
+ return false ;
279
274
280
- PushUsersToWorklist (&Root);
281
- while (!Worklist.empty ()) {
282
- Instruction *Inst = Worklist.pop_back_val ();
275
+ // Ensure that all outstanding (indirect) users of I
276
+ // are inserted into the Worklist. Return false
277
+ // otherwise.
278
+ return llvm::set_is_subset (ValuesToRevisit, Worklist);
279
+ }
280
+
281
+ bool PointerReplacer::collectUsersRecursive (Instruction &I) {
282
+ for (auto *U : I.users ()) {
283
+ auto *Inst = cast<Instruction>(&*U);
283
284
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
284
285
if (Load->isVolatile ())
285
286
return false ;
286
- UsersToReplace .insert (Load);
287
+ Worklist .insert (Load);
287
288
} else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
288
- // / TODO: Handle poison and null pointers for PHI and select.
289
- // If all incoming values are available, mark this PHI as
290
- // replacable and push it's users into the worklist.
291
- bool IsReplacable = true ;
292
- if (all_of (PHI->incoming_values (), [&](Value *V) {
293
- if (!isa<Instruction>(V))
294
- return IsReplacable = false ;
295
- return isAvailable (cast<Instruction>(V));
289
+ // All incoming values must be instructions for replacability
290
+ if (any_of (PHI->incoming_values (),
291
+ [](Value *V) { return !isa<Instruction>(V); }))
292
+ return false ;
293
+
294
+ // If at least one incoming value of the PHI is not in Worklist,
295
+ // store the PHI for revisiting and skip this iteration of the
296
+ // loop.
297
+ if (any_of (PHI->incoming_values (), [this ](Value *V) {
298
+ return !isAvailable (cast<Instruction>(V));
296
299
})) {
297
- UsersToReplace.insert (PHI);
298
- PushUsersToWorklist (PHI);
300
+ ValuesToRevisit.insert (Inst);
299
301
continue ;
300
302
}
301
303
302
- // Either an incoming value is not an instruction or not all
303
- // incoming values are available. If this PHI was already
304
- // visited prior to this iteration, return false.
305
- if (!IsReplacable || !ValuesToRevisit.insert (PHI))
304
+ Worklist.insert (PHI);
305
+ if (!collectUsersRecursive (*PHI))
306
306
return false ;
307
-
308
- // Push PHI back into the stack, followed by unavailable
309
- // incoming values.
310
- Worklist.emplace_back (PHI);
311
- for (unsigned Idx = 0 ; Idx < PHI->getNumIncomingValues (); ++Idx) {
312
- auto *IncomingValue = cast<Instruction>(PHI->getIncomingValue (Idx));
313
- if (UsersToReplace.contains (IncomingValue))
314
- continue ;
315
- if (!ValuesToRevisit.insert (IncomingValue))
316
- return false ;
317
- Worklist.emplace_back (IncomingValue);
318
- }
319
307
} else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
320
- auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue ());
321
- auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue ());
322
- if (!TrueInst || !FalseInst)
308
+ if (!isa<Instruction>(SI->getTrueValue ()) ||
309
+ !isa<Instruction>(SI->getFalseValue ()))
323
310
return false ;
324
311
325
- UsersToReplace.insert (SI);
326
- PushUsersToWorklist (SI);
327
- } else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
328
- UsersToReplace.insert (GEP);
329
- PushUsersToWorklist (GEP);
312
+ if (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
313
+ !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
314
+ ValuesToRevisit.insert (Inst);
315
+ continue ;
316
+ }
317
+ Worklist.insert (SI);
318
+ if (!collectUsersRecursive (*SI))
319
+ return false ;
320
+ } else if (isa<GetElementPtrInst>(Inst)) {
321
+ Worklist.insert (Inst);
322
+ if (!collectUsersRecursive (*Inst))
323
+ return false ;
330
324
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
331
325
if (MI->isVolatile ())
332
326
return false ;
333
- UsersToReplace .insert (Inst);
327
+ Worklist .insert (Inst);
334
328
} else if (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
335
- UsersToReplace.insert (Inst);
336
- PushUsersToWorklist (Inst);
329
+ Worklist.insert (Inst);
330
+ if (!collectUsersRecursive (*Inst))
331
+ return false ;
337
332
} else if (Inst->isLifetimeStartOrEnd ()) {
338
333
continue ;
339
334
} else {
340
335
// TODO: For arbitrary uses with address space mismatches, should we check
341
336
// if we can introduce a valid addrspacecast?
342
- LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *Inst << ' \n ' );
337
+ LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *U << ' \n ' );
343
338
return false ;
344
339
}
345
340
}
346
341
347
342
return true ;
348
343
}
349
344
350
- void PointerReplacer::replacePointer (Value *V) {
351
- assert (cast<PointerType>(Root.getType ()) != cast<PointerType>(V->getType ()) &&
352
- " Invalid usage" );
353
- WorkMap[&Root] = V;
354
- SmallVector<Instruction *> Worklist;
355
- SetVector<Instruction *> PostOrderWorklist;
356
- SmallPtrSet<Instruction *, 32 > Visited;
357
-
358
- // Perform a postorder traversal of the users of Root.
359
- Worklist.push_back (&Root);
360
- while (!Worklist.empty ()) {
361
- Instruction *I = Worklist.back ();
362
-
363
- // If I has not been processed before, push each of its
364
- // replacable users into the worklist.
365
- if (Visited.insert (I).second ) {
366
- for (auto *U : I->users ()) {
367
- auto *UserInst = cast<Instruction>(U);
368
- if (UsersToReplace.contains (UserInst))
369
- Worklist.push_back (UserInst);
370
- }
371
- // Otherwise, users of I have already been pushed into
372
- // the PostOrderWorklist. Push I as well.
373
- } else {
374
- PostOrderWorklist.insert (I);
375
- Worklist.pop_back ();
376
- }
377
- }
378
-
379
- // Replace pointers in reverse-postorder.
380
- for (Instruction *I : reverse (PostOrderWorklist))
381
- replace (I);
382
- }
345
+ Value *PointerReplacer::getReplacement (Value *V) { return WorkMap.lookup (V); }
383
346
384
347
void PointerReplacer::replace (Instruction *I) {
385
348
if (getReplacement (I))
@@ -401,15 +364,13 @@ void PointerReplacer::replace(Instruction *I) {
401
364
// replacement (new value).
402
365
WorkMap[NewI] = NewI;
403
366
} else if (auto *PHI = dyn_cast<PHINode>(I)) {
404
- // Create a new PHI by replacing any incoming value that is a user of the
405
- // root pointer and has a replacement.
406
- Value *V = WorkMap.lookup (PHI->getIncomingValue (0 ));
407
- PHI->mutateType (V ? V->getType () : PHI->getIncomingValue (0 )->getType ());
408
- for (unsigned int I = 0 ; I < PHI->getNumIncomingValues (); ++I) {
409
- Value *V = WorkMap.lookup (PHI->getIncomingValue (I));
410
- PHI->setIncomingValue (I, V ? V : PHI->getIncomingValue (I));
411
- }
412
- WorkMap[PHI] = PHI;
367
+ Type *NewTy = getReplacement (PHI->getIncomingValue (0 ))->getType ();
368
+ auto *NewPHI = PHINode::Create (NewTy, PHI->getNumIncomingValues (),
369
+ PHI->getName (), PHI->getIterator ());
370
+ for (unsigned int I = 0 ; I < PHI->getNumIncomingValues (); ++I)
371
+ NewPHI->addIncoming (getReplacement (PHI->getIncomingValue (I)),
372
+ PHI->getIncomingBlock (I));
373
+ WorkMap[PHI] = NewPHI;
413
374
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
414
375
auto *V = getReplacement (GEP->getPointerOperand ());
415
376
assert (V && " Operand not replaced" );
@@ -473,6 +434,18 @@ void PointerReplacer::replace(Instruction *I) {
473
434
}
474
435
}
475
436
437
+ void PointerReplacer::replacePointer (Value *V) {
438
+ #ifndef NDEBUG
439
+ auto *PT = cast<PointerType>(Root.getType ());
440
+ auto *NT = cast<PointerType>(V->getType ());
441
+ assert (PT != NT && " Invalid usage" );
442
+ #endif
443
+ WorkMap[&Root] = V;
444
+
445
+ for (Instruction *Workitem : Worklist)
446
+ replace (Workitem);
447
+ }
448
+
476
449
Instruction *InstCombinerImpl::visitAllocaInst (AllocaInst &AI) {
477
450
if (auto *I = simplifyAllocaArraySize (*this , AI, DT))
478
451
return I;
0 commit comments