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