add_mlir_interface(TosaInterfaces)
set(LLVM_TARGET_DEFINITIONS TosaOps.td)
-mlir_tablegen(TosaStructs.h.inc -gen-struct-attr-decls)
-mlir_tablegen(TosaStructs.cpp.inc -gen-struct-attr-defs)
-add_public_tablegen_target(MLIRTosaStructsIncGen)
-
+mlir_tablegen(TosaAttributes.h.inc -gen-attrdef-decls)
+mlir_tablegen(TosaAttributes.cpp.inc -gen-attrdef-defs)
+add_public_tablegen_target(MLIRTosaAttributesIncGen)
//
//===----------------------------------------------------------------------===//
-
#ifndef TOSA_OP_BASE
#define TOSA_OP_BASE
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/OpBase.td"
+
//===----------------------------------------------------------------------===//
// The TOSA Dialect.
//===----------------------------------------------------------------------===//
+
def Tosa_Dialect : Dialect {
let name = "tosa";
let cppNamespace = "mlir::tosa";
let hasConstantMaterializer = 1;
+ let useDefaultAttributePrinterParser = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// TOSA Attributes.
+//===----------------------------------------------------------------------===//
+
+class Tosa_Attr<string attrName, string attrMnemonic, list<Trait> traits = []>
+ : AttrDef<Tosa_Dialect, attrName, traits> {
+ let mnemonic = attrMnemonic;
}
//===----------------------------------------------------------------------===//
// feed numerical precision parameters to the functional implementation of TOSA
// operators.
// The functional behavior is defined in the TOSA specification maintained at
-// https://developer.mlplatform.org/w/tosa/ . TOSA leverages MLIR's built in
+// https://developer.mlplatform.org/w/tosa/. TOSA leverages MLIR's built in
// quantization support: https://mlir.llvm.org/docs/Quantization/, and supports
// uniform quantization. Depending on datatype, asymmetric and symmetric
// quantization are supported. The types themselves are described in
// This quantization attribute expresses numerical behavior of operators where
// the operator has a numerical relationship between a single input and output.
// For example: tosa.negate.
-def Tosa_UnaryOpQuantizationAttr : StructAttr<"UnaryOpQuantizationAttr",
- Tosa_Dialect, [
- StructFieldAttr<"input_zp", I32Attr>,
- StructFieldAttr<"output_zp", I32Attr>
- ]> {
+def Tosa_UnaryOpQuantizationAttr
+ : Tosa_Attr<"UnaryOpQuantization", "unary_quant"> {
let summary = "Attribute for UnaryOp quantization information.";
+ let parameters = (ins "int64_t":$input_zp, "int64_t":$output_zp);
+ let assemblyFormat = "`<` struct(params) `>`";
}
// There is no explicit BinaryOpQuantizationAttr for 2-input/1-output ops. In
// the inputs.
// The scaling of their accumulator output is done using an explicit
// tosa.rescale operator that scales the accumulator result to output scale.
-def Tosa_ConvOpQuantizationAttr : StructAttr<"ConvOpQuantizationAttr",
- Tosa_Dialect, [
- StructFieldAttr<"input_zp", I32Attr>,
- StructFieldAttr<"weight_zp", I32Attr>
- ]> {
+def Tosa_ConvOpQuantizationAttr
+ : Tosa_Attr<"ConvOpQuantization", "conv_quant"> {
let summary = "Attribute for Conv type op quantization information.";
+ let parameters = (ins "int64_t":$input_zp, "int64_t":$weight_zp);
+ let assemblyFormat = "`<` struct(params) `>`";
}
-def Tosa_MatMulOpQuantizationAttr : StructAttr<"MatMulOpQuantizationAttr",
- Tosa_Dialect, [
- StructFieldAttr<"a_zp", I32Attr>,
- StructFieldAttr<"b_zp", I32Attr>
- ]> {
+def Tosa_MatMulOpQuantizationAttr
+ : Tosa_Attr< "MatMulOpQuantization", "matmul_quant"> {
let summary = "Attribute for MatMulOp quantization information.";
+ let parameters = (ins "int64_t":$a_zp, "int64_t":$b_zp);
+ let assemblyFormat = "`<` struct(params) `>`";
}
// This attribute holds input zero point correction applied to the padding
// zeros to ensure numerical accuracy in the subsequent TOSA operations.
// Its functional application is described in the tosa.pad() operator
// description in the specification.
-def Tosa_PadOpQuantizationAttr : StructAttr<"PadOpQuantizationAttr",
- Tosa_Dialect, [
- StructFieldAttr<"input_zp", I32Attr>
- ]> {
+def Tosa_PadOpQuantizationAttr : Tosa_Attr<"PadOpQuantization", "pad_quant"> {
let summary = "Attribute for PadOp quantization information.";
+ let parameters = (ins "int64_t":$input_zp);
+ let assemblyFormat = "`<` struct(params) `>`";
}
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// TOSA dialect and structs includes.
//===----------------------------------------------------------------------===//
+
#include "mlir/Dialect/Tosa/IR/TosaOpsDialect.h.inc"
-#include "mlir/Dialect/Tosa/IR/TosaStructs.h.inc"
namespace mlir {
class PatternRewriter;
} // namespace tosa
} // namespace mlir
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Tosa/IR/TosaAttributes.h.inc"
+
#define GET_OP_CLASSES
#include "mlir/Dialect/Tosa/IR/TosaOps.h.inc"
cast<tosa::NegateOp>(op).quantization_info()) {
auto quantizationInfo = cast<tosa::NegateOp>(op).quantization_info();
int32_t inputBitWidth = elementTy.getIntOrFloatBitWidth();
- int64_t inZp =
- quantizationInfo.getValue().input_zp().getValue().getSExtValue();
- int64_t outZp =
- quantizationInfo.getValue().output_zp().getValue().getSExtValue();
+ int64_t inZp = quantizationInfo.getValue().getInput_zp();
+ int64_t outZp = quantizationInfo.getValue().getOutput_zp();
// Compute the maximum value that can occur in the intermediate buffer.
int64_t zpAdd = inZp + outZp;
loc, padOp.pad_const(), ValueRange({}));
} else {
Attribute constantAttr;
- if (elementTy.isa<FloatType>())
+ if (elementTy.isa<FloatType>()) {
constantAttr = rewriter.getFloatAttr(elementTy, 0.0);
- else if (elementTy.isa<IntegerType>() && !padOp.quantization_info())
+ } else if (elementTy.isa<IntegerType>() && !padOp.quantization_info()) {
constantAttr = rewriter.getIntegerAttr(elementTy, 0);
- else if (elementTy.isa<IntegerType>() && padOp.quantization_info()) {
- auto value = padOp.quantization_info().getValue().input_zp().getValue();
- constantAttr = rewriter.getIntegerAttr(elementTy, value.getZExtValue());
+ } else if (elementTy.isa<IntegerType>() && padOp.quantization_info()) {
+ int64_t value = padOp.quantization_info().getValue().getInput_zp();
+ constantAttr = rewriter.getIntegerAttr(elementTy, value);
}
if (constantAttr)
padConstant = rewriter.create<arith::ConstantOp>(loc, constantAttr);
if (isQuantized) {
auto quantizationInfo =
op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
- auto iZp = quantizationInfo.input_zp().getValue().getSExtValue();
+ int64_t iZp = quantizationInfo.getInput_zp();
int64_t intMin =
APInt::getSignedMinValue(inputETy.getIntOrFloatBitWidth())
if (isQuantized) {
auto quantizationInfo =
op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
- auto iZp = rewriter.getI32IntegerAttr(
- quantizationInfo.input_zp().getValue().getSExtValue());
- auto kZp = rewriter.getI32IntegerAttr(
- quantizationInfo.weight_zp().getValue().getSExtValue());
+ auto iZp = rewriter.getI32IntegerAttr(quantizationInfo.getInput_zp());
+ auto kZp = rewriter.getI32IntegerAttr(quantizationInfo.getWeight_zp());
auto iZpVal = rewriter.create<arith::ConstantOp>(loc, iZp);
auto kZpVal = rewriter.create<arith::ConstantOp>(loc, kZp);
if (isQuantized) {
auto quantizationInfo =
op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
- iZp = rewriter.getI32IntegerAttr(
- quantizationInfo.input_zp().getValue().getSExtValue());
- kZp = rewriter.getI32IntegerAttr(
- quantizationInfo.weight_zp().getValue().getSExtValue());
+ iZp = rewriter.getI32IntegerAttr(quantizationInfo.getInput_zp());
+ kZp = rewriter.getI32IntegerAttr(quantizationInfo.getWeight_zp());
}
auto weightShape = weightTy.getShape();
if (isQuantized) {
auto quantizationInfo =
op->getAttr("quantization_info").cast<tosa::ConvOpQuantizationAttr>();
- auto iZp = quantizationInfo.input_zp().getValue().getSExtValue();
+ int64_t iZp = quantizationInfo.getInput_zp();
int64_t intMin =
APInt::getSignedMinValue(inputETy.getIntOrFloatBitWidth())
auto quantizationInfo = op.quantization_info().getValue();
auto aZp = rewriter.create<arith::ConstantOp>(
- loc, rewriter.getI32IntegerAttr(
- quantizationInfo.a_zp().getValue().getSExtValue()));
+ loc, rewriter.getI32IntegerAttr(quantizationInfo.getA_zp()));
auto bZp = rewriter.create<arith::ConstantOp>(
- loc, rewriter.getI32IntegerAttr(
- quantizationInfo.b_zp().getValue().getSExtValue()));
+ loc, rewriter.getI32IntegerAttr(quantizationInfo.getB_zp()));
rewriter.replaceOpWithNewOp<linalg::QuantizedBatchMatmulOp>(
op, TypeRange{op.getType()},
ValueRange{adaptor.a(), adaptor.b(), aZp, bZp}, zeroTensor);
auto quantizationInfo = op.quantization_info().getValue();
auto inputZp = rewriter.create<arith::ConstantOp>(
- loc, rewriter.getI32IntegerAttr(
- quantizationInfo.input_zp().getValue().getSExtValue()));
+ loc, rewriter.getI32IntegerAttr(quantizationInfo.getInput_zp()));
auto outputZp = rewriter.create<arith::ConstantOp>(
- loc, rewriter.getI32IntegerAttr(
- quantizationInfo.weight_zp().getValue().getSExtValue()));
+ loc, rewriter.getI32IntegerAttr(quantizationInfo.getWeight_zp()));
Value matmul =
rewriter
.create<linalg::QuantizedMatmulOp>(
if (op.quantization_info()) {
auto quantizationInfo = op.quantization_info().getValue();
auto inputZp = rewriter.create<arith::ConstantOp>(
- loc, quantizationInfo.input_zp());
+ loc,
+ b.getIntegerAttr(accETy, quantizationInfo.getInput_zp()));
Value offset =
rewriter.create<arith::MulIOp>(loc, accETy, countI, inputZp);
poolVal =
if (op.quantization_info()) {
auto quantizationInfo = op.quantization_info().getValue();
auto outputZp = rewriter.create<arith::ConstantOp>(
- loc, quantizationInfo.output_zp());
+ loc, b.getIntegerAttr(scaled.getType(),
+ quantizationInfo.getOutput_zp()));
scaled = rewriter.create<arith::AddIOp>(loc, scaled, outputZp)
.getResult();
}
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/Tosa
DEPENDS
+ MLIRTosaAttributesIncGen
MLIRTosaOpsIncGen
- MLIRTosaStructsIncGen
MLIRTosaInterfacesIncGen
LINK_LIBS PUBLIC
#include "mlir/Dialect/Tosa/Utils/QuantUtils.h"
#include "mlir/Dialect/Tosa/Utils/ShapeUtils.h"
#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/FoldUtils.h"
#include "mlir/Transforms/InliningUtils.h"
#include "mlir/Transforms/RegionUtils.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/TypeSwitch.h"
using namespace mlir;
using namespace mlir::tosa;
//===----------------------------------------------------------------------===//
// Tosa dialect structs and interface includes.
//===----------------------------------------------------------------------===//
+
#include "mlir/Dialect/Tosa/IR/TosaInterfaces.cpp.inc"
-#include "mlir/Dialect/Tosa/IR/TosaStructs.cpp.inc"
namespace {
//===----------------------------------------------------------------------===//
#define GET_OP_LIST
#include "mlir/Dialect/Tosa/IR/TosaOps.cpp.inc"
>();
+ addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/Tosa/IR/TosaAttributes.cpp.inc"
+ >();
addInterfaces<TosaInlinerInterface>();
}
Type elementTy = inputTy.getElementType();
Attribute constantAttr;
- if (elementTy.isa<FloatType>())
+ if (elementTy.isa<FloatType>()) {
constantAttr = rewriter.getFloatAttr(elementTy, 0.0);
- else if (elementTy.isa<IntegerType>() && !op.quantization_info())
+ } else if (elementTy.isa<IntegerType>() && !op.quantization_info()) {
constantAttr = rewriter.getIntegerAttr(elementTy, 0);
- else if (elementTy.isa<IntegerType>() && op.quantization_info()) {
- auto value = op.quantization_info().getValue().input_zp().getValue();
- constantAttr = rewriter.getIntegerAttr(elementTy, value.getZExtValue());
+ } else if (elementTy.isa<IntegerType>() && op.quantization_info()) {
+ auto value = op.quantization_info().getValue().getInput_zp();
+ constantAttr = rewriter.getIntegerAttr(elementTy, value);
}
if (!constantAttr) {
}
//===----------------------------------------------------------------------===//
+// TOSA Attribute Definitions.
+//===----------------------------------------------------------------------===//
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Tosa/IR/TosaAttributes.cpp.inc"
+
+//===----------------------------------------------------------------------===//
// TOSA Operator Definitions.
//===----------------------------------------------------------------------===//
weight = createOpAndInfer<tosa::PadOp>(
rewriter, loc, UnrankedTensorType::get(weightETy), weight,
weightPaddingVal, nullptr,
- PadOpQuantizationAttr::get(quantInfo.weight_zp(),
- rewriter.getContext()));
+ rewriter.getAttr<PadOpQuantizationAttr>(quantInfo.getWeight_zp()));
} else {
weight = createOpAndInfer<tosa::PadOp>(rewriter, loc,
input = createOpAndInfer<tosa::PadOp>(
rewriter, loc, UnrankedTensorType::get(inputETy), input,
inputPaddingVal, nullptr,
- PadOpQuantizationAttr::get(quantInfo.input_zp(),
- rewriter.getContext()));
+ rewriter.getAttr<PadOpQuantizationAttr>(quantInfo.getInput_zp()));
} else {
input = createOpAndInfer<tosa::PadOp>(rewriter, loc,
UnrankedTensorType::get(inputETy),
"Inputs and weights must be all quantized or all not quantized");
if (inputQType) {
-
int64_t inputZp = inputQType.getZeroPoint();
int64_t weightZp = 0;
weightZp = weightPerAxisQType.getZeroPoints().front();
}
- auto quantAttr = tosa::ConvOpQuantizationAttr::get(
- builder.getI32IntegerAttr(inputZp), builder.getI32IntegerAttr(weightZp),
- builder.getContext());
-
- return quantAttr;
+ return builder.getAttr<tosa::ConvOpQuantizationAttr>(inputZp, weightZp);
}
return nullptr;
"Matmul operands must be all quantized or all not quantized");
if (aQType) {
-
- int64_t aZp = aQType.getZeroPoint();
- int64_t bZp = bQType.getZeroPoint();
-
- auto quantAttr = tosa::MatMulOpQuantizationAttr::get(
- builder.getI32IntegerAttr(aZp), builder.getI32IntegerAttr(bZp),
- builder.getContext());
-
- return quantAttr;
+ return builder.getAttr<tosa::MatMulOpQuantizationAttr>(
+ aQType.getZeroPoint(), bQType.getZeroPoint());
}
return nullptr;
"Unary inputs/outputs must be all quantized or all not quantized");
if (inputQType) {
-
- int64_t inputZp = inputQType.getZeroPoint();
- int64_t outputZp = outputQType.getZeroPoint();
-
- auto quantAttr = tosa::UnaryOpQuantizationAttr::get(
- builder.getI32IntegerAttr(inputZp), builder.getI32IntegerAttr(outputZp),
- builder.getContext());
-
- return quantAttr;
+ return builder.getAttr<UnaryOpQuantizationAttr>(inputQType.getZeroPoint(),
+ outputQType.getZeroPoint());
}
return nullptr;
auto inputQType = GET_UQTYPE(inputType);
if (inputQType) {
-
- int64_t inputZp = inputQType.getZeroPoint();
-
- auto quantAttr = tosa::PadOpQuantizationAttr::get(
- builder.getI32IntegerAttr(inputZp), builder.getContext());
-
- return quantAttr;
+ return builder.getAttr<tosa::PadOpQuantizationAttr>(
+ inputQType.getZeroPoint());
}
return nullptr;
// CHECK: [[ONE:%.+]] = arith.constant 1
// CHECK: [[TWO:%.+]] = arith.constant 2
// CHECK: linalg.quantized_batch_matmul ins(%arg0, %arg1, [[ONE]], [[TWO]] : tensor<1x5x3xi8>, tensor<1x3x6xi8>, i32, i32) outs([[FILLED]] : tensor<1x5x6xi32>) -> tensor<1x5x6xi32>
- %0 = "tosa.matmul"(%arg0, %arg1) {quantization_info = {a_zp = 1 : i32, b_zp = 2 : i32}} : (tensor<1x5x3xi8>, tensor<1x3x6xi8>) -> (tensor<1x5x6xi32>)
+ %0 = "tosa.matmul"(%arg0, %arg1) {quantization_info = #tosa.matmul_quant<a_zp = 1, b_zp = 2>} : (tensor<1x5x3xi8>, tensor<1x3x6xi8>) -> (tensor<1x5x6xi32>)
return %0 : tensor<1x5x6xi32>
}
// CHECK: ^bb0([[IN1:%.+]]: i32, [[IN2:%.+]]: i32, [[UNUSED:%.+]]: i32):
// CHECK: [[ADD:%.+]] = arith.addi
// CHECK: linalg.yield [[ADD]] : i32
- %0 = "tosa.fully_connected"(%arg0, %arg1, %arg2) {quantization_info = {input_zp = 1:i32, weight_zp = 2:i32}} : (tensor<5x3xi8>, tensor<6x3xi8>, tensor<6xi32>) -> (tensor<5x6xi32>)
+ %0 = "tosa.fully_connected"(%arg0, %arg1, %arg2) {quantization_info = #tosa.conv_quant<input_zp = 1, weight_zp = 2>} : (tensor<5x3xi8>, tensor<6x3xi8>, tensor<6xi32>) -> (tensor<5x6xi32>)
return %0 : tensor<5x6xi32>
}
// CHECK: %[[CLMP_MAX:.+]] = arith.select %[[CMP_MAX]], %[[MAX]], %[[CLMP_MIN]]
// CHECK: %[[TRUNC:.+]] = arith.trunci %[[CLMP_MAX]]
// CHECK: linalg.yield %[[TRUNC]]
- %0 = "tosa.avg_pool2d"(%arg0) {kernel = [4, 4], pad = [0, 0, 0, 0], quantization_info = {input_zp = -128 : i32, output_zp = -128 : i32}, stride = [4, 4]} : (tensor<1x128x128x2xi8>) -> tensor<1x32x32x2xi8>
+ %0 = "tosa.avg_pool2d"(%arg0) {kernel = [4, 4], pad = [0, 0, 0, 0], quantization_info = #tosa.unary_quant<input_zp = -128, output_zp = -128>, stride = [4, 4]} : (tensor<1x128x128x2xi8>) -> tensor<1x32x32x2xi8>
return
}
// CHECK: %[[CLMP_MAX:.+]] = arith.select %[[CMP_MAX]], %[[MAX]], %[[CLMP_MIN]]
// CHECK: %[[TRUNC:.+]] = arith.trunci %[[CLMP_MAX]]
// CHECK: linalg.yield %[[TRUNC]]
- %0 = "tosa.avg_pool2d"(%arg0) {kernel = [4, 4], pad = [0, 0, 0, 0], quantization_info = {input_zp = -128 : i32, output_zp = -128 : i32}, stride = [4, 4]} : (tensor<1x128x128x2xi16>) -> tensor<1x32x32x2xi16>
+ %0 = "tosa.avg_pool2d"(%arg0) {kernel = [4, 4], pad = [0, 0, 0, 0], quantization_info = #tosa.unary_quant<input_zp = -128, output_zp = -128>, stride = [4, 4]} : (tensor<1x128x128x2xi16>) -> tensor<1x32x32x2xi16>
return
}
// CHECK: tensor.pad %arg0 low[0, 1, 1, 0] high[0, 1, 1, 0]
// CHECK: tensor.yield %[[C22]]
// CHECK: linalg.conv_2d_nhwc_hwcf_q
- %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], pad = [1, 1, 1, 1], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, stride = [1, 1]} : (tensor<1x12x12x1xi8>, tensor<1024x3x3x1xi8>, tensor<1024xi32>) -> tensor<1x12x12x1024xi32>
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], pad = [1, 1, 1, 1], quantization_info = #tosa.conv_quant<input_zp = -22, weight_zp = 42>, stride = [1, 1]} : (tensor<1x12x12x1xi8>, tensor<1024x3x3x1xi8>, tensor<1024xi32>) -> tensor<1x12x12x1024xi32>
return
}
// CHECK: [[ADD:%.+]] = arith.addi %arg3, %arg4 : i32
// CHECK: linalg.yield [[ADD]] : i32
// CHECK: } -> tensor<1x12x12x512xi32>
- %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [1, 1, 1, 1], quantization_info = {input_zp = -128 : i32, weight_zp = 42 : i32}, stride = [1, 1], dilation = [1, 1] } : (tensor<1x12x12x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x12x12x512xi32>
+ %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [1, 1, 1, 1], quantization_info = #tosa.conv_quant<input_zp = -128, weight_zp = 42>, stride = [1, 1], dilation = [1, 1] } : (tensor<1x12x12x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x12x12x512xi32>
return
}
// CHECK: [[ADD:%.+]] = arith.addi %arg3, %arg4 : i32
// CHECK: linalg.yield [[ADD]] : i32
// CHECK: } -> tensor<1x10x10x512xi32>
- %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], quantization_info = {input_zp = -128 : i32, weight_zp = 42 : i32}, stride = [1, 1], dilation = [2, 2] } : (tensor<1x14x14x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x10x10x512xi32>
+ %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], quantization_info = #tosa.conv_quant<input_zp = -128, weight_zp = 42>, stride = [1, 1], dilation = [2, 2] } : (tensor<1x14x14x4xi8>, tensor<3x3x4x128xi8>, tensor<512xi32>) -> tensor<1x10x10x512xi32>
return
}
// CHECK: [[UBOUND:%.+]] = arith.select [[PRED2]], [[MAX]], [[LBOUND]]
// CHECK: [[TRUNC:%.+]] = arith.trunci [[UBOUND]]
// CHECK: linalg.yield [[TRUNC]]
- %0 = "tosa.negate"(%arg0) {quantization_info = { input_zp = 0 : i32, output_zp = 0 : i32}} : (tensor<1xi8>) -> tensor<1xi8>
+ %0 = "tosa.negate"(%arg0) {quantization_info = #tosa.unary_quant<input_zp = 0, output_zp = 0>} : (tensor<1xi8>) -> tensor<1xi8>
// CHECK: linalg.generic
// CHECK: [[EXT:%.+]] = arith.extsi %arg1 : i8 to i16
- %1 = "tosa.negate"(%arg0) {quantization_info = { input_zp = 32639 : i32, output_zp = 0 : i32}} : (tensor<1xi8>) -> tensor<1xi8>
+ %1 = "tosa.negate"(%arg0) {quantization_info = #tosa.unary_quant<input_zp = 32639, output_zp = 0>} : (tensor<1xi8>) -> tensor<1xi8>
// CHECK: linalg.generic
// CHECK: [[EXT:%.+]] = arith.extsi %arg1 : i8 to i32
- %2 = "tosa.negate"(%arg0) {quantization_info = { input_zp = 32640 : i32, output_zp = 0 : i32}} : (tensor<1xi8>) -> tensor<1xi8>
+ %2 = "tosa.negate"(%arg0) {quantization_info = #tosa.unary_quant<input_zp = 32640, output_zp = 0>} : (tensor<1xi8>) -> tensor<1xi8>
return
}
// CHECK: [[CST:%.+]] = arith.constant 42 : i32
// CHECK: tensor.pad
// CHECK: tensor.yield [[CST]]
- %1 = "tosa.pad"(%arg0, %0) { quantization_info = { input_zp = 42 : i32}} : (tensor<1x2xi32>, tensor<2x2xi32>) -> (tensor<4x9xi32>)
+ %1 = "tosa.pad"(%arg0, %0) {quantization_info = #tosa.pad_quant<input_zp = 42>} : (tensor<1x2xi32>, tensor<2x2xi32>) -> (tensor<4x9xi32>)
return %1 : tensor<4x9xi32>
}
// CHECK: %[[ZERO:.+]] = "tosa.const"() {value = dense<42> : tensor<i32>}
// CHECK: "tosa.pad"(%arg0, %arg1, %[[ZERO]])
%0 = "tosa.const"() { value = dense<[[1, 0], [0, 1]]> : tensor<2x2xi32>} : () -> tensor<2x2xi32>
- %1 = "tosa.pad"(%arg0, %arg1) { quantization_info = {input_zp = 42:i32} } : (tensor<?x?xi32>, tensor<2x2xi32>) -> tensor<?x?xi32>
+ %1 = "tosa.pad"(%arg0, %arg1) {quantization_info = #tosa.pad_quant<input_zp = 42>} : (tensor<?x?xi32>, tensor<2x2xi32>) -> tensor<?x?xi32>
return %1 : tensor<?x?xi32>
}
// CHECK-LABEL: test_build_mult_and_shift
func.func @test_build_mult_and_shift(%arg0: tensor<1x32x32x8x!quant.uniform<i8:f32, 0.015684768557548523>>, %arg1 : tensor<16x1x1x8x!quant.uniform<i8<-127:127>:f32, 0.015680249780416489>>, %arg2 : tensor<16xi32>) -> tensor<1x32x32x16x!quant.uniform<i8:f32, 0.078431375324726104>> {
// CHECK: tosa.conv2d
- %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {pad = [1, 1, 2, 2], dilation = [2, 1], stride = [1, 1], quantization_info = {input_zp = -1 : i32, weight_zp = 0 : i32}} : (tensor<1x32x32x8x!quant.uniform<i8:f32, 0.015684768557548523>>, tensor<16x1x1x8x!quant.uniform<i8<-127:127>:f32, 0.015680249780416489>>, tensor<16xi32>) -> tensor<1x32x32x16x!quant.uniform<i8:f32, 0.078431375324726104>>
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {pad = [1, 1, 2, 2], dilation = [2, 1], stride = [1, 1], quantization_info = #tosa.conv_quant<input_zp = -1, weight_zp = 0>} : (tensor<1x32x32x8x!quant.uniform<i8:f32, 0.015684768557548523>>, tensor<16x1x1x8x!quant.uniform<i8<-127:127>:f32, 0.015680249780416489>>, tensor<16xi32>) -> tensor<1x32x32x16x!quant.uniform<i8:f32, 0.078431375324726104>>
return %0 : tensor<1x32x32x16x!quant.uniform<i8:f32, 0.078431375324726104>>
}
// CHECK: %[[VAR1:.*]] = "tosa.reshape"(%arg1) {new_shape = [3, 2]}
// CHECK-SAME: -> tensor<3x2xi8>
// CHECK: %[[VAR2:.*]] = "tosa.fully_connected"(%[[VAR0]], %[[VAR1]], %arg2)
- // CHECK-SAME: quantization_info = {input_zp = 42 : i32, weight_zp = 24 : i32}
+ // CHECK-SAME: quantization_info = #tosa.conv_quant<input_zp = 42, weight_zp = 24>
// CHECK-SAME: -> tensor<400x3xi32>
// CHECK: %[[VAR3:.*]] = "tosa.reshape"(%[[VAR2]]) {new_shape = [4, 10, 10, 3]}
// CHECK-SAME: -> tensor<4x10x10x3xi32>
// CHECK: return %[[VAR3]]
- %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], stride = [1, 1], dilation = [1, 1], quantization_info = {input_zp = 42 : i32, weight_zp = 24 : i32}} : (tensor<4x10x10x2xi8>, tensor<3x1x1x2xi8>, tensor<3xi32>) -> tensor<4x10x10x3xi32>
+ %0 = "tosa.conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], stride = [1, 1], dilation = [1, 1], quantization_info = #tosa.conv_quant<input_zp = 42, weight_zp = 24>} : (tensor<4x10x10x2xi8>, tensor<3x1x1x2xi8>, tensor<3xi32>) -> tensor<4x10x10x3xi32>
return %0 : tensor<4x10x10x3xi32>
}
// CHECK-LABEL: @depthwise_conv2d_as_mul_q
func.func @depthwise_conv2d_as_mul_q(%arg0: tensor<4x10x10x2xi8>, %arg1: tensor<1x1x2x3xi8>, %arg2: tensor<6xi32>) -> tensor<4x10x10x6xi32> {
// CHECK: "tosa.depthwise_conv2d"
- %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], stride = [1, 1], dilation = [1, 1], quantization_info = {input_zp = 0 : i32, weight_zp = 0 : i32}} : (tensor<4x10x10x2xi8>, tensor<1x1x2x3xi8>, tensor<6xi32>) -> tensor<4x10x10x6xi32>
+ %0 = "tosa.depthwise_conv2d"(%arg0, %arg1, %arg2) {pad = [0, 0, 0, 0], stride = [1, 1], dilation = [1, 1], quantization_info = #tosa.conv_quant<input_zp = 0, weight_zp = 0>} : (tensor<4x10x10x2xi8>, tensor<1x1x2x3xi8>, tensor<6xi32>) -> tensor<4x10x10x6xi32>
return %0 : tensor<4x10x10x6xi32>
}
func.func @transpose_conv2d_quantized(%arg0: tensor<2x16x14x3xi8>, %arg1: tensor<5x3x6x3xi8>, %arg2: tensor<5xi32>) -> (tensor<2x18x19x5xi32>) {
// CHECK: %[[REV1:.+]] = "tosa.reverse"(%arg1) {axis = 1 : i64}
// CHECK: %[[REV2:.+]] = "tosa.reverse"(%[[REV1]]) {axis = 2 : i64}
- // CHECK: "tosa.conv2d"(%arg0, %[[REV2]], %arg2) {dilation = [1, 1], pad = [2, 2, 5, 5], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, stride = [1, 1]}
- %0 = "tosa.transpose_conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], out_pad = [0, 0], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, out_shape = [-1, -1, -1, -1], stride = [1, 1]} : (tensor<2x16x14x3xi8>, tensor<5x3x6x3xi8>, tensor<5xi32>) -> tensor<2x18x19x5xi32>
+ // CHECK: "tosa.conv2d"(%arg0, %[[REV2]], %arg2) {dilation = [1, 1], pad = [2, 2, 5, 5], quantization_info = #tosa.conv_quant<input_zp = -22, weight_zp = 42>, stride = [1, 1]}
+ %0 = "tosa.transpose_conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], out_pad = [0, 0], quantization_info = #tosa.conv_quant<input_zp = -22, weight_zp = 42>, out_shape = [-1, -1, -1, -1], stride = [1, 1]} : (tensor<2x16x14x3xi8>, tensor<5x3x6x3xi8>, tensor<5xi32>) -> tensor<2x18x19x5xi32>
return %0 : tensor<2x18x19x5xi32>
}
// Manipulate the weight matrix to handle striding.
// CHECK-DAG: %[[PADV:.+]] = "tosa.const"() {value = dense<{{\[\[}}0, 0], [0, 1], [0, 1], [0, 0]]> : tensor<4x2xi32>}
// CHECK-DAG: %[[TRANSV:.+]] = "tosa.const"() {value = dense<[2, 4, 0, 1, 3, 5]> : tensor<6xi32>}
- // CHECK-DAG: %[[PADW:.+]] = "tosa.pad"(%arg1, %[[PADV]]) {quantization_info = {input_zp = 42 : i32}}
+ // CHECK-DAG: %[[PADW:.+]] = "tosa.pad"(%arg1, %[[PADV]]) {quantization_info = #tosa.pad_quant<input_zp = 42>}
// CHECK-DAG: %[[RESW1:.+]] = "tosa.reshape"(%[[PADW]]) {new_shape = [5, 2, 2, 2, 3, 3]}
// CHECK-DAG: %[[TRANS:.+]] = "tosa.transpose"(%[[RESW1]], %[[TRANSV]])
// CHECK-DAG: %[[RESW2:.+]] = "tosa.reshape"(%[[TRANS]]) {new_shape = [30, 2, 2, 3]}
// Pad out the input matrix to handle the transpose conv.
// CHECK-DAG: %[[PAD:.+]] = "tosa.const"() {value = dense<{{\[\[}}0, 0], [1, 1], [1, 1], [0, 0]]> : tensor<4x2xi32>}
// CHECK-DAG: %[[TRANS2:.+]] = "tosa.const"() {value = dense<[0, 1, 3, 2, 4, 5]> : tensor<6xi32>}
- // CHECK-DAG: %[[NEWINPUT:.+]] = "tosa.pad"(%arg0, %[[PAD]]) {quantization_info = {input_zp = -22 : i32}}
+ // CHECK-DAG: %[[NEWINPUT:.+]] = "tosa.pad"(%arg0, %[[PAD]]) {quantization_info = #tosa.pad_quant<input_zp = -22>}
// Manipulate the final shape.
// CHECK-DAG: %[[BIAS:.+]] = "tosa.const"() {value = dense<0> : tensor<30xi32>}
- // CHECK-DAG: %[[CONV:.+]] = "tosa.conv2d"(%[[NEWINPUT]], %[[NEWWEIGHT]], %[[BIAS]]) {dilation = [1, 1], pad = [0, 0, 0, 0], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, stride = [1, 1]}
+ // CHECK-DAG: %[[CONV:.+]] = "tosa.conv2d"(%[[NEWINPUT]], %[[NEWWEIGHT]], %[[BIAS]]) {dilation = [1, 1], pad = [0, 0, 0, 0], quantization_info = #tosa.conv_quant<input_zp = -22, weight_zp = 42>, stride = [1, 1]}
// CHECK-DAG: %[[RESHAPE_OUT_1:.+]] = "tosa.reshape"(%[[CONV]]) {new_shape = [2, 18, 16, 2, 3, 5]}
// CHECK-DAG: %[[TRANS_OUT:.+]] = "tosa.transpose"(%[[RESHAPE_OUT_1]], %[[TRANS2]])
// CHECK-DAG: %[[RESHAPE_OUT_2:.+]] = "tosa.reshape"(%[[TRANS_OUT]]) {new_shape = [2, 36, 48, 5]}
// CHECK-DAG: %[[SLICE:.+]] = "tosa.slice"(%[[RESHAPE_OUT_2]]) {size = [2, 35, 47, 5], start = [0, 0, 0, 0]}
// CHECK: %[[ADD:.+]] = "tosa.add"(%[[SLICE]], %arg2)
- %0 = "tosa.transpose_conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], out_pad = [0, 0], quantization_info = {input_zp = -22 : i32, weight_zp = 42 : i32}, out_shape = [-1, -1, -1, -1], stride = [2, 3]} : (tensor<2x17x15x3xi8>, tensor<5x3x5x3xi8>, tensor<5xi32>) -> tensor<2x35x47x5xi32>
+ %0 = "tosa.transpose_conv2d"(%arg0, %arg1, %arg2) {dilation = [1, 1], out_pad = [0, 0], quantization_info = #tosa.conv_quant<input_zp = -22, weight_zp = 42>, out_shape = [-1, -1, -1, -1], stride = [2, 3]} : (tensor<2x17x15x3xi8>, tensor<5x3x5x3xi8>, tensor<5xi32>) -> tensor<2x35x47x5xi32>
return %0 : tensor<2x35x47x5xi32>
}
"include/mlir/Dialect/Tosa/IR/TosaOpsDialect.cpp.inc",
),
(
+ ["-gen-attrdef-decls"],
+ "include/mlir/Dialect/Tosa/IR/TosaAttributes.h.inc",
+ ),
+ (
+ ["-gen-attrdef-defs"],
+ "include/mlir/Dialect/Tosa/IR/TosaAttributes.cpp.inc",
+ ),
+ (
["-gen-op-doc"],
"g3doc/Dialects/Tosa/TosaOps.md",
),