2020-10-02 09:59:58 +08:00
|
|
|
//===- func_builder.h -------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// This file is licensed under a pytorch-style license
|
|
|
|
// See frontends/pytorch/LICENSE for license information.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2020-11-13 14:27:05 +08:00
|
|
|
#ifndef NPCOMP_FRONTENDS_PYTORCH_CSRC_BUILDER_FUNC_BUILDER_H
|
|
|
|
#define NPCOMP_FRONTENDS_PYTORCH_CSRC_BUILDER_FUNC_BUILDER_H
|
2020-10-02 09:59:58 +08:00
|
|
|
|
2020-11-25 05:10:27 +08:00
|
|
|
#include "mlir_utils.h"
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
#include "mlir-c/IR.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
|
|
|
|
#include <ATen/Tensor.h>
|
2020-11-21 09:03:23 +08:00
|
|
|
#include <ATen/core/function_schema.h>
|
2020-10-02 09:59:58 +08:00
|
|
|
|
|
|
|
namespace torch_mlir {
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
/// Wraps an MlirOperationState, deallocating it on destruction unless if
|
|
|
|
/// it has been consumed.
|
|
|
|
class OperationStateHolder {
|
|
|
|
public:
|
|
|
|
OperationStateHolder(const char *name, MlirLocation loc)
|
2020-11-24 11:20:26 +08:00
|
|
|
: state(mlirOperationStateGet(toMlirStringRef(name), loc)) {}
|
2020-10-06 14:21:21 +08:00
|
|
|
OperationStateHolder(const OperationStateHolder &) = delete;
|
|
|
|
OperationStateHolder(OperationStateHolder &&other) = delete;
|
|
|
|
~OperationStateHolder() {
|
|
|
|
if (owned) {
|
2020-11-24 07:01:51 +08:00
|
|
|
// Destroying is done by creating and then destroying the operation.
|
2020-10-06 14:21:21 +08:00
|
|
|
mlirOperationDestroy(createOperation());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-17 08:38:07 +08:00
|
|
|
operator MlirOperationState *() { return &state; }
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
MlirOperation createOperation() {
|
|
|
|
assert(owned && "cannot createOperation on unowned state");
|
|
|
|
owned = false;
|
|
|
|
return mlirOperationCreate(&state);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-10-17 08:38:07 +08:00
|
|
|
MlirOperationState state;
|
2020-10-06 14:21:21 +08:00
|
|
|
bool owned = true;
|
|
|
|
};
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
/// Maps various runtime types to MlirType.
|
|
|
|
class TypeMapper {
|
|
|
|
public:
|
|
|
|
TypeMapper(MlirContext context) : context(context) {}
|
|
|
|
|
|
|
|
/// Gets a corresponding MlirType for the Torch ScalarType.
|
|
|
|
/// Throws std::invalid_argument on failure.
|
2020-11-21 09:03:23 +08:00
|
|
|
MlirType mapFromTorchScalarType(c10::ScalarType scalarType);
|
2020-10-02 09:59:58 +08:00
|
|
|
|
|
|
|
/// Gets a corresponding MlirType for the forward component of a tensor.
|
|
|
|
/// Throws std::invalid_argument on failure.
|
|
|
|
MlirType forwardTensorToType(at::Tensor tensor);
|
|
|
|
|
2020-11-21 09:03:23 +08:00
|
|
|
/// Gets a corresponding MlirType for the Torch ScalarType.
|
|
|
|
/// Returns a null type on failure and emits a diagnostic.
|
|
|
|
MlirType mapFromTorchScalarType(MlirLocation loc, c10::ScalarType scalarType);
|
|
|
|
|
|
|
|
/// Maps a torch type to a corresponding MlirType. Returns a null type
|
|
|
|
/// on failure and emits a diagnostic.
|
|
|
|
MlirType mapFromTorchType(MlirLocation loc, const c10::TypePtr &torchType);
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
private:
|
2020-11-21 09:03:23 +08:00
|
|
|
/// Maps from a scalar type and returns null if no match (no other error
|
|
|
|
/// reporting).
|
|
|
|
MlirType rawMapFromTorchScalarType(c10::ScalarType scalarType);
|
2020-10-02 09:59:58 +08:00
|
|
|
MlirContext context;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Wraps an MlirBlock under construction, primarily tracking the terminator
|
|
|
|
/// and supporting manipulation of it. The terminator may be null if it has
|
2020-11-21 09:03:23 +08:00
|
|
|
/// not yet been constructed.
|
2020-10-02 09:59:58 +08:00
|
|
|
class BlockBuilder {
|
|
|
|
public:
|
|
|
|
BlockBuilder(MlirBlock block, MlirOperation terminator, bool isReturn)
|
|
|
|
: block(block), terminator(terminator), isReturn(isReturn) {}
|
|
|
|
|
|
|
|
MlirBlock getBlock() { return block; }
|
|
|
|
MlirOperation getTerminator() { return terminator; }
|
|
|
|
bool getIsReturnTerminator() { return isReturn; }
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
/// Inserts an owned operation before the terminator.
|
|
|
|
void insertBeforeTerminator(MlirOperation op) {
|
|
|
|
mlirBlockInsertOwnedOperationBefore(block, terminator, op);
|
|
|
|
}
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
private:
|
|
|
|
MlirBlock block;
|
|
|
|
MlirOperation terminator;
|
|
|
|
bool isReturn;
|
|
|
|
};
|
|
|
|
|
2020-11-21 09:03:23 +08:00
|
|
|
/// Builds a kernel call step by step.
|
|
|
|
class KernelCallBuilder {
|
|
|
|
public:
|
|
|
|
KernelCallBuilder(MlirContext context, MlirLocation loc,
|
|
|
|
llvm::StringRef kernelName,
|
|
|
|
const c10::FunctionSchema &schema);
|
|
|
|
void addOperand(MlirValue operand);
|
|
|
|
void addResultType(MlirType resultType);
|
|
|
|
MlirOperation create();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
MlirContext context;
|
|
|
|
MlirLocation loc;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void addSchemaAttrs();
|
|
|
|
OperationStateHolder state;
|
|
|
|
llvm::StringRef kernelName;
|
|
|
|
const c10::FunctionSchema &schema;
|
|
|
|
};
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
/// Wraps a 'func' MlirOperation and provides facilities for constructing
|
|
|
|
/// IR from some stream of Torch operations.
|
|
|
|
class FuncBuilder {
|
|
|
|
public:
|
2020-11-21 09:03:23 +08:00
|
|
|
/// Callback for inserting a function.
|
|
|
|
using Inserter = std::function<void(MlirOperation funcOp)>;
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
/// Creates a new func op with the given characteristics. The created
|
|
|
|
/// operation is not attached. The caller must either destroy it or add it
|
|
|
|
/// to a parent.
|
|
|
|
static std::unique_ptr<FuncBuilder>
|
2020-11-21 09:03:23 +08:00
|
|
|
createFunction(Inserter &inserter, MlirLocation location,
|
2020-10-02 09:59:58 +08:00
|
|
|
llvm::StringRef name,
|
|
|
|
llvm::SmallVectorImpl<MlirType> &inputTypes);
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
MlirContext getContext() { return context; }
|
2020-10-02 09:59:58 +08:00
|
|
|
MlirOperation getFuncOp() { return funcOp; }
|
|
|
|
|
|
|
|
/// Gets the function's entry block.
|
|
|
|
MlirBlock getEntryBlock() { return entryBlock.getBlock(); }
|
2020-10-06 14:21:21 +08:00
|
|
|
BlockBuilder &getEntryBlockBuilder() { return entryBlock; }
|
|
|
|
|
|
|
|
/// Rewrites the function's signature to return the given types. It is
|
|
|
|
/// assumed that a compatible terminator has been added.
|
|
|
|
void rewriteFuncReturnTypes(llvm::SmallVectorImpl<MlirType> &resultTypes);
|
2020-10-02 09:59:58 +08:00
|
|
|
|
|
|
|
/// Maps a live Tensor to an MlirValue.
|
|
|
|
void mapTensor(at::Tensor tensor, MlirValue value) {
|
|
|
|
tensorValueMap.push_back(std::make_pair(tensor, value));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Looks up a current mapping of tensor to an MlirValue, returning a null
|
|
|
|
/// value if not found.
|
|
|
|
MlirValue lookupTensor(at::Tensor tensor);
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
/// Gets a scalar constant value.
|
|
|
|
MlirValue getScalarConstant(MlirLocation loc, at::Scalar s);
|
|
|
|
|
2020-10-16 09:28:30 +08:00
|
|
|
/// Gets a bool constant value.
|
|
|
|
MlirValue getBoolConstant(MlirLocation loc, bool v);
|
|
|
|
|
2020-10-17 08:38:07 +08:00
|
|
|
/// Gets a None constant value.
|
|
|
|
MlirValue getNoneConstant(MlirLocation loc);
|
|
|
|
|
2020-10-16 09:28:30 +08:00
|
|
|
/// Gets a general constant value representing the given value
|
|
|
|
/// attribute.
|
|
|
|
MlirValue getGeneralConstant(MlirLocation loc, MlirAttribute value);
|
|
|
|
|
2020-11-03 07:30:21 +08:00
|
|
|
/// Builds a list with the given elements
|
|
|
|
MlirValue buildList(MlirLocation loc,
|
|
|
|
llvm::SmallVectorImpl<MlirValue> &elements);
|
2020-10-17 08:38:07 +08:00
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
private:
|
|
|
|
FuncBuilder(MlirContext context, MlirOperation funcOp,
|
|
|
|
BlockBuilder entryBlock)
|
|
|
|
: context(context), funcOp(funcOp), entryBlock(std::move(entryBlock)) {
|
|
|
|
(void)this->context;
|
|
|
|
}
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
/// Inserts a constant op into the function, returning its first result.
|
|
|
|
/// The function maintains a constant area at the top where these are
|
|
|
|
/// inserted.
|
|
|
|
MlirValue insertConstantOp(MlirOperation op);
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
MlirContext context;
|
|
|
|
|
|
|
|
/// The func op under construction.
|
|
|
|
MlirOperation funcOp;
|
|
|
|
|
|
|
|
/// Block builder for the entry block.
|
|
|
|
BlockBuilder entryBlock;
|
|
|
|
|
2020-10-06 14:21:21 +08:00
|
|
|
/// Previously inserted constant op or null.
|
|
|
|
MlirOperation prevConstantOp = {nullptr};
|
|
|
|
|
2020-10-02 09:59:58 +08:00
|
|
|
/// Maps tensors to MlirValue. Unfortunately, this needs to be a linear scan
|
|
|
|
/// because the impl pointer for the Tensor is not accessible. To make this
|
|
|
|
/// slightly better, we add to the back and lookup in reverse under the idea
|
|
|
|
/// that tensors may be mapped and accessed in proximity.
|
2020-10-06 14:21:21 +08:00
|
|
|
/// TODO: Tensors referenced via an IValue support hash code lookup and
|
|
|
|
/// identity checks. Switch to this instead of a linear scan.
|
2020-10-02 09:59:58 +08:00
|
|
|
llvm::SmallVector<std::pair<at::Tensor, MlirValue>, 16> tensorValueMap;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace torch_mlir
|
|
|
|
|
2020-11-13 14:27:05 +08:00
|
|
|
#endif // NPCOMP_FRONTENDS_PYTORCH_CSRC_BUILDER_FUNC_BUILDER_H
|