std::string getEdgeAttributes(RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI, ScopDetection *SD) { RegionNode *destNode = *CI; if (srcNode->isSubRegion() || destNode->isSubRegion()) return ""; // In case of a backedge, do not use it to define the layout of the nodes. BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); RegionInfo *RI = SD->getRI(); Region *R = RI->getRegionFor(destBB); while (R && R->getParent()) if (R->getParent()->getEntry() == destBB) R = R->getParent(); else break; if (R && R->getEntry() == destBB && R->contains(srcBB)) return "constraint=false"; return ""; }
// Print the cluster of the subregions. This groups the single basic blocks // and adds a different background color for each group. static void printRegionCluster(const Region *R, GraphWriter<RegionInfo*> &GW, unsigned depth = 0) { raw_ostream &O = GW.getOStream(); O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(R) << " {\n"; O.indent(2 * (depth + 1)) << "label = \"\";\n"; if (!onlySimpleRegions || R->isSimple()) { O.indent(2 * (depth + 1)) << "style = filled;\n"; O.indent(2 * (depth + 1)) << "color = " << ((R->getDepth() * 2 % 12) + 1) << "\n"; } else { O.indent(2 * (depth + 1)) << "style = solid;\n"; O.indent(2 * (depth + 1)) << "color = " << ((R->getDepth() * 2 % 12) + 2) << "\n"; } for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) printRegionCluster(*RI, GW, depth + 1); RegionInfo *RI = R->getRegionInfo(); for (Region::const_block_iterator BI = R->block_begin(), BE = R->block_end(); BI != BE; ++BI) if (RI->getRegionFor(*BI) == R) O.indent(2 * (depth + 1)) << "Node" << static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(*BI)) << ";\n"; O.indent(2 * depth) << "}\n"; }
/// \brief Analyze the predecessors of each block and build up predicates void StructurizeCFG::gatherPredicates(RegionNode *N) { RegionInfo *RI = ParentRegion->getRegionInfo(); BasicBlock *BB = N->getEntry(); BBPredicates &Pred = Predicates[BB]; BBPredicates &LPred = LoopPreds[BB]; for (BasicBlock *P : predecessors(BB)) { // Ignore it if it's a branch from outside into our region entry if (!ParentRegion->contains(P)) continue; Region *R = RI->getRegionFor(P); if (R == ParentRegion) { // It's a top level block in our region BranchInst *Term = cast<BranchInst>(P->getTerminator()); for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) { BasicBlock *Succ = Term->getSuccessor(i); if (Succ != BB) continue; if (Visited.count(P)) { // Normal forward edge if (Term->isConditional()) { // Try to treat it like an ELSE block BasicBlock *Other = Term->getSuccessor(!i); if (Visited.count(Other) && !Loops.count(Other) && !Pred.count(Other) && !Pred.count(P)) { Pred[Other] = BoolFalse; Pred[P] = BoolTrue; continue; } } Pred[P] = buildCondition(Term, i, false); } else { // Back edge LPred[P] = buildCondition(Term, i, true); } } } else { // It's an exit from a sub region while (R->getParent() != ParentRegion) R = R->getParent(); // Edge from inside a subregion to its entry, ignore it if (*R == *N) continue; BasicBlock *Entry = R->getEntry(); if (Visited.count(Entry)) Pred[Entry] = BoolTrue; else LPred[Entry] = BoolFalse; } } }
// Print the cluster of the subregions. This groups the single basic blocks // and adds a different background color for each group. static void printRegionCluster(const ScopDetection *SD, const Region *R, raw_ostream &O, unsigned depth = 0) { O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R) << " {\n"; unsigned LineBegin, LineEnd; std::string FileName; getDebugLocation(R, LineBegin, LineEnd, FileName); std::string Location; if (LineBegin != (unsigned)-1) { Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" + std::to_string(LineEnd) + "\n"); } std::string ErrorMessage = SD->regionIsInvalidBecause(R); ErrorMessage = escapeString(ErrorMessage); O.indent(2 * (depth + 1)) << "label = \"" << Location << ErrorMessage << "\";\n"; if (SD->isMaxRegionInScop(*R)) { O.indent(2 * (depth + 1)) << "style = filled;\n"; // Set color to green. O.indent(2 * (depth + 1)) << "color = 3"; } else { O.indent(2 * (depth + 1)) << "style = solid;\n"; int color = (R->getDepth() * 2 % 12) + 1; // We do not want green again. if (color == 3) color = 6; O.indent(2 * (depth + 1)) << "color = " << color << "\n"; } for (const auto &SubRegion : *R) printRegionCluster(SD, SubRegion.get(), O, depth + 1); RegionInfo *RI = R->getRegionInfo(); for (const auto &BB : R->blocks()) if (RI->getRegionFor(BB) == R) O.indent(2 * (depth + 1)) << "Node" << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB)) << ";\n"; O.indent(2 * depth) << "}\n"; }
void TempScopInfo::buildCondition(BasicBlock *BB, Region &R) { BasicBlock *RegionEntry = R.getEntry(); BBCond Cond; DomTreeNode *BBNode = DT->getNode(BB), *EntryNode = DT->getNode(RegionEntry); assert(BBNode && EntryNode && "Get null node while building condition!"); // Walk up the dominance tree until reaching the entry node. Collect all // branching blocks on the path to BB except if BB postdominates the block // containing the condition. SmallVector<BasicBlock *, 4> DominatorBrBlocks; while (BBNode != EntryNode) { BasicBlock *CurBB = BBNode->getBlock(); BBNode = BBNode->getIDom(); assert(BBNode && "BBNode should not reach the root node!"); if (PDT->dominates(CurBB, BBNode->getBlock())) continue; BranchInst *Br = dyn_cast<BranchInst>(BBNode->getBlock()->getTerminator()); assert(Br && "A Valid Scop should only contain branch instruction"); if (Br->isUnconditional()) continue; DominatorBrBlocks.push_back(BBNode->getBlock()); } RegionInfo *RI = R.getRegionInfo(); // Iterate in reverse order over the dominating blocks. Until a non-affine // branch was encountered add all conditions collected. If a non-affine branch // was encountered, stop as we overapproximate from here on anyway. for (auto BIt = DominatorBrBlocks.rbegin(), BEnd = DominatorBrBlocks.rend(); BIt != BEnd; BIt++) { BasicBlock *BBNode = *BIt; BranchInst *Br = dyn_cast<BranchInst>(BBNode->getTerminator()); assert(Br && "A Valid Scop should only contain branch instruction"); assert(Br->isConditional() && "Assumed a conditional branch"); if (SD->isNonAffineSubRegion(RI->getRegionFor(BBNode), &R)) break; BasicBlock *TrueBB = Br->getSuccessor(0), *FalseBB = Br->getSuccessor(1); // Is BB on the ELSE side of the branch? bool inverted = DT->dominates(FalseBB, BB); // If both TrueBB and FalseBB dominate BB, one of them must be the target of // a back-edge, i.e. a loop header. if (inverted && DT->dominates(TrueBB, BB)) { assert( (DT->dominates(TrueBB, FalseBB) || DT->dominates(FalseBB, TrueBB)) && "One of the successors should be the loop header and dominate the" "other!"); // It is not an invert if the FalseBB is the header. if (DT->dominates(FalseBB, TrueBB)) inverted = false; } Comparison *Cmp; buildAffineCondition(*(Br->getCondition()), inverted, &Cmp); Cond.push_back(*Cmp); } if (!Cond.empty()) BBConds[BB] = Cond; }
std::pair<polly::BBPair, BranchInst *> polly::executeScopConditionally(Scop &S, Value *RTC, DominatorTree &DT, RegionInfo &RI, LoopInfo &LI) { Region &R = S.getRegion(); PollyIRBuilder Builder(S.getEntry()); // Before: // // \ / // // EnteringBB // // _____|_____ // // / EntryBB \ // // | (region) | // // \_ExitingBB_/ // // | // // ExitBB // // / \ // // Create a fork block. BasicBlock *EnteringBB = S.getEnteringBlock(); BasicBlock *EntryBB = S.getEntry(); assert(EnteringBB && "Must be a simple region"); BasicBlock *SplitBlock = splitEdge(EnteringBB, EntryBB, ".split_new_and_old", &DT, &LI, &RI); SplitBlock->setName("polly.split_new_and_old"); // If EntryBB is the exit block of the region that includes Prev, exclude // SplitBlock from that region by making it itself the exit block. This is // trivially possible because there is just one edge to EnteringBB. // This is necessary because we will add an outgoing edge from SplitBlock, // which would violate the single exit block requirement of PrevRegion. Region *PrevRegion = RI.getRegionFor(EnteringBB); while (PrevRegion->getExit() == EntryBB) { PrevRegion->replaceExit(SplitBlock); PrevRegion = PrevRegion->getParent(); } RI.setRegionFor(SplitBlock, PrevRegion); // Create a join block BasicBlock *ExitingBB = S.getExitingBlock(); BasicBlock *ExitBB = S.getExit(); assert(ExitingBB && "Must be a simple region"); BasicBlock *MergeBlock = splitEdge(ExitingBB, ExitBB, ".merge_new_and_old", &DT, &LI, &RI); MergeBlock->setName("polly.merge_new_and_old"); // Exclude the join block from the region. R.replaceExitRecursive(MergeBlock); RI.setRegionFor(MergeBlock, R.getParent()); // \ / // // EnteringBB // // | // // SplitBlock // // _____|_____ // // / EntryBB \ // // | (region) | // // \_ExitingBB_/ // // | // // MergeBlock // // | // // ExitBB // // / \ // // Create the start and exiting block. Function *F = SplitBlock->getParent(); BasicBlock *StartBlock = BasicBlock::Create(F->getContext(), "polly.start", F); BasicBlock *ExitingBlock = BasicBlock::Create(F->getContext(), "polly.exiting", F); SplitBlock->getTerminator()->eraseFromParent(); Builder.SetInsertPoint(SplitBlock); BranchInst *CondBr = Builder.CreateCondBr(RTC, StartBlock, S.getEntry()); if (Loop *L = LI.getLoopFor(SplitBlock)) { L->addBasicBlockToLoop(StartBlock, LI); L->addBasicBlockToLoop(ExitingBlock, LI); } DT.addNewBlock(StartBlock, SplitBlock); DT.addNewBlock(ExitingBlock, StartBlock); RI.setRegionFor(StartBlock, RI.getRegionFor(SplitBlock)); RI.setRegionFor(ExitingBlock, RI.getRegionFor(SplitBlock)); // \ / // // EnteringBB // // | // // SplitBlock---------\ // // _____|_____ | // // / EntryBB \ StartBlock // // | (region) | | // // \_ExitingBB_/ ExitingBlock // // | // // MergeBlock // // | // // ExitBB // // / \ // // Connect start block to exiting block. Builder.SetInsertPoint(StartBlock); Builder.CreateBr(ExitingBlock); DT.changeImmediateDominator(ExitingBlock, StartBlock); // Connect exiting block to join block. Builder.SetInsertPoint(ExitingBlock); Builder.CreateBr(MergeBlock); DT.changeImmediateDominator(MergeBlock, SplitBlock); // \ / // // EnteringBB // // | // // SplitBlock---------\ // // _____|_____ | // // / EntryBB \ StartBlock // // | (region) | | // // \_ExitingBB_/ ExitingBlock // // | | // // MergeBlock---------/ // // | // // ExitBB // // / \ // // // Split the edge between SplitBlock and EntryBB, to avoid a critical edge. splitEdge(SplitBlock, EntryBB, ".pre_entry_bb", &DT, &LI, &RI); // \ / // // EnteringBB // // | // // SplitBlock---------\ // // | | // // PreEntryBB | // // _____|_____ | // // / EntryBB \ StartBlock // // | (region) | | // // \_ExitingBB_/ ExitingBlock // // | | // // MergeBlock---------/ // // | // // ExitBB // // / \ // return std::make_pair(std::make_pair(StartBlock, ExitingBlock), CondBr); }