Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/GVN.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class GVNPass : public PassInfoMixin<GVNPass> {
ImplicitControlFlowTracking *ICF = nullptr;
LoopInfo *LI = nullptr;
MemorySSAUpdater *MSSAU = nullptr;
bool DomTreeCacheValid;

ValueTable VN;

Expand All @@ -237,6 +238,8 @@ class GVNPass : public PassInfoMixin<GVNPass> {
struct LeaderTableEntry {
Value *Val;
const BasicBlock *BB;
// Cache domtree node in LeaderTableEntry to avoid having to look it up.
DomTreeNode *DTNode;
};

private:
Expand All @@ -246,6 +249,7 @@ class GVNPass : public PassInfoMixin<GVNPass> {
};
DenseMap<uint32_t, LeaderListNode> NumToLeaders;
BumpPtrAllocator TableAllocator;
DominatorTree *DT;

public:
class leader_iterator {
Expand Down Expand Up @@ -291,6 +295,7 @@ class GVNPass : public PassInfoMixin<GVNPass> {
NumToLeaders.clear();
TableAllocator.Reset();
}
void setDomTree(DominatorTree *D) { DT = D; }
};
LeaderMap LeaderTable;

Expand Down Expand Up @@ -381,6 +386,10 @@ class GVNPass : public PassInfoMixin<GVNPass> {
void addDeadBlock(BasicBlock *BB);
void assignValNumForDeadCode();
void assignBlockRPONumber(Function &F);

// DT node cache-related routines
DomTreeNode *getDomTreeNode(const LeaderMap::LeaderTableEntry &Vals);
void invalidateDTCache();
};

/// Create a legacy GVN pass. This also allows parameterizing whether or not
Expand Down
32 changes: 31 additions & 1 deletion llvm/lib/Transforms/Scalar/GVN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ static cl::opt<uint32_t> MaxNumInsnsPerBlock(
cl::desc("Max number of instructions to scan in each basic block in GVN "
"(default = 100)"));

static cl::opt<bool>
EnableDomTreeCache("gvn-dom-cache", cl::init(true), cl::Hidden,
cl::desc("enable caching of dom tree nodes"));

struct llvm::GVNPass::Expression {
uint32_t opcode;
bool commutative = false;
Expand Down Expand Up @@ -735,13 +739,15 @@ void GVNPass::LeaderMap::insert(uint32_t N, Value *V, const BasicBlock *BB) {
if (!Curr.Entry.Val) {
Curr.Entry.Val = V;
Curr.Entry.BB = BB;
Curr.Entry.DTNode = DT->getNode(BB);
return;
}

LeaderListNode *Node = TableAllocator.Allocate<LeaderListNode>();
Node->Entry.Val = V;
Node->Entry.BB = BB;
Node->Next = Curr.Next;
Node->Entry.DTNode = DT->getNode(BB);
Curr.Next = Node;
}

Expand Down Expand Up @@ -771,6 +777,7 @@ void GVNPass::LeaderMap::erase(uint32_t N, Instruction *I,
Curr->Entry.Val = Next->Entry.Val;
Curr->Entry.BB = Next->Entry.BB;
Curr->Next = Next->Next;
Curr->Entry.DTNode = Next->Entry.DTNode;
}
}
}
Expand Down Expand Up @@ -827,6 +834,7 @@ PreservedAnalyses GVNPass::run(Function &F, FunctionAnalysisManager &AM) {
auto &LI = AM.getResult<LoopAnalysis>(F);
auto *MSSA = AM.getCachedResult<MemorySSAAnalysis>(F);
auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
DomTreeCacheValid = true;
bool Changed = runImpl(F, AC, DT, TLI, AA, MemDep, LI, &ORE,
MSSA ? &MSSA->getMSSA() : nullptr);
if (!Changed)
Expand Down Expand Up @@ -2382,6 +2390,14 @@ void GVNPass::ValueTable::eraseTranslateCacheEntry(
PhiTranslateTable.erase({Num, Pred});
}

DomTreeNode *GVNPass::getDomTreeNode(const LeaderMap::LeaderTableEntry &Vals) {
if (EnableDomTreeCache && DomTreeCacheValid) {
assert(DT->getNode(Vals.BB) == Vals.DTNode);
return Vals.DTNode;
}
return DT->getNode(Vals.BB);
}

// In order to find a leader for a given value number at a
// specific basic block, we first obtain the list of all Values for that number,
// and then scan the list to find one whose block dominates the block in
Expand All @@ -2393,8 +2409,10 @@ Value *GVNPass::findLeader(const BasicBlock *BB, uint32_t num) {
return nullptr;

Value *Val = nullptr;
DomTreeNode *BBDTNode = DT->getNode(BB);

for (const auto &Entry : Leaders) {
if (DT->dominates(Entry.BB, BB)) {
if (DT->dominates(getDomTreeNode(Entry), BBDTNode)) {
Val = Entry.Val;
if (isa<Constant>(Val))
return Val;
Expand Down Expand Up @@ -2762,8 +2780,10 @@ bool GVNPass::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
AC = &RunAC;
DT = &RunDT;
VN.setDomTree(DT);
LeaderTable.setDomTree(DT);
TLI = &RunTLI;
VN.setAliasAnalysis(&RunAA);
DomTreeCacheValid = true;
MD = RunMD;
ImplicitControlFlowTracking ImplicitCFT;
ICF = &ImplicitCFT;
Expand Down Expand Up @@ -3137,9 +3157,19 @@ BasicBlock *GVNPass::splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ) {
MD->invalidateCachedPredecessors();
InvalidBlockRPONumbers = true;
}
invalidateDTCache();
return BB;
}

void GVNPass::invalidateDTCache() {
// It is possible to refresh the leader table here but there are several
// reasons not to do so:
// 1. Invalidation is rare and usually occurs w/ PRE splitting critical edges.
// 2. In cases where invalidation happens, it can happen hundreds of times.
if (!EnableDomTreeCache)
return;
DomTreeCacheValid = false;
}
/// Split critical edges found during the previous
/// iteration that may enable further optimization.
bool GVNPass::splitCriticalEdges() {
Expand Down