MLIR 24.0.0git
TosaProfileCompliance.cpp
Go to the documentation of this file.
1//===--- TosaProfileCompliance.cpp - Tosa Profile Compliance Validation ---===//
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
10#include "llvm/ADT/StringExtras.h"
11#include "llvm/Support/Compiler.h"
12#include "llvm/Support/raw_ostream.h"
13
14namespace mlir {
15namespace tosa {
16LLVM_ATTRIBUTE_NOINLINE
17VersionedTypeInfo::VersionedTypeInfo(std::initializer_list<TypeInfoRef> types,
18 SpecificationVersion version)
19 : second(version) {
20 first.reserve(types.size());
21 for (const TypeInfoRef &type : types)
22 first.push_back(*type.ptr);
23}
24
25LLVM_ATTRIBUTE_NOINLINE
27 SpecificationVersion version)
28 : first(std::move(types)), second(version) {}
29
30LLVM_ATTRIBUTE_NOINLINE
32
33LLVM_ATTRIBUTE_NOINLINE
35
36LLVM_ATTRIBUTE_NOINLINE
39
40LLVM_ATTRIBUTE_NOINLINE
43
44LLVM_ATTRIBUTE_NOINLINE
46
47template <typename T>
49 std::initializer_list<T> mode,
50 std::initializer_list<VersionedTypeInfo> operandTypeInfoSet,
53}
54
55template <typename T>
61
62template <typename T>
63LLVM_ATTRIBUTE_NOINLINE
65
66template <typename T>
67LLVM_ATTRIBUTE_NOINLINE
69
70template <typename T>
71LLVM_ATTRIBUTE_NOINLINE OpComplianceInfo<T> &
73
74template <typename T>
75LLVM_ATTRIBUTE_NOINLINE OpComplianceInfo<T> &
77
78template <typename T>
79LLVM_ATTRIBUTE_NOINLINE OpComplianceInfo<T>::~OpComplianceInfo() = default;
80
81template struct OpComplianceInfo<Profile>;
82template struct OpComplianceInfo<Extension>;
83
85 static const TypeInfo boolT = {mlir::IntegerType::getTypeID(), 1};
86 static const TypeInfo i4T = {mlir::IntegerType::getTypeID(), 4};
87 static const TypeInfo i8T = {mlir::IntegerType::getTypeID(), 8};
88 static const TypeInfo i16T = {mlir::IntegerType::getTypeID(), 16};
89 static const TypeInfo i32T = {mlir::IntegerType::getTypeID(), 32};
90 static const TypeInfo i48T = {mlir::IntegerType::getTypeID(), 48};
91 static const TypeInfo i64T = {mlir::IntegerType::getTypeID(), 64};
92 static const TypeInfo bf16T = {mlir::BFloat16Type::getTypeID(), 16};
93 static const TypeInfo fp16T = {mlir::Float16Type::getTypeID(), 16};
94 static const TypeInfo fp32T = {mlir::Float32Type::getTypeID(), 32};
95 static const TypeInfo fp8e4m3T = {mlir::Float8E4M3FNType::getTypeID(), 8};
96 static const TypeInfo fp8e5m2T = {mlir::Float8E5M2Type::getTypeID(), 8};
97
98 // micro-scaling formats
99 // Note: these types exist to suppport the deprecated block_scaled operations
100 // and can be removed once those operations are removed.
101 static const TypeInfo fp6e2m3T = {mlir::Float6E2M3FNType::getTypeID(), 6};
102 static const TypeInfo fp6e3m2T = {mlir::Float6E3M2FNType::getTypeID(), 6};
103 static const TypeInfo fp4e2m1T = {mlir::Float4E2M1FNType::getTypeID(), 4};
104 static const TypeInfo fp8ue8m0T = {mlir::Float8E8M0FNUType::getTypeID(), 8};
105 static const TypeInfo mxint8T = {mlir::tosa::mxint8Type::getTypeID(), 8};
106
107 // Block scaled formats
108 const TypeID blockScaledID = mlir::tosa::BlockScaledType::getTypeID();
109 const TypeID fp4e2m1ID = mlir::Float4E2M1FNType::getTypeID();
110 const TypeID fp6e2m3ID = mlir::Float6E2M3FNType::getTypeID();
111 const TypeID fp6e3m2ID = mlir::Float6E3M2FNType::getTypeID();
112 const TypeID fp8e4m3ID = mlir::Float8E4M3FNType::getTypeID();
113 const TypeID fp8e5m2ID = mlir::Float8E5M2Type::getTypeID();
114 const TypeID fp8ue8m0ID = mlir::Float8E8M0FNUType::getTypeID();
115 const TypeID mxint8ID = mlir::tosa::mxint8Type::getTypeID();
116
117 static const TypeInfo bs32_fp8ue8m0_fp4e2m1T = {
118 blockScaledID, 4, fp4e2m1ID, fp8ue8m0ID,
119 tosa::BlockShape::BLOCK_SHAPE_32};
120 static const TypeInfo bs32_fp8ue8m0_fp6e2m3T = {
121 blockScaledID, 6, fp6e2m3ID, fp8ue8m0ID,
122 tosa::BlockShape::BLOCK_SHAPE_32};
123 static const TypeInfo bs32_fp8ue8m0_fp6e3m2T = {
124 blockScaledID, 6, fp6e3m2ID, fp8ue8m0ID,
125 tosa::BlockShape::BLOCK_SHAPE_32};
126 static const TypeInfo bs32_fp8ue8m0_fp8e4m3T = {
127 blockScaledID, 8, fp8e4m3ID, fp8ue8m0ID,
128 tosa::BlockShape::BLOCK_SHAPE_32};
129 static const TypeInfo bs32_fp8ue8m0_fp8e5m2T = {
130 blockScaledID, 8, fp8e5m2ID, fp8ue8m0ID,
131 tosa::BlockShape::BLOCK_SHAPE_32};
132 static const TypeInfo bs32_fp8ue8m0_mxint8T = {
133 blockScaledID, 8, mxint8ID, fp8ue8m0ID, tosa::BlockShape::BLOCK_SHAPE_32};
134
135// The profile-based compliance content below is auto-generated by a script
136// in https://github.com/arm/tosa-specification
138 // End of auto-generated metadata
139}
140
141template <>
145
146template <>
149 return extensionComplianceMap;
150}
151
152// Base populating function
153LogicalResult ProfileInfoDepot::populateProfileInfo(ValueRange operands,
154 ValueRange results) {
155 for (const auto &operand : operands)
156 addValue(operand);
157 for (const auto &result : results)
159 return success();
160}
161
162template <>
163LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ConcatOp op) {
164 addValue(op.getInput1().front());
165 addValue(op.getOutput());
166 return success();
167}
168
169template <>
170LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dOp op) {
171 addValue(op.getInput());
172 addValue(op.getInputZp());
173 addValue(op.getOutputZp());
174 addType(op.getAccType());
175 addValue(op.getOutput());
176 return success();
177}
178
179template <>
180LogicalResult
181ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dAdaptiveOp op) {
182 addValue(op.getInput());
183 addValue(op.getInputZp());
184 addValue(op.getOutputZp());
185 addType(op.getAccType());
186 addValue(op.getOutput());
187 return success();
188}
189
190template <>
191LogicalResult
192ProfileInfoDepot::populateProfileInfo(tosa::MaxPool2dAdaptiveOp op) {
193 addValue(op.getInput());
194 addValue(op.getOutput());
195 return success();
196}
197
198template <typename T>
199LogicalResult ProfileInfoDepot::populateProfileInfoConv(T op) {
200 addValue(op.getInput());
201 addValue(op.getWeight());
202 addValue(op.getBias());
203 addValue(op.getInputZp());
204 addValue(op.getWeightZp());
205 addType(op.getAccType());
206 addValue(op.getOutput());
207 return success();
208}
209
210template <>
211LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv2DOp op) {
212 return populateProfileInfoConv(op);
213}
214
215template <>
216LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv3DOp op) {
217 return populateProfileInfoConv(op);
218}
219
220template <>
221LogicalResult
222ProfileInfoDepot::populateProfileInfo(tosa::TransposeConv2DOp op) {
223 return populateProfileInfoConv(op);
224}
225
226template <>
227LogicalResult
228ProfileInfoDepot::populateProfileInfo(tosa::DepthwiseConv2DOp op) {
229 return populateProfileInfoConv(op);
230}
231
232template <>
233LogicalResult
234ProfileInfoDepot::populateProfileInfo(tosa::Conv2DBlockScaledOp op) {
235 addValue(op.getInputData());
236 addValue(op.getInputScale());
237 addValue(op.getWeightData());
238 addValue(op.getWeightScale());
239 addValue(op.getBias());
240 addValue(op.getOutput());
241 return success();
242}
243
244template <>
245LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::PadOp op) {
246 addValue(op.getInput1());
247 addValue(op.getPadConst());
248 addValue(op.getOutput());
249 return success();
250}
251
252template <typename T>
253LogicalResult ProfileInfoDepot::populateProfileInfoDataLayout(T op) {
254 addValue(op.getInput1());
255 addValue(op.getOutput());
256 return success();
257}
258
259template <>
260LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ReshapeOp op) {
261 return populateProfileInfoDataLayout(op);
262}
263
264template <>
265LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SliceOp op) {
266 return populateProfileInfoDataLayout(op);
267}
268
269template <>
270LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TileOp op) {
271 return populateProfileInfoDataLayout(op);
272}
273
274template <>
275LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TransposeOp op) {
276 return populateProfileInfoDataLayout(op);
277}
278
279template <>
280LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::GatherOp op) {
281 addValue(op.getValues());
282 addValue(op.getIndices());
283 addValue(op.getOutput());
284 return success();
285}
286
287template <>
288LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RowGatherOp op) {
289 addValue(op.getValues());
290 addValue(op.getIndices());
291 addValue(op.getOutput());
292 return success();
293}
294
295template <>
296LogicalResult
297ProfileInfoDepot::populateProfileInfo(tosa::RowGatherBlockScaledOp op) {
298 for (Value value : op.getValues())
299 addValue(value);
300 addValue(op.getIndices());
301 addValue(op.getRowCount());
302 for (Value result : op.getOutput())
304 return success();
305}
306
307template <>
308LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ScatterOp op) {
309 addValue(op.getValuesIn());
310 addValue(op.getIndices());
311 addValue(op.getInput());
312 addValue(op.getValuesOut());
313 return success();
314}
315
316template <>
317LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MulOp op) {
318 addValue(op.getInput1());
319 addValue(op.getInput2());
320 addValue(op.getOutput());
321 return success();
322}
323
324template <>
325LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ResizeOp op) {
326 addValue(op.getInput());
327 addValue(op.getOutput());
328 return success();
329}
330
331template <>
332LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SelectOp op) {
333 addValue(op.getOnTrue());
334 addValue(op.getOnFalse());
335 addValue(op.getOutput());
336 return success();
337}
338
339template <>
340LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RescaleOp op) {
341 addValue(op.getInput());
342 addValue(op.getInputZp());
343 addValue(op.getOutputZp());
344 addValue(op.getOutput());
345 return success();
346}
347
348template <>
349LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulOp op) {
350 addValue(op.getA());
351 addValue(op.getB());
352 addValue(op.getAZp());
353 addValue(op.getBZp());
354 addValue(op.getOutput());
355 return success();
356}
357
358template <>
359LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulTOp op) {
360 addValue(op.getA());
361 addValue(op.getB());
362 addValue(op.getAZp());
363 addValue(op.getBZp());
364 addValue(op.getOutput());
365 return success();
366}
367
368template <>
369LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableOp op) {
370 addType(op.getType());
371 return success();
372}
373
374template <>
375LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableWriteOp op) {
376 addValue(op.getInput1());
377 return success();
378}
379
380template <>
381LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::DimOp op) {
382 addValue(op.getInput1());
383 return success();
384}
385
386LogicalResult ProfileInfoDepot::populatationDispatch(Operation *op) {
387// This helper function only populates the info for the customised operands.
388#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp) \
389 if (isa<tosa::tosaOp##Op>(op)) { \
390 return populateProfileInfo(cast<tosa::tosaOp##Op>(op)); \
391 }
392
393#define POPULATE_PROFILE_INFO_SKIP(tosaOp) \
394 if (isa<tosa::tosaOp##Op>(op)) \
395 return success();
396
397// This helper function populates the info for all operands.
398#define POPULATE_PROFILE_INFO_COMMON(tosaOp) \
399 if (isa<tosa::tosaOp##Op>(op)) { \
400 return populateProfileInfo(op->getOperands(), op->getResults()); \
401 }
402
403 // Skip irrelevant operands when they are independent and not tied to any
404 // specific profile/extension.
406 POPULATE_PROFILE_INFO_CUSTOM(AvgPool2dAdaptive)
407 POPULATE_PROFILE_INFO_CUSTOM(TransposeConv2D)
409 POPULATE_PROFILE_INFO_CUSTOM(Conv2DBlockScaled)
411 POPULATE_PROFILE_INFO_CUSTOM(DepthwiseConv2D)
421 POPULATE_PROFILE_INFO_CUSTOM(RowGatherBlockScaled)
429 POPULATE_PROFILE_INFO_CUSTOM(VariableWrite)
431 POPULATE_PROFILE_INFO_CUSTOM(MaxPool2dAdaptive)
432
433 // For the most of tosa operators, all operands are profile/extension related
434 // and hence are all considered in this profile-based compilance check.
435 POPULATE_PROFILE_INFO_COMMON(MatmulTBlockScaled)
439 POPULATE_PROFILE_INFO_COMMON(CastFromBlockScaled)
440 POPULATE_PROFILE_INFO_COMMON(CastToBlockScaled)
453 POPULATE_PROFILE_INFO_COMMON(ArithmeticRightShift)
458 POPULATE_PROFILE_INFO_COMMON(LogicalLeftShift)
459 POPULATE_PROFILE_INFO_COMMON(LogicalRightShift)
482 POPULATE_PROFILE_INFO_COMMON(ReduceProduct)
485 POPULATE_PROFILE_INFO_COMMON(GreaterEqual)
489 POPULATE_PROFILE_INFO_COMMON(VariableRead)
490
491 // Type Invariant Extension, a capability extension that is independent
492 // of the data type, meaning any compatible type can be used. No type
493 // constraint for those operations.
495 POPULATE_PROFILE_INFO_SKIP(AssertEqualShape)
496 POPULATE_PROFILE_INFO_SKIP(ConcatShape)
498 POPULATE_PROFILE_INFO_SKIP(DivCeilShape)
499 POPULATE_PROFILE_INFO_SKIP(DivFloorShape)
501 POPULATE_PROFILE_INFO_SKIP(Log2CeilShape)
502 POPULATE_PROFILE_INFO_SKIP(Log2FloorShape)
512
513 return failure();
514}
515
516//===----------------------------------------------------------------------===//
517// Tosa Profile And Extension Compliance Checker
518//===----------------------------------------------------------------------===//
519
520template <typename T>
521FailureOr<SmallVector<OpComplianceInfo<T>>>
522TosaProfileCompliance::getOperatorMatchedEntries(Operation *op) {
523 const std::string opName = op->getName().getStringRef().str();
524 const auto complianceMap = getProfileComplianceMap<T>();
525 const auto it = complianceMap.find(opName);
526 if (it == complianceMap.end())
527 return {};
528
529 return findMatchedEntries<T>(op, it->second);
530}
531
532template <typename T>
534 Operation *op, const tosa::TargetEnv &targetEnv) {
535 const auto maybeOpEntries = getOperatorMatchedEntries<T>(op);
536 if (failed(maybeOpEntries))
537 return success();
538
539 const auto opEntries = maybeOpEntries.value();
540 if (opEntries.size() == 0) {
541 // No matched restriction found.
542 return success();
543 }
544
545 // Check the profile/extension requirement according to the current target
546 // profiles/extensions.
547 const auto isModeAllowed = [&](const OpComplianceInfo<T> &info) -> bool {
548 if (info.condition == CheckCondition::allOf)
549 return targetEnv.allowsAllOf(info.mode);
550 return targetEnv.allowsAnyOf(info.mode);
551 };
552
553 // Check the matched op compliance version does not exceed the target
554 // specification version.
555 const TosaSpecificationVersion targetVersion{targetEnv.getSpecVersion()};
556 const auto isVersionCompatible =
557 [&targetVersion](const OpComplianceInfo<T> &info) -> bool {
558 // Assume compatible if there are no versioned type constraints
559 if (info.operandTypeInfoSet.empty())
560 return true;
561 const TosaSpecificationVersion complianceVersion{
562 info.operandTypeInfoSet.front().second};
563 return targetVersion.isBackwardsCompatibleWith(complianceVersion);
564 };
565
566 for (const auto &info : opEntries) {
567 // Type constraints exist, check if they are compatible with the current
568 // target definition, including: profile, extension and specification
569 // version
570 if (isModeAllowed(info) && isVersionCompatible(info))
571 return success();
572 }
573
574 // No valid entry was found, now emit appropriate error message and return
575 // failure
576 std::string message;
577 llvm::raw_string_ostream os(message);
578
579 os << "illegal: ";
580 const size_t numOpEntries = opEntries.size();
581 for (const auto &[index, info] : llvm::enumerate(opEntries)) {
582 bool mismatchedVersion = false;
583 if (!isVersionCompatible(info)) {
584 mismatchedVersion = true;
585 os << "requires specification version compatible with "
586 << stringifyVersion(info.operandTypeInfoSet.front().second) << " (got "
587 << stringifyVersion(targetVersion) << ") ";
588 }
589
590 if (!isModeAllowed(info)) {
591 if (mismatchedVersion)
592 os << "and ";
593 os << "requires "
594 << (info.condition == CheckCondition::allOf ? "all of " : "any of ")
595 << "[" << llvm::join(stringifyProfile<T>(info.mode), ", ")
596 << "] profiles/extensions ";
597 }
598
599 if (index != numOpEntries - 1)
600 os << "OR ";
601 }
602 os << "to be specified in the target environment";
603
604 return op->emitOpError(message);
605}
606
607LogicalResult
609 const tosa::TargetEnv &targetEnv) {
610 return checkProfileOrExtension<Profile>(op, targetEnv);
611}
612
613LogicalResult
618
620 const auto maybeProfEntries = getOperatorMatchedEntries<Profile>(op);
621 const auto maybeExtEntries = getOperatorMatchedEntries<Extension>(op);
622 if (failed(maybeProfEntries) && failed(maybeExtEntries))
623 return success();
624
625 const bool hasEntry =
626 (succeeded(maybeProfEntries) && !maybeProfEntries.value().empty()) ||
627 (succeeded(maybeExtEntries) && !maybeExtEntries.value().empty());
628
629 if (!hasEntry) {
630 std::string message;
631 llvm::raw_string_ostream os(message);
632 os << "illegal: operation operand/result data types did not align with any "
633 "profile or extension, got (";
634
635 ProfileInfoDepot depot(op);
636 SmallVector<TypeInfo> current = depot.getInfo();
637 for (const auto &typeInfo : llvm::drop_end(current))
638 os << stringifyTypeInfo(typeInfo) << ",";
639 os << stringifyTypeInfo(current.back()) << ")";
640
641 // avoid polluting the error message output by outputting only
642 // the best match
643 const std::string opName = op->getName().getStringRef().str();
644 int maxMatches = -1;
645 SmallVector<TypeInfo> bestTypeInfo;
646 const auto searchBestMatch = [&](auto map) {
647 for (const auto &complianceInfos : map[opName]) {
648 for (const auto &versionedTypeInfos :
649 complianceInfos.operandTypeInfoSet) {
650 const SmallVector<TypeInfo> typeInfos = versionedTypeInfos.first;
651 if (current.size() != typeInfos.size())
652 continue;
653 const int matches = llvm::count_if(
654 llvm::zip_equal(current, typeInfos), [&](const auto zipType) {
655 return isSameTypeInfo(std::get<0>(zipType),
656 std::get<1>(zipType));
657 });
658 if (matches > maxMatches) {
659 maxMatches = matches;
660 bestTypeInfo = typeInfos;
661 }
662 }
663 }
664 };
665 searchBestMatch(getProfileComplianceMap<Profile>());
666 searchBestMatch(getProfileComplianceMap<Extension>());
667
668 os << ", did you mean (";
669 for (const auto &typeInfo : llvm::drop_end(bestTypeInfo))
670 os << stringifyTypeInfo(typeInfo) << ",";
671 os << stringifyTypeInfo(bestTypeInfo.back()) << ")? ";
672 os << "Otherwise, please refer to the 'supported data types' for '"
673 << opName << "' in the specification.";
674 op->emitOpError(message);
675 return failure();
676 }
677
678 return success();
679}
680
681// Find the profiles or extensions requirement according to the signature of
682// type of the operand list.
683template <typename T>
686 assert(compInfo.size() != 0 &&
687 "profile-based compliance information is empty");
688
689 // If there are no type constraints for the given operation, return the
690 // matched entries directly so required profile/extension information can
691 // be checked
693 if (llvm::all_of(compInfo, [&matchedInfos](const OpComplianceInfo<T> &info) {
694 if (info.operandTypeInfoSet.empty()) {
695 matchedInfos.push_back(info);
696 return true;
697 }
698 return false;
699 }))
700 return matchedInfos;
701
702 // Get the type information of the operator we're trying to match
703 ProfileInfoDepot depot(op);
704 SmallVector<TypeInfo> present = depot.getInfo();
705 if (present.size() == 0)
706 return {};
707
708 // Compare 'present' against known type signatures in the compliance metadata
709 for (size_t i = 0; i < compInfo.size(); i++) {
710 SmallVector<VersionedTypeInfo> sets = compInfo[i].operandTypeInfoSet;
711 for (const auto &set : sets) {
712 SmallVector<TypeInfo> expected = set.first;
713 // Tensor-list operators can legitimately have multiple valid signatures
714 // with different operand/result counts, e.g. data-only and data+scale
715 // forms. Treat those as non-matches instead of asserting.
716 if (present.size() != expected.size())
717 continue;
718
719 bool isFound = true;
720 // Compare the type signature between the given operation and the
721 // compliance metadata.
722 for (size_t j = 0; j < expected.size(); j++) {
723 if (!isSameTypeInfo(present[j], expected[j])) {
724 // Verify the next mode set from the list.
725 isFound = false;
726 break;
727 }
728 }
729
730 if (isFound == true) {
731 SmallVector<VersionedTypeInfo> typeInfoSet{set};
732 OpComplianceInfo<T> info{compInfo[i].mode, typeInfoSet,
733 compInfo[i].condition};
734 matchedInfos.push_back(info);
735 }
736 }
737 }
738
739 return matchedInfos;
740}
741
742// Debug utilites.
743template <typename T>
746 SmallVector<StringRef> debugStrings;
747 for (const auto &profile : profiles) {
748 if constexpr (std::is_same_v<T, Profile>)
749 debugStrings.push_back(tosa::stringifyProfile(profile));
750 else
751 debugStrings.push_back(tosa::stringifyExtension(profile));
752 }
753 return debugStrings;
754}
755
756template <typename T>
758 const SmallVector<ArrayRef<T>> &profileSet) {
759 SmallVector<StringRef> debugStrings;
760
761 for (const auto &profiles : profileSet) {
762 auto tempStrings = stringifyProfile<T>(profiles);
763 llvm::append_range(debugStrings, tempStrings);
764 }
765
766 return debugStrings;
767}
768
771 const auto stringifyScalarTypeInfo =
772 [](const TypeInfo &typeInfo) -> llvm::SmallString<32> {
773 if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
774 return {"i" + llvm::utostr(typeInfo.bitWidth)};
775 }
776 if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
777 return {"f16"};
778 } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
779 return {"f32"};
780 } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
781 return {"bf16"};
782 } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
783 return {"fp8e4m3"};
784 } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
785 return {"fp8e5m2"};
786 } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
787 return {"fp6e2m3"};
788 } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
789 return {"fp6e3m2"};
790 } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
791 return {"fp4e2m1"};
792 } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
793 return {"fp8e8m0"};
794 } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
795 return {"mxint8"};
796 }
797 llvm_unreachable("unknown type");
798 };
799
800 if (typeInfo.typeID == tosa::BlockScaledType::getTypeID()) {
801 TypeInfo valueInfo = {typeInfo.valueTypeID, typeInfo.bitWidth};
802 TypeInfo scaleInfo = {typeInfo.scaleTypeID, 8};
804 llvm::raw_svector_ostream os(result);
805 os << "bs"
806 << tosa::BlockShapeAttr::getBlockShapeValue(typeInfo.blockShape.value())
807 << "_" << stringifyScalarTypeInfo(scaleInfo) << "_"
808 << stringifyScalarTypeInfo(valueInfo);
809 return result;
810 }
811
812 return stringifyScalarTypeInfo(typeInfo);
813}
814} // namespace tosa
815} // namespace mlir
for(Operation *op :ops)
return success()
#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp)
#define POPULATE_PROFILE_INFO_COMMON(tosaOp)
#define POPULATE_PROFILE_INFO_SKIP(tosaOp)
@ Gather
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OperationName getName()
The name of an operation is the key identifier for it.
Definition Operation.h:115
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
SmallVector< TypeInfo > getInfo()
This class represents the capability enabled in the target implementation such as profile,...
Definition TargetEnv.h:119
bool allowsAllOf(ArrayRef< Profile > profs) const
Definition TargetEnv.h:145
bool allowsAnyOf(ArrayRef< Profile > profs) const
Definition TargetEnv.h:141
TosaSpecificationVersion getSpecVersion() const
Definition TargetEnv.h:132
static llvm::SmallString< 32 > stringifyTypeInfo(const TypeInfo &typeInfo)
LogicalResult checkExtension(Operation *op, const tosa::TargetEnv &targetEnv)
LogicalResult checkInvalid(Operation *op)
std::unordered_map< std::string, SmallVector< OpComplianceInfo< T > > > getProfileComplianceMap()
SmallVector< OpComplianceInfo< T > > findMatchedEntries(Operation *op, SmallVector< OpComplianceInfo< T > > compInfo)
LogicalResult checkProfileOrExtension(Operation *op, const tosa::TargetEnv &targetEnv)
LogicalResult checkProfile(Operation *op, const tosa::TargetEnv &targetEnv)
SmallVector< StringRef > stringifyProfile(ArrayRef< T > profiles)
bool isSameTypeInfo(TypeInfo a, TypeInfo b)
A thin wrapper around the SpecificationVersion enum to represent and provide utilities around the TOS...
Definition TargetEnv.h:60
bool isBackwardsCompatibleWith(TosaSpecificationVersion baseVersion) const
Definition TargetEnv.h:69
llvm::SmallString< 4 > stringifyVersion(TosaSpecificationVersion version)
Definition TargetEnv.cpp:25
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Extension > > > OperationExtensionComplianceMap
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Profile > > > OperationProfileComplianceMap
Include the generated interface declarations.
@ Mul
RHS of mul is always a constant or a symbolic expression.
Definition AffineExpr.h:43
SmallVector< VersionedTypeInfo > operandTypeInfoSet
OpComplianceInfo & operator=(const OpComplianceInfo &other)
std::optional< tosa::BlockShape > blockShape
VersionedTypeInfo & operator=(const VersionedTypeInfo &other)
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.