Skip to content

Commit

Permalink
LoopOptTutorial: Update detail usage of domtree
Browse files Browse the repository at this point in the history
we discussed in previous commit message, updated how to update
domtree as details. as default, we choose the way to update
domtree by `DT.recalculate()`.

if you want to see detail, use 'DOMTREE_DETAIL_LEVEL' as given
argument when build by `make`. here is details usage:

$ make DOMTREE_DETAIL_LEVEL=0

this option use almost LLVM API to update domtree

`DOMTREE_DETAIL_LEVEL` level 1~2 use handcrafted way to update
domtree.
  • Loading branch information
ParkHanbum committed Oct 24, 2023
1 parent 17d2235 commit 0a96c88
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 3 deletions.
98 changes: 95 additions & 3 deletions llvm-study-recently-opt/LoopOptTutorial/LoopOptTutorial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
//===----------------------------------------------------------------------===

#include "LoopOptTutorial.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopIterator.h"
Expand All @@ -35,6 +37,9 @@ using namespace llvm;

#define DEBUG_TYPE "loop-opt-tutorial"

#define STRINGIFY(x) #x
#define STRINGIFYMACRO(y) STRINGIFY(y)

#define LLVM_DEBUG(X) \
do { \
dbgs() << "[" << DEBUG_TYPE << "]" << __FUNCTION__ << ":" << __LINE__ << "\t"; \
Expand Down Expand Up @@ -159,6 +164,85 @@ static Loop *myCloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
// LoopSplit implementation
//

#if 1==DOMTREE_DETAIL_LEVEL
void LoopSplit::updateDominatorTree(const Loop &OrigLoop,
const Loop &ClonedLoop,
BasicBlock &InsertBefore,
BasicBlock &Pred,
ValueToValueMapTy &VMap) const {
// Add the basic block that belongs to the cloned loop we have created to the
// dominator tree.
BasicBlock *NewPH = ClonedLoop.getLoopPreheader();
assert(NewPH && "Expecting a valid preheader");

DT.addNewBlock(NewPH, &Pred);
for (BasicBlock *BB : ClonedLoop.getBlocks())
DT.addNewBlock(BB, NewPH);

// Now update the immediate dominator of the cloned loop blocks.
for (BasicBlock *BB : OrigLoop.getBlocks()) {
BasicBlock *IDomBB = DT.getNode(BB)->getIDom()->getBlock();
DT.changeImmediateDominator(cast<BasicBlock>(VMap[BB]),
cast<BasicBlock>(VMap[IDomBB]));
}

// The cloned loop exiting block now dominates the original loop.
DT.changeImmediateDominator(&InsertBefore, ClonedLoop.getExitingBlock());
}
#elif 1<DOMTREE_DETAIL_LEVEL
void LoopSplit::updateDominatorTree(const Loop &OrigLoop,
const Loop &ClonedLoop,
BasicBlock &InsertBefore,
BasicBlock &Pred,
ValueToValueMapTy &VMap) const {
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
SmallVector<DominatorTree::UpdateType, 8> TreeUpdates;

BasicBlock *NewPH = ClonedLoop.getLoopPreheader();
assert(NewPH && "Expecting a valid preheader");

TreeUpdates.emplace_back(
DominatorTree::UpdateType(DominatorTree::Insert, &Pred, NewPH));

#if 1==DOMTREE_DETAIL_LEVEL
for (BasicBlock *BB : ClonedLoop.getBlocks())
TreeUpdates.emplace_back(
DominatorTree::UpdateType(DominatorTree::Insert, NewPH, BB));
#elif 2==DOMTREE_DETAIL_LEVEL
for (BasicBlock *BB : OrigLoop.getBlocks()) {
BasicBlock *IDomBB = DT.getNode(BB)->getIDom()->getBlock();
assert(VMap[IDomBB] && "Expecting immediate dominator of loop block to have been mapped.");
TreeUpdates.emplace_back(DominatorTree::UpdateType(
DominatorTree::Insert, cast<BasicBlock>(VMap[IDomBB]), cast<BasicBlock>(VMap[BB])));
}
#endif

assert(&InsertBefore == OrigLoop.getLoopPreheader() &&
"Expecting InsertBefore to be the Preheader!!");

// The cloned loop exiting block now dominates the original loop
TreeUpdates.emplace_back(DominatorTree::UpdateType(
DominatorTree::Delete,
DT.getNode(OrigLoop.getLoopPreheader())->getIDom()->getBlock(),
OrigLoop.getLoopPreheader()));
TreeUpdates.emplace_back(DominatorTree::UpdateType(
DominatorTree::Insert, ClonedLoop.getExitingBlock(),
OrigLoop.getLoopPreheader()));

LLVM_DEBUG({
dbgs() << "KIT: DomTree Updates: \n";
for (auto u : TreeUpdates) {
u.print(dbgs().indent(2));
dbgs() << "\n";
}
});

DTU.applyUpdates(TreeUpdates);
DTU.flush();
}

#endif

void LoopSplit::dumpLoopFunction(const StringRef Msg, const Loop &L) const {
const Function &F = *L.getHeader()->getParent();
dbgs() << Msg;
Expand Down Expand Up @@ -264,12 +348,21 @@ Loop *LoopSplit::cloneLoop(Loop &L, BasicBlock &InsertBefore, BasicBlock &Pred)
Pred.getTerminator()->replaceUsesOfWith(&InsertBefore,
NewLoop->getLoopPreheader());

#if 0==DOMTREE_DETAIL_LEVEL
// Recompute the dominator tree
LLVM_DEBUGM("Update Domtree by using recalculate");
DT.recalculate(F);
#elif 0<DOMTREE_DETAIL_LEVEL
LLVM_DEBUG(dbgs() << "Update Domtree with more detail handcrafted way \n";);
LLVM_DEBUG(dbgs() << "DETAIL LEVEL : " STRINGIFYMACRO(DOMTREE_DETAIL_LEVEL) "\n";);
// Now that we have cloned the loop we need to update the dominator tree.
updateDominatorTree(L, *NewLoop, InsertBefore, Pred, VMap);
LLVM_DEBUG(dbgs() << "Dominator Tree: "; DT.print(dbgs()););
#endif

// Verify that the dominator tree and the loops are correct.
#ifndef NDEBUG
assert(DT.verify(DominatorTree::VerificationLevel::Fast) &&
LLVM_DEBUGM("KIT: Verifying data structures after splitting loop.");
assert(DT.verify(DominatorTree::VerificationLevel::Full) &&
"Dominator tree is invalid");

L.verifyLoop();
Expand All @@ -278,7 +371,6 @@ Loop *LoopSplit::cloneLoop(Loop &L, BasicBlock &InsertBefore, BasicBlock &Pred)
L.getParentLoop()->verifyLoop();

LI.verify(DT);
#endif

return NewLoop;
}
Expand Down
9 changes: 9 additions & 0 deletions llvm-study-recently-opt/LoopOptTutorial/LoopOptTutorial.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ class LoopSplit {
/// Get the latch comparison instruction of loop \p L.
ICmpInst *getLatchCmpInst(const Loop &L) const;

#if (DOMTREE_DETAIL >= 0) && (DOMTREE_DETAIL <= 2)
/// Update the dominator tree after cloning the loop.
void updateDominatorTree(const Loop &OrigLoop, const Loop &ClonedLoop,
BasicBlock &InsertBefore, BasicBlock &Pred,
ValueToValueMapTy &VMap) const;
#else
#error "Invalid DOMTREE_DETAIL. Use 0, 1, or 2."
#endif

// Dump the LLVM IR for function containing the given loop \p L.
void dumpLoopFunction(const StringRef Msg, const Loop &L) const;

Expand Down
11 changes: 11 additions & 0 deletions llvm-study-recently-opt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ LLVM_CXXFLAGS := $(shell $(LLVM_CONFIG) --cxxflags) -Wno-unused-value -Wno-macro
LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags)
LLVM_BLDFLAGS := $(shell $(LLVM_CONFIG) --ldflags --libs)

# DOMTREE Detail related option
ifdef DOMTREE_DETAIL_LEVEL
DOMTREE_DETAIL_LEVEL := 0
ifeq ($(filter-out 0 1 2,$(DOMTREE_DETAIL_LEVEL)),)
LLVM_CXXFLAGS += -DDOMTREE_DETAIL_LEVEL=$(DOMTREE_DETAIL_LEVEL)
else
$(error Input value must be 0, 1, or 2)
endif
endif


# Loop Optimization Tutorial
TUTORIAL := LoopOptTutorial
TUTORIAL_SRC := $(srcdir)/$(TUTORIAL)/$(TUTORIAL).cpp
Expand Down

0 comments on commit 0a96c88

Please sign in to comment.