github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Analysis/Dominance.cpp (about)

     1  //===- Dominance.cpp - Dominator analysis for CFGs ------------------------===//
     2  //
     3  // Copyright 2019 The MLIR Authors.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //   http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  // =============================================================================
    17  //
    18  // Implementation of dominance related classes and instantiations of extern
    19  // templates.
    20  //
    21  //===----------------------------------------------------------------------===//
    22  
    23  #include "mlir/Analysis/Dominance.h"
    24  #include "mlir/IR/Operation.h"
    25  #include "llvm/Support/GenericDomTreeConstruction.h"
    26  
    27  using namespace mlir;
    28  using namespace mlir::detail;
    29  
    30  template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/false>;
    31  template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/true>;
    32  template class llvm::DomTreeNodeBase<Block>;
    33  
    34  //===----------------------------------------------------------------------===//
    35  // DominanceInfoBase
    36  //===----------------------------------------------------------------------===//
    37  
    38  template <bool IsPostDom>
    39  void DominanceInfoBase<IsPostDom>::recalculate(Operation *op) {
    40    dominanceInfos.clear();
    41  
    42    /// Build the dominance for each of the operation regions.
    43    op->walk([&](Operation *op) {
    44      for (auto &region : op->getRegions()) {
    45        // Don't compute dominance if the region is empty.
    46        if (region.empty())
    47          continue;
    48        auto opDominance = std::make_unique<base>();
    49        opDominance->recalculate(region);
    50        dominanceInfos.try_emplace(&region, std::move(opDominance));
    51      }
    52    });
    53  }
    54  
    55  /// Return true if the specified block A properly dominates block B.
    56  template <bool IsPostDom>
    57  bool DominanceInfoBase<IsPostDom>::properlyDominates(Block *a, Block *b) {
    58    // A block dominates itself but does not properly dominate itself.
    59    if (a == b)
    60      return false;
    61  
    62    // If either a or b are null, then conservatively return false.
    63    if (!a || !b)
    64      return false;
    65  
    66    // If both blocks are not in the same region, 'a' properly dominates 'b' if
    67    // 'b' is defined in an operation region that (recursively) ends up being
    68    // dominated by 'a'. Walk up the list of containers enclosing B.
    69    auto *regionA = a->getParent(), *regionB = b->getParent();
    70    if (regionA != regionB) {
    71      Operation *bAncestor;
    72      do {
    73        bAncestor = regionB->getParentOp();
    74        // If 'bAncestor' is the top level region, then 'a' is a block that post
    75        // dominates 'b'.
    76        if (!bAncestor || !bAncestor->getBlock())
    77          return IsPostDom;
    78  
    79        regionB = bAncestor->getBlock()->getParent();
    80      } while (regionA != regionB);
    81  
    82      // Check to see if the ancestor of 'b' is the same block as 'a'.
    83      b = bAncestor->getBlock();
    84      if (a == b)
    85        return true;
    86    }
    87  
    88    // Otherwise, use the standard dominance functionality.
    89  
    90    // If we don't have a dominance information for this region, assume that b is
    91    // dominated by anything.
    92    auto baseInfoIt = dominanceInfos.find(regionA);
    93    if (baseInfoIt == dominanceInfos.end())
    94      return true;
    95    return baseInfoIt->second->properlyDominates(a, b);
    96  }
    97  
    98  template class mlir::detail::DominanceInfoBase</*IsPostDom=*/true>;
    99  template class mlir::detail::DominanceInfoBase</*IsPostDom=*/false>;
   100  
   101  //===----------------------------------------------------------------------===//
   102  // DominanceInfo
   103  //===----------------------------------------------------------------------===//
   104  
   105  /// Return true if operation A properly dominates operation B.
   106  bool DominanceInfo::properlyDominates(Operation *a, Operation *b) {
   107    auto *aBlock = a->getBlock(), *bBlock = b->getBlock();
   108  
   109    // If a or b are not within a block, then a does not dominate b.
   110    if (!aBlock || !bBlock)
   111      return false;
   112  
   113    // If the blocks are the same, then check if b is before a in the block.
   114    if (aBlock == bBlock)
   115      return a->isBeforeInBlock(b);
   116  
   117    // Traverse up b's hierarchy to check if b's block is contained in a's.
   118    if (auto *bAncestor = aBlock->findAncestorInstInBlock(*b)) {
   119      // Since we already know that aBlock != bBlock, here bAncestor != b.
   120      // a and bAncestor are in the same block; check if 'a' dominates
   121      // bAncestor.
   122      return dominates(a, bAncestor);
   123    }
   124  
   125    // If the blocks are different, check if a's block dominates b's.
   126    return properlyDominates(aBlock, bBlock);
   127  }
   128  
   129  /// Return true if value A properly dominates operation B.
   130  bool DominanceInfo::properlyDominates(Value *a, Operation *b) {
   131    if (auto *aInst = a->getDefiningOp())
   132      return properlyDominates(aInst, b);
   133  
   134    // block arguments properly dominate all operations in their own block, so
   135    // we use a dominates check here, not a properlyDominates check.
   136    return dominates(cast<BlockArgument>(a)->getOwner(), b->getBlock());
   137  }
   138  
   139  //===----------------------------------------------------------------------===//
   140  // PostDominanceInfo
   141  //===----------------------------------------------------------------------===//
   142  
   143  /// Returns true if statement 'a' properly postdominates statement b.
   144  bool PostDominanceInfo::properlyPostDominates(Operation *a, Operation *b) {
   145    auto *aBlock = a->getBlock(), *bBlock = b->getBlock();
   146  
   147    // If a or b are not within a block, then a does not post dominate b.
   148    if (!aBlock || !bBlock)
   149      return false;
   150  
   151    // If the blocks are the same, check if b is before a in the block.
   152    if (aBlock == bBlock)
   153      return b->isBeforeInBlock(a);
   154  
   155    // Traverse up b's hierarchy to check if b's block is contained in a's.
   156    if (auto *bAncestor = a->getBlock()->findAncestorInstInBlock(*b))
   157      // Since we already know that aBlock != bBlock, here bAncestor != b.
   158      // a and bAncestor are in the same block; check if 'a' postdominates
   159      // bAncestor.
   160      return postDominates(a, bAncestor);
   161  
   162    // If the blocks are different, check if a's block post dominates b's.
   163    return properlyDominates(aBlock, bBlock);
   164  }