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