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