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

     1  //===- Function.cpp - MLIR Function Classes -------------------------------===//
     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/Function.h"
    19  #include "mlir/IR/BlockAndValueMapping.h"
    20  #include "mlir/IR/Builders.h"
    21  #include "mlir/IR/Diagnostics.h"
    22  #include "mlir/IR/Dialect.h"
    23  #include "mlir/IR/MLIRContext.h"
    24  #include "mlir/IR/Module.h"
    25  #include "mlir/IR/OpImplementation.h"
    26  #include "llvm/ADT/MapVector.h"
    27  #include "llvm/ADT/SmallString.h"
    28  #include "llvm/ADT/Twine.h"
    29  
    30  using namespace mlir;
    31  
    32  //===----------------------------------------------------------------------===//
    33  // Function Operation.
    34  //===----------------------------------------------------------------------===//
    35  
    36  FuncOp FuncOp::create(Location location, StringRef name, FunctionType type,
    37                        ArrayRef<NamedAttribute> attrs) {
    38    OperationState state(location, "func");
    39    Builder builder(location->getContext());
    40    FuncOp::build(&builder, &state, name, type, attrs);
    41    return llvm::cast<FuncOp>(Operation::create(state));
    42  }
    43  FuncOp FuncOp::create(Location location, StringRef name, FunctionType type,
    44                        llvm::iterator_range<dialect_attr_iterator> attrs) {
    45    SmallVector<NamedAttribute, 8> attrRef(attrs);
    46    return create(location, name, type, llvm::makeArrayRef(attrRef));
    47  }
    48  FuncOp FuncOp::create(Location location, StringRef name, FunctionType type,
    49                        ArrayRef<NamedAttribute> attrs,
    50                        ArrayRef<NamedAttributeList> argAttrs) {
    51    FuncOp func = create(location, name, type, attrs);
    52    func.setAllArgAttrs(argAttrs);
    53    return func;
    54  }
    55  
    56  void FuncOp::build(Builder *builder, OperationState *result, StringRef name,
    57                     FunctionType type, ArrayRef<NamedAttribute> attrs) {
    58    result->addAttribute(SymbolTable::getSymbolAttrName(),
    59                         builder->getStringAttr(name));
    60    result->addAttribute(getTypeAttrName(), builder->getTypeAttr(type));
    61    result->attributes.append(attrs.begin(), attrs.end());
    62    result->addRegion();
    63  }
    64  
    65  void FuncOp::build(Builder *builder, OperationState *result, StringRef name,
    66                     FunctionType type, ArrayRef<NamedAttribute> attrs,
    67                     ArrayRef<NamedAttributeList> argAttrs) {
    68    build(builder, result, name, type, attrs);
    69    assert(type.getNumInputs() == argAttrs.size());
    70    SmallString<8> argAttrName;
    71    for (unsigned i = 0, e = type.getNumInputs(); i != e; ++i)
    72      if (auto argDict = argAttrs[i].getDictionary())
    73        result->addAttribute(getArgAttrName(i, argAttrName), argDict);
    74  }
    75  
    76  /// Parsing/Printing methods.
    77  
    78  ParseResult FuncOp::parse(OpAsmParser *parser, OperationState *result) {
    79    auto buildFuncType = [](Builder &builder, ArrayRef<Type> argTypes,
    80                            ArrayRef<Type> results, impl::VariadicFlag,
    81                            std::string &) {
    82      return builder.getFunctionType(argTypes, results);
    83    };
    84  
    85    return impl::parseFunctionLikeOp(parser, result, /*allowVariadic=*/false,
    86                                     buildFuncType);
    87  }
    88  
    89  void FuncOp::print(OpAsmPrinter *p) {
    90    FunctionType fnType = getType();
    91    impl::printFunctionLikeOp(p, *this, fnType.getInputs(), /*isVariadic=*/false,
    92                              fnType.getResults());
    93  }
    94  
    95  LogicalResult FuncOp::verify() {
    96    // If this function is external there is nothing to do.
    97    if (isExternal())
    98      return success();
    99  
   100    // Verify that the argument list of the function and the arg list of the entry
   101    // block line up.  The trait already verified that the number of arguments is
   102    // the same between the signature and the block.
   103    auto fnInputTypes = getType().getInputs();
   104    Block &entryBlock = front();
   105    for (unsigned i = 0, e = entryBlock.getNumArguments(); i != e; ++i)
   106      if (fnInputTypes[i] != entryBlock.getArgument(i)->getType())
   107        return emitOpError("type of entry block argument #")
   108               << i << '(' << entryBlock.getArgument(i)->getType()
   109               << ") must match the type of the corresponding argument in "
   110               << "function signature(" << fnInputTypes[i] << ')';
   111  
   112    return success();
   113  }
   114  
   115  /// Add an entry block to an empty function, and set up the block arguments
   116  /// to match the signature of the function.
   117  Block *FuncOp::addEntryBlock() {
   118    assert(empty() && "function already has an entry block");
   119    auto *entry = new Block();
   120    push_back(entry);
   121    entry->addArguments(getType().getInputs());
   122    return entry;
   123  }
   124  
   125  /// Clone the internal blocks from this function into dest and all attributes
   126  /// from this function to dest.
   127  void FuncOp::cloneInto(FuncOp dest, BlockAndValueMapping &mapper) {
   128    // Add the attributes of this function to dest.
   129    llvm::MapVector<Identifier, Attribute> newAttrs;
   130    for (auto &attr : dest.getAttrs())
   131      newAttrs.insert(attr);
   132    for (auto &attr : getAttrs())
   133      newAttrs.insert(attr);
   134    dest.getOperation()->setAttrs(
   135        DictionaryAttr::get(newAttrs.takeVector(), getContext()));
   136  
   137    // Clone the body.
   138    getBody().cloneInto(&dest.getBody(), mapper);
   139  }
   140  
   141  /// Create a deep copy of this function and all of its blocks, remapping
   142  /// any operands that use values outside of the function using the map that is
   143  /// provided (leaving them alone if no entry is present). Replaces references
   144  /// to cloned sub-values with the corresponding value that is copied, and adds
   145  /// those mappings to the mapper.
   146  FuncOp FuncOp::clone(BlockAndValueMapping &mapper) {
   147    FunctionType newType = getType();
   148  
   149    // If the function has a body, then the user might be deleting arguments to
   150    // the function by specifying them in the mapper. If so, we don't add the
   151    // argument to the input type vector.
   152    bool isExternalFn = isExternal();
   153    if (!isExternalFn) {
   154      SmallVector<Type, 4> inputTypes;
   155      inputTypes.reserve(newType.getNumInputs());
   156      for (unsigned i = 0, e = getNumArguments(); i != e; ++i)
   157        if (!mapper.contains(getArgument(i)))
   158          inputTypes.push_back(newType.getInput(i));
   159      newType = FunctionType::get(inputTypes, newType.getResults(), getContext());
   160    }
   161  
   162    // Create the new function.
   163    FuncOp newFunc = llvm::cast<FuncOp>(getOperation()->cloneWithoutRegions());
   164    newFunc.setType(newType);
   165  
   166    /// Set the argument attributes for arguments that aren't being replaced.
   167    for (unsigned i = 0, e = getNumArguments(), destI = 0; i != e; ++i)
   168      if (isExternalFn || !mapper.contains(getArgument(i)))
   169        newFunc.setArgAttrs(destI++, getArgAttrs(i));
   170  
   171    /// Clone the current function into the new one and return it.
   172    cloneInto(newFunc, mapper);
   173    return newFunc;
   174  }
   175  FuncOp FuncOp::clone() {
   176    BlockAndValueMapping mapper;
   177    return clone(mapper);
   178  }