16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/DenseMap.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/Support/CommandLine.h"
20#include "llvm/Support/MathExtras.h"
29class parser<std::pair<unsigned, unsigned>>
34 bool parse(Option &option, StringRef argName, StringRef arg,
35 std::pair<unsigned, unsigned> &value) {
36 auto [source, destination] = arg.split(
':');
37 if (source.getAsInteger(10, value.first) ||
38 destination.getAsInteger(10, value.second))
39 return option.error(
"expected <source>:<destination> integer bitwidths",
44 StringRef
getValueName()
const override {
return "source:destination"; }
46 static void print(raw_ostream &os,
47 const std::pair<unsigned, unsigned> &value) {
48 os << value.first <<
":" << value.second;
54#define GEN_PASS_DEF_TOSACONVERTINTEGERTYPESBITWIDTHPASS
55#include "mlir/Dialect/Tosa/Transforms/Passes.h.inc"
64 IntegerType convertedType) {
65 const unsigned inputElementSizeInBytes = llvm::divideCeil(type.getWidth(), 8);
66 const unsigned outputElementSizeInBytes = convertedType.getWidth() / 8;
67 const size_t numElements = rawData.size() / inputElementSizeInBytes;
69 const auto *input =
reinterpret_cast<const uint8_t *
>(rawData.data());
70 auto *output =
reinterpret_cast<uint8_t *
>(data.data());
71 for (
size_t i = 0; i < numElements; ++i) {
72 APInt value(inputElementSizeInBytes * 8, 0);
73 llvm::LoadIntFromMemory(value, input + i * inputElementSizeInBytes,
74 inputElementSizeInBytes);
76 value = value.trunc(type.getWidth());
77 llvm::StoreIntToMemory(value.sext(convertedType.getWidth()),
78 output + i * outputElementSizeInBytes,
79 outputElementSizeInBytes);
88 addReplacement([&mappings](IntegerType type) -> std::optional<Type> {
89 auto mapping = mappings.find(type.getWidth());
90 if (mapping == mappings.end())
92 return IntegerType::get(type.getContext(), mapping->second);
95 [
this](IntegerAttr attr) {
return skip(convertInteger(attr)); });
97 [
this](DenseArrayAttr attr) {
return skip(convertDenseArray(attr)); });
98 addReplacement([
this](DenseTypedElementsAttr attr) {
99 return skip(convertDenseElements(attr));
101 addReplacement([
this](DenseResourceElementsAttr attr) {
102 return skip(convertDenseResource(attr));
106 bool hasFailed()
const {
return conversionFailed; }
109 Attribute convertInteger(IntegerAttr attr) {
110 Type type = attr.getType();
111 Type convertedType = replace(type);
112 if (type == convertedType)
114 return IntegerAttr::get(
116 attr.getValue().sext(cast<IntegerType>(convertedType).getWidth()));
119 Attribute convertDenseArray(DenseArrayAttr attr) {
120 Type type = attr.getElementType();
121 Type convertedType = replace(type);
122 if (type == convertedType)
125 const SmallVector<char> data =
126 convertRawValues(attr.getRawData(), cast<IntegerType>(type),
127 cast<IntegerType>(convertedType));
128 return DenseArrayAttr::get(convertedType, attr.size(), data);
131 Attribute convertDenseElements(DenseTypedElementsAttr attr) {
132 auto convertedType = dyn_cast_or_null<ShapedType>(replace(attr.getType()));
136 Type elementType = attr.getElementType();
137 Type convertedElementType = convertedType.getElementType();
138 if (elementType == convertedElementType) {
140 return attr.reshape(convertedType);
143 auto convertedIntegerType = dyn_cast<IntegerType>(convertedElementType);
144 if (!convertedIntegerType)
147 .mapValues(convertedElementType,
148 [convertedIntegerType](
const APInt &value) {
149 return value.sext(convertedIntegerType.getWidth());
151 .reshape(convertedType);
154 Attribute convertDenseResource(DenseResourceElementsAttr attr) {
155 ShapedType type = attr.getType();
156 Type elementType = type.getElementType();
157 auto convertedType = dyn_cast_or_null<ShapedType>(replace(type));
160 Type convertedElementType = convertedType.getElementType();
161 if (elementType == convertedElementType)
162 return DenseResourceElementsAttr::get(convertedType, attr.getRawHandle());
163 auto convertedIntegerType = dyn_cast<IntegerType>(convertedElementType);
164 if (!convertedIntegerType)
166 auto integerType = cast<IntegerType>(elementType);
167 const AsmResourceBlob *blob = attr.getRawHandle().getBlob();
170 ArrayRef<char> rawData = blob->
getData();
171 const unsigned elementSizeInBytes =
172 llvm::divideCeil(integerType.getWidth(), 8);
173 if (rawData.size() % elementSizeInBytes != 0)
176 if (type.hasStaticShape() &&
178 elementSizeInBytes *
static_cast<uint64_t
>(type.getNumElements()))
180 const SmallVector<char> data =
181 convertRawValues(rawData, integerType, convertedIntegerType);
182 const unsigned alignment = convertedIntegerType.getWidth() / 8;
183 return DenseResourceElementsAttr::get(
184 convertedType, attr.getRawHandle().getKey(),
189 ReplaceFnResult<Attribute> skip(Attribute attr) {
191 conversionFailed |= !attr;
195 bool conversionFailed =
false;
198struct TosaConvertIntegerTypesBitwidth
200 TosaConvertIntegerTypesBitwidth> {
203 void runOnOperation()
override {
204 if (bitwidthMappings.empty()) {
205 getOperation().emitError(
206 "The 'bitwidth-mappings' option must be specified and non-empty.");
207 return signalPassFailure();
210 for (
auto [source, destination] : bitwidthMappings) {
211 if (!((source == 4 && destination == 8) ||
212 (source == 48 && destination == 64))) {
213 getOperation().emitError(
"unsupported integer bitwidth mapping ")
214 << source <<
":" << destination <<
": expected 4:8 or 48:64";
215 return signalPassFailure();
217 mappings.try_emplace(source, destination);
219 IntegerTypeReplacer replacer(mappings);
220 replacer.recursivelyReplaceElementsIn(getOperation(),
true,
223 if (replacer.hasFailed()) {
224 getOperation().emitError(
"failed to convert integer types or attributes");
StringRef getValueName() const override
bool parse(Option &option, StringRef argName, StringRef arg, std::pair< unsigned, unsigned > &value)
static void print(raw_ostream &os, const std::pair< unsigned, unsigned > &value)
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
This is an attribute/type replacer that is naively cached.
static AsmResourceBlob allocateAndCopyWithAlign(ArrayRef< char > data, size_t align, bool dataIsMutable=true)
Create a new heap allocated blob and copy the provided data into it.
Include the generated interface declarations.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap