16 #include "llvm/ADT/SmallVectorExtras.h"
17 #include "llvm/ADT/StringSet.h"
18 #include "llvm/Support/FormatVariadic.h"
28 workgroupBuffers.reserve(gpuFuncOp.getNumWorkgroupAttributions());
29 for (
const auto [idx, attribution] :
31 auto type = dyn_cast<MemRefType>(attribution.getType());
32 assert(type && type.hasStaticShape() &&
"unexpected type in attribution");
34 uint64_t numElements = type.getNumElements();
40 std::string(llvm::formatv(
"__wg_{0}_{1}", gpuFuncOp.getName(), idx));
41 uint64_t alignment = 0;
43 dyn_cast_or_null<IntegerAttr>(gpuFuncOp.getWorkgroupAttributionAttr(
44 idx, LLVM::LLVMDialect::getAlignAttrName())))
45 alignment = alignAttr.getInt();
46 auto globalOp = rewriter.
create<LLVM::GlobalOp>(
47 gpuFuncOp.getLoc(), arrayType,
false,
48 LLVM::Linkage::Internal, name,
Attribute(), alignment,
50 workgroupBuffers.push_back(globalOp);
55 gpuFuncOp.front().getNumArguments());
58 gpuFuncOp.getFunctionType(),
false,
62 diag <<
"failed to convert function signature type for: "
63 << gpuFuncOp.getFunctionType();
71 for (
const auto &attr : gpuFuncOp->getAttrs()) {
73 attr.getName() == gpuFuncOp.getFunctionTypeAttrName() ||
75 gpu::GPUFuncOp::getNumWorkgroupAttributionsAttrName() ||
76 attr.getName() == gpuFuncOp.getWorkgroupAttribAttrsAttrName() ||
77 attr.getName() == gpuFuncOp.getPrivateAttribAttrsAttrName())
79 if (attr.getName() == gpuFuncOp.getArgAttrsAttrName()) {
80 argAttrs = gpuFuncOp.getArgAttrsAttr();
83 attributes.push_back(attr);
88 if (gpuFuncOp.isKernel()) {
89 attributes.emplace_back(kernelAttributeName, rewriter.
getUnitAttr());
92 if (kernelBlockSizeAttributeName.has_value()) {
93 std::optional<int32_t> dimX =
94 gpuFuncOp.getKnownBlockSize(gpu::Dimension::x);
95 std::optional<int32_t> dimY =
96 gpuFuncOp.getKnownBlockSize(gpu::Dimension::y);
97 std::optional<int32_t> dimZ =
98 gpuFuncOp.getKnownBlockSize(gpu::Dimension::z);
99 if (dimX.has_value() || dimY.has_value() || dimZ.has_value()) {
101 attributes.emplace_back(
102 kernelBlockSizeAttributeName.value(),
104 {dimX.value_or(1), dimY.value_or(1), dimZ.value_or(1)}));
108 auto llvmFuncOp = rewriter.
create<LLVM::LLVMFuncOp>(
109 gpuFuncOp.getLoc(), gpuFuncOp.getName(), funcType,
110 LLVM::Linkage::External,
false, LLVM::CConv::C,
111 nullptr, attributes);
123 unsigned numProperArguments = gpuFuncOp.getNumArguments();
127 global.getAddrSpace());
128 Value address = rewriter.
create<LLVM::AddressOfOp>(
129 loc, ptrType, global.getSymNameAttr());
131 rewriter.
create<LLVM::GEPOp>(loc, ptrType, global.getType(), address,
138 Value attribution = gpuFuncOp.getWorkgroupAttributions()[idx];
139 auto type = cast<MemRefType>(attribution.getType());
142 signatureConversion.
remapInput(numProperArguments + idx, descr);
146 unsigned numWorkgroupAttributions = gpuFuncOp.getNumWorkgroupAttributions();
148 for (
const auto [idx, attribution] :
150 auto type = cast<MemRefType>(attribution.getType());
151 assert(type && type.hasStaticShape() &&
"unexpected type in attribution");
159 Value numElements = rewriter.
create<LLVM::ConstantOp>(
160 gpuFuncOp.getLoc(), int64Ty, type.getNumElements());
161 uint64_t alignment = 0;
163 dyn_cast_or_null<IntegerAttr>(gpuFuncOp.getPrivateAttributionAttr(
164 idx, LLVM::LLVMDialect::getAlignAttrName())))
165 alignment = alignAttr.getInt();
167 gpuFuncOp.getLoc(), ptrType, elementType, numElements, alignment);
171 numProperArguments + numWorkgroupAttributions + idx, descr);
179 &signatureConversion)))
188 for (
const auto [idx, argTy] :
190 auto memrefTy = dyn_cast<MemRefType>(argTy);
193 assert(memrefTy.hasStaticShape() &&
194 "Bare pointer convertion used with dynamically-shaped memrefs");
198 assert(remapping && remapping->size == 1 &&
199 "Type converter should produce 1-to-1 mapping for bare memrefs");
201 llvmFuncOp.getBody().getArgument(remapping->inputNo);
202 auto placeholder = rewriter.
create<LLVM::UndefOp>(
213 for (
const auto [idx, argTy] :
217 argAttrs ? argAttrs[idx].cast<DictionaryAttr>() :
NamedAttrList();
218 auto copyAttribute = [&](StringRef attrName) {
222 for (
size_t i = 0, e = remapping->size; i < e; ++i)
223 llvmFuncOp.setArgAttr(remapping->inputNo + i, attrName, attr);
225 auto copyPointerAttribute = [&](StringRef attrName) {
230 if (remapping->size > 1 &&
231 attrName == LLVM::LLVMDialect::getNoAliasAttrName()) {
233 "Cannot copy noalias with non-bare pointers.\n");
236 for (
size_t i = 0, e = remapping->size; i < e; ++i) {
237 if (llvmFuncOp.getArgument(remapping->inputNo + i)
239 .isa<LLVM::LLVMPointerType>()) {
240 llvmFuncOp.setArgAttr(remapping->inputNo + i, attrName, attr);
248 copyAttribute(LLVM::LLVMDialect::getReturnedAttrName());
249 copyAttribute(LLVM::LLVMDialect::getNoUndefAttrName());
250 copyAttribute(LLVM::LLVMDialect::getInRegAttrName());
251 bool lowersToPointer =
false;
252 for (
size_t i = 0, e = remapping->size; i < e; ++i) {
253 lowersToPointer |= isa<LLVM::LLVMPointerType>(
254 llvmFuncOp.getArgument(remapping->inputNo + i).getType());
257 if (lowersToPointer) {
258 copyPointerAttribute(LLVM::LLVMDialect::getNoAliasAttrName());
259 copyPointerAttribute(LLVM::LLVMDialect::getNoCaptureAttrName());
260 copyPointerAttribute(LLVM::LLVMDialect::getNoFreeAttrName());
261 copyPointerAttribute(LLVM::LLVMDialect::getAlignAttrName());
262 copyPointerAttribute(LLVM::LLVMDialect::getReadonlyAttrName());
263 copyPointerAttribute(LLVM::LLVMDialect::getWriteOnlyAttrName());
264 copyPointerAttribute(LLVM::LLVMDialect::getReadnoneAttrName());
265 copyPointerAttribute(LLVM::LLVMDialect::getNonNullAttrName());
266 copyPointerAttribute(LLVM::LLVMDialect::getDereferenceableAttrName());
267 copyPointerAttribute(
268 LLVM::LLVMDialect::getDereferenceableOrNullAttrName());
276 const char formatStringPrefix[] =
"printfFormat_";
278 unsigned stringNumber = 0;
281 stringConstName.clear();
282 (formatStringPrefix + Twine(stringNumber++)).toStringRef(stringConstName);
283 }
while (moduleOp.lookupSymbol(stringConstName));
284 return stringConstName;
287 template <
typename T>
291 LLVM::LLVMFunctionType type) {
292 LLVM::LLVMFuncOp ret;
293 if (!(ret = moduleOp.template lookupSymbol<LLVM::LLVMFuncOp>(name))) {
294 ConversionPatternRewriter::InsertionGuard guard(rewriter);
296 ret = rewriter.
create<LLVM::LLVMFuncOp>(loc, name, type,
297 LLVM::Linkage::External);
303 gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor,
305 Location loc = gpuPrintfOp->getLoc();
314 auto moduleOp = gpuPrintfOp->getParentOfType<gpu::GPUModuleOp>();
319 LLVM::LLVMFuncOp ocklAppendArgs;
320 if (!adaptor.getArgs().empty()) {
322 moduleOp, loc, rewriter,
"__ockl_printf_append_args",
324 llvmI64, {llvmI64, llvmI32, llvmI64, llvmI64, llvmI64,
325 llvmI64, llvmI64, llvmI64, llvmI64, llvmI32}));
328 moduleOp, loc, rewriter,
"__ockl_printf_append_string_n",
331 {llvmI64, ptrType, llvmI64, llvmI32}));
334 Value zeroI64 = rewriter.
create<LLVM::ConstantOp>(loc, llvmI64, 0);
335 auto printfBeginCall = rewriter.
create<LLVM::CallOp>(loc, ocklBegin, zeroI64);
336 Value printfDesc = printfBeginCall.getResult();
342 formatString.push_back(
'\0');
343 size_t formatStringSize = formatString.size_in_bytes();
346 LLVM::GlobalOp global;
350 global = rewriter.
create<LLVM::GlobalOp>(
352 true, LLVM::Linkage::Internal, stringConstName,
357 Value globalPtr = rewriter.
create<LLVM::AddressOfOp>(
360 global.getSymNameAttr());
364 rewriter.
create<LLVM::ConstantOp>(loc, llvmI64, formatStringSize);
366 Value oneI32 = rewriter.
create<LLVM::ConstantOp>(loc, llvmI32, 1);
367 Value zeroI32 = rewriter.
create<LLVM::ConstantOp>(loc, llvmI32, 0);
369 auto appendFormatCall = rewriter.
create<LLVM::CallOp>(
370 loc, ocklAppendStringN,
371 ValueRange{printfDesc, stringStart, stringLen,
372 adaptor.getArgs().empty() ? oneI32 : zeroI32});
373 printfDesc = appendFormatCall.
getResult();
376 constexpr
size_t argsPerAppend = 7;
377 size_t nArgs = adaptor.getArgs().size();
378 for (
size_t group = 0; group < nArgs; group += argsPerAppend) {
379 size_t bound =
std::min(group + argsPerAppend, nArgs);
380 size_t numArgsThisCall = bound - group;
383 arguments.push_back(printfDesc);
385 rewriter.
create<LLVM::ConstantOp>(loc, llvmI32, numArgsThisCall));
386 for (
size_t i = group; i < bound; ++i) {
387 Value arg = adaptor.getArgs()[i];
388 if (
auto floatType = dyn_cast<FloatType>(arg.
getType())) {
389 if (!floatType.isF64())
390 arg = rewriter.
create<LLVM::FPExtOp>(
392 arg = rewriter.
create<LLVM::BitcastOp>(loc, llvmI64, arg);
395 arg = rewriter.
create<LLVM::ZExtOp>(loc, llvmI64, arg);
397 arguments.push_back(arg);
400 for (
size_t extra = numArgsThisCall; extra < argsPerAppend; ++extra) {
401 arguments.push_back(zeroI64);
404 auto isLast = (bound == nArgs) ? oneI32 : zeroI32;
405 arguments.push_back(isLast);
406 auto call = rewriter.
create<LLVM::CallOp>(loc, ocklAppendArgs, arguments);
414 gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor,
416 Location loc = gpuPrintfOp->getLoc();
425 auto moduleOp = gpuPrintfOp->getParentOfType<gpu::GPUModuleOp>();
430 LLVM::LLVMFuncOp printfDecl =
437 formatString.push_back(
'\0');
440 LLVM::GlobalOp global;
444 global = rewriter.
create<LLVM::GlobalOp>(
446 true, LLVM::Linkage::Internal, stringConstName,
451 Value globalPtr = rewriter.
create<LLVM::AddressOfOp>(
454 global.getSymNameAttr());
459 auto argsRange = adaptor.getArgs();
461 printfArgs.reserve(argsRange.size() + 1);
462 printfArgs.push_back(stringStart);
463 printfArgs.append(argsRange.begin(), argsRange.end());
465 rewriter.
create<LLVM::CallOp>(loc, printfDecl, printfArgs);
471 gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor,
473 Location loc = gpuPrintfOp->getLoc();
481 auto moduleOp = gpuPrintfOp->getParentOfType<gpu::GPUModuleOp>();
485 LLVM::LLVMFuncOp vprintfDecl =
492 formatString.push_back(
'\0');
495 LLVM::GlobalOp global;
499 global = rewriter.
create<LLVM::GlobalOp>(
501 true, LLVM::Linkage::Internal, stringConstName,
506 Value globalPtr = rewriter.
create<LLVM::AddressOfOp>(loc, global);
512 for (
Value arg : adaptor.getArgs()) {
513 Type type = arg.getType();
514 Value promotedArg = arg;
516 if (isa<FloatType>(type)) {
518 promotedArg = rewriter.
create<LLVM::FPExtOp>(loc, type, arg);
520 types.push_back(type);
521 args.push_back(promotedArg);
528 rewriter.
create<LLVM::AllocaOp>(loc, ptrType, structType, one,
532 loc, ptrType, structType, tempAlloc,
534 rewriter.
create<LLVM::StoreOp>(loc, arg, ptr);
536 std::array<Value, 2> printfArgs = {stringStart, tempAlloc};
538 rewriter.
create<LLVM::CallOp>(loc, vprintfDecl, printfArgs);
548 if (llvm::none_of(operandTypes,
549 [](
Type type) {
return isa<VectorType>(type); })) {
561 Value result = rewriter.
create<LLVM::UndefOp>(loc, vectorType);
564 Type elementType = vectorType.getElementType();
566 for (int64_t i = 0; i < vectorType.getNumElements(); ++i) {
567 Value index = rewriter.
create<LLVM::ConstantOp>(loc, indexType, i);
568 auto extractElement = [&](
Value operand) ->
Value {
569 if (!isa<VectorType>(operand.getType()))
571 return rewriter.
create<LLVM::ExtractElementOp>(loc, operand, index);
573 auto scalarOperands = llvm::map_to_vector(operands, extractElement);
575 rewriter.
create(loc, name, scalarOperands, elementType, op->
getAttrs());
576 result = rewriter.
create<LLVM::InsertElementOp>(
577 loc, result, scalarOp->
getResult(0), index);
592 Operation *moduleOp, gpu::DynamicSharedMemoryOp op,
594 MemRefType memrefType,
unsigned alignmentBit) {
595 uint64_t alignmentByte = alignmentBit / memrefType.getElementTypeBitWidth();
599 if (
failed(addressSpace)) {
600 op->
emitError() <<
"conversion of memref memory space "
601 << memrefType.getMemorySpace()
602 <<
" to integer address space "
603 "failed. Consider adding memory space conversions.";
611 existingGlobalNames.insert(globalOp.getSymName());
612 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(globalOp.getType())) {
613 if (globalOp.getAddrSpace() == addressSpace.value() &&
614 arrayType.getNumElements() == 0 &&
615 globalOp.getAlignment().value_or(0) == alignmentByte) {
622 unsigned uniquingCounter = 0;
625 [&](StringRef candidate) {
626 return existingGlobalNames.contains(candidate);
635 typeConverter->
convertType(memrefType.getElementType()), 0);
637 return rewriter.
create<LLVM::GlobalOp>(
638 op->
getLoc(), zeroSizedArrayType,
false,
639 LLVM::Linkage::Internal, symName,
Attribute(), alignmentByte,
640 addressSpace.value());
644 gpu::DynamicSharedMemoryOp op, OpAdaptor adaptor,
647 MemRefType memrefType = op.getResultMemref().getType();
651 MemRefLayoutAttrInterface layout = {};
653 MemRefType::get({0}, elementType, layout, memrefType.getMemorySpace());
658 LLVM::GlobalOp shmemOp = {};
666 auto basePtr = rewriter.
create<LLVM::AddressOfOp>(loc, shmemOp);
667 Type baseType = basePtr->getResultTypes().front();
671 Value shmemPtr = rewriter.
create<LLVM::GEPOp>(loc, baseType, elementType,
679 loc, memrefType0sz, shmemPtr, shmemPtr, shape, strides, rewriter);
682 rewriter.
replaceOp(op, {memRefDescriptor});
689 [mapping](
BaseMemRefType type, gpu::AddressSpaceAttr memorySpaceAttr) {
690 gpu::AddressSpace memorySpace = memorySpaceAttr.getValue();
691 unsigned addressSpace = mapping(memorySpace);
static LLVM::LLVMFuncOp getOrDefineFunction(T &moduleOp, const Location loc, ConversionPatternRewriter &rewriter, StringRef name, LLVM::LLVMFunctionType type)
LLVM::GlobalOp getDynamicSharedMemorySymbol(ConversionPatternRewriter &rewriter, Operation *moduleOp, gpu::DynamicSharedMemoryOp op, const LLVMTypeConverter *typeConverter, MemRefType memrefType, unsigned alignmentBit)
Generates a symbol with 0-sized array type for dynamic shared memory usage, or uses existing symbol.
static IntegerAttr wrapNumericMemorySpace(MLIRContext *ctx, unsigned space)
static SmallString< 16 > getUniqueFormatGlobalName(gpu::GPUModuleOp moduleOp)
static std::string diag(const llvm::Value &value)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
Attributes are known-constant values of operations.
This class provides a shared interface for ranked and unranked memref types.
This class represents an argument of a Block.
iterator_range< op_iterator< OpT > > getOps()
Return an iterator range over the operations within this block that are of 'OpT'.
IntegerAttr getIndexAttr(int64_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerType getIntegerType(unsigned width)
StringAttr getStringAttr(const Twine &bytes)
MLIRContext * getContext() const
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
PatternRewriter hook for replacing an operation.
FailureOr< Block * > convertRegionTypes(Region *region, const TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Convert the types of block arguments within the given region.
void eraseOp(Operation *op) override
PatternRewriter hook for erasing a dead operation.
void replaceUsesOfBlockArgument(BlockArgument from, Value to)
Replace all the uses of the block argument from with value to.
const TypeConverter * typeConverter
An optional type converter for use by this pattern.
MemRefDescriptor createMemRefDescriptor(Location loc, MemRefType memRefType, Value allocatedPtr, Value alignedPtr, ArrayRef< Value > sizes, ArrayRef< Value > strides, ConversionPatternRewriter &rewriter) const
Creates and populates a canonical memref descriptor struct.
void getMemRefDescriptorSizes(Location loc, MemRefType memRefType, ValueRange dynamicSizes, ConversionPatternRewriter &rewriter, SmallVectorImpl< Value > &sizes, SmallVectorImpl< Value > &strides, Value &size, bool sizeInBytes=true) const
Computes sizes, strides and buffer size of memRefType with identity layout.
const LLVMTypeConverter * getTypeConverter() const
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
This class provides support for representing a failure result, or a valid value of type T.
Conversion from types to the LLVM IR dialect.
Type convertFunctionSignature(FunctionType funcTy, bool isVariadic, bool useBarePtrCallConv, SignatureConversion &result) const
Convert a function type.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
FailureOr< unsigned > getMemRefAddressSpace(BaseMemRefType type) const
Return the LLVM address space corresponding to the memory space of the memref type type or failure if...
static LLVMStructType getLiteral(MLIRContext *context, ArrayRef< Type > types, bool isPacked=false)
Gets or creates a literal struct with the given body in the provided context.
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.
static MemRefDescriptor fromStaticShape(OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, MemRefType type, Value memory)
Builds IR creating a MemRef descriptor that represents type and populates it with static shape and st...
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
Attribute erase(StringAttr name)
Erase the attribute with the given name from the list.
RAII guard to reset the insertion point of the builder when destroyed.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
A trait used to provide symbol table functionalities to a region operation.
StringAttr getIdentifier() const
Return the name of this operation as a StringAttr.
Operation is the basic unit of execution within MLIR.
unsigned getNumSuccessors()
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
OperationName getName()
The name of an operation is the key identifier for it.
unsigned getNumResults()
Return the number of results held by this operation.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
void inlineRegionBefore(Region ®ion, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
This class provides all of the information necessary to convert a type signature.
std::optional< InputMapping > getInputMapping(unsigned input) const
Get the input mapping for the given argument.
void remapInput(unsigned origInputNo, Value replacement)
Remap an input of the original signature to another replacement value.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
void addTypeAttributeConversion(FnT &&callback)
Register a conversion function for attributes within types.
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...
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
LogicalResult scalarizeVectorOp(Operation *op, ValueRange operands, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter)
Unrolls op if it's operating on vectors.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
std::function< unsigned(gpu::AddressSpace)> MemorySpaceMapping
A function that maps a MemorySpace enum to a target-specific integer value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
void populateGpuMemorySpaceAttributeConversions(TypeConverter &typeConverter, const MemorySpaceMapping &mapping)
Populates memory space attribute conversion rules for lowering gpu.address_space to integer values.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
LogicalResult matchAndRewrite(gpu::DynamicSharedMemoryOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(gpu::GPUFuncOp gpuFuncOp, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
LogicalResult matchAndRewrite(gpu::PrintfOp gpuPrintfOp, gpu::PrintfOpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override
This class represents an efficient way to signal success or failure.