| //===--- CFG.h - Utilities for SIL CFG transformations ----------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H |
| #define SWIFT_SILOPTIMIZER_UTILS_CFG_H |
| |
| #include "swift/SIL/SILInstruction.h" |
| #include "swift/SIL/SILBuilder.h" |
| |
| namespace swift { |
| |
| class DominanceInfo; |
| class SILLoop; |
| class SILLoopInfo; |
| |
| /// \brief Adds a new argument to an edge between a branch and a destination |
| /// block. |
| /// |
| /// \param Branch The terminator to add the argument to. |
| /// \param Dest The destination block of the edge. |
| /// \param Val The value to the arguments of the branch. |
| /// \return The created branch. The old branch is deleted. |
| /// The argument is appended at the end of the argument tuple. |
| TermInst *addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest, |
| SILValue Val); |
| |
| /// \brief Changes the edge value between a branch and destination basic block |
| /// at the specified index. Changes all edges from \p Branch to \p Dest to carry |
| /// the value. |
| /// |
| /// \param Branch The branch to modify. |
| /// \param Dest The destination of the edge. |
| /// \param Idx The index of the argument to modify. |
| /// \param Val The new value to use. |
| /// \return The new branch. Deletes the old one. |
| TermInst *changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, size_t Idx, |
| SILValue Val); |
| |
| /// \brief Replace a branch target. |
| /// |
| /// \param T The terminating instruction to modify. |
| /// \param EdgeIdx The successor edges index that will be replaced. |
| /// \param NewDest The new target block. |
| /// \param PreserveArgs If set, preserve arguments on the replaced edge. |
| void changeBranchTarget(TermInst *T, unsigned EdgeIdx, SILBasicBlock *NewDest, |
| bool PreserveArgs); |
| |
| /// \brief Replace a branch target. |
| /// |
| /// \param T The terminating instruction to modify. |
| /// \param OldDest The successor block that will be replaced. |
| /// \param NewDest The new target block. |
| /// \param PreserveArgs If set, preserve arguments on the replaced edge. |
| void replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, SILBasicBlock *NewDest, |
| bool PreserveArgs); |
| |
| /// \brief Check if the edge from the terminator is critical. |
| bool isCriticalEdge(TermInst *T, unsigned EdgeIdx); |
| |
| /// \brief Splits the edge from terminator if it is critical. |
| /// |
| /// Updates dominance information and loop information if not null. |
| /// Returns the newly created basic block on success or nullptr otherwise (if |
| /// the edge was not critical). |
| SILBasicBlock *splitCriticalEdge(TermInst *T, unsigned EdgeIdx, |
| DominanceInfo *DT = nullptr, |
| SILLoopInfo *LI = nullptr); |
| |
| /// Splits the critical edges between from and to. This code assumes there is |
| /// exactly one edge between the two basic blocks. It will return the wrong |
| /// result if there are multiple edges and will assert if there are no edges in |
| /// between the two blocks. |
| /// |
| /// Updates dominance information and loop information if not null. |
| SILBasicBlock *splitIfCriticalEdge(SILBasicBlock *From, SILBasicBlock *To, |
| DominanceInfo *DT = nullptr, |
| SILLoopInfo *LI = nullptr); |
| |
| /// \brief Splits the edge from terminator. |
| /// |
| /// Updates dominance information and loop information if not null. |
| /// Returns the newly created basic block. |
| SILBasicBlock *splitEdge(TermInst *T, unsigned EdgeIdx, |
| DominanceInfo *DT = nullptr, |
| SILLoopInfo *LI = nullptr); |
| |
| /// \brief Splits the edges between two basic blocks. |
| /// |
| /// Updates dominance information and loop information if not null. |
| void splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To, |
| DominanceInfo *DT = nullptr, SILLoopInfo *LI = nullptr); |
| |
| /// \brief Rotate a loop's header as long as it is exiting and not equal to the |
| /// passed basic block. |
| /// If \p RotateSingleBlockLoops is true a single basic block loop will be |
| /// rotated once. ShouldVerify specifies whether to perform verification after |
| /// the transformation. |
| /// Returns true if the loop could be rotated. |
| bool rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, |
| bool RotateSingleBlockLoops, SILBasicBlock *UpTo, |
| bool ShouldVerify); |
| |
| /// \brief Splits the basic block before the instruction with an unconditional |
| /// branch and updates the dominator tree and loop info. |
| SILBasicBlock *splitBasicBlockAndBranch(SILBuilder &B, |
| SILInstruction *SplitBeforeInst, |
| DominanceInfo *DT, SILLoopInfo *LI); |
| |
| /// \brief Return true if the function has a critical edge, false otherwise. |
| bool hasCriticalEdges(SILFunction &F, bool OnlyNonCondBr); |
| |
| /// \brief Split all critical edges in the function updating the dominator tree |
| /// and loop information (if they are not set to null). If \p OnlyNonCondBr is |
| /// true this will not split cond_br edges (Only edges which can't carry |
| /// arguments will be split). |
| bool splitAllCriticalEdges(SILFunction &F, bool OnlyNonCondBr, |
| DominanceInfo *DT, SILLoopInfo *LI); |
| |
| /// \brief Merge a basic block ending in a branch with its successor |
| /// if possible. If dominance information or loop info is non null update it. |
| /// Return true if block was merged. |
| bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT, |
| SILLoopInfo *LI); |
| |
| } // end namespace swift |
| #endif |