@@ -243,11 +243,10 @@ class PointerReplacer {
243
243
void replacePointer (Value *V);
244
244
245
245
private:
246
- bool collectUsersRecursive (Instruction &I);
247
246
void replace (Instruction *I);
248
- Value *getReplacement (Value *I);
247
+ Value *getReplacement (Value *V) const { return WorkMap. lookup (V); }
249
248
bool isAvailable (Instruction *I) const {
250
- return I == &Root || Worklist .contains (I);
249
+ return I == &Root || UsersToReplace .contains (I);
251
250
}
252
251
253
252
bool isEqualOrValidAddrSpaceCast (const Instruction *I,
@@ -259,8 +258,7 @@ class PointerReplacer {
259
258
return (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
260
259
}
261
260
262
- SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
263
- SmallSetVector<Instruction *, 4 > Worklist;
261
+ SmallSetVector<Instruction *, 32 > UsersToReplace;
264
262
MapVector<Value *, Value *> WorkMap;
265
263
InstCombinerImpl &IC;
266
264
Instruction &Root;
@@ -269,80 +267,119 @@ class PointerReplacer {
269
267
} // end anonymous namespace
270
268
271
269
bool PointerReplacer::collectUsers () {
272
- if (!collectUsersRecursive (Root))
273
- return false ;
274
-
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
- }
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
+ };
280
279
281
- bool PointerReplacer::collectUsersRecursive (Instruction &I) {
282
- for ( auto *U : I. users ()) {
283
- auto *Inst = cast<Instruction>(&*U );
280
+ PushUsersToWorklist (&Root);
281
+ while (!Worklist. empty ()) {
282
+ Instruction *Inst = Worklist. pop_back_val ( );
284
283
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
285
284
if (Load->isVolatile ())
286
285
return false ;
287
- Worklist .insert (Load);
286
+ UsersToReplace .insert (Load);
288
287
} else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
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));
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));
299
296
})) {
300
- ValuesToRevisit.insert (Inst);
297
+ UsersToReplace.insert (PHI);
298
+ PushUsersToWorklist (PHI);
301
299
continue ;
302
300
}
303
301
304
- Worklist.insert (PHI);
305
- if (!collectUsersRecursive (*PHI))
306
- return false ;
307
- } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
308
- if (!isa<Instruction>(SI->getTrueValue ()) ||
309
- !isa<Instruction>(SI->getFalseValue ()))
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))
310
306
return false ;
311
307
312
- if (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
313
- !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
314
- ValuesToRevisit.insert (Inst);
315
- continue ;
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);
316
318
}
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))
319
+ } 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)
323
323
return false ;
324
+
325
+ UsersToReplace.insert (SI);
326
+ PushUsersToWorklist (SI);
327
+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
328
+ UsersToReplace.insert (GEP);
329
+ PushUsersToWorklist (GEP);
324
330
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
325
331
if (MI->isVolatile ())
326
332
return false ;
327
- Worklist .insert (Inst);
333
+ UsersToReplace .insert (Inst);
328
334
} else if (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
329
- Worklist.insert (Inst);
330
- if (!collectUsersRecursive (*Inst))
331
- return false ;
335
+ UsersToReplace.insert (Inst);
336
+ PushUsersToWorklist (Inst);
332
337
} else if (Inst->isLifetimeStartOrEnd ()) {
333
338
continue ;
334
339
} else {
335
340
// TODO: For arbitrary uses with address space mismatches, should we check
336
341
// if we can introduce a valid addrspacecast?
337
- LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *U << ' \n ' );
342
+ LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *Inst << ' \n ' );
338
343
return false ;
339
344
}
340
345
}
341
346
342
347
return true ;
343
348
}
344
349
345
- Value *PointerReplacer::getReplacement (Value *V) { return WorkMap.lookup (V); }
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
+ }
346
383
347
384
void PointerReplacer::replace (Instruction *I) {
348
385
if (getReplacement (I))
@@ -364,13 +401,15 @@ void PointerReplacer::replace(Instruction *I) {
364
401
// replacement (new value).
365
402
WorkMap[NewI] = NewI;
366
403
} else if (auto *PHI = dyn_cast<PHINode>(I)) {
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;
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;
374
413
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
375
414
auto *V = getReplacement (GEP->getPointerOperand ());
376
415
assert (V && " Operand not replaced" );
@@ -434,18 +473,6 @@ void PointerReplacer::replace(Instruction *I) {
434
473
}
435
474
}
436
475
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
-
449
476
Instruction *InstCombinerImpl::visitAllocaInst (AllocaInst &AI) {
450
477
if (auto *I = simplifyAllocaArraySize (*this , AI, DT))
451
478
return I;
0 commit comments