21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/Debug.h"
27 #define DEBUG_TYPE "mlir-spirv-conversion"
41 template <
typename LabelT>
45 for (
const auto &ors : candidates) {
51 for (spirv::Extension ext : ors)
52 extStrings.push_back(spirv::stringifyExtension(ext));
54 llvm::dbgs() << label <<
" illegal: requires at least one extension in ["
55 << llvm::join(extStrings,
", ")
56 <<
"] but none allowed in target environment\n";
69 template <
typename LabelT>
73 for (
const auto &ors : candidates) {
79 for (spirv::Capability cap : ors)
80 capStrings.push_back(spirv::stringifyCapability(cap));
82 llvm::dbgs() << label <<
" illegal: requires at least one capability in ["
83 << llvm::join(capStrings,
", ")
84 <<
"] but none allowed in target environment\n";
94 switch (storageClass) {
95 case spirv::StorageClass::PhysicalStorageBuffer:
96 case spirv::StorageClass::PushConstant:
97 case spirv::StorageClass::StorageBuffer:
98 case spirv::StorageClass::Uniform:
121 return cast<spirv::ScalarType>(
122 IntegerType::get(ctx,
options.use64bitIndex ? 64 : 32));
129 MLIRContext *SPIRVTypeConverter::getContext()
const {
130 return targetEnv.
getAttr().getContext();
134 return targetEnv.
allows(capability);
139 static std::optional<int64_t>
154 if (
auto complexType = type.
dyn_cast<ComplexType>()) {
158 return 2 * *elementSize;
161 if (
auto vecType = type.
dyn_cast<VectorType>()) {
165 return vecType.getNumElements() * *elementSize;
168 if (
auto memRefType = type.
dyn_cast<MemRefType>()) {
173 if (!memRefType.hasStaticShape() ||
184 if (memRefType.getRank() == 0)
187 auto dims = memRefType.getShape();
188 if (llvm::is_contained(dims, ShapedType::kDynamic) ||
189 ShapedType::isDynamic(offset) ||
190 llvm::is_contained(strides, ShapedType::kDynamic))
193 int64_t memrefSize = -1;
194 for (
const auto &shape :
enumerate(dims))
195 memrefSize =
std::max(memrefSize, shape.value() * strides[shape.index()]);
197 return (offset + memrefSize) * *elementSize;
201 if (!tensorType.hasStaticShape())
208 int64_t size = *elementSize;
209 for (
auto shape : tensorType.getShape())
223 std::optional<spirv::StorageClass> storageClass = {}) {
237 if (!
options.emulateLT32BitScalarTypes)
242 LLVM_DEBUG(llvm::dbgs()
244 <<
" not converted to 32-bit for SPIR-V to avoid truncation\n");
249 LLVM_DEBUG(llvm::dbgs() << type <<
" converted to 32-bit for SPIR-V\n");
253 auto intType = type.
cast<IntegerType>();
254 LLVM_DEBUG(llvm::dbgs() << type <<
" converted to 32-bit for SPIR-V\n");
255 return IntegerType::get(targetEnv.
getContext(), 32,
256 intType.getSignedness());
265 Type indexType = dyn_cast<IndexType>(type.getElementType());
276 std::optional<spirv::StorageClass> storageClass = {}) {
278 auto scalarType = dyn_cast_or_null<spirv::ScalarType>(type.getElementType());
280 LLVM_DEBUG(llvm::dbgs()
281 << type <<
" illegal: cannot convert non-scalar element type\n");
285 if (type.getRank() <= 1 && type.getNumElements() == 1)
289 LLVM_DEBUG(llvm::dbgs() << type <<
" illegal: > 4-element unimplemented\n");
307 return VectorType::get(type.getShape(), elementType);
314 std::optional<spirv::StorageClass> storageClass = {}) {
315 auto scalarType = dyn_cast_or_null<spirv::ScalarType>(type.getElementType());
317 LLVM_DEBUG(llvm::dbgs()
318 << type <<
" illegal: cannot convert non-scalar element type\n");
326 if (elementType != type.getElementType()) {
327 LLVM_DEBUG(llvm::dbgs()
328 << type <<
" illegal: complex type emulation unsupported\n");
332 return VectorType::get(2, elementType);
345 if (!type.hasStaticShape()) {
346 LLVM_DEBUG(llvm::dbgs()
347 << type <<
" illegal: dynamic shape unimplemented\n");
352 auto scalarType = dyn_cast_or_null<spirv::ScalarType>(type.
getElementType());
354 LLVM_DEBUG(llvm::dbgs()
355 << type <<
" illegal: cannot convert non-scalar element type\n");
361 if (!scalarSize || !tensorSize) {
362 LLVM_DEBUG(llvm::dbgs()
363 << type <<
" illegal: cannot deduce element count\n");
367 auto arrayElemCount = *tensorSize / *scalarSize;
371 std::optional<int64_t> arrayElemSize =
373 if (!arrayElemSize) {
374 LLVM_DEBUG(llvm::dbgs()
375 << type <<
" illegal: cannot deduce converted element size\n");
385 spirv::StorageClass storageClass) {
386 unsigned numBoolBits =
options.boolNumBits;
387 if (numBoolBits != 8) {
388 LLVM_DEBUG(llvm::dbgs()
389 <<
"using non-8-bit storage for bool types unimplemented");
392 auto elementType = IntegerType::get(type.getContext(), numBoolBits)
400 std::optional<int64_t> arrayElemSize =
402 if (!arrayElemSize) {
403 LLVM_DEBUG(llvm::dbgs()
404 << type <<
" illegal: cannot deduce converted element size\n");
408 if (!type.hasStaticShape()) {
411 if (targetEnv.
allows(spirv::Capability::Kernel))
420 int64_t memrefSize = (type.getNumElements() * numBoolBits + 7) / 8;
421 auto arrayElemCount = llvm::divideCeil(memrefSize, *arrayElemSize);
424 if (targetEnv.
allows(spirv::Capability::Kernel))
432 auto attr = type.getMemorySpace().
dyn_cast_or_null<spirv::StorageClassAttr>();
437 <<
" illegal: expected memory space to be a SPIR-V storage class "
438 "attribute; please use MemorySpaceToStorageClassConverter to map "
439 "numeric memory spaces beforehand\n");
442 spirv::StorageClass storageClass = attr.getValue();
444 if (type.getElementType().isa<IntegerType>() &&
445 type.getElementTypeBitWidth() == 1) {
450 Type elementType = type.getElementType();
451 if (
auto vecType = elementType.
dyn_cast<VectorType>()) {
454 }
else if (
auto complexType = elementType.
dyn_cast<ComplexType>()) {
460 }
else if (
auto indexType = elementType.
dyn_cast<IndexType>()) {
462 arrayElemType = type.getElementType();
467 <<
" unhandled: can only convert scalar or vector element type\n");
473 std::optional<int64_t> arrayElemSize =
475 if (!arrayElemSize) {
476 LLVM_DEBUG(llvm::dbgs()
477 << type <<
" illegal: cannot deduce converted element size\n");
481 if (!type.hasStaticShape()) {
484 if (targetEnv.
allows(spirv::Capability::Kernel))
495 LLVM_DEBUG(llvm::dbgs()
496 << type <<
" illegal: cannot deduce element count\n");
500 auto arrayElemCount = llvm::divideCeil(*memrefSize, *arrayElemSize);
503 if (targetEnv.
allows(spirv::Capability::Kernel))
525 addConversion([
this](IntegerType intType) -> std::optional<Type> {
566 matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
572 FuncOpConversion::matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
574 auto fnType = funcOp.getFunctionType();
575 if (fnType.getNumResults() > 1)
579 for (
const auto &argType :
enumerate(fnType.getInputs())) {
580 auto convertedType = getTypeConverter()->convertType(argType.value());
583 signatureConverter.addInputs(argType.index(), convertedType);
587 if (fnType.getNumResults() == 1) {
588 resultType = getTypeConverter()->convertType(fnType.getResult(0));
594 auto newFuncOp = rewriter.
create<spirv::FuncOp>(
595 funcOp.getLoc(), funcOp.getName(),
601 for (
const auto &namedAttr : funcOp->getAttrs()) {
602 if (namedAttr.getName() != funcOp.getFunctionTypeAttrName() &&
604 newFuncOp->
setAttr(namedAttr.getName(), namedAttr.getValue());
610 &newFuncOp.getBody(), *getTypeConverter(), &signatureConverter)))
618 patterns.
add<FuncOpConversion>(typeConverter, patterns.
getContext());
626 spirv::BuiltIn builtin) {
629 for (
auto varOp : body.
getOps<spirv::GlobalVariableOp>()) {
630 if (
auto builtinAttr = varOp->getAttrOfType<StringAttr>(
631 spirv::SPIRVDialect::getAttributeName(
632 spirv::Decoration::BuiltIn))) {
633 auto varBuiltIn = spirv::symbolizeBuiltIn(builtinAttr.getValue());
634 if (varBuiltIn && *varBuiltIn == builtin) {
644 return std::string(
"__builtin_var_") + stringifyBuiltIn(builtin).str() +
"__";
648 static spirv::GlobalVariableOp
657 spirv::GlobalVariableOp newVarOp;
659 case spirv::BuiltIn::NumWorkgroups:
660 case spirv::BuiltIn::WorkgroupSize:
661 case spirv::BuiltIn::WorkgroupId:
662 case spirv::BuiltIn::LocalInvocationId:
663 case spirv::BuiltIn::GlobalInvocationId: {
665 spirv::StorageClass::Input);
668 builder.
create<spirv::GlobalVariableOp>(loc, ptrType, name, builtin);
671 case spirv::BuiltIn::SubgroupId:
672 case spirv::BuiltIn::NumSubgroups:
673 case spirv::BuiltIn::SubgroupSize: {
678 builder.
create<spirv::GlobalVariableOp>(loc, ptrType, name, builtin);
682 emitError(loc,
"unimplemented builtin variable generation for ")
683 << stringifyBuiltIn(builtin);
689 spirv::BuiltIn builtin,
694 op->
emitError(
"expected operation to be within a module-like op");
698 spirv::GlobalVariableOp varOp =
700 builtin, integerType, builder);
702 return builder.
create<spirv::LoadOp>(op->
getLoc(), ptr);
723 unsigned elementCount) {
724 for (
auto varOp : body.
getOps<spirv::GlobalVariableOp>()) {
732 if (ptrType.getStorageClass() == spirv::StorageClass::PushConstant) {
738 if (numElements == elementCount)
747 static spirv::GlobalVariableOp
756 const char *name =
"__push_constant_var__";
757 return builder.
create<spirv::GlobalVariableOp>(loc, type, name,
762 unsigned offset,
Type integerType,
767 op->
emitError(
"expected operation to be within a module-like op");
772 loc, parent->
getRegion(0).
front(), elementCount, builder, integerType);
775 Value offsetOp = builder.
create<spirv::ConstantOp>(
777 auto addrOp = builder.
create<spirv::AddressOfOp>(loc, varOp);
778 auto acOp = builder.
create<spirv::AccessChainOp>(
780 return builder.
create<spirv::LoadOp>(loc, acOp);
788 int64_t offset,
Type integerType,
790 assert(indices.size() == strides.size() &&
791 "must provide indices for all dimensions");
798 Value linearizedIndex = builder.
create<spirv::ConstantOp>(
799 loc, integerType, IntegerAttr::get(integerType, offset));
801 Value strideVal = builder.
create<spirv::ConstantOp>(
803 IntegerAttr::get(integerType, strides[index.index()]));
804 Value update = builder.
create<spirv::IMulOp>(loc, strideVal, index.value());
806 builder.
create<spirv::IAddOp>(loc, linearizedIndex, update);
808 return linearizedIndex;
812 MemRefType baseType,
Value basePtr,
820 llvm::is_contained(strides, ShapedType::kDynamic) ||
821 ShapedType::isDynamic(offset)) {
831 linearizedIndices.push_back(zero);
833 if (baseType.getRank() == 0) {
834 linearizedIndices.push_back(zero);
836 linearizedIndices.push_back(
837 linearizeIndex(indices, strides, offset, indexType, loc, builder));
839 return builder.
create<spirv::AccessChainOp>(loc, basePtr, linearizedIndices);
843 MemRefType baseType,
Value basePtr,
851 llvm::is_contained(strides, ShapedType::kDynamic) ||
852 ShapedType::isDynamic(offset)) {
860 if (baseType.getRank() == 0) {
864 linearizeIndex(indices, strides, offset, indexType, loc, builder);
869 linearizedIndices.push_back(linearIndex);
870 return builder.
create<spirv::AccessChainOp>(loc, basePtr,
873 return builder.
create<spirv::PtrAccessChainOp>(loc, basePtr, linearIndex,
878 MemRefType baseType,
Value basePtr,
882 if (typeConverter.
allows(spirv::Capability::Kernel)) {
895 std::unique_ptr<SPIRVConversionTarget>
897 std::unique_ptr<SPIRVConversionTarget> target(
901 target->addDynamicallyLegalDialect<spirv::SPIRVDialect>(
904 [targetPtr](
Operation *op) {
return targetPtr->isLegalOp(op); });
911 bool SPIRVConversionTarget::isLegalOp(
Operation *op) {
915 if (
auto minVersionIfx = dyn_cast<spirv::QueryMinVersionInterface>(op)) {
916 std::optional<spirv::Version> minVersion = minVersionIfx.getMinVersion();
917 if (minVersion && *minVersion > this->targetEnv.
getVersion()) {
918 LLVM_DEBUG(llvm::dbgs()
919 << op->
getName() <<
" illegal: requiring min version "
920 << spirv::stringifyVersion(*minVersion) <<
"\n");
924 if (
auto maxVersionIfx = dyn_cast<spirv::QueryMaxVersionInterface>(op)) {
925 std::optional<spirv::Version> maxVersion = maxVersionIfx.getMaxVersion();
926 if (maxVersion && *maxVersion < this->targetEnv.
getVersion()) {
927 LLVM_DEBUG(llvm::dbgs()
928 << op->
getName() <<
" illegal: requiring max version "
929 << spirv::stringifyVersion(*maxVersion) <<
"\n");
937 if (
auto extensions = dyn_cast<spirv::QueryExtensionInterface>(op))
939 extensions.getExtensions())))
945 if (
auto capabilities = dyn_cast<spirv::QueryCapabilityInterface>(op))
947 capabilities.getCapabilities())))
955 if (llvm::any_of(valueTypes,
961 if (
auto globalVar = dyn_cast<spirv::GlobalVariableOp>(op))
962 valueTypes.push_back(globalVar.getType());
968 for (
Type valueType : valueTypes) {
969 typeExtensions.clear();
975 typeCapabilities.clear();
static Value getZero(OpBuilder &b, Location loc, Type elementType)
Get zero value for an element type.
static llvm::ManagedStatic< PassManagerOptions > options
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
static bool needsExplicitLayout(spirv::StorageClass storageClass)
Returns true if the given storageClass needs explicit layout when used in Shader environments.
static spirv::GlobalVariableOp getPushConstantVariable(Block &body, unsigned elementCount)
Returns the push constant varible containing elementCount 32-bit integer values in body.
static Type convertTensorType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, TensorType type)
Converts a tensor type to a suitable type under the given targetEnv.
static std::string getBuiltinVarName(spirv::BuiltIn builtin)
Gets name of global variable for a builtin.
static LogicalResult checkCapabilityRequirements(LabelT label, const spirv::TargetEnv &targetEnv, const spirv::SPIRVType::CapabilityArrayRefVector &candidates)
Checks that candidatescapability requirements are possible to be satisfied with the given isAllowedFn...
static std::optional< int64_t > getTypeNumBytes(const SPIRVConversionOptions &options, Type type)
static spirv::GlobalVariableOp getBuiltinVariable(Block &body, spirv::BuiltIn builtin)
static ShapedType convertIndexElementType(ShapedType type, const SPIRVConversionOptions &options)
Returns a type with the same shape but with any index element type converted to the matching integer ...
static spirv::GlobalVariableOp getOrInsertPushConstantVariable(Location loc, Block &block, unsigned elementCount, OpBuilder &b, Type indexType)
Gets or inserts a global variable for push constant storage containing elementCount 32-bit integer va...
static Type convertComplexType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, ComplexType type, std::optional< spirv::StorageClass > storageClass={})
static LogicalResult checkExtensionRequirements(LabelT label, const spirv::TargetEnv &targetEnv, const spirv::SPIRVType::ExtensionArrayRefVector &candidates)
Checks that candidates extension requirements are possible to be satisfied with the given targetEnv.
static spirv::ScalarType getIndexType(MLIRContext *ctx, const SPIRVConversionOptions &options)
static Type convertScalarType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, spirv::ScalarType type, std::optional< spirv::StorageClass > storageClass={})
Converts a scalar type to a suitable type under the given targetEnv.
static Type convertBoolMemrefType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, MemRefType type, spirv::StorageClass storageClass)
static Type convertVectorType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, VectorType type, std::optional< spirv::StorageClass > storageClass={})
Converts a vector type to a suitable type under the given targetEnv.
static spirv::PointerType wrapInStructAndGetPointer(Type elementType, spirv::StorageClass storageClass)
Wraps the given elementType in a struct and gets the pointer to the struct.
static spirv::PointerType getPushConstantStorageType(unsigned elementCount, Builder &builder, Type indexType)
Returns the pointer type for the push constant storage containing elementCount 32-bit integer values.
static Type convertMemrefType(const spirv::TargetEnv &targetEnv, const SPIRVConversionOptions &options, MemRefType type)
static spirv::GlobalVariableOp getOrInsertBuiltinVariable(Block &body, Location loc, spirv::BuiltIn builtin, Type integerType, OpBuilder &builder)
Gets or inserts a global variable for a builtin within body block.
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static int64_t getNumElements(ShapedType type)
Block represents an ordered list of Operations.
iterator_range< op_iterator< OpT > > getOps()
Return an iterator range over the operations within this block that are of 'OpT'.
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
This class implements a pattern rewriter for use with ConversionPatterns.
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before) override
PatternRewriter hook for moving blocks out of a region.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
FailureOr< Block * > convertRegionTypes(Region *region, TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Convert the types of block arguments within the given region.
This class describes a specific conversion target.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
static OpBuilder atBlockBegin(Block *block, Listener *listener=nullptr)
Create a builder and set the insertion point to before the first operation in the block but still ins...
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
OpConversionPattern is a wrapper around ConversionPattern that allows for matching and rewriting agai...
Operation is the basic unit of execution within MLIR.
operand_type_iterator operand_type_end()
Location getLoc()
The source location the operation was defined or derived from.
result_type_iterator result_type_end()
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
result_type_iterator result_type_begin()
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
OperationName getName()
The name of an operation is the key identifier for it.
operand_type_iterator operand_type_begin()
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
static std::unique_ptr< SPIRVConversionTarget > get(spirv::TargetEnvAttr targetAttr)
Creates a SPIR-V conversion target for the given target environment.
Type conversion from builtin types to SPIR-V types for shader interface.
Type getIndexType() const
Gets the SPIR-V correspondence for the standard index type.
SPIRVTypeConverter(spirv::TargetEnvAttr targetAttr, const SPIRVConversionOptions &options={})
bool allows(spirv::Capability capability)
Checks if the SPIR-V capability inquired is supported.
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
Type getElementType() const
Returns the element type of this tensor type.
This class provides all of the information necessary to convert a type signature.
void addConversion(FnT &&callback)
Register a conversion function.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
U dyn_cast_or_null() const
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
static ArrayType get(Type elementType, unsigned elementCount)
static bool isValid(VectorType)
Returns true if the given vector type is valid for the SPIR-V dialect.
Type getPointeeType() const
static PointerType get(Type pointeeType, StorageClass storageClass)
static RuntimeArrayType get(Type elementType)
void getExtensions(SPIRVType::ExtensionArrayRefVector &extensions, std::optional< StorageClass > storage=std::nullopt)
void getCapabilities(SPIRVType::CapabilityArrayRefVector &capabilities, std::optional< StorageClass > storage=std::nullopt)
static StructType get(ArrayRef< Type > memberTypes, ArrayRef< OffsetInfo > offsetInfo={}, ArrayRef< MemberDecorationInfo > memberDecorations={})
Construct a literal StructType with at least one member.
An attribute that specifies the target version, allowed extensions and capabilities,...
A wrapper class around a spirv::TargetEnvAttr to provide query methods for allowed version/capabiliti...
Version getVersion() const
bool allows(Capability) const
Returns true if the given capability is allowed.
TargetEnvAttr getAttr() const
MLIRContext * getContext() const
Returns the MLIRContext.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Value getBuiltinVariableValue(Operation *op, BuiltIn builtin, Type integerType, OpBuilder &builder)
Returns the value for the given builtin variable.
Value getPushConstantValue(Operation *op, unsigned elementCount, unsigned offset, Type integerType, OpBuilder &builder)
Gets the value at the given offset of the push constant storage with a total of elementCount integerT...
Value getElementPtr(SPIRVTypeConverter &typeConverter, MemRefType baseType, Value basePtr, ValueRange indices, Location loc, OpBuilder &builder)
Performs the index computation to get to the element at indices of the memory pointed to by basePtr,...
Value getOpenCLElementPtr(SPIRVTypeConverter &typeConverter, MemRefType baseType, Value basePtr, ValueRange indices, Location loc, OpBuilder &builder)
Value linearizeIndex(ValueRange indices, ArrayRef< int64_t > strides, int64_t offset, Type integerType, Location loc, OpBuilder &builder)
Generates IR to perform index linearization with the given indices and their corresponding strides,...
Value getVulkanElementPtr(SPIRVTypeConverter &typeConverter, MemRefType baseType, Value basePtr, ValueRange indices, Location loc, OpBuilder &builder)
This header declares functions that assit transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
void populateBuiltinFuncToSPIRVPatterns(SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns)
Appends to a pattern list additional patterns for translating the builtin func op to the SPIR-V diale...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult getStridesAndOffset(MemRefType t, SmallVectorImpl< int64_t > &strides, int64_t &offset)
Returns the strides of the MemRef if the layout map is in strided form.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.