Skip to content

Commit c62a613

Browse files
authored
Revert "[InstCombine] Iterative replacement in PtrReplacer" (#144394)
Reverts #137215 This commit caused a failure in the LLVM CI: https://lab.llvm.org/buildbot/#/builders/10/builds/7442
1 parent a733c6c commit c62a613

File tree

2 files changed

+69
-175
lines changed

2 files changed

+69
-175
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 69 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,11 @@ class PointerReplacer {
243243
void replacePointer(Value *V);
244244

245245
private:
246+
bool collectUsersRecursive(Instruction &I);
246247
void replace(Instruction *I);
247-
Value *getReplacement(Value *V) const { return WorkMap.lookup(V); }
248+
Value *getReplacement(Value *I);
248249
bool isAvailable(Instruction *I) const {
249-
return I == &Root || UsersToReplace.contains(I);
250+
return I == &Root || Worklist.contains(I);
250251
}
251252

252253
bool isEqualOrValidAddrSpaceCast(const Instruction *I,
@@ -258,7 +259,8 @@ class PointerReplacer {
258259
return (FromAS == ToAS) || IC.isValidAddrSpaceCast(FromAS, ToAS);
259260
}
260261

261-
SmallSetVector<Instruction *, 32> UsersToReplace;
262+
SmallPtrSet<Instruction *, 32> ValuesToRevisit;
263+
SmallSetVector<Instruction *, 4> Worklist;
262264
MapVector<Value *, Value *> WorkMap;
263265
InstCombinerImpl &IC;
264266
Instruction &Root;
@@ -267,119 +269,80 @@ class PointerReplacer {
267269
} // end anonymous namespace
268270

269271
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;
279274

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);
283284
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
284285
if (Load->isVolatile())
285286
return false;
286-
UsersToReplace.insert(Load);
287+
Worklist.insert(Load);
287288
} 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));
296299
})) {
297-
UsersToReplace.insert(PHI);
298-
PushUsersToWorklist(PHI);
300+
ValuesToRevisit.insert(Inst);
299301
continue;
300302
}
301303

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))
306306
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-
}
319307
} 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()))
323310
return false;
324311

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;
330324
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
331325
if (MI->isVolatile())
332326
return false;
333-
UsersToReplace.insert(Inst);
327+
Worklist.insert(Inst);
334328
} else if (isEqualOrValidAddrSpaceCast(Inst, FromAS)) {
335-
UsersToReplace.insert(Inst);
336-
PushUsersToWorklist(Inst);
329+
Worklist.insert(Inst);
330+
if (!collectUsersRecursive(*Inst))
331+
return false;
337332
} else if (Inst->isLifetimeStartOrEnd()) {
338333
continue;
339334
} else {
340335
// TODO: For arbitrary uses with address space mismatches, should we check
341336
// 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');
343338
return false;
344339
}
345340
}
346341

347342
return true;
348343
}
349344

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); }
383346

384347
void PointerReplacer::replace(Instruction *I) {
385348
if (getReplacement(I))
@@ -401,15 +364,13 @@ void PointerReplacer::replace(Instruction *I) {
401364
// replacement (new value).
402365
WorkMap[NewI] = NewI;
403366
} 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;
413374
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
414375
auto *V = getReplacement(GEP->getPointerOperand());
415376
assert(V && "Operand not replaced");
@@ -473,6 +434,18 @@ void PointerReplacer::replace(Instruction *I) {
473434
}
474435
}
475436

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+
476449
Instruction *InstCombinerImpl::visitAllocaInst(AllocaInst &AI) {
477450
if (auto *I = simplifyAllocaArraySize(*this, AI, DT))
478451
return I;

llvm/test/Transforms/InstCombine/AMDGPU/ptr-replace-alloca.ll

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)