Skip to content

Commit 4de1a9e

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 0813c5c commit 4de1a9e

File tree

2 files changed

+21
-50
lines changed
  • llvm
    • include/llvm/Transforms/Scalar
    • lib/Transforms/Scalar

2 files changed

+21
-50
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: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -730,8 +730,9 @@ void GVNPass::ValueTable::erase(Value *V) {
730730
/// verifyRemoved - Verify that the value is removed from all internal data
731731
/// structures.
732732
void GVNPass::ValueTable::verifyRemoved(const Value *V) const {
733-
assert(!valueNumbering.contains(V) &&
734-
"Inst still occurs in value numbering map!");
733+
if (V != nullptr)
734+
assert(!valueNumbering.contains(V) &&
735+
"Inst still occurs in value numbering map!");
735736
}
736737

737738
//===----------------------------------------------------------------------===//
@@ -1574,7 +1575,7 @@ void GVNPass::eliminatePartiallyRedundantLoad(
15741575
I->setDebugLoc(Load->getDebugLoc());
15751576
if (V->getType()->isPtrOrPtrVectorTy())
15761577
MD->invalidateCachedPointerInfo(V);
1577-
markInstructionForDeletion(Load);
1578+
doInstructionDeletion(Load);
15781579
ORE->emit([&]() {
15791580
return OptimizationRemark(DEBUG_TYPE, "LoadPRE", Load)
15801581
<< "load eliminated by PRE";
@@ -1798,7 +1799,7 @@ bool GVNPass::PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
17981799
// Erase instructions generated by the failed PHI translation before
17991800
// trying to number them. PHI translation might insert instructions
18001801
// in basic blocks other than the current one, and we delete them
1801-
// directly, as markInstructionForDeletion only allows removing from the
1802+
// directly, as doInstructionDeletion only allows removing from the
18021803
// current basic block.
18031804
NewInsts.pop_back_val()->eraseFromParent();
18041805
}
@@ -1997,7 +1998,7 @@ bool GVNPass::processNonLocalLoad(LoadInst *Load) {
19971998
I->setDebugLoc(Load->getDebugLoc());
19981999
if (V->getType()->isPtrOrPtrVectorTy())
19992000
MD->invalidateCachedPointerInfo(V);
2000-
markInstructionForDeletion(Load);
2001+
doInstructionDeletion(Load);
20012002
++NumGVNLoad;
20022003
reportLoadElim(Load, V, ORE);
20032004
return true;
@@ -2067,7 +2068,7 @@ bool GVNPass::processAssumeIntrinsic(AssumeInst *IntrinsicI) {
20672068
}
20682069
}
20692070
if (isAssumeWithEmptyBundle(*IntrinsicI)) {
2070-
markInstructionForDeletion(IntrinsicI);
2071+
doInstructionDeletion(IntrinsicI);
20712072
return true;
20722073
}
20732074
return false;
@@ -2179,7 +2180,7 @@ bool GVNPass::processLoad(LoadInst *L) {
21792180
return false;
21802181

21812182
if (L->use_empty()) {
2182-
markInstructionForDeletion(L);
2183+
doInstructionDeletion(L);
21832184
return true;
21842185
}
21852186

@@ -2209,13 +2210,13 @@ bool GVNPass::processLoad(LoadInst *L) {
22092210
// MaterializeAdjustedValue is responsible for combining metadata.
22102211
ICF->removeUsersOf(L);
22112212
L->replaceAllUsesWith(AvailableValue);
2212-
markInstructionForDeletion(L);
22132213
if (MSSAU)
22142214
MSSAU->removeMemoryAccess(L);
22152215
++NumGVNLoad;
22162216
reportLoadElim(L, AvailableValue, ORE);
22172217
// Tell MDA to reexamine the reused pointer since we might have more
22182218
// information after forwarding it.
2219+
doInstructionDeletion(L);
22192220
if (MD && AvailableValue->getType()->isPtrOrPtrVectorTy())
22202221
MD->invalidateCachedPointerInfo(AvailableValue);
22212222
return true;
@@ -2605,7 +2606,7 @@ bool GVNPass::processInstruction(Instruction *I) {
26052606
Changed = true;
26062607
}
26072608
if (isInstructionTriviallyDead(I, TLI)) {
2608-
markInstructionForDeletion(I);
2609+
doInstructionDeletion(I);
26092610
Changed = true;
26102611
}
26112612
if (Changed) {
@@ -2723,7 +2724,7 @@ bool GVNPass::processInstruction(Instruction *I) {
27232724
patchAndReplaceAllUsesWith(I, Repl);
27242725
if (MD && Repl->getType()->isPtrOrPtrVectorTy())
27252726
MD->invalidateCachedPointerInfo(Repl);
2726-
markInstructionForDeletion(I);
2727+
doInstructionDeletion(I);
27272728
return true;
27282729
}
27292730

@@ -2799,10 +2800,6 @@ bool GVNPass::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
27992800
}
28002801

28012802
bool GVNPass::processBlock(BasicBlock *BB) {
2802-
// FIXME: Kill off InstrsToErase by doing erasing eagerly in a helper function
2803-
// (and incrementing BI before processing an instruction).
2804-
assert(InstrsToErase.empty() &&
2805-
"We expect InstrsToErase to be empty across iterations");
28062803
if (DeadBlocks.count(BB))
28072804
return false;
28082805

@@ -2820,41 +2817,12 @@ bool GVNPass::processBlock(BasicBlock *BB) {
28202817
VN.erase(PN);
28212818
removeInstruction(PN);
28222819
}
2823-
2824-
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
2825-
BI != BE;) {
2820+
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
2821+
Instruction *Inst = &*BI++;
28262822
if (!ReplaceOperandsWithMap.empty())
2827-
ChangedFunction |= replaceOperandsForInBlockEquality(&*BI);
2828-
ChangedFunction |= processInstruction(&*BI);
2829-
2830-
if (InstrsToErase.empty()) {
2831-
++BI;
2832-
continue;
2833-
}
2834-
2835-
// If we need some instructions deleted, do it now.
2836-
NumGVNInstr += InstrsToErase.size();
2837-
2838-
// Avoid iterator invalidation.
2839-
bool AtStart = BI == BB->begin();
2840-
if (!AtStart)
2841-
--BI;
2842-
2843-
for (auto *I : InstrsToErase) {
2844-
assert(I->getParent() == BB && "Removing instruction from wrong block?");
2845-
LLVM_DEBUG(dbgs() << "GVN removed: " << *I << '\n');
2846-
salvageKnowledge(I, AC);
2847-
salvageDebugInfo(*I);
2848-
removeInstruction(I);
2849-
}
2850-
InstrsToErase.clear();
2851-
2852-
if (AtStart)
2853-
BI = BB->begin();
2854-
else
2855-
++BI;
2823+
ChangedFunction |= replaceOperandsForInBlockEquality(Inst);
2824+
ChangedFunction |= processInstruction(Inst);
28562825
}
2857-
28582826
return ChangedFunction;
28592827
}
28602828

0 commit comments

Comments
 (0)