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

     1  //===- Block.cpp - MLIR Block Class ---------------------------------------===//
     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  #include "mlir/IR/Block.h"
    19  #include "mlir/IR/Builders.h"
    20  #include "mlir/IR/Operation.h"
    21  using namespace mlir;
    22  
    23  //===----------------------------------------------------------------------===//
    24  // BlockArgument
    25  //===----------------------------------------------------------------------===//
    26  
    27  /// Returns the number of this argument.
    28  unsigned BlockArgument::getArgNumber() {
    29    // Arguments are not stored in place, so we have to find it within the list.
    30    auto argList = getOwner()->getArguments();
    31    return std::distance(argList.begin(), llvm::find(argList, this));
    32  }
    33  
    34  //===----------------------------------------------------------------------===//
    35  // Block
    36  //===----------------------------------------------------------------------===//
    37  
    38  Block::~Block() {
    39    assert(!verifyInstOrder() && "Expected valid operation ordering.");
    40    clear();
    41  
    42    for (auto *arg : arguments)
    43      if (!arg->use_empty())
    44        arg->user_begin()->dump();
    45  
    46    llvm::DeleteContainerPointers(arguments);
    47  }
    48  
    49  Region *Block::getParent() { return parentValidInstOrderPair.getPointer(); }
    50  
    51  /// Returns the closest surrounding operation that contains this block or
    52  /// nullptr if this block is unlinked.
    53  Operation *Block::getParentOp() {
    54    return getParent() ? getParent()->getParentOp() : nullptr;
    55  }
    56  
    57  /// Return if this block is the entry block in the parent region.
    58  bool Block::isEntryBlock() { return this == &getParent()->front(); }
    59  
    60  /// Insert this block (which must not already be in a region) right before the
    61  /// specified block.
    62  void Block::insertBefore(Block *block) {
    63    assert(!getParent() && "already inserted into a block!");
    64    assert(block->getParent() && "cannot insert before a block without a parent");
    65    block->getParent()->getBlocks().insert(Region::iterator(block), this);
    66  }
    67  
    68  /// Unlink this Block from its parent Region and delete it.
    69  void Block::erase() {
    70    assert(getParent() && "Block has no parent");
    71    getParent()->getBlocks().erase(this);
    72  }
    73  
    74  /// Returns 'op' if 'op' lies in this block, or otherwise finds the
    75  /// ancestor operation of 'op' that lies in this block. Returns nullptr if
    76  /// the latter fails.
    77  Operation *Block::findAncestorInstInBlock(Operation &op) {
    78    // Traverse up the operation hierarchy starting from the owner of operand to
    79    // find the ancestor operation that resides in the block of 'forInst'.
    80    auto *currInst = &op;
    81    while (currInst->getBlock() != this) {
    82      currInst = currInst->getParentOp();
    83      if (!currInst)
    84        return nullptr;
    85    }
    86    return currInst;
    87  }
    88  
    89  /// This drops all operand uses from operations within this block, which is
    90  /// an essential step in breaking cyclic dependences between references when
    91  /// they are to be deleted.
    92  void Block::dropAllReferences() {
    93    for (Operation &i : *this)
    94      i.dropAllReferences();
    95  }
    96  
    97  void Block::dropAllDefinedValueUses() {
    98    for (auto *arg : getArguments())
    99      arg->dropAllUses();
   100    for (auto &op : *this)
   101      op.dropAllDefinedValueUses();
   102    dropAllUses();
   103  }
   104  
   105  /// Returns true if the ordering of the child operations is valid, false
   106  /// otherwise.
   107  bool Block::isInstOrderValid() { return parentValidInstOrderPair.getInt(); }
   108  
   109  /// Invalidates the current ordering of operations.
   110  void Block::invalidateInstOrder() {
   111    // Validate the current ordering.
   112    assert(!verifyInstOrder());
   113    parentValidInstOrderPair.setInt(false);
   114  }
   115  
   116  /// Verifies the current ordering of child operations. Returns false if the
   117  /// order is valid, true otherwise.
   118  bool Block::verifyInstOrder() {
   119    // The order is already known to be invalid.
   120    if (!isInstOrderValid())
   121      return false;
   122    // The order is valid if there are less than 2 operations.
   123    if (operations.empty() || std::next(operations.begin()) == operations.end())
   124      return false;
   125  
   126    Operation *prev = nullptr;
   127    for (auto &i : *this) {
   128      // The previous operation must have a smaller order index than the next as
   129      // it appears earlier in the list.
   130      if (prev && prev->orderIndex >= i.orderIndex)
   131        return true;
   132      prev = &i;
   133    }
   134    return false;
   135  }
   136  
   137  /// Recomputes the ordering of child operations within the block.
   138  void Block::recomputeInstOrder() {
   139    parentValidInstOrderPair.setInt(true);
   140  
   141    // TODO(riverriddle) Have non-congruent indices to reduce the number of times
   142    // an insert invalidates the list.
   143    unsigned orderIndex = 0;
   144    for (auto &op : *this)
   145      op.orderIndex = orderIndex++;
   146  }
   147  
   148  //===----------------------------------------------------------------------===//
   149  // Argument list management.
   150  //===----------------------------------------------------------------------===//
   151  
   152  BlockArgument *Block::addArgument(Type type) {
   153    auto *arg = new BlockArgument(type, this);
   154    arguments.push_back(arg);
   155    return arg;
   156  }
   157  
   158  /// Add one argument to the argument list for each type specified in the list.
   159  auto Block::addArguments(ArrayRef<Type> types)
   160      -> llvm::iterator_range<args_iterator> {
   161    arguments.reserve(arguments.size() + types.size());
   162    auto initialSize = arguments.size();
   163    for (auto type : types) {
   164      addArgument(type);
   165    }
   166    return {arguments.data() + initialSize, arguments.data() + arguments.size()};
   167  }
   168  
   169  void Block::eraseArgument(unsigned index, bool updatePredTerms) {
   170    assert(index < arguments.size());
   171  
   172    // Delete the argument.
   173    delete arguments[index];
   174    arguments.erase(arguments.begin() + index);
   175  
   176    // If we aren't updating predecessors, there is nothing left to do.
   177    if (!updatePredTerms)
   178      return;
   179  
   180    // Erase this argument from each of the predecessor's terminator.
   181    for (auto predIt = pred_begin(), predE = pred_end(); predIt != predE;
   182         ++predIt) {
   183      auto *predTerminator = (*predIt)->getTerminator();
   184      predTerminator->eraseSuccessorOperand(predIt.getSuccessorIndex(), index);
   185    }
   186  }
   187  
   188  //===----------------------------------------------------------------------===//
   189  // Terminator management
   190  //===----------------------------------------------------------------------===//
   191  
   192  /// Get the terminator operation of this block. This function asserts that
   193  /// the block has a valid terminator operation.
   194  Operation *Block::getTerminator() {
   195    assert(!empty() && !back().isKnownNonTerminator());
   196    return &back();
   197  }
   198  
   199  /// Return true if this block has no predecessors.
   200  bool Block::hasNoPredecessors() { return pred_begin() == pred_end(); }
   201  
   202  // Indexed successor access.
   203  unsigned Block::getNumSuccessors() {
   204    return empty() ? 0 : back().getNumSuccessors();
   205  }
   206  
   207  Block *Block::getSuccessor(unsigned i) {
   208    assert(i < getNumSuccessors());
   209    return getTerminator()->getSuccessor(i);
   210  }
   211  
   212  /// If this block has exactly one predecessor, return it.  Otherwise, return
   213  /// null.
   214  ///
   215  /// Note that multiple edges from a single block (e.g. if you have a cond
   216  /// branch with the same block as the true/false destinations) is not
   217  /// considered to be a single predecessor.
   218  Block *Block::getSinglePredecessor() {
   219    auto it = pred_begin();
   220    if (it == pred_end())
   221      return nullptr;
   222    auto *firstPred = *it;
   223    ++it;
   224    return it == pred_end() ? firstPred : nullptr;
   225  }
   226  
   227  //===----------------------------------------------------------------------===//
   228  // Other
   229  //===----------------------------------------------------------------------===//
   230  
   231  /// Split the block into two blocks before the specified operation or
   232  /// iterator.
   233  ///
   234  /// Note that all operations BEFORE the specified iterator stay as part of
   235  /// the original basic block, and the rest of the operations in the original
   236  /// block are moved to the new block, including the old terminator.  The
   237  /// original block is left without a terminator.
   238  ///
   239  /// The newly formed Block is returned, and the specified iterator is
   240  /// invalidated.
   241  Block *Block::splitBlock(iterator splitBefore) {
   242    // Start by creating a new basic block, and insert it immediate after this
   243    // one in the containing region.
   244    auto newBB = new Block();
   245    getParent()->getBlocks().insert(std::next(Region::iterator(this)), newBB);
   246  
   247    // Move all of the operations from the split point to the end of the region
   248    // into the new block.
   249    newBB->getOperations().splice(newBB->end(), getOperations(), splitBefore,
   250                                  end());
   251    return newBB;
   252  }
   253  
   254  //===----------------------------------------------------------------------===//
   255  // Predecessors
   256  //===----------------------------------------------------------------------===//
   257  
   258  Block *PredecessorIterator::unwrap(BlockOperand &value) {
   259    return value.getOwner()->getBlock();
   260  }
   261  
   262  /// Get the successor number in the predecessor terminator.
   263  unsigned PredecessorIterator::getSuccessorIndex() const {
   264    return I->getOperandNumber();
   265  }