26 const double mantissa =
std::frexp(scale, &shift);
27 auto shiftedM =
std::round(mantissa * (int64_t(1) << 15));
30 assert(shiftedM <= (int64_t(1) << 15) &&
31 "Shifted mantissa exceeds 16 signed bits");
33 if (shiftedM == (int64_t(1) << 15)) {
40 shift = (-shift) + 15;
43 "Shifted mantissa exceeds 32-bit signed output type");
45 multiplier =
static_cast<int32_t
>(shiftedM);
52 multiplier = multiplier >> std::min<int32_t>(31, shift - 62);
64 const double mantissa =
std::frexp(scale, &shift);
65 auto shiftedM =
std::round(mantissa * (int64_t(1) << 31));
68 assert(shiftedM <= (int64_t(1) << 31) &&
69 "Shifted mantissa exceeds 32 signed bits");
70 if (shiftedM == (int64_t(1) << 31)) {
77 shift = (-shift) + 31;
80 "Shifted mantissa exceeds 32-bit signed output type");
82 multiplier =
static_cast<int32_t
>(shiftedM);
89 multiplier = multiplier >> std::min<int32_t>(31, shift - 62);
96 int32_t &shift, int32_t scaleWidth) {
106 assert(0 &&
"Unsupported Tosa quantized_scale regime specified!");
110 #define GET_UQTYPE(inputType) \
111 (llvm::dyn_cast<quant::UniformQuantizedType>((inputType).getElementType()))
112 #define GET_QTYPE(inputType) \
113 (llvm::dyn_cast<quant::QuantizedType>((inputType).getElementType()))
119 ConvOpQuantizationAttr
123 auto inputType = dyn_cast<ShapedType>(input.
getType());
124 auto weightType = dyn_cast<ShapedType>(weight.
getType());
126 if (!inputType || !weightType)
130 auto weightPerTensorQType =
GET_UQTYPE(weightType);
131 auto weightPerAxisQType =
132 dyn_cast<quant::UniformQuantizedPerAxisType>(weightType.getElementType());
135 assert(!((
bool)weightPerTensorQType && (
bool)weightPerAxisQType) &&
136 "Weights must be either per-tensor or per-axis quantized");
139 assert(!((
bool)inputQType ^
140 ((
bool)weightPerTensorQType || (
bool)weightPerAxisQType)) &&
141 "Inputs and weights must be all quantized or all not quantized");
144 int64_t inputZp = inputQType.getZeroPoint();
145 int64_t weightZp = 0;
147 if (weightPerTensorQType) {
148 weightZp = weightPerTensorQType.getZeroPoint();
149 }
else if (weightPerAxisQType) {
150 weightZp = weightPerAxisQType.getZeroPoints().front();
153 return builder.
getAttr<tosa::ConvOpQuantizationAttr>(inputZp, weightZp);
163 MatMulOpQuantizationAttr
167 auto aType = dyn_cast<ShapedType>(a.
getType());
168 auto bType = dyn_cast<ShapedType>(b.
getType());
170 if (!aType || !bType)
177 assert(!((
bool)aQType ^ (
bool)bQType) &&
178 "Matmul operands must be all quantized or all not quantized");
181 return builder.
getAttr<tosa::MatMulOpQuantizationAttr>(
182 aQType.getZeroPoint(), bQType.getZeroPoint());
192 UnaryOpQuantizationAttr
194 Type outputRawType) {
196 auto inputType = dyn_cast<ShapedType>(input.
getType());
197 auto outputType = dyn_cast<ShapedType>(outputRawType);
199 if (!inputType || !outputType)
206 assert(!((
bool)inputQType ^ (
bool)outputQType) &&
207 "Unary inputs/outputs must be all quantized or all not quantized");
210 return builder.
getAttr<UnaryOpQuantizationAttr>(inputQType.getZeroPoint(),
211 outputQType.getZeroPoint());
222 auto inputType = dyn_cast<ShapedType>(input.
getType());
230 return builder.
getAttr<tosa::PadOpQuantizationAttr>(
231 inputQType.getZeroPoint());
242 auto inputType = dyn_cast<ShapedType>(input.
getType());
243 auto weightType = dyn_cast<ShapedType>(weight.
getType());
245 assert(inputType && weightType &&
246 "Could not extract input or weight tensors from Conv op");
249 auto weightQType =
GET_QTYPE(weightType);
251 assert(inputQType && weightQType &&
252 "Could not extract input or weight tensor types from Conv op");
254 unsigned inputBits = inputQType.getStorageTypeIntegralWidth();
255 unsigned weightBits = weightQType.getStorageTypeIntegralWidth();
257 auto outputShapedType = dyn_cast<ShapedType>(outputType);
258 assert(outputShapedType &&
259 "Could not extract output shape type from Conv op");
261 IntegerType accElementType;
262 if (inputBits == 16 && weightBits == 8)
266 auto accType = outputShapedType.clone(accElementType);
273 IntegerAttr quantBits,
int filterQuantDim,
274 bool isSigned,
BoolAttr narrowRange) {
281 auto minElems = dyn_cast<DenseFPElementsAttr>(minAttr);
282 auto maxElems = dyn_cast<DenseFPElementsAttr>(maxAttr);
287 if (minElems || maxElems) {
289 if (minElems.getNumElements() != maxElems.getNumElements())
291 min.reserve(minElems.getNumElements());
292 max.reserve(maxElems.getNumElements());
293 for (
auto i : minElems)
294 min.push_back(FloatAttr::getValueAsDouble(i));
295 for (
auto i : maxElems)
296 max.push_back(FloatAttr::getValueAsDouble(i));
298 auto minVal = dyn_cast<FloatAttr>(minAttr);
300 min.push_back(minVal.getValueAsDouble());
303 auto maxVal = dyn_cast<FloatAttr>(maxAttr);
305 max.push_back(maxVal.getValueAsDouble());
310 if (
min.size() ==
max.size()) {
311 if (
min.size() == 1) {
314 narrowRange.
getValue(), convfunc.expressedType, isSigned);
315 }
else if (
min.size() > 1) {
316 auto shape = dyn_cast<ShapedType>(inputDType);
319 if ((filterQuantDim) >= 0 && (shape.getRank() > filterQuantDim)) {
322 max[0], narrowRange.
getValue(), convfunc.expressedType, isSigned);
334 return convfunc.convert(retType);
341 IntegerAttr quantBits,
int filterQuantDim,
342 bool isSigned,
BoolAttr narrowRange) {
345 maxAttr, quantBits, filterQuantDim,
346 isSigned, narrowRange));
static std::pair< Value, Value > frexp(ImplicitLocOpBuilder &builder, Value arg, bool isPositive=false)
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
#define GET_UQTYPE(inputType)
static void computeMultiplierAndShiftTosaScale16(double scale, int32_t &multiplier, int32_t &shift)
From a scale value, generates multiplier and shift values where mantissa is in [-1....
#define GET_QTYPE(inputType)
static void computeMultiplierAndShiftTosaScale32(double scale, int32_t &multiplier, int32_t &shift)
From a scale value, generates multiplier and shift values where mantissa is in [-1....
Attributes are known-constant values of operations.
Special case of IntegerAttr to represent boolean integers, i.e., signless i1 integers.
bool getValue() const
Return the boolean value of this attribute.
IntegerType getIntegerType(unsigned width)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
This class helps build Operations.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Base class for all quantized types known to this dialect.
DynamicAPInt round(const Fraction &f)
UniformQuantizedType fakeQuantAttrsToType(Location loc, unsigned numBits, double rmin, double rmax, bool narrowRange, Type expressedType, bool isSigned=false)
Converts per-layer FakeQuant attributes to the corresponding type.
ConvOpQuantizationAttr buildConvOpQuantizationAttr(OpBuilder &builder, Value input, Value weight)
Method to build ConvOpQuantizationAttr, called from ConvOpQuantInfoBuilder/TransConvOpQuantInfoBuilde...
TypeAttr buildQTypeAttrFromMinMax(OpBuilder builder, Type inputDType, Attribute minAttr, Attribute maxAttr, IntegerAttr quantBits, int filterQuantDim, bool isSigned, BoolAttr narrowRange)
Builds Tosa quantization attributes from min/max values.
Type buildConvOpResultTypeInfo(OpBuilder &builder, Type outputType, Value input, Value weight)
construct ConvOp output type with correct bitwidth based on input/weight width.
Type buildQTypeFromMinMax(OpBuilder builder, Type inputDType, Attribute minAttr, Attribute maxAttr, IntegerAttr quantBits, int filterQuantDim, bool isSigned, BoolAttr narrowRange)
Builds Tosa quantization attributes from min/max values.
PadOpQuantizationAttr buildPadOpQuantizationAttr(OpBuilder &builder, Value input)
Builds PadOpQuantizationAttr, called from PadOpQuantInfoBuilder: inputZp: input zeropoint.
MatMulOpQuantizationAttr buildMatMulOpQuantizationAttr(OpBuilder &builder, Value a, Value b)
Builds MatMulOpQuantizationAttr, called from MatMulOpQuantInfoBuilder: aZp: input a zeropoint bZp: in...
void computeMultiplierAndShift(double scale, int32_t &multiplier, int32_t &shift, int32_t scaleWidth)
From a scale value, computes multiplier and shift values for 16 or 32-bit scale widths.
UnaryOpQuantizationAttr buildUnaryOpQuantizationAttr(OpBuilder &builder, Value input, Type outputRawType)
Builds UnaryOpQuantizationAttr UnaryOpQuantInfoBuilder: inputZp: input zeropoint outputZp: output zer...
Include the generated interface declarations.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
static ExpressedToQuantizedConverter forInputType(Type inputType)
Creates a converter for the given input type.