|  | //===--- Utils.cpp - Utility functions for the code generation --*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains utility functions for the code generation. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "polly/CodeGen/Utils.h" | 
|  | #include "polly/CodeGen/IRBuilder.h" | 
|  | #include "polly/ScopInfo.h" | 
|  | #include "llvm/Analysis/LoopInfo.h" | 
|  | #include "llvm/Analysis/RegionInfo.h" | 
|  | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | // Alternative to llvm::SplitCriticalEdge. | 
|  | // | 
|  | // Creates a new block which branches to Succ. The edge to split is redirected | 
|  | // to the new block. | 
|  | // | 
|  | // The issue with llvm::SplitCriticalEdge is that it does nothing if the edge is | 
|  | // not critical. | 
|  | // The issue with llvm::SplitEdge is that it does not always create the middle | 
|  | // block, but reuses Prev/Succ if it can. We always want a new middle block. | 
|  | static BasicBlock *splitEdge(BasicBlock *Prev, BasicBlock *Succ, | 
|  | const char *Suffix, DominatorTree *DT, | 
|  | LoopInfo *LI, RegionInfo *RI) { | 
|  | assert(Prev && Succ); | 
|  |  | 
|  | // Before: | 
|  | //   \    /     /   // | 
|  | //    Prev     /    // | 
|  | //     |  \___/     // | 
|  | //     |   ___      // | 
|  | //     |  /   \     // | 
|  | //    Succ     \    // | 
|  | //   /    \     \   // | 
|  |  | 
|  | // The algorithm to update DominatorTree and LoopInfo of | 
|  | // llvm::SplitCriticalEdge is more efficient than | 
|  | // llvm::SplitBlockPredecessors, which is more general. In the future we might | 
|  | // either modify llvm::SplitCriticalEdge to allow skipping the critical edge | 
|  | // check; or Copy&Pase it here. | 
|  | BasicBlock *MiddleBlock = SplitBlockPredecessors( | 
|  | Succ, ArrayRef<BasicBlock *>(Prev), Suffix, DT, LI); | 
|  |  | 
|  | if (RI) { | 
|  | Region *PrevRegion = RI->getRegionFor(Prev); | 
|  | Region *SuccRegion = RI->getRegionFor(Succ); | 
|  | if (PrevRegion->contains(MiddleBlock)) { | 
|  | RI->setRegionFor(MiddleBlock, PrevRegion); | 
|  | } else { | 
|  | RI->setRegionFor(MiddleBlock, SuccRegion); | 
|  | } | 
|  | } | 
|  |  | 
|  | // After: | 
|  | //   \    /     /   // | 
|  | //    Prev     /    // | 
|  | //     |  \___/     // | 
|  | //     |            // | 
|  | // MiddleBlock      // | 
|  | //     |   ___      // | 
|  | //     |  /   \     // | 
|  | //    Succ     \    // | 
|  | //   /    \     \   // | 
|  |  | 
|  | return MiddleBlock; | 
|  | } | 
|  |  | 
|  | 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); | 
|  | } |