aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp')
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp135
1 files changed, 85 insertions, 50 deletions
diff --git a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
index 379988733312..84b0dac862b6 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
@@ -42,9 +42,6 @@ private:
// Vectorization plan that we are working on.
VPlan &Plan;
- // Output Top Region.
- VPRegionBlock *TopRegion = nullptr;
-
// Builder of the VPlan instruction-level representation.
VPBuilder VPIRBuilder;
@@ -59,6 +56,9 @@ private:
// Hold phi node's that need to be fixed once the plain CFG has been built.
SmallVector<PHINode *, 8> PhisToFix;
+ /// Maps loops in the original IR to their corresponding region.
+ DenseMap<Loop *, VPRegionBlock *> Loop2Region;
+
// Utility functions.
void setVPBBPredsFromBB(VPBasicBlock *VPBB, BasicBlock *BB);
void fixPhiNodes();
@@ -73,8 +73,9 @@ public:
PlainCFGBuilder(Loop *Lp, LoopInfo *LI, VPlan &P)
: TheLoop(Lp), LI(LI), Plan(P) {}
- // Build the plain CFG and return its Top Region.
- VPRegionBlock *buildPlainCFG();
+ /// Build plain CFG for TheLoop. Return the pre-header VPBasicBlock connected
+ /// to a new VPRegionBlock (TopRegion) enclosing the plain CFG.
+ VPBasicBlock *buildPlainCFG();
};
} // anonymous namespace
@@ -106,19 +107,32 @@ void PlainCFGBuilder::fixPhiNodes() {
}
}
-// Create a new empty VPBasicBlock for an incoming BasicBlock or retrieve an
-// existing one if it was already created.
+// Create a new empty VPBasicBlock for an incoming BasicBlock in the region
+// corresponding to the containing loop or retrieve an existing one if it was
+// already created. If no region exists yet for the loop containing \p BB, a new
+// one is created.
VPBasicBlock *PlainCFGBuilder::getOrCreateVPBB(BasicBlock *BB) {
auto BlockIt = BB2VPBB.find(BB);
if (BlockIt != BB2VPBB.end())
// Retrieve existing VPBB.
return BlockIt->second;
+ // Get or create a region for the loop containing BB.
+ Loop *CurrentLoop = LI->getLoopFor(BB);
+ VPRegionBlock *ParentR = nullptr;
+ if (CurrentLoop) {
+ auto Iter = Loop2Region.insert({CurrentLoop, nullptr});
+ if (Iter.second)
+ Iter.first->second = new VPRegionBlock(
+ CurrentLoop->getHeader()->getName().str(), false /*isReplicator*/);
+ ParentR = Iter.first->second;
+ }
+
// Create new VPBB.
LLVM_DEBUG(dbgs() << "Creating VPBasicBlock for " << BB->getName() << "\n");
VPBasicBlock *VPBB = new VPBasicBlock(BB->getName());
BB2VPBB[BB] = VPBB;
- VPBB->setParent(TopRegion);
+ VPBB->setParent(ParentR);
return VPBB;
}
@@ -182,8 +196,7 @@ VPValue *PlainCFGBuilder::getOrCreateVPOperand(Value *IRVal) {
// A and B: Create VPValue and add it to the pool of external definitions and
// to the Value->VPValue map.
- VPValue *NewVPVal = new VPValue(IRVal);
- Plan.addExternalDef(NewVPVal);
+ VPValue *NewVPVal = Plan.getOrAddExternalDef(IRVal);
IRDef2VPValue[IRVal] = NewVPVal;
return NewVPVal;
}
@@ -203,10 +216,13 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
"Instruction shouldn't have been visited.");
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
- // Branch instruction is not explicitly represented in VPlan but we need
- // to represent its condition bit when it's conditional.
- if (Br->isConditional())
- getOrCreateVPOperand(Br->getCondition());
+ // Conditional branch instruction are represented using BranchOnCond
+ // recipes.
+ if (Br->isConditional()) {
+ VPValue *Cond = getOrCreateVPOperand(Br->getCondition());
+ VPBB->appendRecipe(
+ new VPInstruction(VPInstruction::BranchOnCond, {Cond}));
+ }
// Skip the rest of the Instruction processing for Branch instructions.
continue;
@@ -238,11 +254,8 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
}
// Main interface to build the plain CFG.
-VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
- // 1. Create the Top Region. It will be the parent of all VPBBs.
- TopRegion = new VPRegionBlock("TopRegion", false /*isReplicator*/);
-
- // 2. Scan the body of the loop in a topological order to visit each basic
+VPBasicBlock *PlainCFGBuilder::buildPlainCFG() {
+ // 1. Scan the body of the loop in a topological order to visit each basic
// block after having visited its predecessor basic blocks. Create a VPBB for
// each BB and link it to its successor and predecessor VPBBs. Note that
// predecessors must be set in the same order as they are in the incomming IR.
@@ -251,21 +264,20 @@ VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
// Loop PH needs to be explicitly visited since it's not taken into account by
// LoopBlocksDFS.
- BasicBlock *PreheaderBB = TheLoop->getLoopPreheader();
- assert((PreheaderBB->getTerminator()->getNumSuccessors() == 1) &&
+ BasicBlock *ThePreheaderBB = TheLoop->getLoopPreheader();
+ assert((ThePreheaderBB->getTerminator()->getNumSuccessors() == 1) &&
"Unexpected loop preheader");
- VPBasicBlock *PreheaderVPBB = getOrCreateVPBB(PreheaderBB);
- for (auto &I : *PreheaderBB) {
+ VPBasicBlock *ThePreheaderVPBB = getOrCreateVPBB(ThePreheaderBB);
+ ThePreheaderVPBB->setName("vector.ph");
+ for (auto &I : *ThePreheaderBB) {
if (I.getType()->isVoidTy())
continue;
- VPValue *VPV = new VPValue(&I);
- Plan.addExternalDef(VPV);
- IRDef2VPValue[&I] = VPV;
+ IRDef2VPValue[&I] = Plan.getOrAddExternalDef(&I);
}
// Create empty VPBB for Loop H so that we can link PH->H.
VPBlockBase *HeaderVPBB = getOrCreateVPBB(TheLoop->getHeader());
- // Preheader's predecessors will be set during the loop RPO traversal below.
- PreheaderVPBB->setOneSuccessor(HeaderVPBB);
+ HeaderVPBB->setName("vector.body");
+ ThePreheaderVPBB->setOneSuccessor(HeaderVPBB);
LoopBlocksRPO RPO(TheLoop);
RPO.perform(LI);
@@ -295,16 +307,13 @@ VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
// Get VPBB's condition bit.
assert(isa<BranchInst>(TI) && "Unsupported terminator!");
- auto *Br = cast<BranchInst>(TI);
- Value *BrCond = Br->getCondition();
// Look up the branch condition to get the corresponding VPValue
// representing the condition bit in VPlan (which may be in another VPBB).
- assert(IRDef2VPValue.count(BrCond) &&
+ assert(IRDef2VPValue.count(cast<BranchInst>(TI)->getCondition()) &&
"Missing condition bit in IRDef2VPValue!");
- VPValue *VPCondBit = IRDef2VPValue[BrCond];
- // Link successors using condition bit.
- VPBB->setTwoSuccessors(SuccVPBB0, SuccVPBB1, VPCondBit);
+ // Link successors.
+ VPBB->setTwoSuccessors(SuccVPBB0, SuccVPBB1);
} else
llvm_unreachable("Number of successors not supported.");
@@ -312,30 +321,61 @@ VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
setVPBBPredsFromBB(VPBB, BB);
}
- // 3. Process outermost loop exit. We created an empty VPBB for the loop
+ // 2. Process outermost loop exit. We created an empty VPBB for the loop
// single exit BB during the RPO traversal of the loop body but Instructions
// weren't visited because it's not part of the the loop.
BasicBlock *LoopExitBB = TheLoop->getUniqueExitBlock();
assert(LoopExitBB && "Loops with multiple exits are not supported.");
VPBasicBlock *LoopExitVPBB = BB2VPBB[LoopExitBB];
- createVPInstructionsForVPBB(LoopExitVPBB, LoopExitBB);
// Loop exit was already set as successor of the loop exiting BB.
// We only set its predecessor VPBB now.
setVPBBPredsFromBB(LoopExitVPBB, LoopExitBB);
+ // 3. Fix up region blocks for loops. For each loop,
+ // * use the header block as entry to the corresponding region,
+ // * use the latch block as exit of the corresponding region,
+ // * set the region as successor of the loop pre-header, and
+ // * set the exit block as successor to the region.
+ SmallVector<Loop *> LoopWorkList;
+ LoopWorkList.push_back(TheLoop);
+ while (!LoopWorkList.empty()) {
+ Loop *L = LoopWorkList.pop_back_val();
+ BasicBlock *Header = L->getHeader();
+ BasicBlock *Exiting = L->getLoopLatch();
+ assert(Exiting == L->getExitingBlock() &&
+ "Latch must be the only exiting block");
+ VPRegionBlock *Region = Loop2Region[L];
+ VPBasicBlock *HeaderVPBB = getOrCreateVPBB(Header);
+ VPBasicBlock *ExitingVPBB = getOrCreateVPBB(Exiting);
+
+ // Disconnect backedge and pre-header from header.
+ VPBasicBlock *PreheaderVPBB = getOrCreateVPBB(L->getLoopPreheader());
+ VPBlockUtils::disconnectBlocks(PreheaderVPBB, HeaderVPBB);
+ VPBlockUtils::disconnectBlocks(ExitingVPBB, HeaderVPBB);
+
+ Region->setParent(PreheaderVPBB->getParent());
+ Region->setEntry(HeaderVPBB);
+ VPBlockUtils::connectBlocks(PreheaderVPBB, Region);
+
+ // Disconnect exit block from exiting (=latch) block, set exiting block and
+ // connect region to exit block.
+ VPBasicBlock *ExitVPBB = getOrCreateVPBB(L->getExitBlock());
+ VPBlockUtils::disconnectBlocks(ExitingVPBB, ExitVPBB);
+ Region->setExiting(ExitingVPBB);
+ VPBlockUtils::connectBlocks(Region, ExitVPBB);
+
+ // Queue sub-loops for processing.
+ LoopWorkList.append(L->begin(), L->end());
+ }
// 4. The whole CFG has been built at this point so all the input Values must
// have a VPlan couterpart. Fix VPlan phi nodes by adding their corresponding
// VPlan operands.
fixPhiNodes();
- // 5. Final Top Region setup. Set outermost loop pre-header and single exit as
- // Top Region entry and exit.
- TopRegion->setEntry(PreheaderVPBB);
- TopRegion->setExit(LoopExitVPBB);
- return TopRegion;
+ return ThePreheaderVPBB;
}
-VPRegionBlock *VPlanHCFGBuilder::buildPlainCFG() {
+VPBasicBlock *VPlanHCFGBuilder::buildPlainCFG() {
PlainCFGBuilder PCFGBuilder(TheLoop, LI, Plan);
return PCFGBuilder.buildPlainCFG();
}
@@ -343,20 +383,15 @@ VPRegionBlock *VPlanHCFGBuilder::buildPlainCFG() {
// Public interface to build a H-CFG.
void VPlanHCFGBuilder::buildHierarchicalCFG() {
// Build Top Region enclosing the plain CFG and set it as VPlan entry.
- VPRegionBlock *TopRegion = buildPlainCFG();
- Plan.setEntry(TopRegion);
+ VPBasicBlock *EntryVPBB = buildPlainCFG();
+ Plan.setEntry(EntryVPBB);
LLVM_DEBUG(Plan.setName("HCFGBuilder: Plain CFG\n"); dbgs() << Plan);
+ VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
Verifier.verifyHierarchicalCFG(TopRegion);
// Compute plain CFG dom tree for VPLInfo.
VPDomTree.recalculate(*TopRegion);
LLVM_DEBUG(dbgs() << "Dominator Tree after building the plain CFG.\n";
VPDomTree.print(dbgs()));
-
- // Compute VPLInfo and keep it in Plan.
- VPLoopInfo &VPLInfo = Plan.getVPLoopInfo();
- VPLInfo.analyze(VPDomTree);
- LLVM_DEBUG(dbgs() << "VPLoop Info After buildPlainCFG:\n";
- VPLInfo.print(dbgs()));
}