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;
42 assert(shiftedM <= std::numeric_limits<int32_t>::max() &&
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;
79 assert(shiftedM <= std::numeric_limits<int32_t>::max() &&
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) {
104 return (!(shift < 2));
110 return (!(shift < 2));
112 assert(0 &&
"Unsupported Tosa quantized_scale regime specified!");
117#define GET_UQTYPE(inputType) \
118 (llvm::dyn_cast<quant::UniformQuantizedType>((inputType).getElementType()))
119#define GET_QTYPE(inputType) \
120 (llvm::dyn_cast<quant::QuantizedType>((inputType).getElementType()))
122static std::optional<std::pair<std::int64_t, std::int64_t>>
125 auto inputType = dyn_cast<ShapedType>(input.
getType());
126 auto weightType = dyn_cast<ShapedType>(weight.
getType());
128 if (!inputType || !weightType)
132 auto weightPerTensorQType =
GET_UQTYPE(weightType);
133 auto weightPerAxisQType =
134 dyn_cast<quant::UniformQuantizedPerAxisType>(weightType.getElementType());
137 assert(!((
bool)weightPerTensorQType && (
bool)weightPerAxisQType) &&
138 "Weights must be either per-tensor or per-axis quantized");
141 assert(!((
bool)inputQType ^
142 ((
bool)weightPerTensorQType || (
bool)weightPerAxisQType)) &&
143 "Inputs and weights must be all quantized or all not quantized");
146 int64_t inputZp = inputQType.getZeroPoint();
149 if (weightPerTensorQType) {
150 weightZp = weightPerTensorQType.getZeroPoint();
151 }
else if (weightPerAxisQType) {
152 weightZp = weightPerAxisQType.getZeroPoints().front();
155 return std::make_pair(inputZp, weightZp);
161std::pair<Value, Value>
163 std::int64_t inputZp, weightZp;
166 if (isa<BlockScaledType>(inputZpType))
169 if (isa<BlockScaledType>(weightZpType))
172 if (mlir::isa<FloatType>(inputZpType) && mlir::isa<FloatType>(weightZpType)) {
177 if (!maybeZps.has_value())
180 inputZp = maybeZps->first;
181 weightZp = maybeZps->second;
184 auto maybeInputZpValue =
186 if (!maybeInputZpValue.has_value())
189 auto maybeWeightZpValue =
191 if (!maybeWeightZpValue.has_value())
194 return std::make_pair(*maybeInputZpValue, *maybeWeightZpValue);
201ConvOpQuantizationAttr
206 if (!maybeZps.has_value())
209 return builder.
getAttr<tosa::ConvOpQuantizationAttr>(maybeZps->first,
217MatMulOpQuantizationAttr
221 auto aType = dyn_cast<ShapedType>(a.
getType());
222 auto bType = dyn_cast<ShapedType>(
b.getType());
224 if (!aType || !bType)
231 assert(!((
bool)aQType ^ (
bool)bQType) &&
232 "Matmul operands must be all quantized or all not quantized");
235 return builder.
getAttr<tosa::MatMulOpQuantizationAttr>(
236 aQType.getZeroPoint(), bQType.getZeroPoint());
246UnaryOpQuantizationAttr
248 Type outputRawType) {
250 auto inputType = dyn_cast<ShapedType>(input.
getType());
251 auto outputType = dyn_cast<ShapedType>(outputRawType);
253 if (!inputType || !outputType)
260 assert(!((
bool)inputQType ^ (
bool)outputQType) &&
261 "Unary inputs/outputs must be all quantized or all not quantized");
264 return builder.
getAttr<UnaryOpQuantizationAttr>(inputQType.getZeroPoint(),
265 outputQType.getZeroPoint());
276 auto inputType = dyn_cast<ShapedType>(input.
getType());
284 return builder.
getAttr<tosa::PadOpQuantizationAttr>(
285 inputQType.getZeroPoint());
296 auto inputType = dyn_cast<ShapedType>(input.
getType());
297 auto weightType = dyn_cast<ShapedType>(weight.
getType());
299 assert(inputType && weightType &&
300 "Could not extract input or weight tensors from Conv op");
303 auto weightQType =
GET_QTYPE(weightType);
305 assert(inputQType && weightQType &&
306 "Could not extract input or weight tensor types from Conv op");
308 unsigned inputBits = inputQType.getStorageTypeIntegralWidth();
309 unsigned weightBits = weightQType.getStorageTypeIntegralWidth();
311 auto outputShapedType = dyn_cast<ShapedType>(outputType);
312 assert(outputShapedType &&
313 "Could not extract output shape type from Conv op");
315 IntegerType accElementType;
316 if (inputBits == 16 && weightBits == 8)
320 auto accType = outputShapedType.clone(accElementType);
327 IntegerAttr quantBits,
int filterQuantDim,
328 bool isSigned,
BoolAttr narrowRange) {
335 auto minElems = dyn_cast<DenseFPElementsAttr>(minAttr);
336 auto maxElems = dyn_cast<DenseFPElementsAttr>(maxAttr);
341 if (minElems || maxElems) {
343 if (minElems.getNumElements() != maxElems.getNumElements())
345 min.reserve(minElems.getNumElements());
346 max.reserve(maxElems.getNumElements());
347 for (
auto i : minElems)
348 min.push_back(FloatAttr::getValueAsDouble(i));
349 for (
auto i : maxElems)
350 max.push_back(FloatAttr::getValueAsDouble(i));
352 auto minVal = dyn_cast<FloatAttr>(minAttr);
354 min.push_back(minVal.getValueAsDouble());
357 auto maxVal = dyn_cast<FloatAttr>(maxAttr);
359 max.push_back(maxVal.getValueAsDouble());
364 if (
min.size() ==
max.size()) {
365 if (
min.size() == 1) {
368 narrowRange.
getValue(), convfunc.expressedType, isSigned);
369 }
else if (
min.size() > 1) {
370 auto shape = dyn_cast<ShapedType>(inputDType);
373 if ((filterQuantDim) >= 0 && (
shape.getRank() > filterQuantDim)) {
376 max[0], narrowRange.
getValue(), convfunc.expressedType, isSigned);
388 return convfunc.convert(retType);
395 IntegerAttr quantBits,
int filterQuantDim,
396 bool isSigned,
BoolAttr narrowRange) {
399 maxAttr, quantBits, filterQuantDim,
400 isSigned, narrowRange));
409 quantEty = IntegerType::get(quantEty.getContext(),
410 quantEty.getIntOrFloatBitWidth(),
411 IntegerType::Unsigned);
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
#define GET_UQTYPE(inputType)
static std::optional< std::pair< std::int64_t, std::int64_t > > getConvZeroPoints(Value input, Value weight)
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.
Location getLoc() const
Return the location of this value.
Base class for all quantized types known to this dialect.
bool isSigned() const
Whether the storage type should be interpreted as a signed quantity (true) or an unsigned value (fals...
Type getStorageType() const
Gets the underlying type used for to store values.
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.
bool 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.
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.
std::pair< Value, Value > createZPsAsConst(OpBuilder &builder, Value input, Value weight)
MatMulOpQuantizationAttr buildMatMulOpQuantizationAttr(OpBuilder &builder, Value a, Value b)
Builds MatMulOpQuantizationAttr, called from MatMulOpQuantInfoBuilder: aZp: input a zeropoint bZp: in...
std::optional< Value > createZeroPointTensor(OpBuilder &builder, Location loc, Type srcElemType, int64_t zp=0)
UnaryOpQuantizationAttr buildUnaryOpQuantizationAttr(OpBuilder &builder, Value input, Type outputRawType)
Builds UnaryOpQuantizationAttr UnaryOpQuantInfoBuilder: inputZp: input zeropoint outputZp: output zer...
Type getStorageElementTypeFromQuantized(quant::QuantizedType quantizedType)
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
static ExpressedToQuantizedConverter forInputType(Type inputType)
Creates a converter for the given input type.