Skip to content

Commit 7c973e5

Browse files
committed
[InstCombine] Collect users iteratively
This is an NFC patch to collect (indirect) users of an alloca non-recursively instead.
1 parent dea5aa7 commit 7c973e5

File tree

1 file changed

+56
-47
lines changed

1 file changed

+56
-47
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

+56-47
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,10 @@ class PointerReplacer {
244244
void replacePointer(Value *V);
245245

246246
private:
247-
bool collectUsersRecursive(Instruction &I);
248247
void replace(Instruction *I);
249248
Value *getReplacement(Value *I);
250249
bool isAvailable(Instruction *I) const {
251-
return I == &Root || Worklist.contains(I);
250+
return I == &Root || UsersToReplace.contains(I);
252251
}
253252

254253
bool isEqualOrValidAddrSpaceCast(const Instruction *I,
@@ -260,8 +259,7 @@ class PointerReplacer {
260259
return (FromAS == ToAS) || IC.isValidAddrSpaceCast(FromAS, ToAS);
261260
}
262261

263-
SmallPtrSet<Instruction *, 32> ValuesToRevisit;
264-
SmallSetVector<Instruction *, 4> Worklist;
262+
SmallSetVector<Instruction *, 4> UsersToReplace;
265263
MapVector<Value *, Value *> WorkMap;
266264
InstCombinerImpl &IC;
267265
Instruction &Root;
@@ -270,77 +268,88 @@ class PointerReplacer {
270268
} // end anonymous namespace
271269

272270
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 *, 4> 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+
}
280+
}
281+
};
281282

282-
bool PointerReplacer::collectUsersRecursive(Instruction &I) {
283-
for (auto *U : I.users()) {
284-
auto *Inst = cast<Instruction>(&*U);
283+
PushUsersToWorklist(&Root);
284+
while (!Worklist.empty()) {
285+
auto *Inst = Worklist.pop_back_val();
286+
if (!Inst)
287+
return false;
288+
if (isAvailable(Inst))
289+
continue;
285290
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
286291
if (Load->isVolatile())
287292
return false;
288-
Worklist.insert(Load);
293+
UsersToReplace.insert(Load);
289294
} else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
290295
// All incoming values must be instructions for replacability
291296
if (any_of(PHI->incoming_values(),
292297
[](Value *V) { return !isa<Instruction>(V); }))
293298
return false;
294299

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);
302306
continue;
303307
}
304308

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.insert(PHI))
311312
return false;
312313

313-
if (!isAvailable(cast<Instruction>(SI->getTrueValue())) ||
314-
!isAvailable(cast<Instruction>(SI->getFalseValue()))) {
315-
ValuesToRevisit.insert(Inst);
316-
continue;
314+
// Push PHI back into the stack, followed by unavailable
315+
// incoming values.
316+
Worklist.emplace_back(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.insert(IncomingValue))
322+
return false;
323+
Worklist.emplace_back(IncomingValue);
317324
}
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))
325+
} else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
326+
auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue());
327+
auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue());
328+
if (!TrueInst || !FalseInst)
324329
return false;
330+
331+
UsersToReplace.insert(SI);
332+
PushUsersToWorklist(SI);
333+
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
334+
UsersToReplace.insert(GEP);
335+
PushUsersToWorklist(GEP);
325336
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
326337
if (MI->isVolatile())
327338
return false;
328-
Worklist.insert(Inst);
339+
UsersToReplace.insert(Inst);
329340
} else if (isEqualOrValidAddrSpaceCast(Inst, FromAS)) {
330-
Worklist.insert(Inst);
331-
if (!collectUsersRecursive(*Inst))
332-
return false;
341+
UsersToReplace.insert(Inst);
342+
PushUsersToWorklist(Inst);
333343
} else if (Inst->isLifetimeStartOrEnd()) {
334344
continue;
335345
} else {
336346
// TODO: For arbitrary uses with address space mismatches, should we check
337347
// if we can introduce a valid addrspacecast?
338-
LLVM_DEBUG(dbgs() << "Cannot handle pointer user: " << *U << '\n');
348+
LLVM_DEBUG(dbgs() << "Cannot handle pointer user: " << *Inst << '\n');
339349
return false;
340350
}
341351
}
342-
343-
return true;
352+
return llvm::set_is_subset(ValuesToRevisit, UsersToReplace);
344353
}
345354

346355
Value *PointerReplacer::getReplacement(Value *V) { return WorkMap.lookup(V); }
@@ -443,7 +452,7 @@ void PointerReplacer::replacePointer(Value *V) {
443452
#endif
444453
WorkMap[&Root] = V;
445454

446-
for (Instruction *Workitem : Worklist)
455+
for (Instruction *Workitem : UsersToReplace)
447456
replace(Workitem);
448457
}
449458

0 commit comments

Comments
 (0)