13
13
#include " InstCombineInternal.h"
14
14
#include " llvm/ADT/MapVector.h"
15
15
#include " llvm/ADT/SetOperations.h"
16
+ #include " llvm/ADT/SetVector.h"
16
17
#include " llvm/ADT/SmallString.h"
17
18
#include " llvm/ADT/Statistic.h"
18
19
#include " llvm/Analysis/AliasAnalysis.h"
24
25
#include " llvm/IR/PatternMatch.h"
25
26
#include " llvm/Transforms/InstCombine/InstCombiner.h"
26
27
#include " llvm/Transforms/Utils/Local.h"
28
+ #include < stack>
27
29
using namespace llvm ;
28
30
using namespace PatternMatch ;
29
31
@@ -244,11 +246,10 @@ class PointerReplacer {
244
246
void replacePointer (Value *V);
245
247
246
248
private:
247
- bool collectUsersRecursive (Instruction &I);
248
249
void replace (Instruction *I);
249
250
Value *getReplacement (Value *I);
250
251
bool isAvailable (Instruction *I) const {
251
- return I == &Root || Worklist .contains (I);
252
+ return I == &Root || UsersToReplace .contains (I);
252
253
}
253
254
254
255
bool isEqualOrValidAddrSpaceCast (const Instruction *I,
@@ -260,8 +261,7 @@ class PointerReplacer {
260
261
return (FromAS == ToAS) || IC.isValidAddrSpaceCast (FromAS, ToAS);
261
262
}
262
263
263
- SmallPtrSet<Instruction *, 32 > ValuesToRevisit;
264
- SmallSetVector<Instruction *, 4 > Worklist;
264
+ SmallSetVector<Instruction *, 4 > UsersToReplace;
265
265
MapVector<Value *, Value *> WorkMap;
266
266
InstCombinerImpl &IC;
267
267
Instruction &Root;
@@ -270,77 +270,87 @@ class PointerReplacer {
270
270
} // end anonymous namespace
271
271
272
272
bool PointerReplacer::collectUsers () {
273
- if (! collectUsersRecursive (Root))
274
- return false ;
273
+ std::stack<User *> Worklist;
274
+ SmallSetVector<Instruction *, 4 > ValuesToRevisit ;
275
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
- }
276
+ auto PushUsersToWorklist = [&](Instruction *Inst) {
277
+ for ( auto *U : Inst-> users ())
278
+ if (isa<Instruction>(U) && ! isAvailable (cast<Instruction>(U)))
279
+ Worklist. push (U );
280
+ };
281
281
282
- bool PointerReplacer::collectUsersRecursive (Instruction &I) {
283
- for (auto *U : I.users ()) {
284
- auto *Inst = cast<Instruction>(&*U);
282
+ PushUsersToWorklist (&Root);
283
+ while (!Worklist.empty ()) {
284
+ auto *Inst = dyn_cast<Instruction>(Worklist.top ());
285
+ Worklist.pop ();
286
+ if (!Inst)
287
+ return false ;
288
+ if (isAvailable (Inst))
289
+ continue ;
285
290
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
286
291
if (Load->isVolatile ())
287
292
return false ;
288
- Worklist .insert (Load);
293
+ UsersToReplace .insert (Load);
289
294
} else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
290
295
// All incoming values must be instructions for replacability
291
296
if (any_of (PHI->incoming_values (),
292
297
[](Value *V) { return !isa<Instruction>(V); }))
293
298
return false ;
294
299
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));
300
- })) {
301
- ValuesToRevisit.insert (Inst);
300
+ // If all incoming values are available, mark this PHI as
301
+ // replacable and push it's users into the worklist.
302
+ if (all_of (PHI->incoming_values (),
303
+ [&](Value *V) { return isAvailable (cast<Instruction>(V)); })) {
304
+ UsersToReplace.insert (PHI);
305
+ PushUsersToWorklist (PHI);
302
306
continue ;
303
307
}
304
308
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 ()))
309
+ // Not all incoming values are available. If this PHI was already
310
+ // visited prior to this iteration, return false.
311
+ if (ValuesToRevisit.contains (PHI))
311
312
return false ;
312
313
313
- if (!isAvailable (cast<Instruction>(SI->getTrueValue ())) ||
314
- !isAvailable (cast<Instruction>(SI->getFalseValue ()))) {
315
- ValuesToRevisit.insert (Inst);
316
- continue ;
314
+ // Revisit PHI, after all it's incoming values have been visited.
315
+ Worklist.push (PHI);
316
+ ValuesToRevisit.insert (PHI);
317
+ for (unsigned Idx = 0 ; Idx < PHI->getNumIncomingValues (); ++Idx) {
318
+ auto *IncomingValue = cast<Instruction>(PHI->getIncomingValue (Idx));
319
+ if (UsersToReplace.contains (IncomingValue))
320
+ continue ;
321
+ if (ValuesToRevisit.contains (IncomingValue))
322
+ return false ;
323
+ ValuesToRevisit.insert (IncomingValue);
324
+ Worklist.push (IncomingValue);
317
325
}
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))
326
+ } else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
327
+ auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue ());
328
+ auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue ());
329
+ if (!TrueInst || !FalseInst)
324
330
return false ;
331
+
332
+ UsersToReplace.insert (SI);
333
+ PushUsersToWorklist (SI);
334
+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
335
+ UsersToReplace.insert (GEP);
336
+ PushUsersToWorklist (GEP);
325
337
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
326
338
if (MI->isVolatile ())
327
339
return false ;
328
- Worklist .insert (Inst);
340
+ UsersToReplace .insert (Inst);
329
341
} else if (isEqualOrValidAddrSpaceCast (Inst, FromAS)) {
330
- Worklist.insert (Inst);
331
- if (!collectUsersRecursive (*Inst))
332
- return false ;
342
+ UsersToReplace.insert (Inst);
343
+ PushUsersToWorklist (Inst);
333
344
} else if (Inst->isLifetimeStartOrEnd ()) {
334
345
continue ;
335
346
} else {
336
347
// TODO: For arbitrary uses with address space mismatches, should we check
337
348
// if we can introduce a valid addrspacecast?
338
- LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *U << ' \n ' );
349
+ LLVM_DEBUG (dbgs () << " Cannot handle pointer user: " << *Inst << ' \n ' );
339
350
return false ;
340
351
}
341
352
}
342
-
343
- return true ;
353
+ return llvm::set_is_subset (ValuesToRevisit, UsersToReplace);
344
354
}
345
355
346
356
Value *PointerReplacer::getReplacement (Value *V) { return WorkMap.lookup (V); }
@@ -443,7 +453,7 @@ void PointerReplacer::replacePointer(Value *V) {
443
453
#endif
444
454
WorkMap[&Root] = V;
445
455
446
- for (Instruction *Workitem : Worklist )
456
+ for (Instruction *Workitem : UsersToReplace )
447
457
replace (Workitem);
448
458
}
449
459
0 commit comments