MLIR  14.0.0git
QuantizeUtils.cpp
Go to the documentation of this file.
1 //===- QuantizeUtils.cpp - Support utilities for quantization -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "mlir/IR/Attributes.h"
12 #include "mlir/IR/BuiltinTypes.h"
13 
14 using namespace mlir;
15 using namespace mlir::quant;
16 
17 /// Converts a possible primitive, real expressed value attribute to a
18 /// corresponding storage attribute (typically FloatAttr -> IntegerAttr).
19 /// quantizedElementType is the QuantizedType that describes the expressed
20 /// origValue.
21 /// Returns a converter Attribute or nullptr if conversion is not possible.
23  Attribute origRealValue, QuantizedType quantizedElementType,
24  const UniformQuantizedValueConverter &converter, Type &outConvertedType) {
25  if (origRealValue.isa<FloatAttr>()) {
26  FloatAttr floatAttr = origRealValue.cast<FloatAttr>();
27  outConvertedType = quantizedElementType.getStorageType();
28  return IntegerAttr::get(quantizedElementType.getStorageType(),
29  converter.quantizeFloatToInt(floatAttr.getValue()));
30  }
31 
32  return nullptr;
33 }
34 
35 /// Converts a real expressed DenseFPElementsAttr to a corresponding
36 /// DenseElementsAttr (typically DenseIntElementsAttr) containing quantized
37 /// storage values assuming the given quantizedElementType and converter.
38 static DenseElementsAttr
40  QuantizedType quantizedElementType,
41  const UniformQuantizedValueConverter &converter) {
42  // Convert to corresponding quantized value attributes.
43  SmallVector<APInt, 8> quantValues;
44  if (realFPElementsAttr.isSplat()) {
45  quantValues.push_back(
46  converter.quantizeFloatToInt(*realFPElementsAttr.begin()));
47  } else {
48  quantValues.reserve(realFPElementsAttr.getNumElements());
49  for (APFloat realVal : realFPElementsAttr) {
50  quantValues.push_back(converter.quantizeFloatToInt(realVal));
51  }
52  }
53 
54  // Cast from an expressed-type-based type to storage-type-based type,
55  // preserving the dense shape (i.e. tensor<4xf32> -> tensor<4xi8>).
56  ShapedType newDenseType =
57  quantizedElementType
58  .castExpressedToStorageType(realFPElementsAttr.getType())
59  .dyn_cast_or_null<ShapedType>();
60  if (!newDenseType) {
61  return nullptr;
62  }
63  return DenseIntElementsAttr::get(newDenseType, quantValues);
64 }
65 
66 /// Converts a real expressed SplatElementsAttr to a corresponding
67 /// SplatElementsAttr containing quantized storage values assuming the given
68 /// quantizedElementType and converter.
69 static SparseElementsAttr
70 convertSparseElementsAttr(SparseElementsAttr realSparseAttr,
71  QuantizedType quantizedElementType,
72  const UniformQuantizedValueConverter &converter) {
73  DenseElementsAttr realDenseAttr = realSparseAttr.getValues();
74  if (!realDenseAttr.isa<DenseFPElementsAttr>()) {
75  return nullptr;
76  }
77  DenseElementsAttr quantDenseAttr =
79  quantizedElementType, converter);
80  if (!quantDenseAttr) {
81  return nullptr;
82  }
83 
84  // Cast from an expressed-type-based type to storage-type-based type,
85  // preserving the sparse shape (i.e. tensor<4xf32> -> tensor<4xi8>).
86  ShapedType newSparseType =
87  quantizedElementType.castExpressedToStorageType(realSparseAttr.getType())
88  .dyn_cast_or_null<ShapedType>();
89  if (!newSparseType) {
90  return nullptr;
91  }
92  return SparseElementsAttr::get(newSparseType, realSparseAttr.getIndices(),
93  quantDenseAttr);
94 }
95 
96 /// Converts a real expressed Attribute to a corresponding Attribute containing
97 /// quantized storage values assuming the given uniform quantizedElementType and
98 /// converter.
100  Attribute realValue, UniformQuantizedType quantizedElementType,
101  const UniformQuantizedValueConverter &converter, Type &outConvertedType) {
102  // Fork to handle different variants of constants supported.
103  if (realValue.isa<DenseFPElementsAttr>()) {
104  // Dense tensor or vector constant.
105  auto converted = convertDenseFPElementsAttr(
106  realValue.cast<DenseFPElementsAttr>(), quantizedElementType, converter);
107  outConvertedType = converted.getType();
108  return converted;
109  }
110  if (realValue.isa<SparseElementsAttr>()) {
111  // Sparse tensor or vector constant.
112  auto converted = convertSparseElementsAttr(
113  realValue.cast<SparseElementsAttr>(), quantizedElementType, converter);
114  outConvertedType = converted.getType();
115  return converted;
116  }
117  // Nothing else matched: try to convert a primitive.
118  return convertPrimitiveValueAttr(realValue, quantizedElementType, converter,
119  outConvertedType);
120 }
121 
122 /// Convert an attribute from a type based on
123 /// quantizedElementType.getExpressedType() to one based on
124 /// quantizedElementType.getStorageType().
125 /// Returns nullptr if the conversion is not supported.
126 /// On success, stores the converted type in outConvertedType.
128  QuantizedType quantizedElementType,
129  Type &outConvertedType) {
130  if (auto uniformQuantized =
131  quantizedElementType.dyn_cast<UniformQuantizedType>()) {
132  UniformQuantizedValueConverter converter(uniformQuantized);
133  return quantizeAttrUniform(realValue, uniformQuantized, converter,
134  outConvertedType);
135  }
136  if (auto uniformQuantizedPerAxis =
137  quantizedElementType.dyn_cast<UniformQuantizedPerAxisType>()) {
138  UniformQuantizedPerAxisValueConverter converter(uniformQuantizedPerAxis);
139  auto converted = converter.convert(realValue);
140  // TODO: why we need this outConvertedType? remove it?
141  if (converted) {
142  outConvertedType = converted.getType();
143  }
144  return converted;
145  }
146  return nullptr;
147 }
Include the generated interface declarations.
An attribute that represents a reference to a dense float vector or tensor object.
U cast() const
Definition: Attributes.h:123
Type getStorageType() const
Gets the underlying type used for to store values.
Definition: QuantTypes.cpp:63
static SparseElementsAttr convertSparseElementsAttr(SparseElementsAttr realSparseAttr, QuantizedType quantizedElementType, const UniformQuantizedValueConverter &converter)
Converts a real expressed SplatElementsAttr to a corresponding SplatElementsAttr containing quantized...
Attribute quantizeAttrUniform(Attribute realValue, UniformQuantizedType quantizedElementType, const UniformQuantizedValueConverter &converter, Type &outConvertedType)
Converts an attribute from a type based on quantizedElementType.getExpressedType() to one based on qu...
Represents a family of uniform, quantized types.
Definition: QuantTypes.h:256
bool isa() const
Definition: Attributes.h:107
Reference implementation of converting between real numbers and values represented by a UniformQuanti...
iterator begin() const
Iterator access to the float element values.
Type castExpressedToStorageType(Type candidateType)
Casts from a type based on the expressedType to the equivalent type based on storageType by way of th...
Definition: QuantTypes.cpp:208
An attribute that represents a reference to a dense vector or tensor object.
iterator_range_impl< ElementIterator< T > > getValues() const
Attribute quantizeAttr(Attribute realValue, QuantizedType quantizedElementType, Type &outConvertedType)
Converts an attribute from a type based on quantizedElementType.getExpressedType() to one based on qu...
static Attribute convertPrimitiveValueAttr(Attribute origRealValue, QuantizedType quantizedElementType, const UniformQuantizedValueConverter &converter, Type &outConvertedType)
Converts a possible primitive, real expressed value attribute to a corresponding storage attribute (t...
U dyn_cast() const
Definition: Types.h:244
Attributes are known-constant values of operations.
Definition: Attributes.h:24
static DenseElementsAttr convertDenseFPElementsAttr(DenseFPElementsAttr realFPElementsAttr, QuantizedType quantizedElementType, const UniformQuantizedValueConverter &converter)
Converts a real expressed DenseFPElementsAttr to a corresponding DenseElementsAttr (typically DenseIn...
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
Represents per-axis (also known as per-channel quantization).
Definition: QuantTypes.h:314
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
ElementsAttr convert(Attribute realValue)
Quantize an Attribute by the quantization parameters.
Base class for all quantized types known to this dialect.
Definition: QuantTypes.h:52
An utility class to quantize an attribute by the per-axis quantization parameters.
virtual APInt quantizeFloatToInt(APFloat expressedValue) const