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
14using namespace mlir;
15using namespace mlir::tosa;
16
17// Building this ~5,000-line generated initializer map under HWAddressSanitizer
18// or MemorySanitizer leads to extreme compile times (>3.5 minutes) during
19// InstCombine and greedy register allocation due to instrumentation
20// overhead. Disable optimization under MSan/HWAsan to keep build times
21// manageable.
22#if LLVM_MEMORY_SANITIZER_BUILD || LLVM_HWADDRESS_SANITIZER_BUILD
23__attribute__((optnone))
24#else
25LLVM_ATTRIBUTE_MINSIZE
26#endif
28 const TypeInfo boolT = {mlir::IntegerType::getTypeID(), 1};
29 const TypeInfo i4T = {mlir::IntegerType::getTypeID(), 4};
30 const TypeInfo i8T = {mlir::IntegerType::getTypeID(), 8};
31 const TypeInfo i16T = {mlir::IntegerType::getTypeID(), 16};
32 const TypeInfo i32T = {mlir::IntegerType::getTypeID(), 32};
33 const TypeInfo i48T = {mlir::IntegerType::getTypeID(), 48};
34 const TypeInfo i64T = {mlir::IntegerType::getTypeID(), 64};
35 const TypeInfo bf16T = {mlir::BFloat16Type::getTypeID(), 16};
36 const TypeInfo fp16T = {mlir::Float16Type::getTypeID(), 16};
37 const TypeInfo fp32T = {mlir::Float32Type::getTypeID(), 32};
38 const TypeInfo fp8e4m3T = {mlir::Float8E4M3FNType::getTypeID(), 8};
39 const TypeInfo fp8e5m2T = {mlir::Float8E5M2Type::getTypeID(), 8};
40
41 // micro-scaling formats
42 // Note: these types exist to suppport the deprecated block_scaled operations
43 // and can be removed once those operations are removed.
44 const TypeInfo fp6e2m3T = {mlir::Float6E2M3FNType::getTypeID(), 6};
45 const TypeInfo fp6e3m2T = {mlir::Float6E3M2FNType::getTypeID(), 6};
46 const TypeInfo fp4e2m1T = {mlir::Float4E2M1FNType::getTypeID(), 4};
47 const TypeInfo fp8ue8m0T = {mlir::Float8E8M0FNUType::getTypeID(), 8};
48 const TypeInfo mxint8T = {mlir::tosa::mxint8Type::getTypeID(), 8};
49
50 // Block scaled formats
51 const TypeID blockScaledID = mlir::tosa::BlockScaledType::getTypeID();
52 const TypeID fp4e2m1ID = mlir::Float4E2M1FNType::getTypeID();
53 const TypeID fp6e2m3ID = mlir::Float6E2M3FNType::getTypeID();
54 const TypeID fp6e3m2ID = mlir::Float6E3M2FNType::getTypeID();
55 const TypeID fp8e4m3ID = mlir::Float8E4M3FNType::getTypeID();
56 const TypeID fp8e5m2ID = mlir::Float8E5M2Type::getTypeID();
57 const TypeID fp8ue8m0ID = mlir::Float8E8M0FNUType::getTypeID();
58 const TypeID mxint8ID = mlir::tosa::mxint8Type::getTypeID();
59
60 const TypeInfo bs32_fp8ue8m0_fp4e2m1T = {blockScaledID, 4, fp4e2m1ID,
61 fp8ue8m0ID,
62 tosa::BlockShape::BLOCK_SHAPE_32};
63 const TypeInfo bs32_fp8ue8m0_fp6e2m3T = {blockScaledID, 6, fp6e2m3ID,
64 fp8ue8m0ID,
65 tosa::BlockShape::BLOCK_SHAPE_32};
66 const TypeInfo bs32_fp8ue8m0_fp6e3m2T = {blockScaledID, 6, fp6e3m2ID,
67 fp8ue8m0ID,
68 tosa::BlockShape::BLOCK_SHAPE_32};
69 const TypeInfo bs32_fp8ue8m0_fp8e4m3T = {blockScaledID, 8, fp8e4m3ID,
70 fp8ue8m0ID,
71 tosa::BlockShape::BLOCK_SHAPE_32};
72 const TypeInfo bs32_fp8ue8m0_fp8e5m2T = {blockScaledID, 8, fp8e5m2ID,
73 fp8ue8m0ID,
74 tosa::BlockShape::BLOCK_SHAPE_32};
75 const TypeInfo bs32_fp8ue8m0_mxint8T = {
76 blockScaledID, 8, mxint8ID, fp8ue8m0ID, tosa::BlockShape::BLOCK_SHAPE_32};
77
78// The profile-based compliance content below is auto-generated by a script
79// in https://github.com/arm/tosa-specification
81 // End of auto-generated metadata
82}
83
84template <>
88
89template <>
92 return extensionComplianceMap;
93}
94
95// Base populating function
96LogicalResult ProfileInfoDepot::populateProfileInfo(ValueRange operands,
97 ValueRange results) {
98 for (const auto &operand : operands)
99 addValue(operand);
100 for (const auto &result : results)
102 return success();
103}
104
105template <>
106LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ConcatOp op) {
107 addValue(op.getInput1().front());
108 addValue(op.getOutput());
109 return success();
110}
111
112template <>
113LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dOp op) {
114 addValue(op.getInput());
115 addValue(op.getInputZp());
116 addValue(op.getOutputZp());
117 addType(op.getAccType());
118 addValue(op.getOutput());
119 return success();
120}
121
122template <>
123LogicalResult
124ProfileInfoDepot::populateProfileInfo(tosa::AvgPool2dAdaptiveOp op) {
125 addValue(op.getInput());
126 addValue(op.getInputZp());
127 addValue(op.getOutputZp());
128 addType(op.getAccType());
129 addValue(op.getOutput());
130 return success();
131}
132
133template <>
134LogicalResult
135ProfileInfoDepot::populateProfileInfo(tosa::MaxPool2dAdaptiveOp op) {
136 addValue(op.getInput());
137 addValue(op.getOutput());
138 return success();
139}
140
141template <typename T>
142LogicalResult ProfileInfoDepot::populateProfileInfoConv(T op) {
143 addValue(op.getInput());
144 addValue(op.getWeight());
145 addValue(op.getBias());
146 addValue(op.getInputZp());
147 addValue(op.getWeightZp());
148 addType(op.getAccType());
149 addValue(op.getOutput());
150 return success();
151}
152
153template <>
154LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv2DOp op) {
155 return populateProfileInfoConv(op);
156}
157
158template <>
159LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::Conv3DOp op) {
160 return populateProfileInfoConv(op);
161}
162
163template <>
164LogicalResult
165ProfileInfoDepot::populateProfileInfo(tosa::TransposeConv2DOp op) {
166 return populateProfileInfoConv(op);
167}
168
169template <>
170LogicalResult
171ProfileInfoDepot::populateProfileInfo(tosa::DepthwiseConv2DOp op) {
172 return populateProfileInfoConv(op);
173}
174
175template <>
176LogicalResult
177ProfileInfoDepot::populateProfileInfo(tosa::Conv2DBlockScaledOp op) {
178 addValue(op.getInputData());
179 addValue(op.getInputScale());
180 addValue(op.getWeightData());
181 addValue(op.getWeightScale());
182 addValue(op.getBias());
183 addValue(op.getOutput());
184 return success();
185}
186
187template <>
188LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::PadOp op) {
189 addValue(op.getInput1());
190 addValue(op.getPadConst());
191 addValue(op.getOutput());
192 return success();
193}
194
195template <typename T>
196LogicalResult ProfileInfoDepot::populateProfileInfoDataLayout(T op) {
197 addValue(op.getInput1());
198 addValue(op.getOutput());
199 return success();
200}
201
202template <>
203LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ReshapeOp op) {
204 return populateProfileInfoDataLayout(op);
205}
206
207template <>
208LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SliceOp op) {
209 return populateProfileInfoDataLayout(op);
210}
211
212template <>
213LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TileOp op) {
214 return populateProfileInfoDataLayout(op);
215}
216
217template <>
218LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::TransposeOp op) {
219 return populateProfileInfoDataLayout(op);
220}
221
222template <>
223LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::GatherOp op) {
224 addValue(op.getValues());
225 addValue(op.getIndices());
226 addValue(op.getOutput());
227 return success();
228}
229
230template <>
231LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RowGatherOp op) {
232 addValue(op.getValues());
233 addValue(op.getIndices());
234 addValue(op.getOutput());
235 return success();
236}
237
238template <>
239LogicalResult
240ProfileInfoDepot::populateProfileInfo(tosa::RowGatherBlockScaledOp op) {
241 for (Value value : op.getValues())
242 addValue(value);
243 addValue(op.getIndices());
244 addValue(op.getRowCount());
245 for (Value result : op.getOutput())
247 return success();
248}
249
250template <>
251LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ScatterOp op) {
252 addValue(op.getValuesIn());
253 addValue(op.getIndices());
254 addValue(op.getInput());
255 addValue(op.getValuesOut());
256 return success();
257}
258
259template <>
260LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MulOp op) {
261 addValue(op.getInput1());
262 addValue(op.getInput2());
263 addValue(op.getOutput());
264 return success();
265}
266
267template <>
268LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::ResizeOp op) {
269 addValue(op.getInput());
270 addValue(op.getOutput());
271 return success();
272}
273
274template <>
275LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::SelectOp op) {
276 addValue(op.getOnTrue());
277 addValue(op.getOnFalse());
278 addValue(op.getOutput());
279 return success();
280}
281
282template <>
283LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::RescaleOp op) {
284 addValue(op.getInput());
285 addValue(op.getInputZp());
286 addValue(op.getOutputZp());
287 addValue(op.getOutput());
288 return success();
289}
290
291template <>
292LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulOp op) {
293 addValue(op.getA());
294 addValue(op.getB());
295 addValue(op.getAZp());
296 addValue(op.getBZp());
297 addValue(op.getOutput());
298 return success();
299}
300
301template <>
302LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::MatMulTOp op) {
303 addValue(op.getA());
304 addValue(op.getB());
305 addValue(op.getAZp());
306 addValue(op.getBZp());
307 addValue(op.getOutput());
308 return success();
309}
310
311template <>
312LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableOp op) {
313 addType(op.getType());
314 return success();
315}
316
317template <>
318LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableWriteOp op) {
319 addValue(op.getInput1());
320 return success();
321}
322
323template <>
324LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::DimOp op) {
325 addValue(op.getInput1());
326 return success();
327}
328
329LogicalResult ProfileInfoDepot::populatationDispatch(Operation *op) {
330// This helper function only populates the info for the customised operands.
331#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp) \
332 if (isa<tosa::tosaOp##Op>(op)) { \
333 return populateProfileInfo(cast<tosa::tosaOp##Op>(op)); \
334 }
335
336#define POPULATE_PROFILE_INFO_SKIP(tosaOp) \
337 if (isa<tosa::tosaOp##Op>(op)) \
338 return success();
339
340// This helper function populates the info for all operands.
341#define POPULATE_PROFILE_INFO_COMMON(tosaOp) \
342 if (isa<tosa::tosaOp##Op>(op)) { \
343 return populateProfileInfo(op->getOperands(), op->getResults()); \
344 }
345
346 // Skip irrelevant operands when they are independent and not tied to any
347 // specific profile/extension.
349 POPULATE_PROFILE_INFO_CUSTOM(AvgPool2dAdaptive)
350 POPULATE_PROFILE_INFO_CUSTOM(TransposeConv2D)
352 POPULATE_PROFILE_INFO_CUSTOM(Conv2DBlockScaled)
354 POPULATE_PROFILE_INFO_CUSTOM(DepthwiseConv2D)
364 POPULATE_PROFILE_INFO_CUSTOM(RowGatherBlockScaled)
372 POPULATE_PROFILE_INFO_CUSTOM(VariableWrite)
374 POPULATE_PROFILE_INFO_CUSTOM(MaxPool2dAdaptive)
375
376 // For the most of tosa operators, all operands are profile/extension related
377 // and hence are all considered in this profile-based compilance check.
378 POPULATE_PROFILE_INFO_COMMON(MatmulTBlockScaled)
382 POPULATE_PROFILE_INFO_COMMON(CastFromBlockScaled)
383 POPULATE_PROFILE_INFO_COMMON(CastToBlockScaled)
396 POPULATE_PROFILE_INFO_COMMON(ArithmeticRightShift)
401 POPULATE_PROFILE_INFO_COMMON(LogicalLeftShift)
402 POPULATE_PROFILE_INFO_COMMON(LogicalRightShift)
425 POPULATE_PROFILE_INFO_COMMON(ReduceProduct)
428 POPULATE_PROFILE_INFO_COMMON(GreaterEqual)
432 POPULATE_PROFILE_INFO_COMMON(VariableRead)
433
434 // Type Invariant Extension, a capability extension that is independent
435 // of the data type, meaning any compatible type can be used. No type
436 // constraint for those operations.
438 POPULATE_PROFILE_INFO_SKIP(AssertEqualShape)
439 POPULATE_PROFILE_INFO_SKIP(ConcatShape)
441 POPULATE_PROFILE_INFO_SKIP(DivCeilShape)
442 POPULATE_PROFILE_INFO_SKIP(DivFloorShape)
444 POPULATE_PROFILE_INFO_SKIP(Log2CeilShape)
445 POPULATE_PROFILE_INFO_SKIP(Log2FloorShape)
455
456 return failure();
457}
458
459//===----------------------------------------------------------------------===//
460// Tosa Profile And Extension Compliance Checker
461//===----------------------------------------------------------------------===//
462
463template <typename T>
464FailureOr<SmallVector<OpComplianceInfo<T>>>
465TosaProfileCompliance::getOperatorMatchedEntries(Operation *op) {
466 const std::string opName = op->getName().getStringRef().str();
467 const auto complianceMap = getProfileComplianceMap<T>();
468 const auto it = complianceMap.find(opName);
469 if (it == complianceMap.end())
470 return {};
471
472 return findMatchedEntries<T>(op, it->second);
473}
474
475template <typename T>
477 Operation *op, const tosa::TargetEnv &targetEnv) {
478 const auto maybeOpEntries = getOperatorMatchedEntries<T>(op);
479 if (failed(maybeOpEntries))
480 return success();
481
482 const auto opEntries = maybeOpEntries.value();
483 if (opEntries.size() == 0) {
484 // No matched restriction found.
485 return success();
486 }
487
488 // Check the profile/extension requirement according to the current target
489 // profiles/extensions.
490 const auto isModeAllowed = [&](const OpComplianceInfo<T> &info) -> bool {
491 if (info.condition == CheckCondition::allOf)
492 return targetEnv.allowsAllOf(info.mode);
493 return targetEnv.allowsAnyOf(info.mode);
494 };
495
496 // Check the matched op compliance version does not exceed the target
497 // specification version.
498 const TosaSpecificationVersion targetVersion{targetEnv.getSpecVersion()};
499 const auto isVersionCompatible =
500 [&targetVersion](const OpComplianceInfo<T> &info) -> bool {
501 // Assume compatible if there are no versioned type constraints
502 if (info.operandTypeInfoSet.empty())
503 return true;
504 const TosaSpecificationVersion complianceVersion{
505 info.operandTypeInfoSet.front().second};
506 return targetVersion.isBackwardsCompatibleWith(complianceVersion);
507 };
508
509 for (const auto &info : opEntries) {
510 // Type constraints exist, check if they are compatible with the current
511 // target definition, including: profile, extension and specification
512 // version
513 if (isModeAllowed(info) && isVersionCompatible(info))
514 return success();
515 }
516
517 // No valid entry was found, now emit appropriate error message and return
518 // failure
519 std::string message;
520 llvm::raw_string_ostream os(message);
521
522 os << "illegal: ";
523 const size_t numOpEntries = opEntries.size();
524 for (const auto &[index, info] : llvm::enumerate(opEntries)) {
525 bool mismatchedVersion = false;
526 if (!isVersionCompatible(info)) {
527 mismatchedVersion = true;
528 os << "requires specification version compatible with "
529 << stringifyVersion(info.operandTypeInfoSet.front().second) << " (got "
530 << stringifyVersion(targetVersion) << ") ";
531 }
532
533 if (!isModeAllowed(info)) {
534 if (mismatchedVersion)
535 os << "and ";
536 os << "requires "
537 << (info.condition == CheckCondition::allOf ? "all of " : "any of ")
538 << "[" << llvm::join(stringifyProfile<T>(info.mode), ", ")
539 << "] profiles/extensions ";
540 }
541
542 if (index != numOpEntries - 1)
543 os << "OR ";
544 }
545 os << "to be specified in the target environment";
546
547 return op->emitOpError(message);
548}
549
550LogicalResult
552 const tosa::TargetEnv &targetEnv) {
553 return checkProfileOrExtension<Profile>(op, targetEnv);
554}
555
556LogicalResult
561
563 const auto maybeProfEntries = getOperatorMatchedEntries<Profile>(op);
564 const auto maybeExtEntries = getOperatorMatchedEntries<Extension>(op);
565 if (failed(maybeProfEntries) && failed(maybeExtEntries))
566 return success();
567
568 const bool hasEntry =
569 (succeeded(maybeProfEntries) && !maybeProfEntries.value().empty()) ||
570 (succeeded(maybeExtEntries) && !maybeExtEntries.value().empty());
571
572 if (!hasEntry) {
573 std::string message;
574 llvm::raw_string_ostream os(message);
575 os << "illegal: operation operand/result data types did not align with any "
576 "profile or extension, got (";
577
578 ProfileInfoDepot depot(op);
579 SmallVector<TypeInfo> current = depot.getInfo();
580 for (const auto &typeInfo : llvm::drop_end(current))
581 os << stringifyTypeInfo(typeInfo) << ",";
582 os << stringifyTypeInfo(current.back()) << ")";
583
584 // avoid polluting the error message output by outputting only
585 // the best match
586 const std::string opName = op->getName().getStringRef().str();
587 int maxMatches = -1;
588 SmallVector<TypeInfo> bestTypeInfo;
589 const auto searchBestMatch = [&](auto map) {
590 for (const auto &complianceInfos : map[opName]) {
591 for (const auto &versionedTypeInfos :
592 complianceInfos.operandTypeInfoSet) {
593 const SmallVector<TypeInfo> typeInfos = versionedTypeInfos.first;
594 if (current.size() != typeInfos.size())
595 continue;
596 const int matches = llvm::count_if(
597 llvm::zip_equal(current, typeInfos), [&](const auto zipType) {
598 return isSameTypeInfo(std::get<0>(zipType),
599 std::get<1>(zipType));
600 });
601 if (matches > maxMatches) {
602 maxMatches = matches;
603 bestTypeInfo = typeInfos;
604 }
605 }
606 }
607 };
608 searchBestMatch(getProfileComplianceMap<Profile>());
609 searchBestMatch(getProfileComplianceMap<Extension>());
610
611 os << ", did you mean (";
612 for (const auto &typeInfo : llvm::drop_end(bestTypeInfo))
613 os << stringifyTypeInfo(typeInfo) << ",";
614 os << stringifyTypeInfo(bestTypeInfo.back()) << ")? ";
615 os << "Otherwise, please refer to the 'supported data types' for '"
616 << opName << "' in the specification.";
617 op->emitOpError(message);
618 return failure();
619 }
620
621 return success();
622}
623
624// Find the profiles or extensions requirement according to the signature of
625// type of the operand list.
626template <typename T>
629 assert(compInfo.size() != 0 &&
630 "profile-based compliance information is empty");
631
632 // If there are no type constraints for the given operation, return the
633 // matched entries directly so required profile/extension information can
634 // be checked
636 if (llvm::all_of(compInfo, [&matchedInfos](const OpComplianceInfo<T> &info) {
637 if (info.operandTypeInfoSet.empty()) {
638 matchedInfos.push_back(info);
639 return true;
640 }
641 return false;
642 }))
643 return matchedInfos;
644
645 // Get the type information of the operator we're trying to match
646 ProfileInfoDepot depot(op);
647 SmallVector<TypeInfo> present = depot.getInfo();
648 if (present.size() == 0)
649 return {};
650
651 // Compare 'present' against known type signatures in the compliance metadata
652 for (size_t i = 0; i < compInfo.size(); i++) {
653 SmallVector<VersionedTypeInfo> sets = compInfo[i].operandTypeInfoSet;
654 for (const auto &set : sets) {
655 SmallVector<TypeInfo> expected = set.first;
656 // Tensor-list operators can legitimately have multiple valid signatures
657 // with different operand/result counts, e.g. data-only and data+scale
658 // forms. Treat those as non-matches instead of asserting.
659 if (present.size() != expected.size())
660 continue;
661
662 bool isFound = true;
663 // Compare the type signature between the given operation and the
664 // compliance metadata.
665 for (size_t j = 0; j < expected.size(); j++) {
666 if (!isSameTypeInfo(present[j], expected[j])) {
667 // Verify the next mode set from the list.
668 isFound = false;
669 break;
670 }
671 }
672
673 if (isFound == true) {
674 SmallVector<VersionedTypeInfo> typeInfoSet{set};
675 OpComplianceInfo<T> info{compInfo[i].mode, typeInfoSet,
676 compInfo[i].condition};
677 matchedInfos.push_back(info);
678 }
679 }
680 }
681
682 return matchedInfos;
683}
684
685// Debug utilites.
686template <typename T>
689 SmallVector<StringRef> debugStrings;
690 for (const auto &profile : profiles) {
691 if constexpr (std::is_same_v<T, Profile>)
692 debugStrings.push_back(tosa::stringifyProfile(profile));
693 else
694 debugStrings.push_back(tosa::stringifyExtension(profile));
695 }
696 return debugStrings;
697}
698
699template <typename T>
701 const SmallVector<ArrayRef<T>> &profileSet) {
702 SmallVector<StringRef> debugStrings;
703
704 for (const auto &profiles : profileSet) {
705 auto tempStrings = stringifyProfile<T>(profiles);
706 llvm::append_range(debugStrings, tempStrings);
707 }
708
709 return debugStrings;
710}
711
714 const auto stringifyScalarTypeInfo =
715 [](const TypeInfo &typeInfo) -> llvm::SmallString<32> {
716 if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
717 return {"i" + llvm::utostr(typeInfo.bitWidth)};
718 }
719 if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
720 return {"f16"};
721 } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
722 return {"f32"};
723 } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
724 return {"bf16"};
725 } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
726 return {"fp8e4m3"};
727 } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
728 return {"fp8e5m2"};
729 } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
730 return {"fp6e2m3"};
731 } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
732 return {"fp6e3m2"};
733 } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
734 return {"fp4e2m1"};
735 } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
736 return {"fp8e8m0"};
737 } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
738 return {"mxint8"};
739 }
740 llvm_unreachable("unknown type");
741 };
742
743 if (typeInfo.typeID == tosa::BlockScaledType::getTypeID()) {
744 TypeInfo valueInfo = {typeInfo.valueTypeID, typeInfo.bitWidth};
745 TypeInfo scaleInfo = {typeInfo.scaleTypeID, 8};
747 llvm::raw_svector_ostream os(result);
748 os << "bs"
749 << tosa::BlockShapeAttr::getBlockShapeValue(typeInfo.blockShape.value())
750 << "_" << stringifyScalarTypeInfo(scaleInfo) << "_"
751 << stringifyScalarTypeInfo(valueInfo);
752 return result;
753 }
754
755 return stringifyScalarTypeInfo(typeInfo);
756}
return success()
#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp)
#define POPULATE_PROFILE_INFO_COMMON(tosaOp)
#define POPULATE_PROFILE_INFO_SKIP(tosaOp)
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Profile > > > OperationProfileComplianceMap
std::unordered_map< std::string, SmallVector< OpComplianceInfo< Extension > > > OperationExtensionComplianceMap
@ Gather
SmallVector< TypeInfo > getInfo()
bool isSameTypeInfo(TypeInfo a, TypeInfo b)
LogicalResult checkProfile(Operation *op, const tosa::TargetEnv &targetEnv)
static llvm::SmallString< 32 > stringifyTypeInfo(const TypeInfo &typeInfo)
LogicalResult checkExtension(Operation *op, const tosa::TargetEnv &targetEnv)
LogicalResult checkInvalid(Operation *op)
SmallVector< StringRef > stringifyProfile(ArrayRef< T > profiles)
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)
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
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
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
Include the generated interface declarations.
@ Mul
RHS of mul is always a constant or a symbolic expression.
Definition AffineExpr.h:43
SmallVector< VersionedTypeInfo > operandTypeInfoSet
mlir::TypeID valueTypeID
mlir::TypeID scaleTypeID
std::optional< tosa::BlockShape > blockShape
mlir::TypeID typeID
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.