本章主要讲解了如何创建一个自己的Dialect并创建其中的Operations。
我们使用ODS框架(Operation Defination Specification)来讲编写的.td文件自动转换成c++文件。下面的思路图我偷了知乎的法斯特豪斯:
图里说的很明白,三步:定义自己的Dialect,创建自己Dialect Operation的基类,在自己的Dialect里创建各种Operations。
下面我们就添加一个自己的Operation,作用是实现向量的自增,首先在.td里定义如下:
def SelfAddOp : Toy_Op<"selfadd"> {
let summary = "self-add operation";
let arguments = (ins F64Tensor:$input);
let results = (outs F64Tensor);
let assemblyFormat = [{
`(` $input `:` type($input) `)` attr-dict `to` type(results)
}];
// Allow building a TransposeOp with from the input operand.
let builders = [
OpBuilder<(ins "Value":$input)>
];
// Invoke a static verify method to verify this transpose operation.
let hasVerifier = 1;
}
之后我们可以使用mlir-tblgen工具搭配-gen-op-decls查看生成的operations C++声明。
bin/mlir-tblgen -gen-op-decls ../mlir/examples/toy/Ch2/include/toy/Ops.td -I ../mlir/include/
使用mlir-tblgen工具搭配-gen-op-defs查看生成的operations C++定义。
bin/mlir-tblgen -gen-op-defs ../mlir/examples/toy/Ch2/include/toy/Ops.td -I ../mlir/include/
然后我们在Dialect.cpp里添加selfadd operation的build和verify函数实现:
void SelfAddOp::build(mlir::OpBuilder &builder, mlir::OperationState &state,
mlir::Value value) {
state.addTypes(UnrankedTensorType::get(builder.getF64Type()));
state.addOperands(value);
} //配置一个新的操作状态:将操作的结果Type设置为UnrankedTensorType,元素类型为F64;设置操作数为操作输入值value。
llvm::LogicalResult SelfAddOp::verify() {
auto inputType = llvm::dyn_cast<RankedTensorType>(getOperand().getType());
auto resultType = llvm::dyn_cast<RankedTensorType>(getType());
if (!inputType || !resultType)
return mlir::success();
auto inputShape = inputType.getShape();
if (!std::equal(inputShape.begin(), inputShape.end(),
resultType.getShape().begin())) {
return emitError()
<< "the shape does not fit";
}
return mlir::success();
} //verify用于验证操作的合法性。inputType是操作数的Type,resultType是结果的Type,通过检查操作数Type的shape是否和结果Type的shape相同来验证合法性。
最后,我们在MLIRGen.cpp里的mlir::Value mlirGen(CallExprAST &call)函数里添加对selfadd调用时的操作:
if (callee == "selfadd") {
if (call.getArgs().size() != 1) {
emitError(location, "MLIR codegen encountered an error: toy.selfadd "
"does not accept multiple arguments");
return nullptr;
}
return builder.create<SelfAddOp>(location, operands[0]);
}
至此,添加自己的Operation(一个selfadd操作)完成。