40#include "llvm/ADT/STLExtras.h"
42#define DEBUG_TYPE "gpu-to-llvm"
45#define GEN_PASS_DEF_GPUTOLLVMCONVERSIONPASS
46#include "mlir/Conversion/Passes.h.inc"
52class GpuToLLVMConversionPass
56 void getDependentDialects(DialectRegistry ®istry)
const final {
57 Base::getDependentDialects(registry);
61 void runOnOperation()
override;
64template <
typename OpTy>
67 explicit ConvertOpToGpuRuntimeCallPattern(
68 const LLVMTypeConverter &typeConverter, PatternBenefit benefit = 1)
69 : ConvertOpToLLVMPattern<OpTy>(typeConverter, benefit) {}
72 Value
getNumElements(ConversionPatternRewriter &rewriter, Location loc,
73 MemRefType type, MemRefDescriptor desc)
const {
75 if (type.hasStaticShape())
77 rewriter, loc, indexType, type.getNumElements());
79 uint64_t rank = type.getRank();
80 Value numElements = desc.
size(rewriter, loc, 0);
81 for (
unsigned i = 1; i < rank; i++)
82 numElements = LLVM::MulOp::create(rewriter, loc, numElements,
83 desc.
size(rewriter, loc, i));
87 MLIRContext *context = &this->getTypeConverter()->
getContext();
89 Type llvmVoidType = LLVM::LLVMVoidType::get(context);
90 LLVM::LLVMPointerType llvmPointerType = LLVM::LLVMPointerType::get(context);
91 Type llvmInt8Type = IntegerType::get(context, 8);
92 Type llvmInt16Type = IntegerType::get(context, 16);
93 Type llvmInt32Type = IntegerType::get(context, 32);
94 Type llvmInt64Type = IntegerType::get(context, 64);
95 Type llvmFloat32Type = Float32Type::get(context);
96 Type llvmIntPtrType = IntegerType::get(
97 context, this->getTypeConverter()->getPointerBitwidth(0));
99 FunctionCallBuilder streamCreateCallBuilder = {
100 "mgpuStreamCreate", llvmPointerType , {}};
101 FunctionCallBuilder streamDestroyCallBuilder = {
102 "mgpuStreamDestroy", llvmVoidType, {llvmPointerType }};
103 FunctionCallBuilder streamSynchronizeCallBuilder = {
104 "mgpuStreamSynchronize",
107 FunctionCallBuilder streamWaitEventCallBuilder = {
108 "mgpuStreamWaitEvent",
110 {llvmPointerType , llvmPointerType }};
111 FunctionCallBuilder eventCreateCallBuilder = {
112 "mgpuEventCreate", llvmPointerType , {}};
113 FunctionCallBuilder eventDestroyCallBuilder = {
114 "mgpuEventDestroy", llvmVoidType, {llvmPointerType }};
115 FunctionCallBuilder eventSynchronizeCallBuilder = {
116 "mgpuEventSynchronize",
119 FunctionCallBuilder eventRecordCallBuilder = {
122 {llvmPointerType , llvmPointerType }};
123 FunctionCallBuilder hostRegisterCallBuilder = {
124 "mgpuMemHostRegisterMemRef",
129 FunctionCallBuilder hostUnregisterCallBuilder = {
130 "mgpuMemHostUnregisterMemRef",
135 FunctionCallBuilder allocCallBuilder = {
141 FunctionCallBuilder deallocCallBuilder = {
144 {llvmPointerType , llvmPointerType }};
145 FunctionCallBuilder memcpyCallBuilder = {
148 {llvmPointerType , llvmPointerType ,
151 FunctionCallBuilder memset16CallBuilder = {
158 FunctionCallBuilder memset32CallBuilder = {
161 {llvmPointerType , llvmInt32Type ,
164 FunctionCallBuilder setDefaultDeviceCallBuilder = {
165 "mgpuSetDefaultDevice",
168 FunctionCallBuilder createDnVecCallBuilder = {
171 {llvmIntPtrType, llvmPointerType, llvmInt32Type,
173 FunctionCallBuilder destroyDnVecCallBuilder = {
176 {llvmPointerType, llvmPointerType }};
177 FunctionCallBuilder createDnMatCallBuilder = {
180 {llvmIntPtrType, llvmIntPtrType, llvmPointerType, llvmInt32Type,
182 FunctionCallBuilder destroyDnMatCallBuilder = {
185 {llvmPointerType, llvmPointerType }};
186 FunctionCallBuilder createCooCallBuilder = {
189 {llvmIntPtrType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
190 llvmPointerType, llvmPointerType, llvmInt32Type, llvmInt32Type,
192 FunctionCallBuilder createCooAoSCallBuilder = {
195 {llvmIntPtrType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
196 llvmPointerType, llvmInt32Type, llvmInt32Type,
198 FunctionCallBuilder createCsrCallBuilder = {
201 {llvmIntPtrType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
202 llvmPointerType, llvmPointerType, llvmInt32Type, llvmInt32Type,
203 llvmInt32Type, llvmPointerType }};
204 FunctionCallBuilder createCscCallBuilder = {
207 {llvmIntPtrType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
208 llvmPointerType, llvmPointerType, llvmInt32Type, llvmInt32Type,
209 llvmInt32Type, llvmPointerType }};
210 FunctionCallBuilder createBsrCallBuilder = {
213 {llvmIntPtrType, llvmIntPtrType, llvmIntPtrType, llvmIntPtrType,
214 llvmIntPtrType, llvmPointerType, llvmPointerType, llvmPointerType,
215 llvmInt32Type, llvmInt32Type, llvmInt32Type,
217 FunctionCallBuilder destroySpMatCallBuilder = {
220 {llvmPointerType, llvmPointerType }};
221 FunctionCallBuilder spMVBufferSizeCallBuilder = {
222 "mgpuSpMVBufferSize",
224 {llvmInt32Type, llvmPointerType, llvmPointerType, llvmPointerType,
225 llvmInt32Type, llvmPointerType }};
226 FunctionCallBuilder spMVCallBuilder = {
229 {llvmInt32Type, llvmPointerType, llvmPointerType, llvmPointerType,
230 llvmInt32Type, llvmPointerType, llvmPointerType }};
231 FunctionCallBuilder createSpMMBufferSizeCallBuilder = {
232 "mgpuSpMMBufferSize",
234 {llvmInt32Type, llvmInt32Type, llvmPointerType, llvmPointerType,
235 llvmPointerType, llvmInt32Type, llvmPointerType }};
236 FunctionCallBuilder createSpMMCallBuilder = {
239 {llvmInt32Type, llvmInt32Type, llvmPointerType, llvmPointerType,
240 llvmPointerType, llvmInt32Type, llvmPointerType,
242 FunctionCallBuilder createSDDMMBufferSizeCallBuilder = {
243 "mgpuSDDMMBufferSize",
245 {llvmInt32Type, llvmInt32Type, llvmPointerType, llvmPointerType,
246 llvmPointerType, llvmInt32Type, llvmPointerType }};
247 FunctionCallBuilder createSDDMMCallBuilder = {
250 {llvmInt32Type, llvmInt32Type, llvmPointerType, llvmPointerType,
251 llvmPointerType, llvmInt32Type, llvmPointerType,
253 FunctionCallBuilder createLtDnMatCallBuilder = {
254 "mgpuCreateCuSparseLtDnMat",
256 {llvmPointerType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
257 llvmInt32Type, llvmPointerType }};
258 FunctionCallBuilder destroyCuSparseLtSpMatBuilder = {
259 "mgpuDestroyCuSparseLtSpMat",
261 {llvmPointerType, llvmPointerType }};
262 FunctionCallBuilder destroyCuSparseLtDnMatBuilder = {
263 "mgpuDestroyCuSparseLtDnMat",
265 {llvmPointerType, llvmPointerType }};
266 FunctionCallBuilder create2To4SpMatCallBuilder = {
267 "mgpuCusparseLtCreate2To4SpMat",
269 {llvmPointerType, llvmIntPtrType, llvmIntPtrType, llvmPointerType,
270 llvmInt32Type, llvmPointerType }};
271 FunctionCallBuilder createCuSparseLtSpMMBufferSizeBuilder = {
272 "mgpuCuSparseLtSpMMBufferSize",
274 {llvmPointerType, llvmInt32Type, llvmInt32Type, llvmPointerType,
275 llvmPointerType, llvmPointerType, llvmInt32Type, llvmInt32Type,
277 FunctionCallBuilder createCuSparseLtSpMMBuilder = {
278 "mgpuCuSparseLtSpMM",
280 {llvmPointerType, llvmPointerType, llvmPointerType, llvmPointerType,
281 llvmPointerType, llvmPointerType, llvmPointerType }};
282 FunctionCallBuilder createSpGEMMCreateDescrBuilder = {
283 "mgpuSpGEMMCreateDescr",
286 FunctionCallBuilder createSpGEMMDestroyDescrBuilder = {
287 "mgpuSpGEMMDestroyDescr",
289 {llvmPointerType , llvmPointerType }};
290 FunctionCallBuilder createSpGEMMWorkEstimationBuilder = {
291 "mgpuSpGEMMWorkEstimation",
293 {llvmPointerType , llvmInt32Type , llvmInt32Type ,
294 llvmPointerType , llvmPointerType , llvmPointerType ,
295 llvmInt32Type , llvmIntPtrType , llvmPointerType ,
297 FunctionCallBuilder createSpGEMMComputeBuilder = {
300 {llvmPointerType , llvmInt32Type , llvmInt32Type ,
301 llvmPointerType , llvmPointerType , llvmPointerType ,
302 llvmInt32Type , llvmIntPtrType , llvmPointerType ,
304 FunctionCallBuilder createSpGEMMCopyBuilder = {
307 {llvmPointerType , llvmInt32Type , llvmInt32Type ,
308 llvmPointerType , llvmPointerType , llvmPointerType ,
309 llvmInt32Type , llvmPointerType }};
310 FunctionCallBuilder createSpMatGetSizeBuilder = {
313 {llvmPointerType , llvmPointerType , llvmPointerType ,
314 llvmPointerType , llvmPointerType }};
315 FunctionCallBuilder createSetCsrPointersBuilder = {
316 "mgpuSetCsrPointers",
318 {llvmPointerType , llvmPointerType ,
319 llvmPointerType , llvmPointerType ,
325class ConvertHostRegisterOpToGpuRuntimeCallPattern
326 :
public ConvertOpToGpuRuntimeCallPattern<gpu::HostRegisterOp> {
328 ConvertHostRegisterOpToGpuRuntimeCallPattern(
329 const LLVMTypeConverter &typeConverter)
330 : ConvertOpToGpuRuntimeCallPattern<gpu::HostRegisterOp>(typeConverter) {}
334 matchAndRewrite(gpu::HostRegisterOp hostRegisterOp, OpAdaptor adaptor,
335 ConversionPatternRewriter &rewriter)
const override;
338class ConvertHostUnregisterOpToGpuRuntimeCallPattern
339 :
public ConvertOpToGpuRuntimeCallPattern<gpu::HostUnregisterOp> {
341 ConvertHostUnregisterOpToGpuRuntimeCallPattern(
342 const LLVMTypeConverter &typeConverter)
343 : ConvertOpToGpuRuntimeCallPattern<gpu::HostUnregisterOp>(typeConverter) {
348 matchAndRewrite(gpu::HostUnregisterOp hostUnregisterOp, OpAdaptor adaptor,
349 ConversionPatternRewriter &rewriter)
const override;
354class ConvertAllocOpToGpuRuntimeCallPattern
355 :
public ConvertOpToGpuRuntimeCallPattern<gpu::AllocOp> {
357 ConvertAllocOpToGpuRuntimeCallPattern(
const LLVMTypeConverter &typeConverter)
358 : ConvertOpToGpuRuntimeCallPattern<gpu::AllocOp>(typeConverter) {}
362 matchAndRewrite(gpu::AllocOp allocOp, OpAdaptor adaptor,
363 ConversionPatternRewriter &rewriter)
const override;
368class ConvertDeallocOpToGpuRuntimeCallPattern
369 :
public ConvertOpToGpuRuntimeCallPattern<gpu::DeallocOp> {
371 ConvertDeallocOpToGpuRuntimeCallPattern(
372 const LLVMTypeConverter &typeConverter)
373 : ConvertOpToGpuRuntimeCallPattern<gpu::DeallocOp>(typeConverter) {}
377 matchAndRewrite(gpu::DeallocOp deallocOp, OpAdaptor adaptor,
378 ConversionPatternRewriter &rewriter)
const override;
381class ConvertAsyncYieldToGpuRuntimeCallPattern
382 :
public ConvertOpToGpuRuntimeCallPattern<async::YieldOp> {
384 ConvertAsyncYieldToGpuRuntimeCallPattern(
385 const LLVMTypeConverter &typeConverter, PatternBenefit benefit = 1)
386 : ConvertOpToGpuRuntimeCallPattern<async::YieldOp>(typeConverter,
391 matchAndRewrite(async::YieldOp yieldOp, OpAdaptor adaptor,
392 ConversionPatternRewriter &rewriter)
const override;
397class ConvertWaitOpToGpuRuntimeCallPattern
398 :
public ConvertOpToGpuRuntimeCallPattern<gpu::WaitOp> {
400 ConvertWaitOpToGpuRuntimeCallPattern(
const LLVMTypeConverter &typeConverter)
401 : ConvertOpToGpuRuntimeCallPattern<gpu::WaitOp>(typeConverter) {}
405 matchAndRewrite(gpu::WaitOp waitOp, OpAdaptor adaptor,
406 ConversionPatternRewriter &rewriter)
const override;
411class ConvertWaitAsyncOpToGpuRuntimeCallPattern
412 :
public ConvertOpToGpuRuntimeCallPattern<gpu::WaitOp> {
414 ConvertWaitAsyncOpToGpuRuntimeCallPattern(
415 const LLVMTypeConverter &typeConverter)
416 : ConvertOpToGpuRuntimeCallPattern<gpu::WaitOp>(typeConverter) {}
420 matchAndRewrite(gpu::WaitOp waitOp, OpAdaptor adaptor,
421 ConversionPatternRewriter &rewriter)
const override;
425class LegalizeLaunchFuncOpPattern
426 :
public ConvertOpToGpuRuntimeCallPattern<gpu::LaunchFuncOp> {
428 LegalizeLaunchFuncOpPattern(
const LLVMTypeConverter &typeConverter,
429 bool kernelBarePtrCallConv,
430 bool kernelIntersperseSizeCallConv)
431 : ConvertOpToGpuRuntimeCallPattern<gpu::LaunchFuncOp>(typeConverter),
432 kernelBarePtrCallConv(kernelBarePtrCallConv),
433 kernelIntersperseSizeCallConv(kernelIntersperseSizeCallConv) {}
437 matchAndRewrite(gpu::LaunchFuncOp launchOp, OpAdaptor adaptor,
438 ConversionPatternRewriter &rewriter)
const override;
440 bool kernelBarePtrCallConv;
441 bool kernelIntersperseSizeCallConv;
446class ConvertMemcpyOpToGpuRuntimeCallPattern
447 :
public ConvertOpToGpuRuntimeCallPattern<gpu::MemcpyOp> {
449 ConvertMemcpyOpToGpuRuntimeCallPattern(
const LLVMTypeConverter &typeConverter)
450 : ConvertOpToGpuRuntimeCallPattern<gpu::MemcpyOp>(typeConverter) {}
454 matchAndRewrite(gpu::MemcpyOp memcpyOp, OpAdaptor adaptor,
455 ConversionPatternRewriter &rewriter)
const override;
460class ConvertMemsetOpToGpuRuntimeCallPattern
461 :
public ConvertOpToGpuRuntimeCallPattern<gpu::MemsetOp> {
463 ConvertMemsetOpToGpuRuntimeCallPattern(
const LLVMTypeConverter &typeConverter)
464 : ConvertOpToGpuRuntimeCallPattern<gpu::MemsetOp>(typeConverter) {}
468 matchAndRewrite(gpu::MemsetOp memsetOp, OpAdaptor adaptor,
469 ConversionPatternRewriter &rewriter)
const override;
474class ConvertSetDefaultDeviceOpToGpuRuntimeCallPattern
475 :
public ConvertOpToGpuRuntimeCallPattern<gpu::SetDefaultDeviceOp> {
477 ConvertSetDefaultDeviceOpToGpuRuntimeCallPattern(
478 const LLVMTypeConverter &typeConverter)
479 : ConvertOpToGpuRuntimeCallPattern<gpu::SetDefaultDeviceOp>(
483 matchAndRewrite(gpu::SetDefaultDeviceOp op, OpAdaptor adaptor,
484 ConversionPatternRewriter &rewriter)
const override;
489#define DECLARE_CONVERT_OP_TO_GPU_RUNTIME_CALL_PATTERN(op_name) \
490 class Convert##op_name##ToGpuRuntimeCallPattern \
491 : public ConvertOpToGpuRuntimeCallPattern<gpu::op_name> { \
493 Convert##op_name##ToGpuRuntimeCallPattern( \
494 const LLVMTypeConverter &typeConverter) \
495 : ConvertOpToGpuRuntimeCallPattern<gpu::op_name>(typeConverter) {} \
499 matchAndRewrite(gpu::op_name op, OpAdaptor adaptor, \
500 ConversionPatternRewriter &rewriter) const override; \
527void GpuToLLVMConversionPass::runOnOperation() {
538 vector::populateVectorFromElementsUnrollPatterns(patterns);
540 return signalPassFailure();
543 LowerToLLVMOptions
options(context);
544 options.useBarePtrCallConv = hostBarePtrCallConv;
545 RewritePatternSet patterns(context);
546 ConversionTarget
target(*context);
547 target.addLegalDialect<LLVM::LLVMDialect>();
548 LLVMTypeConverter converter(context,
options);
554 llvm::make_isa_range<ConvertToLLVMPatternInterface>(dialects))
555 iface->populateConvertToLLVMConversionPatterns(
target, converter, patterns);
559 target.addLegalOp<gpu::GPUModuleOp, gpu::BinaryOp>();
561 target.addDynamicallyLegalOp<gpu::LaunchFuncOp>(
562 [&](gpu::LaunchFuncOp op) ->
bool {
return converter.isLegal(op); });
570 kernelBarePtrCallConv,
571 kernelIntersperseSizeCallConv);
574 applyPartialConversion(getOperation(),
target, std::move(patterns))))
580 auto module = builder.getBlock()->getParent()->getParentOfType<ModuleOp>();
581 auto function = [&] {
582 if (
auto function = module.lookupSymbol<LLVM::LLVMFuncOp>(
functionName))
587 return LLVM::CallOp::create(builder, loc, function, arguments);
604 llvm_unreachable(
"unsupported type");
610 if (llvm::isa<ComplexType>(type)) {
612 auto elementType = cast<ComplexType>(type).getElementType();
613 if (elementType.isBF16())
615 if (elementType.isF16())
617 if (elementType.isF32())
619 if (elementType.isF64())
621 if (elementType.isInteger(8))
623 if (elementType.isInteger(16))
625 if (elementType.isInteger(32))
643 llvm_unreachable(
"unsupported element type");
647 return spMat.
getDefiningOp<gpu::Create2To4SpMatOp>().getPruneFlag();
672 llvm_unreachable(
"cannot find spmat def");
677 auto spmmOp = dyn_cast<gpu::SpMMOp>(user);
689 ConversionPatternRewriter &rewriter) {
690 if (!llvm::all_of(operands, [](
Value value) {
693 return rewriter.notifyMatchFailure(
694 op,
"Cannot convert if operands aren't of LLVM type.");
700 gpu::AsyncOpInterface op) {
701 if (op.getAsyncDependencies().size() != 1)
702 return rewriter.notifyMatchFailure(
703 op,
"Can only convert with exactly one async dependency.");
705 if (!op.getAsyncToken())
706 return rewriter.notifyMatchFailure(op,
"Can convert only async version.");
711LogicalResult ConvertHostRegisterOpToGpuRuntimeCallPattern::matchAndRewrite(
712 gpu::HostRegisterOp hostRegisterOp, OpAdaptor adaptor,
713 ConversionPatternRewriter &rewriter)
const {
714 auto *op = hostRegisterOp.getOperation();
718 Location loc = op->getLoc();
720 auto memRefType = hostRegisterOp.getValue().getType();
721 auto elementType = cast<UnrankedMemRefType>(memRefType).getElementType();
724 auto arguments = getTypeConverter()->promoteOperands(
725 loc, op->getOperands(), adaptor.getOperands(), rewriter);
726 arguments.push_back(elementSize);
727 hostRegisterCallBuilder.create(loc, rewriter, arguments);
729 rewriter.eraseOp(op);
733LogicalResult ConvertHostUnregisterOpToGpuRuntimeCallPattern::matchAndRewrite(
734 gpu::HostUnregisterOp hostUnregisterOp, OpAdaptor adaptor,
735 ConversionPatternRewriter &rewriter)
const {
736 Operation *op = hostUnregisterOp.getOperation();
740 Location loc = op->
getLoc();
742 auto memRefType = hostUnregisterOp.getValue().getType();
743 auto elementType = cast<UnrankedMemRefType>(memRefType).getElementType();
746 auto arguments = getTypeConverter()->promoteOperands(
747 loc, op->
getOperands(), adaptor.getOperands(), rewriter);
748 arguments.push_back(elementSize);
749 hostUnregisterCallBuilder.create(loc, rewriter, arguments);
751 rewriter.eraseOp(op);
755LogicalResult ConvertAllocOpToGpuRuntimeCallPattern::matchAndRewrite(
756 gpu::AllocOp allocOp, OpAdaptor adaptor,
757 ConversionPatternRewriter &rewriter)
const {
759 MemRefType memRefType = allocOp.getType();
762 !isConvertibleAndHasIdentityMaps(memRefType))
765 auto loc = allocOp.getLoc();
767 bool isShared = allocOp.getHostShared();
769 if (isShared && allocOp.getAsyncToken())
770 return rewriter.notifyMatchFailure(
771 allocOp,
"Host Shared allocation cannot be done async");
772 if (adaptor.getAsyncDependencies().size() > 1)
773 return rewriter.notifyMatchFailure(
774 allocOp,
"Can convert with at most one async dependency.");
778 SmallVector<Value, 4> shape;
779 SmallVector<Value, 4> strides;
781 getMemRefDescriptorSizes(loc, memRefType, adaptor.getDynamicSizes(), rewriter,
782 shape, strides, sizeBytes);
786 auto nullPtr = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPointerType);
787 Value stream = adaptor.getAsyncDependencies().empty()
789 : adaptor.getAsyncDependencies().front();
791 auto isHostShared = mlir::LLVM::ConstantOp::create(
792 rewriter, loc, llvmInt8Type, rewriter.getI8IntegerAttr(isShared));
795 allocCallBuilder.create(loc, rewriter, {sizeBytes, stream, isHostShared})
800 unsigned dstAddrSpace =
801 *getTypeConverter()->getMemRefAddressSpace(memRefType);
802 unsigned srcAddrSpace =
803 cast<LLVM::LLVMPointerType>(allocatedPtr.
getType()).getAddressSpace();
804 if (dstAddrSpace != srcAddrSpace) {
806 LLVM::LLVMPointerType::get(rewriter.getContext(), dstAddrSpace);
808 LLVM::AddrSpaceCastOp::create(rewriter, loc, targetPtrTy, allocatedPtr);
812 Value alignedPtr = allocatedPtr;
815 auto memRefDescriptor = this->createMemRefDescriptor(
816 loc, memRefType, allocatedPtr, alignedPtr, shape, strides, rewriter);
818 if (allocOp.getAsyncToken()) {
820 rewriter.replaceOp(allocOp, {memRefDescriptor, stream});
822 rewriter.replaceOp(allocOp, {memRefDescriptor});
828LogicalResult ConvertDeallocOpToGpuRuntimeCallPattern::matchAndRewrite(
829 gpu::DeallocOp deallocOp, OpAdaptor adaptor,
830 ConversionPatternRewriter &rewriter)
const {
833 if (adaptor.getAsyncDependencies().size() > 1)
834 return rewriter.notifyMatchFailure(
835 deallocOp,
"Can convert with at most one async dependency.");
837 Location loc = deallocOp.getLoc();
840 MemRefDescriptor(adaptor.getMemref()).allocatedPtr(rewriter, loc);
842 if (pointer.
getType() != llvmPointerType)
844 LLVM::AddrSpaceCastOp::create(rewriter, loc, llvmPointerType, pointer);
845 auto nullPtr = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPointerType);
846 Value stream = adaptor.getAsyncDependencies().empty()
848 : adaptor.getAsyncDependencies().front();
849 deallocCallBuilder.create(loc, rewriter, {pointer, stream});
851 if (deallocOp.getAsyncToken()) {
853 rewriter.replaceOp(deallocOp, {stream});
856 rewriter.eraseOp(deallocOp);
862 return isa<gpu::AsyncTokenType>(value.
getType());
877LogicalResult ConvertAsyncYieldToGpuRuntimeCallPattern::matchAndRewrite(
878 async::YieldOp yieldOp, OpAdaptor adaptor,
879 ConversionPatternRewriter &rewriter)
const {
881 return rewriter.notifyMatchFailure(yieldOp,
"no gpu async token operand");
883 Location loc = yieldOp.getLoc();
884 SmallVector<Value, 4> newOperands(adaptor.getOperands());
885 llvm::SmallDenseSet<Value> streams;
886 for (
auto &operand : yieldOp->getOpOperands()) {
889 auto idx = operand.getOperandNumber();
890 auto stream = adaptor.getOperands()[idx];
891 auto event = eventCreateCallBuilder.create(loc, rewriter, {}).getResult();
892 eventRecordCallBuilder.create(loc, rewriter, {event, stream});
893 newOperands[idx] = event;
894 streams.insert(stream);
896 for (
auto stream : streams)
897 streamDestroyCallBuilder.create(loc, rewriter, {stream});
899 rewriter.modifyOpInPlace(yieldOp, [&] { yieldOp->setOperands(newOperands); });
905 assert(isa<LLVM::LLVMPointerType>(value.
getType()));
907 return *defOp.getCallee() == functionName;
915LogicalResult ConvertWaitOpToGpuRuntimeCallPattern::matchAndRewrite(
916 gpu::WaitOp waitOp, OpAdaptor adaptor,
917 ConversionPatternRewriter &rewriter)
const {
918 if (waitOp.getAsyncToken())
919 return rewriter.notifyMatchFailure(waitOp,
"Cannot convert async op.");
921 Location loc = waitOp.getLoc();
923 for (
auto operand : adaptor.getOperands()) {
926 streamSynchronizeCallBuilder.create(loc, rewriter, {operand});
927 streamDestroyCallBuilder.create(loc, rewriter, {operand});
931 eventSynchronizeCallBuilder.create(loc, rewriter, {operand});
932 eventDestroyCallBuilder.create(loc, rewriter, {operand});
936 rewriter.eraseOp(waitOp);
945LogicalResult ConvertWaitAsyncOpToGpuRuntimeCallPattern::matchAndRewrite(
946 gpu::WaitOp waitOp, OpAdaptor adaptor,
947 ConversionPatternRewriter &rewriter)
const {
948 if (!waitOp.getAsyncToken())
949 return rewriter.notifyMatchFailure(waitOp,
"Can only convert async op.");
951 Location loc = waitOp.getLoc();
953 auto insertionPoint = rewriter.saveInsertionPoint();
954 SmallVector<Value, 1> events;
956 llvm::zip(waitOp.getAsyncDependencies(), adaptor.getOperands())) {
957 auto operand = std::get<1>(pair);
961 auto *defOp = std::get<0>(pair).getDefiningOp();
962 rewriter.setInsertionPointAfter(defOp);
963 auto event = eventCreateCallBuilder.create(loc, rewriter, {}).getResult();
964 eventRecordCallBuilder.create(loc, rewriter, {event, operand});
965 events.push_back(event);
969 events.push_back(operand);
972 rewriter.restoreInsertionPoint(insertionPoint);
973 auto stream = streamCreateCallBuilder.create(loc, rewriter, {}).getResult();
974 for (
auto event : events)
975 streamWaitEventCallBuilder.create(loc, rewriter, {stream,
event});
976 for (
auto event : events)
977 eventDestroyCallBuilder.create(loc, rewriter, {
event});
978 rewriter.replaceOp(waitOp, {stream});
984LogicalResult LegalizeLaunchFuncOpPattern::matchAndRewrite(
985 gpu::LaunchFuncOp launchOp, OpAdaptor adaptor,
986 ConversionPatternRewriter &rewriter)
const {
993 if (!launchOp.getAsyncToken() && !launchOp.getAsyncDependencies().empty())
994 return rewriter.notifyMatchFailure(
995 launchOp,
"Cannot convert non-async op with async dependencies.");
997 Location loc = launchOp.getLoc();
999 Value stream = Value();
1000 if (!adaptor.getAsyncDependencies().empty()) {
1001 stream = adaptor.getAsyncDependencies().front();
1004 if (adaptor.getAsyncDependencies().size() > 1) {
1005 auto insertionPoint = rewriter.saveInsertionPoint();
1006 SmallVector<Value, 4> events;
1007 for (
auto [origDep, convertedDep] :
1008 llvm::zip(launchOp.getAsyncDependencies().drop_front(),
1009 adaptor.getAsyncDependencies().drop_front())) {
1011 streamCreateCallBuilder.functionName)) {
1012 events.push_back(convertedDep);
1015 Operation *defOp = origDep.getDefiningOp();
1016 rewriter.setInsertionPointAfter(defOp);
1018 eventCreateCallBuilder.create(loc, rewriter, {}).getResult();
1019 eventRecordCallBuilder.create(loc, rewriter, {event, convertedDep});
1020 events.push_back(event);
1022 rewriter.restoreInsertionPoint(insertionPoint);
1023 for (Value event : events)
1024 streamWaitEventCallBuilder.create(loc, rewriter, {stream,
event});
1025 for (Value event : events)
1026 eventDestroyCallBuilder.create(loc, rewriter, {
event});
1031 else if (launchOp.getAsyncToken())
1032 stream = streamCreateCallBuilder.create(loc, rewriter, {}).getResult();
1037 OperandRange origArguments = launchOp.getKernelOperands();
1038 bool effectiveBarePtr = kernelBarePtrCallConv ||
1039 getTypeConverter()->getOptions().useBarePtrCallConv;
1040 if (effectiveBarePtr) {
1041 for (Value arg : origArguments) {
1042 if (isa<UnrankedMemRefType>(arg.getType()))
1043 return rewriter.notifyMatchFailure(
1044 loc,
"unranked memref kernel argument is not supported with "
1045 "the bare-pointer calling convention");
1048 SmallVector<Value, 8> llvmArguments = getTypeConverter()->promoteOperands(
1049 loc, origArguments, adaptor.getKernelOperands(), rewriter,
1050 kernelBarePtrCallConv);
1051 SmallVector<Value, 8> llvmArgumentsWithSizes;
1054 if (kernelIntersperseSizeCallConv) {
1055 if (origArguments.size() != llvmArguments.size()) {
1057 return rewriter.notifyMatchFailure(
1059 "Cannot add sizes to arguments with one-to-many LLVM IR expansion.");
1062 llvmArgumentsWithSizes.reserve(llvmArguments.size() * 2);
1063 for (
auto [llvmArg, origArg] : zip_equal(llvmArguments, origArguments)) {
1064 auto memrefTy = dyn_cast<MemRefType>(origArg.getType());
1066 return rewriter.notifyMatchFailure(
1067 launchOp,
"Operand to launch op is not a memref.");
1070 if (!memrefTy.hasStaticShape() ||
1071 !memrefTy.getElementType().isIntOrFloat()) {
1072 return rewriter.notifyMatchFailure(
1073 launchOp,
"Operand to launch op is not a memref with a static "
1074 "shape and an integer or float element type.");
1077 unsigned bitwidth = memrefTy.getElementTypeBitWidth();
1078 if (bitwidth % 8 != 0) {
1079 return rewriter.notifyMatchFailure(
1080 launchOp,
"Operand to launch op is not a memref with a "
1081 "byte-aligned element type.");
1084 uint64_t staticSize =
static_cast<uint64_t
>(bitwidth / 8) *
1085 static_cast<uint64_t
>(memrefTy.getNumElements());
1089 llvmArgumentsWithSizes.push_back(llvmArg);
1090 llvmArgumentsWithSizes.push_back(sizeArg);
1094 std::optional<gpu::KernelDim3> clusterSize = std::nullopt;
1095 if (launchOp.hasClusterSize()) {
1097 gpu::KernelDim3{adaptor.getClusterSizeX(), adaptor.getClusterSizeY(),
1098 adaptor.getClusterSizeZ()};
1100 auto newLaunchOp = gpu::LaunchFuncOp::create(
1101 rewriter, launchOp.getLoc(), launchOp.getKernelAttr(),
1102 gpu::KernelDim3{adaptor.getGridSizeX(), adaptor.getGridSizeY(),
1103 adaptor.getGridSizeZ()},
1104 gpu::KernelDim3{adaptor.getBlockSizeX(), adaptor.getBlockSizeY(),
1105 adaptor.getBlockSizeZ()},
1106 adaptor.getDynamicSharedMemorySize(),
1107 llvmArgumentsWithSizes.empty() ? llvmArguments : llvmArgumentsWithSizes,
1108 nullptr, {}, stream, clusterSize);
1109 if (launchOp.getCooperative())
1110 newLaunchOp.setCooperative(
true);
1111 if (launchOp.getAsyncToken())
1112 rewriter.replaceOp(launchOp, {stream});
1114 rewriter.eraseOp(launchOp);
1119 ConversionPatternRewriter &rewriter,
1120 LLVM::LLVMPointerType destinationType,
1123 auto sourceTy = cast<LLVM::LLVMPointerType>(sourcePtr.
getType());
1124 if (destinationType.getAddressSpace() != sourceTy.getAddressSpace())
1125 sourcePtr = LLVM::AddrSpaceCastOp::create(
1127 LLVM::LLVMPointerType::get(rewriter.getContext(),
1128 destinationType.getAddressSpace()),
1133LogicalResult ConvertMemcpyOpToGpuRuntimeCallPattern::matchAndRewrite(
1134 gpu::MemcpyOp memcpyOp, OpAdaptor adaptor,
1135 ConversionPatternRewriter &rewriter)
const {
1136 auto memRefType = cast<MemRefType>(memcpyOp.getSrc().getType());
1139 !isConvertibleAndHasIdentityMaps(memRefType) ||
1143 auto loc = memcpyOp.getLoc();
1145 MemRefDescriptor srcDesc(adaptor.getSrc());
1146 Value numElements =
getNumElements(rewriter, loc, memRefType, srcDesc);
1148 Type elementPtrType = getElementPtrType(memRefType);
1149 Value nullPtr = LLVM::ZeroOp::create(rewriter, loc, elementPtrType);
1150 Value gepPtr = LLVM::GEPOp::create(
1151 rewriter, loc, elementPtrType,
1152 typeConverter->convertType(memRefType.getElementType()), nullPtr,
1155 LLVM::PtrToIntOp::create(rewriter, loc, getIndexType(), gepPtr);
1158 srcDesc.alignedPtr(rewriter, loc),
1159 *getTypeConverter());
1161 loc, rewriter, llvmPointerType,
1162 MemRefDescriptor(adaptor.getDst()).alignedPtr(rewriter, loc),
1163 *getTypeConverter());
1165 auto stream = adaptor.getAsyncDependencies().front();
1166 memcpyCallBuilder.create(loc, rewriter, {dst, src, sizeBytes, stream});
1168 rewriter.replaceOp(memcpyOp, {stream});
1173LogicalResult ConvertMemsetOpToGpuRuntimeCallPattern::matchAndRewrite(
1174 gpu::MemsetOp memsetOp, OpAdaptor adaptor,
1175 ConversionPatternRewriter &rewriter)
const {
1176 auto memRefType = cast<MemRefType>(memsetOp.getDst().getType());
1179 !isConvertibleAndHasIdentityMaps(memRefType) ||
1183 auto loc = memsetOp.getLoc();
1185 Type valueType = adaptor.getValue().getType();
1188 if (!valueType.
isIntOrFloat() || (bitWidth != 16 && bitWidth != 32)) {
1189 return rewriter.notifyMatchFailure(
1190 memsetOp,
"value must be a 16 or 32 bit int or float");
1194 Type bitCastType = valueTypeWidth == 32 ? llvmInt32Type : llvmInt16Type;
1196 MemRefDescriptor dstDesc(adaptor.getDst());
1197 Value numElements =
getNumElements(rewriter, loc, memRefType, dstDesc);
1200 LLVM::BitcastOp::create(rewriter, loc, bitCastType, adaptor.getValue());
1202 dstDesc.alignedPtr(rewriter, loc),
1203 *getTypeConverter());
1205 auto stream = adaptor.getAsyncDependencies().front();
1206 FunctionCallBuilder builder =
1207 valueTypeWidth == 32 ? memset32CallBuilder : memset16CallBuilder;
1208 builder.
create(loc, rewriter, {dst, value, numElements, stream});
1210 rewriter.replaceOp(memsetOp, {stream});
1214LogicalResult ConvertSetDefaultDeviceOpToGpuRuntimeCallPattern::matchAndRewrite(
1215 gpu::SetDefaultDeviceOp op, OpAdaptor adaptor,
1216 ConversionPatternRewriter &rewriter)
const {
1217 Location loc = op.getLoc();
1218 auto call = setDefaultDeviceCallBuilder.create(loc, rewriter,
1219 {adaptor.getDevIndex()});
1220 rewriter.replaceOp(op, call);
1224template <
typename T>
1227 return LLVM::ConstantOp::create(builder, loc, llvmInt32Type,
1228 static_cast<int32_t
>(tValue));
1231LogicalResult ConvertCreateDnTensorOpToGpuRuntimeCallPattern::matchAndRewrite(
1232 gpu::CreateDnTensorOp op, OpAdaptor adaptor,
1233 ConversionPatternRewriter &rewriter)
const {
1237 Location loc = op.getLoc();
1238 auto stream = adaptor.getAsyncDependencies().front();
1240 MemRefDescriptor(adaptor.getMemref()).allocatedPtr(rewriter, loc);
1241 Type dType = op.getMemref().
getType().getElementType();
1244 SmallVector<Value, 4> dims;
1245 for (Value dim : adaptor.getDims()) {
1246 dims.push_back(dim);
1256 if (dims.size() == 2) {
1260 handle = LLVM::AllocaOp::create(rewriter, loc, llvmPointerType,
1261 llvmInt8Type, handleSz, 16);
1262 handle = LLVM::BitcastOp::create(rewriter, loc, llvmPointerType, handle);
1264 createLtDnMatCallBuilder
1265 .create(loc, rewriter,
1266 {handle, dims[0], dims[1], pTensor, dtp, stream})
1270 createDnMatCallBuilder
1271 .create(loc, rewriter, {dims[0], dims[1], pTensor, dtp, stream})
1275 assert(dims.size() == 1 &&
"Only 1D and 2D tensors are supported");
1276 handle = createDnVecCallBuilder
1277 .create(loc, rewriter, {dims[0], pTensor, dtp, stream})
1280 rewriter.replaceOp(op, {handle, stream});
1284LogicalResult ConvertDestroyDnTensorOpToGpuRuntimeCallPattern::matchAndRewrite(
1285 gpu::DestroyDnTensorOp op, OpAdaptor adaptor,
1286 ConversionPatternRewriter &rewriter)
const {
1290 Location loc = op.getLoc();
1291 auto stream = adaptor.getAsyncDependencies().front();
1292 auto definingOp = op.getDnTensor().
getDefiningOp<gpu::CreateDnTensorOp>();
1293 SmallVector<Value, 4> dims;
1294 for (Value dim : definingOp.getDims()) {
1295 dims.push_back(dim);
1297 if (dims.size() == 2) {
1301 destroyCuSparseLtDnMatBuilder.create(loc, rewriter,
1302 {adaptor.getDnTensor(), stream});
1304 destroyDnMatCallBuilder.create(loc, rewriter,
1305 {adaptor.getDnTensor(), stream});
1308 assert(dims.size() == 1 &&
"Only 1D and 2D tensors are supported");
1309 destroyDnVecCallBuilder.create(loc, rewriter,
1310 {adaptor.getDnTensor(), stream});
1312 rewriter.replaceOp(op, {stream});
1316LogicalResult ConvertCreateCooOpToGpuRuntimeCallPattern::matchAndRewrite(
1317 gpu::CreateCooOp op, OpAdaptor adaptor,
1318 ConversionPatternRewriter &rewriter)
const {
1322 Location loc = op.getLoc();
1323 auto stream = adaptor.getAsyncDependencies().front();
1325 MemRefDescriptor(adaptor.getRowIdxs()).allocatedPtr(rewriter, loc);
1327 MemRefDescriptor(adaptor.getColIdxs()).allocatedPtr(rewriter, loc);
1329 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1331 llvm::cast<MemRefType>(op.getColIdxs().getType()).getElementType();
1333 llvm::cast<MemRefType>(op.getValues().getType()).getElementType();
1337 createCooCallBuilder
1338 .create(loc, rewriter,
1339 {adaptor.getRows(), adaptor.getCols(), adaptor.getNnz(),
1340 pRowIdxs, pColIdxs, pValues, itp, dtp, stream})
1342 rewriter.replaceOp(op, {handle, stream});
1346LogicalResult ConvertCreateCooAoSOpToGpuRuntimeCallPattern::matchAndRewrite(
1347 gpu::CreateCooAoSOp op, OpAdaptor adaptor,
1348 ConversionPatternRewriter &rewriter)
const {
1352 Location loc = op.getLoc();
1353 auto stream = adaptor.getAsyncDependencies().front();
1354 Value pIdxs = MemRefDescriptor(adaptor.getIdxs()).allocatedPtr(rewriter, loc);
1356 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1357 Type iType = llvm::cast<MemRefType>(op.getIdxs().getType()).getElementType();
1359 llvm::cast<MemRefType>(op.getValues().getType()).getElementType();
1363 createCooAoSCallBuilder
1364 .create(loc, rewriter,
1365 {adaptor.getRows(), adaptor.getCols(), adaptor.getNnz(),
1366 pIdxs, pValues, itp, dtp, stream})
1368 rewriter.replaceOp(op, {handle, stream});
1372LogicalResult ConvertCreateCsrOpToGpuRuntimeCallPattern::matchAndRewrite(
1373 gpu::CreateCsrOp op, OpAdaptor adaptor,
1374 ConversionPatternRewriter &rewriter)
const {
1378 Location loc = op.getLoc();
1379 auto stream = adaptor.getAsyncDependencies().front();
1381 MemRefDescriptor(adaptor.getRowPos()).allocatedPtr(rewriter, loc);
1383 MemRefDescriptor(adaptor.getColIdxs()).allocatedPtr(rewriter, loc);
1385 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1387 llvm::cast<MemRefType>(op.getRowPos().getType()).getElementType();
1389 llvm::cast<MemRefType>(op.getColIdxs().getType()).getElementType();
1391 llvm::cast<MemRefType>(op.getValues().getType()).getElementType();
1396 createCsrCallBuilder
1397 .create(loc, rewriter,
1398 {adaptor.getRows(), adaptor.getCols(), adaptor.getNnz(),
1399 pRowPos, pColIdxs, pValues, ptp, itp, dtp, stream})
1401 rewriter.replaceOp(op, {handle, stream});
1405LogicalResult ConvertCreate2To4SpMatOpToGpuRuntimeCallPattern::matchAndRewrite(
1406 gpu::Create2To4SpMatOp op, OpAdaptor adaptor,
1407 ConversionPatternRewriter &rewriter)
const {
1411 Location loc = op.getLoc();
1412 auto stream = adaptor.getAsyncDependencies().front();
1414 MemRefDescriptor(adaptor.getMemref()).allocatedPtr(rewriter, loc);
1416 llvm::cast<MemRefType>(op.getMemref().getType()).getElementType();
1421 Value handle = LLVM::AllocaOp::create(
1422 rewriter, loc, llvmPointerType, llvmInt8Type, handleSz, 16);
1423 handle = LLVM::BitcastOp::create(rewriter, loc, llvmPointerType, handle);
1425 create2To4SpMatCallBuilder
1426 .create(loc, rewriter,
1427 {handle, adaptor.getRows(), adaptor.getCols(), pMat, dtp, stream})
1429 rewriter.replaceOp(op, {handle, stream});
1433LogicalResult ConvertDestroySpMatOpToGpuRuntimeCallPattern::matchAndRewrite(
1434 gpu::DestroySpMatOp op, OpAdaptor adaptor,
1435 ConversionPatternRewriter &rewriter)
const {
1439 Location loc = op.getLoc();
1440 auto stream = adaptor.getAsyncDependencies().front();
1443 destroyCuSparseLtSpMatBuilder.create(loc, rewriter,
1444 {adaptor.getSpmat(), stream});
1447 destroySpMatCallBuilder.create(loc, rewriter, {adaptor.getSpmat(), stream});
1449 rewriter.replaceOp(op, {stream});
1453LogicalResult ConvertSpMVBufferSizeOpToGpuRuntimeCallPattern::matchAndRewrite(
1454 gpu::SpMVBufferSizeOp op, OpAdaptor adaptor,
1455 ConversionPatternRewriter &rewriter)
const {
1459 Location loc = op.getLoc();
1463 auto stream = adaptor.getAsyncDependencies().front();
1464 auto bufferSize = spMVBufferSizeCallBuilder
1465 .create(loc, rewriter,
1466 {modeA, adaptor.getSpmatA(), adaptor.getDnX(),
1467 adaptor.getDnY(), computeType, stream})
1469 rewriter.replaceOp(op, {bufferSize, stream});
1473LogicalResult ConvertSpMVOpToGpuRuntimeCallPattern::matchAndRewrite(
1474 gpu::SpMVOp op, OpAdaptor adaptor,
1475 ConversionPatternRewriter &rewriter)
const {
1479 Location loc = op.getLoc();
1483 auto stream = adaptor.getAsyncDependencies().front();
1485 MemRefDescriptor(adaptor.getBuffer()).allocatedPtr(rewriter, loc);
1486 spMVCallBuilder.create(loc, rewriter,
1487 {modeA, adaptor.getSpmatA(), adaptor.getDnX(),
1488 adaptor.getDnY(), computeType, pBuf, stream});
1489 rewriter.replaceOp(op, {stream});
1493LogicalResult ConvertSpMMBufferSizeOpToGpuRuntimeCallPattern::matchAndRewrite(
1494 gpu::SpMMBufferSizeOp op, OpAdaptor adaptor,
1495 ConversionPatternRewriter &rewriter)
const {
1499 Location loc = op.getLoc();
1502 auto stream = adaptor.getAsyncDependencies().front();
1511 LLVM::AllocaOp::create(rewriter, loc, llvmPointerType, llvmPointerType,
1513 createCuSparseLtSpMMBufferSizeBuilder
1514 .create(loc, rewriter,
1515 {bufferSize, modeA, modeB, adaptor.getSpmatA(),
1516 adaptor.getDnmatB(), adaptor.getDnmatC(), computeType,
1520 auto bufferSizePtr1 = LLVM::GEPOp::create(
1521 rewriter, loc, llvmPointerType, llvmPointerType, bufferSize,
1523 auto bufferSizePtr2 = LLVM::GEPOp::create(
1524 rewriter, loc, llvmPointerType, llvmPointerType, bufferSize,
1527 LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, bufferSize);
1529 LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, bufferSizePtr1);
1531 LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, bufferSizePtr2);
1533 rewriter.replaceOp(op, {bufferSize0, bufferSize1, bufferSize2, stream});
1538 createSpMMBufferSizeCallBuilder
1539 .create(loc, rewriter,
1540 {modeA, modeB, adaptor.getSpmatA(), adaptor.getDnmatB(),
1541 adaptor.getDnmatC(), computeType, stream})
1543 rewriter.replaceOp(op, {bufferSize, stream});
1548LogicalResult ConvertSDDMMBufferSizeOpToGpuRuntimeCallPattern::matchAndRewrite(
1549 gpu::SDDMMBufferSizeOp op, OpAdaptor adaptor,
1550 ConversionPatternRewriter &rewriter)
const {
1554 Location loc = op.getLoc();
1559 auto stream = adaptor.getAsyncDependencies().front();
1561 createSDDMMBufferSizeCallBuilder
1562 .create(loc, rewriter,
1563 {modeA, modeB, adaptor.getDnmatA(), adaptor.getDnmatB(),
1564 adaptor.getSpmatC(), computeType, stream})
1566 rewriter.replaceOp(op, {bufferSize, stream});
1570LogicalResult ConvertSpMMOpToGpuRuntimeCallPattern::matchAndRewrite(
1571 gpu::SpMMOp op, OpAdaptor adaptor,
1572 ConversionPatternRewriter &rewriter)
const {
1576 Location loc = op.getLoc();
1582 auto stream = adaptor.getAsyncDependencies().front();
1586 SmallVector<Value> pBufs;
1587 for (Value buffer : adaptor.getBuffers()) {
1588 Value pBuf = MemRefDescriptor(buffer).allocatedPtr(rewriter, loc);
1589 pBufs.push_back(pBuf);
1591 createCuSparseLtSpMMBuilder.create(
1593 {adaptor.getSpmatA(), adaptor.getDnmatB(), adaptor.getDnmatC(),
1594 pBufs[0], pBufs[1], pBufs[2], stream});
1596 Value pBuf = MemRefDescriptor(adaptor.getBuffers().front())
1597 .allocatedPtr(rewriter, loc);
1598 createSpMMCallBuilder.create(loc, rewriter,
1599 {modeA, modeB, adaptor.getSpmatA(),
1600 adaptor.getDnmatB(), adaptor.getDnmatC(),
1601 computeType, pBuf, stream});
1603 rewriter.replaceOp(op, {stream});
1607template <
typename T>
1609 converter.addConversion([&converter](T) ->
Type {
1610 return LLVM::LLVMPointerType::get(&converter.
getContext());
1614LogicalResult ConvertSDDMMOpToGpuRuntimeCallPattern::matchAndRewrite(
1615 gpu::SDDMMOp op, OpAdaptor adaptor,
1616 ConversionPatternRewriter &rewriter)
const {
1620 Location loc = op.getLoc();
1625 auto stream = adaptor.getAsyncDependencies().front();
1627 MemRefDescriptor(adaptor.getBuffer()).allocatedPtr(rewriter, loc);
1628 createSDDMMCallBuilder.create(loc, rewriter,
1629 {modeA, modeB, adaptor.getDnmatA(),
1630 adaptor.getDnmatB(), adaptor.getSpmatC(),
1631 computeType, pBuf, stream});
1632 rewriter.replaceOp(op, {stream});
1637ConvertSpGEMMCreateDescrOpToGpuRuntimeCallPattern::matchAndRewrite(
1638 gpu::SpGEMMCreateDescrOp op, OpAdaptor adaptor,
1639 ConversionPatternRewriter &rewriter)
const {
1643 Location loc = op.getLoc();
1644 auto stream = adaptor.getAsyncDependencies().front();
1645 Value descr = createSpGEMMCreateDescrBuilder.create(loc, rewriter, {stream})
1647 rewriter.replaceOp(op, {descr, stream});
1652ConvertSpGEMMDestroyDescrOpToGpuRuntimeCallPattern::matchAndRewrite(
1653 gpu::SpGEMMDestroyDescrOp op, OpAdaptor adaptor,
1654 ConversionPatternRewriter &rewriter)
const {
1658 Location loc = op.getLoc();
1659 auto stream = adaptor.getAsyncDependencies().front();
1660 createSpGEMMDestroyDescrBuilder.create(loc, rewriter,
1661 {adaptor.getDesc(), stream});
1662 rewriter.replaceOp(op, {stream});
1667ConvertSpGEMMWorkEstimationOrComputeOpToGpuRuntimeCallPattern::matchAndRewrite(
1668 gpu::SpGEMMWorkEstimationOrComputeOp op, OpAdaptor adaptor,
1669 ConversionPatternRewriter &rewriter)
const {
1673 Location loc = op.getLoc();
1678 auto stream = adaptor.getAsyncDependencies().front();
1681 MemRefDescriptor(adaptor.getBuffer()).allocatedPtr(rewriter, loc);
1682 Value bufferSizeNew;
1684 if (adaptor.getKind() ==
1685 gpu::SpGEMMWorkEstimationOrComputeKind::WORK_ESTIMATION) {
1687 createSpGEMMWorkEstimationBuilder
1688 .create(loc, rewriter,
1689 {adaptor.getDesc(), modeA, modeB, adaptor.getSpmatA(),
1690 adaptor.getSpmatB(), adaptor.getSpmatC(), computeType,
1691 adaptor.getBufferSz(), pBuf, stream})
1695 createSpGEMMComputeBuilder
1696 .create(loc, rewriter,
1697 {adaptor.getDesc(), modeA, modeB, adaptor.getSpmatA(),
1698 adaptor.getSpmatB(), adaptor.getSpmatC(), computeType,
1699 adaptor.getBufferSz(), pBuf, stream})
1702 rewriter.replaceOp(op, {bufferSizeNew, stream});
1706LogicalResult ConvertSpGEMMCopyOpToGpuRuntimeCallPattern::matchAndRewrite(
1707 gpu::SpGEMMCopyOp op, OpAdaptor adaptor,
1708 ConversionPatternRewriter &rewriter)
const {
1712 Location loc = op.getLoc();
1717 auto stream = adaptor.getAsyncDependencies().front();
1718 createSpGEMMCopyBuilder.create(loc, rewriter,
1719 {adaptor.getDesc(), modeA, modeB,
1720 adaptor.getSpmatA(), adaptor.getSpmatB(),
1721 adaptor.getSpmatC(), computeType, stream});
1722 rewriter.replaceOp(op, {stream});
1726LogicalResult ConvertSpMatGetSizeOpToGpuRuntimeCallPattern::matchAndRewrite(
1727 gpu::SpMatGetSizeOp op, OpAdaptor adaptor,
1728 ConversionPatternRewriter &rewriter)
const {
1732 Location loc = op.getLoc();
1733 auto stream = adaptor.getAsyncDependencies().front();
1736 auto buffer = LLVM::AllocaOp::create(rewriter, loc, llvmPointerType,
1737 llvmInt64Type, three, 16);
1739 auto rowsPtr = LLVM::GEPOp::create(
1740 rewriter, loc, llvmPointerType, llvmPointerType, buffer,
1742 auto colsPtr = LLVM::GEPOp::create(
1743 rewriter, loc, llvmPointerType, llvmPointerType, buffer,
1745 auto nnzsPtr = LLVM::GEPOp::create(
1746 rewriter, loc, llvmPointerType, llvmPointerType, buffer,
1748 createSpMatGetSizeBuilder.create(
1749 loc, rewriter, {adaptor.getSpmat(), rowsPtr, colsPtr, nnzsPtr, stream});
1750 auto rows = LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, rowsPtr);
1751 auto cols = LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, colsPtr);
1752 auto nnzs = LLVM::LoadOp::create(rewriter, loc, llvmInt64Type, nnzsPtr);
1754 rewriter.replaceOp(op, {rows, cols, nnzs, stream});
1758LogicalResult ConvertSetCsrPointersOpToGpuRuntimeCallPattern::matchAndRewrite(
1759 gpu::SetCsrPointersOp op, OpAdaptor adaptor,
1760 ConversionPatternRewriter &rewriter)
const {
1764 Location loc = op.getLoc();
1765 auto stream = adaptor.getAsyncDependencies().front();
1767 MemRefDescriptor(adaptor.getPositions()).allocatedPtr(rewriter, loc);
1769 MemRefDescriptor(adaptor.getCoordinates()).allocatedPtr(rewriter, loc);
1771 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1772 createSetCsrPointersBuilder.create(
1773 loc, rewriter, {adaptor.getSpmat(), pPos, pCrd, pVal, stream});
1774 rewriter.replaceOp(op, {stream});
1778LogicalResult ConvertCreateCscOpToGpuRuntimeCallPattern::matchAndRewrite(
1779 gpu::CreateCscOp op, OpAdaptor adaptor,
1780 ConversionPatternRewriter &rewriter)
const {
1784 Location loc = op.getLoc();
1785 auto stream = adaptor.getAsyncDependencies().front();
1787 MemRefDescriptor(adaptor.getColPos()).allocatedPtr(rewriter, loc);
1789 MemRefDescriptor(adaptor.getRowIdxs()).allocatedPtr(rewriter, loc);
1791 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1793 llvm::cast<MemRefType>(op.getColPos().getType()).getElementType();
1795 llvm::cast<MemRefType>(op.getRowIdxs().getType()).getElementType();
1797 llvm::cast<MemRefType>(op.getValues().getType()).getElementType();
1802 createCscCallBuilder
1803 .create(loc, rewriter,
1804 {adaptor.getRows(), adaptor.getCols(), adaptor.getNnz(),
1805 pColPos, pRowIdxs, pValues, ptp, itp, dtp, stream})
1807 rewriter.replaceOp(op, {handle, stream});
1811LogicalResult ConvertCreateBsrOpToGpuRuntimeCallPattern::matchAndRewrite(
1812 gpu::CreateBsrOp op, OpAdaptor adaptor,
1813 ConversionPatternRewriter &rewriter)
const {
1817 Location loc = op.getLoc();
1818 auto stream = adaptor.getAsyncDependencies().front();
1820 MemRefDescriptor(adaptor.getBRowPos()).allocatedPtr(rewriter, loc);
1822 MemRefDescriptor(adaptor.getBColIdxs()).allocatedPtr(rewriter, loc);
1824 MemRefDescriptor(adaptor.getValues()).allocatedPtr(rewriter, loc);
1826 llvm::cast<MemRefType>(op.getBRowPos().getType()).getElementType();
1828 llvm::cast<MemRefType>(op.getBColIdxs().getType()).getElementType();
1830 llvm::cast<MemRefType>(op.getValues().getType()).getElementType();
1835 createBsrCallBuilder
1836 .create(loc, rewriter,
1837 {adaptor.getBrows(), adaptor.getBcols(), adaptor.getBnnz(),
1838 adaptor.getRBlockSize(), adaptor.getCBlockSize(), pRowPos,
1839 pColIdxs, pValues, ptp, itp, dtp, stream})
1841 rewriter.replaceOp(op, {handle, stream});
1847 bool kernelBarePtrCallConv,
bool kernelIntersperseSizeCallConv) {
1857 patterns.
add<ConvertAsyncYieldToGpuRuntimeCallPattern>(converter,
1860 patterns.
add<ConvertAllocOpToGpuRuntimeCallPattern,
1861 ConvertDeallocOpToGpuRuntimeCallPattern,
1862 ConvertHostRegisterOpToGpuRuntimeCallPattern,
1863 ConvertHostUnregisterOpToGpuRuntimeCallPattern,
1864 ConvertMemcpyOpToGpuRuntimeCallPattern,
1865 ConvertMemsetOpToGpuRuntimeCallPattern,
1866 ConvertSetDefaultDeviceOpToGpuRuntimeCallPattern,
1867 ConvertWaitAsyncOpToGpuRuntimeCallPattern,
1868 ConvertWaitOpToGpuRuntimeCallPattern,
1869 ConvertCreateDnTensorOpToGpuRuntimeCallPattern,
1870 ConvertDestroyDnTensorOpToGpuRuntimeCallPattern,
1871 ConvertCreateCooOpToGpuRuntimeCallPattern,
1872 ConvertCreateCooAoSOpToGpuRuntimeCallPattern,
1873 ConvertCreateCsrOpToGpuRuntimeCallPattern,
1874 ConvertCreateCscOpToGpuRuntimeCallPattern,
1875 ConvertCreateBsrOpToGpuRuntimeCallPattern,
1876 ConvertCreate2To4SpMatOpToGpuRuntimeCallPattern,
1877 ConvertDestroySpMatOpToGpuRuntimeCallPattern,
1878 ConvertSpMVBufferSizeOpToGpuRuntimeCallPattern,
1879 ConvertSpMVOpToGpuRuntimeCallPattern,
1880 ConvertSpMMBufferSizeOpToGpuRuntimeCallPattern,
1881 ConvertSDDMMBufferSizeOpToGpuRuntimeCallPattern,
1882 ConvertSpMMOpToGpuRuntimeCallPattern,
1883 ConvertSDDMMOpToGpuRuntimeCallPattern,
1884 ConvertSpGEMMCreateDescrOpToGpuRuntimeCallPattern,
1885 ConvertSpGEMMDestroyDescrOpToGpuRuntimeCallPattern,
1886 ConvertSpGEMMWorkEstimationOrComputeOpToGpuRuntimeCallPattern,
1887 ConvertSpGEMMCopyOpToGpuRuntimeCallPattern,
1888 ConvertSpMatGetSizeOpToGpuRuntimeCallPattern,
1889 ConvertSetCsrPointersOpToGpuRuntimeCallPattern>(converter);
1890 patterns.
add<LegalizeLaunchFuncOpPattern>(converter, kernelBarePtrCallConv,
1891 kernelIntersperseSizeCallConv);
1899struct GPUModuleOpConvertToLLVMInterface
1900 :
public ConvertToLLVMOpInterface::ExternalModel<
1901 GPUModuleOpConvertToLLVMInterface, gpu::GPUModuleOp> {
1903 void getConvertToLLVMConversionAttrs(
1908void GPUModuleOpConvertToLLVMInterface::getConvertToLLVMConversionAttrs(
1909 Operation *op, SmallVectorImpl<ConvertToLLVMAttrInterface> &attrs)
const {
1910 auto module = cast<gpu::GPUModuleOp>(op);
1911 ArrayAttr targetsAttr =
module.getTargetsAttr();
1913 if (!targetsAttr || targetsAttr.size() != 1)
1915 if (
auto patternAttr = dyn_cast<ConvertToLLVMAttrInterface>(targetsAttr[0]))
1916 attrs.push_back(patternAttr);
1921 gpu::GPUModuleOp::attachInterface<GPUModuleOpConvertToLLVMInterface>(*ctx);
static void addOpaquePointerConversion(LLVMTypeConverter &converter)
static int32_t getCuSparseDataTypeFrom(Type type)
static LogicalResult areAllLLVMTypes(Operation *op, ValueRange operands, ConversionPatternRewriter &rewriter)
static Value genConstInt32From(OpBuilder &builder, Location loc, T tValue)
static gpu::Prune2To4SpMatFlag get2To4PruneFlag(Value spMat)
static bool isGpuAsyncTokenType(Value value)
#define DECLARE_CONVERT_OP_TO_GPU_RUNTIME_CALL_PATTERN(op_name)
Generic rewriting rule for operation on sparse matrices.
static int32_t getCuSparseLtDataTypeFrom(Type type)
static bool isDefinedByCallTo(Value value, StringRef functionName)
static Value bitAndAddrspaceCast(Location loc, ConversionPatternRewriter &rewriter, LLVM::LLVMPointerType destinationType, Value sourcePtr, const LLVMTypeConverter &typeConverter)
static bool isSpMMCusparseLtOp(Value op)
static int32_t getCuSparseIndexTypeFrom(Type type)
static bool is2To4Sparsity(Value spMat)
static LogicalResult isAsyncWithOneDependency(ConversionPatternRewriter &rewriter, gpu::AsyncOpInterface op)
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
static llvm::Value * getSizeInBytes(DataLayout &dl, const mlir::Type &type, Operation *clauseOp, llvm::Value *basePointer, llvm::Type *baseType, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::ManagedStatic< PassManagerOptions > options
IntegerType getIntegerType(unsigned width)
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Type getIndexType() const
Gets the MLIR type wrapping the LLVM integer type whose bit width is defined by the used type convert...
static Value createIndexAttrConstant(OpBuilder &builder, Location loc, Type resultType, int64_t value)
Create a constant Op producing a value of resultType from an index-typed integer attribute.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Conversion from types to the LLVM IR dialect.
MLIRContext & getContext() const
Returns the MLIR 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.
std::vector< Dialect * > getLoadedDialects()
Return information about all IR dialects loaded in the context.
Value size(OpBuilder &builder, Location loc, unsigned pos)
Builds IR extracting the pos-th size from the descriptor.
This class helps build Operations.
static OpBuilder atBlockEnd(Block *block, Listener *listener=nullptr)
Create a builder and set the insertion point to after the last operation in the block but still insid...
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
operand_range getOperands()
Returns an iterator on the underlying Value's.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isInteger() const
Return true if this is an integer type (with the specified width).
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...
MLIRContext * getContext() const
Utility to get the associated MLIRContext that this value is defined in.
Type getType() const
Return the type of this value.
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Value createIndexAttrConstant(OpBuilder &builder, Location loc, Type resultType, int64_t value)
Creates an llvm.mlir.constant producing value as resultType, which is expected to be the converted in...
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
void registerConvertGpuToLLVMInterface(DialectRegistry ®istry)
Registers the ConvertToLLVMOpInterface interface on the gpu::GPUModuleOP operation.
void populateVectorTransferLoweringPatterns(RewritePatternSet &patterns, std::optional< unsigned > maxTransferRank=std::nullopt, PatternBenefit benefit=1)
Populate the pattern set with the following patterns:
Include the generated interface declarations.
void populateVectorToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, bool reassociateFPReductions=false, bool force32BitVectorIndices=false, bool useVectorAlignment=false, bool enableGEPInboundsNuw=false)
Collect a set of patterns to convert from the Vector dialect to LLVM.
LogicalResult applyPatternsGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
void populateFinalizeMemRefToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect a set of patterns to convert memory-related operations from the MemRef dialect to the LLVM di...
void populateGpuToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns, bool kernelBarePtrCallConv=false, bool kernelIntersperseSizeCallConv=false)
Collect a set of patterns to convert from the GPU dialect to LLVM and populate converter for gpu type...
void registerConvertToLLVMDependentDialectLoading(DialectRegistry ®istry)
Register the extension that will load dependent dialects for LLVM conversion.
void populateAsyncStructuralTypeConversionsAndLegality(TypeConverter &typeConverter, RewritePatternSet &patterns, ConversionTarget &target)
Populates patterns for async structural type conversions.
LLVM::LLVMFunctionType functionType
LLVM::CallOp create(Location loc, OpBuilder &builder, ArrayRef< Value > arguments) const