Skip to content

Commit a54e0a5

Browse files
committed
[GVN] Improve processBlock for instruction erasure
This patch deletes the instructions right away by using the approapriate iterators. Thus avoids collecting the instructions in a vector and then doing the erasure.
1 parent 15cd71a commit a54e0a5

File tree

2 files changed

+20
-51
lines changed
  • llvm
    • include/llvm/Transforms/Scalar
    • lib/Transforms/Scalar

2 files changed

+20
-51
lines changed

llvm/include/llvm/Transforms/Scalar/GVN.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "llvm/IR/ValueHandle.h"
2626
#include "llvm/Support/Allocator.h"
2727
#include "llvm/Support/Compiler.h"
28+
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
29+
#include "llvm/Transforms/Utils/Local.h"
2830
#include <cstdint>
2931
#include <optional>
3032
#include <utility>
@@ -137,9 +139,11 @@ class GVNPass : public PassInfoMixin<GVNPass> {
137139

138140
/// This removes the specified instruction from
139141
/// our various maps and marks it for deletion.
140-
void markInstructionForDeletion(Instruction *I) {
142+
void doInstructionDeletion(Instruction *I) {
143+
salvageKnowledge(I, AC);
144+
salvageDebugInfo(*I);
141145
VN.erase(I);
142-
InstrsToErase.push_back(I);
146+
removeInstruction(I);
143147
}
144148

145149
DominatorTree &getDominatorTree() const { return *DT; }
@@ -306,7 +310,6 @@ class GVNPass : public PassInfoMixin<GVNPass> {
306310
// propagate to any successors. Entries added mid-block are applied
307311
// to the remaining instructions in the block.
308312
SmallMapVector<Value *, Value *, 4> ReplaceOperandsWithMap;
309-
SmallVector<Instruction *, 8> InstrsToErase;
310313

311314
// Map the block to reversed postorder traversal number. It is used to
312315
// find back edge easily.

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 14 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
#include "llvm/Support/Compiler.h"
7070
#include "llvm/Support/Debug.h"
7171
#include "llvm/Support/raw_ostream.h"
72-
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
7372
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
7473
#include "llvm/Transforms/Utils/Local.h"
7574
#include "llvm/Transforms/Utils/SSAUpdater.h"
@@ -728,8 +727,9 @@ void GVNPass::ValueTable::erase(Value *V) {
728727
/// verifyRemoved - Verify that the value is removed from all internal data
729728
/// structures.
730729
void GVNPass::ValueTable::verifyRemoved(const Value *V) const {
731-
assert(!ValueNumbering.contains(V) &&
732-
"Inst still occurs in value numbering map!");
730+
if (V != nullptr)
731+
assert(!ValueNumbering.contains(V) &&
732+
"Inst still occurs in value numbering map!");
733733
}
734734

735735
//===----------------------------------------------------------------------===//
@@ -1572,11 +1572,11 @@ void GVNPass::eliminatePartiallyRedundantLoad(
15721572
I->setDebugLoc(Load->getDebugLoc());
15731573
if (V->getType()->isPtrOrPtrVectorTy())
15741574
MD->invalidateCachedPointerInfo(V);
1575-
markInstructionForDeletion(Load);
15761575
ORE->emit([&]() {
15771576
return OptimizationRemark(DEBUG_TYPE, "LoadPRE", Load)
15781577
<< "load eliminated by PRE";
15791578
});
1579+
doInstructionDeletion(Load);
15801580
}
15811581

15821582
bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
@@ -1795,7 +1795,7 @@ bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
17951795
// Erase instructions generated by the failed PHI translation before
17961796
// trying to number them. PHI translation might insert instructions
17971797
// in basic blocks other than the current one, and we delete them
1798-
// directly, as markInstructionForDeletion only allows removing from the
1798+
// directly, as doInstructionDeletion only allows removing from the
17991799
// current basic block.
18001800
NewInsts.pop_back_val()->eraseFromParent();
18011801
}
@@ -1994,7 +1994,7 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load) {
19941994
I->setDebugLoc(Load->getDebugLoc());
19951995
if (V->getType()->isPtrOrPtrVectorTy())
19961996
MD->invalidateCachedPointerInfo(V);
1997-
markInstructionForDeletion(Load);
1997+
doInstructionDeletion(Load);
19981998
++NumGVNLoad;
19991999
reportLoadElim(Load, V, ORE);
20002000
return true;
@@ -2064,7 +2064,7 @@ bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
20642064
}
20652065
}
20662066
if (isAssumeWithEmptyBundle(*IntrinsicI)) {
2067-
markInstructionForDeletion(IntrinsicI);
2067+
doInstructionDeletion(IntrinsicI);
20682068
return true;
20692069
}
20702070
return false;
@@ -2175,7 +2175,7 @@ bool GVNPass::processLoad(LoadInst *L) {
21752175
return false;
21762176

21772177
if (L->use_empty()) {
2178-
markInstructionForDeletion(L);
2178+
doInstructionDeletion(L);
21792179
return true;
21802180
}
21812181

@@ -2205,13 +2205,13 @@ bool GVNPass::processLoad(LoadInst *L) {
22052205
// MaterializeAdjustedValue is responsible for combining metadata.
22062206
ICF->removeUsersOf(L);
22072207
L->replaceAllUsesWith(AvailableValue);
2208-
markInstructionForDeletion(L);
22092208
if (MSSAU)
22102209
MSSAU->removeMemoryAccess(L);
22112210
++NumGVNLoad;
22122211
reportLoadElim(L, AvailableValue, ORE);
22132212
// Tell MDA to reexamine the reused pointer since we might have more
22142213
// information after forwarding it.
2214+
doInstructionDeletion(L);
22152215
if (MD && AvailableValue->getType()->isPtrOrPtrVectorTy())
22162216
MD->invalidateCachedPointerInfo(AvailableValue);
22172217
return true;
@@ -2601,7 +2601,7 @@ bool GVNPass::processInstruction(Instruction *I) {
26012601
Changed = true;
26022602
}
26032603
if (isInstructionTriviallyDead(I, TLI)) {
2604-
markInstructionForDeletion(I);
2604+
doInstructionDeletion(I);
26052605
Changed = true;
26062606
}
26072607
if (Changed) {
@@ -2718,7 +2718,7 @@ bool GVNPass::processInstruction(Instruction *I) {
27182718
patchAndReplaceAllUsesWith(I, Repl);
27192719
if (MD && Repl->getType()->isPtrOrPtrVectorTy())
27202720
MD->invalidateCachedPointerInfo(Repl);
2721-
markInstructionForDeletion(I);
2721+
doInstructionDeletion(I);
27222722
return true;
27232723
}
27242724

@@ -2794,10 +2794,6 @@ bool GVNPass::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
27942794
}
27952795

27962796
bool GVNPass::processBlock(BasicBlock *BB) {
2797-
// FIXME: Kill off InstrsToErase by doing erasing eagerly in a helper function
2798-
// (and incrementing BI before processing an instruction).
2799-
assert(InstrsToErase.empty() &&
2800-
"We expect InstrsToErase to be empty across iterations");
28012797
if (DeadBlocks.count(BB))
28022798
return false;
28032799

@@ -2815,41 +2811,11 @@ bool GVNPass::processBlock(BasicBlock *BB) {
28152811
VN.erase(PN);
28162812
removeInstruction(PN);
28172813
}
2818-
2819-
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
2820-
BI != BE;) {
2814+
for (Instruction &Inst : make_early_inc_range(*BB)) {
28212815
if (!ReplaceOperandsWithMap.empty())
2822-
ChangedFunction |= replaceOperandsForInBlockEquality(&*BI);
2823-
ChangedFunction |= processInstruction(&*BI);
2824-
2825-
if (InstrsToErase.empty()) {
2826-
++BI;
2827-
continue;
2828-
}
2829-
2830-
// If we need some instructions deleted, do it now.
2831-
NumGVNInstr += InstrsToErase.size();
2832-
2833-
// Avoid iterator invalidation.
2834-
bool AtStart = BI == BB->begin();
2835-
if (!AtStart)
2836-
--BI;
2837-
2838-
for (auto *I : InstrsToErase) {
2839-
assert(I->getParent() == BB && "Removing instruction from wrong block?");
2840-
LLVM_DEBUG(dbgs() << "GVN removed: " << *I << '\n');
2841-
salvageKnowledge(I, AC);
2842-
salvageDebugInfo(*I);
2843-
removeInstruction(I);
2844-
}
2845-
InstrsToErase.clear();
2846-
2847-
if (AtStart)
2848-
BI = BB->begin();
2849-
else
2850-
++BI;
2816+
ChangedFunction |= replaceOperandsForInBlockEquality(&Inst);
2817+
ChangedFunction |= processInstruction(&Inst);
28512818
}
2852-
28532819
return ChangedFunction;
28542820
}
28552821

0 commit comments

Comments
 (0)