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/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.getAZp());
295 addValue(op.getBZp());
296 addValue(op.getOutput());
297 return success();
298}
299
300template <>
301LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableOp op) {
302 addType(op.getType());
303 return success();
304}
305
306template <>
307LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::VariableWriteOp op) {
308 addValue(op.getInput1());
309 return success();
310}
311
312template <>
313LogicalResult ProfileInfoDepot::populateProfileInfo(tosa::DimOp op) {
314 addValue(op.getInput1());
315 return success();
316}
317
318LogicalResult ProfileInfoDepot::populatationDispatch(Operation *op) {
319// This helper function only populates the info for the customised operands.
320#define POPULATE_PROFILE_INFO_CUSTOM(tosaOp) \
321 if (isa<tosa::tosaOp##Op>(op)) { \
322 return populateProfileInfo(cast<tosa::tosaOp##Op>(op)); \
323 }
324
325#define POPULATE_PROFILE_INFO_SKIP(tosaOp) \
326 if (isa<tosa::tosaOp##Op>(op)) \
327 return success();
328
329// This helper function populates the info for all operands.
330#define POPULATE_PROFILE_INFO_COMMON(tosaOp) \
331 if (isa<tosa::tosaOp##Op>(op)) { \
332 return populateProfileInfo(op->getOperands(), op->getResults()); \
333 }
334
335 // Skip irrelevant operands when they are independent and not tied to any
336 // specific profile/extension.
338 POPULATE_PROFILE_INFO_CUSTOM(AvgPool2dAdaptive)
339 POPULATE_PROFILE_INFO_CUSTOM(TransposeConv2D)
341 POPULATE_PROFILE_INFO_CUSTOM(Conv2DBlockScaled)
343 POPULATE_PROFILE_INFO_CUSTOM(DepthwiseConv2D)
353 POPULATE_PROFILE_INFO_CUSTOM(RowGatherBlockScaled)
361 POPULATE_PROFILE_INFO_CUSTOM(VariableWrite)
363 POPULATE_PROFILE_INFO_CUSTOM(MaxPool2dAdaptive)
364
365 // For the most of tosa operators, all operands are profile/extension related
366 // and hence are all considered in this profile-based compilance check.
367 POPULATE_PROFILE_INFO_COMMON(MatmulTBlockScaled)
371 POPULATE_PROFILE_INFO_COMMON(CastFromBlockScaled)
372 POPULATE_PROFILE_INFO_COMMON(CastToBlockScaled)
384 POPULATE_PROFILE_INFO_COMMON(ArithmeticRightShift)
389 POPULATE_PROFILE_INFO_COMMON(LogicalLeftShift)
390 POPULATE_PROFILE_INFO_COMMON(LogicalRightShift)
413 POPULATE_PROFILE_INFO_COMMON(ReduceProduct)
416 POPULATE_PROFILE_INFO_COMMON(GreaterEqual)
420 POPULATE_PROFILE_INFO_COMMON(VariableRead)
421
422 // Type Invariant Extension, a capability extension that is independent
423 // of the data type, meaning any compatible type can be used. No type
424 // constraint for those operations.
426 POPULATE_PROFILE_INFO_SKIP(AssertEqualShape)
427 POPULATE_PROFILE_INFO_SKIP(ConcatShape)
429 POPULATE_PROFILE_INFO_SKIP(DivCeilShape)
430 POPULATE_PROFILE_INFO_SKIP(DivFloorShape)
432 POPULATE_PROFILE_INFO_SKIP(Log2CeilShape)
433 POPULATE_PROFILE_INFO_SKIP(Log2FloorShape)
443
444 return failure();
445}
446
447//===----------------------------------------------------------------------===//
448// Tosa Profile And Extension Compliance Checker
449//===----------------------------------------------------------------------===//
450
451template <typename T>
452FailureOr<SmallVector<OpComplianceInfo<T>>>
453TosaProfileCompliance::getOperatorMatchedEntries(Operation *op) {
454 const std::string opName = op->getName().getStringRef().str();
455 const auto complianceMap = getProfileComplianceMap<T>();
456 const auto it = complianceMap.find(opName);
457 if (it == complianceMap.end())
458 return {};
459
460 return findMatchedEntries<T>(op, it->second);
461}
462
463template <typename T>
465 Operation *op, const tosa::TargetEnv &targetEnv) {
466 const auto maybeOpEntries = getOperatorMatchedEntries<T>(op);
467 if (failed(maybeOpEntries))
468 return success();
469
470 const auto opEntries = maybeOpEntries.value();
471 if (opEntries.size() == 0) {
472 // No matched restriction found.
473 return success();
474 }
475
476 // Check the profile/extension requirement according to the current target
477 // profiles/extensions.
478 const auto isModeAllowed = [&](const OpComplianceInfo<T> &info) -> bool {
479 if (info.condition == CheckCondition::allOf)
480 return targetEnv.allowsAllOf(info.mode);
481 return targetEnv.allowsAnyOf(info.mode);
482 };
483
484 // Check the matched op compliance version does not exceed the target
485 // specification version.
486 const TosaSpecificationVersion targetVersion{targetEnv.getSpecVersion()};
487 const auto isVersionCompatible =
488 [&targetVersion](const OpComplianceInfo<T> &info) -> bool {
489 // Assume compatible if there are no versioned type constraints
490 if (info.operandTypeInfoSet.empty())
491 return true;
492 const TosaSpecificationVersion complianceVersion{
493 info.operandTypeInfoSet.front().second};
494 return targetVersion.isBackwardsCompatibleWith(complianceVersion);
495 };
496
497 for (const auto &info : opEntries) {
498 // Type constraints exist, check if they are compatible with the current
499 // target definition, including: profile, extension and specification
500 // version
501 if (isModeAllowed(info) && isVersionCompatible(info))
502 return success();
503 }
504
505 // No valid entry was found, now emit appropriate error message and return
506 // failure
507 std::string message;
508 llvm::raw_string_ostream os(message);
509
510 os << "illegal: ";
511 const size_t numOpEntries = opEntries.size();
512 for (const auto &[index, info] : llvm::enumerate(opEntries)) {
513 bool mismatchedVersion = false;
514 if (!isVersionCompatible(info)) {
515 mismatchedVersion = true;
516 os << "requires specification version compatible with "
517 << stringifyVersion(info.operandTypeInfoSet.front().second) << " (got "
518 << stringifyVersion(targetVersion) << ") ";
519 }
520
521 if (!isModeAllowed(info)) {
522 if (mismatchedVersion)
523 os << "and ";
524 os << "requires "
525 << (info.condition == CheckCondition::allOf ? "all of " : "any of ")
526 << "[" << llvm::join(stringifyProfile<T>(info.mode), ", ")
527 << "] profiles/extensions ";
528 }
529
530 if (index != numOpEntries - 1)
531 os << "OR ";
532 }
533 os << "to be specified in the target environment";
534
535 return op->emitOpError(message);
536}
537
538LogicalResult
540 const tosa::TargetEnv &targetEnv) {
541 return checkProfileOrExtension<Profile>(op, targetEnv);
542}
543
544LogicalResult
549
551 const auto maybeProfEntries = getOperatorMatchedEntries<Profile>(op);
552 const auto maybeExtEntries = getOperatorMatchedEntries<Extension>(op);
553 if (failed(maybeProfEntries) && failed(maybeExtEntries))
554 return success();
555
556 const bool hasEntry =
557 (succeeded(maybeProfEntries) && !maybeProfEntries.value().empty()) ||
558 (succeeded(maybeExtEntries) && !maybeExtEntries.value().empty());
559
560 if (!hasEntry) {
561 std::string message;
562 llvm::raw_string_ostream os(message);
563 os << "illegal: operation operand/result data types did not align with any "
564 "profile or extension, got (";
565
566 ProfileInfoDepot depot(op);
567 SmallVector<TypeInfo> current = depot.getInfo();
568 for (const auto &typeInfo : llvm::drop_end(current))
569 os << stringifyTypeInfo(typeInfo) << ",";
570 os << stringifyTypeInfo(current.back()) << ")";
571
572 // avoid polluting the error message output by outputting only
573 // the best match
574 const std::string opName = op->getName().getStringRef().str();
575 int maxMatches = -1;
576 SmallVector<TypeInfo> bestTypeInfo;
577 const auto searchBestMatch = [&](auto map) {
578 for (const auto &complianceInfos : map[opName]) {
579 for (const auto &versionedTypeInfos :
580 complianceInfos.operandTypeInfoSet) {
581 const SmallVector<TypeInfo> typeInfos = versionedTypeInfos.first;
582 if (current.size() != typeInfos.size())
583 continue;
584 const int matches = llvm::count_if(
585 llvm::zip_equal(current, typeInfos), [&](const auto zipType) {
586 return isSameTypeInfo(std::get<0>(zipType),
587 std::get<1>(zipType));
588 });
589 if (matches > maxMatches) {
590 maxMatches = matches;
591 bestTypeInfo = typeInfos;
592 }
593 }
594 }
595 };
596 searchBestMatch(getProfileComplianceMap<Profile>());
597 searchBestMatch(getProfileComplianceMap<Extension>());
598
599 os << ", did you mean (";
600 for (const auto &typeInfo : llvm::drop_end(bestTypeInfo))
601 os << stringifyTypeInfo(typeInfo) << ",";
602 os << stringifyTypeInfo(bestTypeInfo.back()) << ")? ";
603 os << "Otherwise, please refer to the 'supported data types' for '"
604 << opName << "' in the specification.";
605 op->emitOpError(message);
606 return failure();
607 }
608
609 return success();
610}
611
612// Find the profiles or extensions requirement according to the signature of
613// type of the operand list.
614template <typename T>
617 assert(compInfo.size() != 0 &&
618 "profile-based compliance information is empty");
619
620 // If there are no type constraints for the given operation, return the
621 // matched entries directly so required profile/extension information can
622 // be checked
624 if (llvm::all_of(compInfo, [&matchedInfos](const OpComplianceInfo<T> &info) {
625 if (info.operandTypeInfoSet.empty()) {
626 matchedInfos.push_back(info);
627 return true;
628 }
629 return false;
630 }))
631 return matchedInfos;
632
633 // Get the type information of the operator we're trying to match
634 ProfileInfoDepot depot(op);
635 SmallVector<TypeInfo> present = depot.getInfo();
636 if (present.size() == 0)
637 return {};
638
639 // Compare 'present' against known type signatures in the compliance metadata
640 for (size_t i = 0; i < compInfo.size(); i++) {
641 SmallVector<VersionedTypeInfo> sets = compInfo[i].operandTypeInfoSet;
642 for (const auto &set : sets) {
643 SmallVector<TypeInfo> expected = set.first;
644 // Tensor-list operators can legitimately have multiple valid signatures
645 // with different operand/result counts, e.g. data-only and data+scale
646 // forms. Treat those as non-matches instead of asserting.
647 if (present.size() != expected.size())
648 continue;
649
650 bool isFound = true;
651 // Compare the type signature between the given operation and the
652 // compliance metadata.
653 for (size_t j = 0; j < expected.size(); j++) {
654 if (!isSameTypeInfo(present[j], expected[j])) {
655 // Verify the next mode set from the list.
656 isFound = false;
657 break;
658 }
659 }
660
661 if (isFound == true) {
662 SmallVector<VersionedTypeInfo> typeInfoSet{set};
663 OpComplianceInfo<T> info{compInfo[i].mode, typeInfoSet,
664 compInfo[i].condition};
665 matchedInfos.push_back(info);
666 }
667 }
668 }
669
670 return matchedInfos;
671}
672
673// Debug utilites.
674template <typename T>
677 SmallVector<StringRef> debugStrings;
678 for (const auto &profile : profiles) {
679 if constexpr (std::is_same_v<T, Profile>)
680 debugStrings.push_back(tosa::stringifyProfile(profile));
681 else
682 debugStrings.push_back(tosa::stringifyExtension(profile));
683 }
684 return debugStrings;
685}
686
687template <typename T>
689 const SmallVector<ArrayRef<T>> &profileSet) {
690 SmallVector<StringRef> debugStrings;
691
692 for (const auto &profiles : profileSet) {
693 auto tempStrings = stringifyProfile<T>(profiles);
694 llvm::append_range(debugStrings, tempStrings);
695 }
696
697 return debugStrings;
698}
699
702 const auto stringifyScalarTypeInfo =
703 [](const TypeInfo &typeInfo) -> llvm::SmallString<32> {
704 if (typeInfo.typeID == mlir::IntegerType::getTypeID()) {
705 return {"i" + llvm::utostr(typeInfo.bitWidth)};
706 }
707 if (typeInfo.typeID == mlir::Float16Type::getTypeID()) {
708 return {"f16"};
709 } else if (typeInfo.typeID == mlir::Float32Type::getTypeID()) {
710 return {"f32"};
711 } else if (typeInfo.typeID == mlir::BFloat16Type::getTypeID()) {
712 return {"bf16"};
713 } else if (typeInfo.typeID == mlir::Float8E4M3FNType::getTypeID()) {
714 return {"fp8e4m3"};
715 } else if (typeInfo.typeID == mlir::Float8E5M2Type::getTypeID()) {
716 return {"fp8e5m2"};
717 } else if (typeInfo.typeID == mlir::Float6E2M3FNType::getTypeID()) {
718 return {"fp6e2m3"};
719 } else if (typeInfo.typeID == mlir::Float6E3M2FNType::getTypeID()) {
720 return {"fp6e3m2"};
721 } else if (typeInfo.typeID == mlir::Float4E2M1FNType::getTypeID()) {
722 return {"fp4e2m1"};
723 } else if (typeInfo.typeID == mlir::Float8E8M0FNUType::getTypeID()) {
724 return {"fp8e8m0"};
725 } else if (typeInfo.typeID == tosa::mxint8Type::getTypeID()) {
726 return {"mxint8"};
727 }
728 llvm_unreachable("unknown type");
729 };
730
731 if (typeInfo.typeID == tosa::BlockScaledType::getTypeID()) {
732 TypeInfo valueInfo = {typeInfo.valueTypeID, typeInfo.bitWidth};
733 TypeInfo scaleInfo = {typeInfo.scaleTypeID, 8};
735 llvm::raw_svector_ostream os(result);
736 os << "bs"
737 << tosa::BlockShapeAttr::getBlockShapeValue(typeInfo.blockShape.value())
738 << "_" << stringifyScalarTypeInfo(scaleInfo) << "_"
739 << stringifyScalarTypeInfo(valueInfo);
740 return result;
741 }
742
743 return stringifyScalarTypeInfo(typeInfo);
744}
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.