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

     1  //===- OperationSupport.cpp -----------------------------------------------===//
     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  // This file contains out-of-line implementations of the support types that
    19  // Operation and related classes build on top of.
    20  //
    21  //===----------------------------------------------------------------------===//
    22  
    23  #include "mlir/IR/OperationSupport.h"
    24  #include "mlir/IR/Block.h"
    25  #include "mlir/IR/Operation.h"
    26  using namespace mlir;
    27  
    28  //===----------------------------------------------------------------------===//
    29  // OperationState
    30  //===----------------------------------------------------------------------===//
    31  
    32  OperationState::OperationState(Location location, StringRef name)
    33      : location(location), name(name, location->getContext()) {}
    34  
    35  OperationState::OperationState(Location location, OperationName name)
    36      : location(location), name(name) {}
    37  
    38  OperationState::OperationState(Location location, StringRef name,
    39                                 ArrayRef<Value *> operands, ArrayRef<Type> types,
    40                                 ArrayRef<NamedAttribute> attributes,
    41                                 ArrayRef<Block *> successors,
    42                                 MutableArrayRef<std::unique_ptr<Region>> regions,
    43                                 bool resizableOperandList)
    44      : location(location), name(name, location->getContext()),
    45        operands(operands.begin(), operands.end()),
    46        types(types.begin(), types.end()),
    47        attributes(attributes.begin(), attributes.end()),
    48        successors(successors.begin(), successors.end()) {
    49    for (std::unique_ptr<Region> &r : regions)
    50      this->regions.push_back(std::move(r));
    51  }
    52  
    53  Region *OperationState::addRegion() {
    54    regions.emplace_back(new Region);
    55    return regions.back().get();
    56  }
    57  
    58  void OperationState::addRegion(std::unique_ptr<Region> &&region) {
    59    regions.push_back(std::move(region));
    60  }
    61  
    62  //===----------------------------------------------------------------------===//
    63  // OperandStorage
    64  //===----------------------------------------------------------------------===//
    65  
    66  /// Replace the operands contained in the storage with the ones provided in
    67  /// 'operands'.
    68  void detail::OperandStorage::setOperands(Operation *owner,
    69                                           ArrayRef<Value *> operands) {
    70    // If the number of operands is less than or equal to the current amount, we
    71    // can just update in place.
    72    if (operands.size() <= numOperands) {
    73      auto opOperands = getOperands();
    74  
    75      // If the number of new operands is less than the current count, then remove
    76      // any extra operands.
    77      for (unsigned i = operands.size(); i != numOperands; ++i)
    78        opOperands[i].~OpOperand();
    79  
    80      // Set the operands in place.
    81      numOperands = operands.size();
    82      for (unsigned i = 0; i != numOperands; ++i)
    83        opOperands[i].set(operands[i]);
    84      return;
    85    }
    86  
    87    // Otherwise, we need to be resizable.
    88    assert(resizable && "Only resizable operations may add operands");
    89  
    90    // Grow the capacity if necessary.
    91    auto &resizeUtil = getResizableStorage();
    92    if (resizeUtil.capacity < operands.size())
    93      grow(resizeUtil, operands.size());
    94  
    95    // Set the operands.
    96    OpOperand *opBegin = getRawOperands();
    97    for (unsigned i = 0; i != numOperands; ++i)
    98      opBegin[i].set(operands[i]);
    99    for (unsigned e = operands.size(); numOperands != e; ++numOperands)
   100      new (&opBegin[numOperands]) OpOperand(owner, operands[numOperands]);
   101  }
   102  
   103  /// Erase an operand held by the storage.
   104  void detail::OperandStorage::eraseOperand(unsigned index) {
   105    assert(index < size());
   106    auto operands = getOperands();
   107    --numOperands;
   108  
   109    // Shift all operands down by 1 if the operand to remove is not at the end.
   110    auto indexIt = std::next(operands.begin(), index);
   111    if (index != numOperands)
   112      std::rotate(indexIt, std::next(indexIt), operands.end());
   113    operands[numOperands].~OpOperand();
   114  }
   115  
   116  /// Grow the internal operand storage.
   117  void detail::OperandStorage::grow(ResizableStorage &resizeUtil,
   118                                    size_t minSize) {
   119    // Allocate a new storage array.
   120    resizeUtil.capacity =
   121        std::max(size_t(llvm::NextPowerOf2(resizeUtil.capacity + 2)), minSize);
   122    OpOperand *newStorage = static_cast<OpOperand *>(
   123        llvm::safe_malloc(resizeUtil.capacity * sizeof(OpOperand)));
   124  
   125    // Move the current operands to the new storage.
   126    auto operands = getOperands();
   127    std::uninitialized_copy(std::make_move_iterator(operands.begin()),
   128                            std::make_move_iterator(operands.end()), newStorage);
   129  
   130    // Destroy the original operands and update the resizable storage pointer.
   131    for (auto &operand : operands)
   132      operand.~OpOperand();
   133    resizeUtil.setDynamicStorage(newStorage);
   134  }