Skip to content

Commit 352f36d

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 bb21a68 commit 352f36d

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"
@@ -729,8 +728,9 @@ void GVNPass::ValueTable::erase(Value *V) {
729728
/// verifyRemoved - Verify that the value is removed from all internal data
730729
/// structures.
731730
void GVNPass::ValueTable::verifyRemoved(const Value *V) const {
732-
assert(!ValueNumbering.contains(V) &&
733-
"Inst still occurs in value numbering map!");
731+
if (V != nullptr)
732+
assert(!ValueNumbering.contains(V) &&
733+
"Inst still occurs in value numbering map!");
734734
}
735735

736736
//===----------------------------------------------------------------------===//
@@ -1573,11 +1573,11 @@ void GVNPass::eliminatePartiallyRedundantLoad(
15731573
I->setDebugLoc(Load->getDebugLoc());
15741574
if (V->getType()->isPtrOrPtrVectorTy())
15751575
MD->invalidateCachedPointerInfo(V);
1576-
markInstructionForDeletion(Load);
15771576
ORE->emit([&]() {
15781577
return OptimizationRemark(DEBUG_TYPE, "LoadPRE", Load)
15791578
<< "load eliminated by PRE";
15801579
});
1580+
doInstructionDeletion(Load);
15811581
}
15821582

15831583
bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
@@ -1796,7 +1796,7 @@ bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
17961796
// Erase instructions generated by the failed PHI translation before
17971797
// trying to number them. PHI translation might insert instructions
17981798
// in basic blocks other than the current one, and we delete them
1799-
// directly, as markInstructionForDeletion only allows removing from the
1799+
// directly, as doInstructionDeletion only allows removing from the
18001800
// current basic block.
18011801
NewInsts.pop_back_val()->eraseFromParent();
18021802
}
@@ -1995,7 +1995,7 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load) {
19951995
I->setDebugLoc(Load->getDebugLoc());
19961996
if (V->getType()->isPtrOrPtrVectorTy())
19971997
MD->invalidateCachedPointerInfo(V);
1998-
markInstructionForDeletion(Load);
1998+
doInstructionDeletion(Load);
19991999
++NumGVNLoad;
20002000
reportLoadElim(Load, V, ORE);
20012001
return true;
@@ -2065,7 +2065,7 @@ bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
20652065
}
20662066
}
20672067
if (isAssumeWithEmptyBundle(*IntrinsicI)) {
2068-
markInstructionForDeletion(IntrinsicI);
2068+
doInstructionDeletion(IntrinsicI);
20692069
return true;
20702070
}
20712071
return false;
@@ -2176,7 +2176,7 @@ bool GVNPass::processLoad(LoadInst *L) {
21762176
return false;
21772177

21782178
if (L->use_empty()) {
2179-
markInstructionForDeletion(L);
2179+
doInstructionDeletion(L);
21802180
return true;
21812181
}
21822182

@@ -2206,13 +2206,13 @@ bool GVNPass::processLoad(LoadInst *L) {
22062206
// MaterializeAdjustedValue is responsible for combining metadata.
22072207
ICF->removeUsersOf(L);
22082208
L->replaceAllUsesWith(AvailableValue);
2209-
markInstructionForDeletion(L);
22102209
if (MSSAU)
22112210
MSSAU->removeMemoryAccess(L);
22122211
++NumGVNLoad;
22132212
reportLoadElim(L, AvailableValue, ORE);
22142213
// Tell MDA to reexamine the reused pointer since we might have more
22152214
// information after forwarding it.
2215+
doInstructionDeletion(L);
22162216
if (MD && AvailableValue->getType()->isPtrOrPtrVectorTy())
22172217
MD->invalidateCachedPointerInfo(AvailableValue);
22182218
return true;
@@ -2602,7 +2602,7 @@ bool GVNPass::processInstruction(Instruction *I) {
26022602
Changed = true;
26032603
}
26042604
if (isInstructionTriviallyDead(I, TLI)) {
2605-
markInstructionForDeletion(I);
2605+
doInstructionDeletion(I);
26062606
Changed = true;
26072607
}
26082608
if (Changed) {
@@ -2719,7 +2719,7 @@ bool GVNPass::processInstruction(Instruction *I) {
27192719
patchAndReplaceAllUsesWith(I, Repl);
27202720
if (MD && Repl->getType()->isPtrOrPtrVectorTy())
27212721
MD->invalidateCachedPointerInfo(Repl);
2722-
markInstructionForDeletion(I);
2722+
doInstructionDeletion(I);
27232723
return true;
27242724
}
27252725

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

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

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

0 commit comments

Comments
 (0)