From c1292a3d84732be60fdf78e146864b296d1dba96 Mon Sep 17 00:00:00 2001 From: Guray Ozen Date: Thu, 7 Aug 2025 14:13:54 +0000 Subject: [PATCH 1/3] [MLIR][NVVM] Add pmevent Add nvvm.pmevent Op that Triggers one or more of a fixed number of performance monitor events, with event index or mask specified by immediate operand. [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-pmevent) --- mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td | 38 +++++++++++++++++++ mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp | 18 +++++++++ .../Conversion/NVVMToLLVM/nvvm-to-llvm.mlir | 14 +++++++ mlir/test/Target/LLVMIR/nvvmir-invalid.mlir | 19 ++++++++++ mlir/test/Target/LLVMIR/nvvmir.mlir | 11 ++++++ 5 files changed, 100 insertions(+) diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td index 30df3b739e5ca..df94f95ced262 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td @@ -401,6 +401,44 @@ def NVVM_ReduxOp : }]; } +//===----------------------------------------------------------------------===// +// NVVM Performance Monitor events +//===----------------------------------------------------------------------===// + +def NVVM_PMEventOp : NVVM_PTXBuilder_Op<"pmevent">, + Arguments<(ins OptionalAttr:$maskedEventId, + OptionalAttr:$eventId)> { + let summary = "Trigger one or more Performance Monitor events."; + + let description = [{ + Triggers one or more of a fixed number of performance monitor events, with + event index or mask specified by immediate operand. + + Without `mask` it triggers a single performance monitor event indexed by + immediate operand a, in the range 0..15. + + With `mask` it triggers one or more of the performance monitor events. Each + bit in the 16-bit immediate operand a controls an event. + + [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-pmevent) + }]; + + string llvmBuilder = [{ + llvm::Value *mId = builder.getInt16(* $maskedEventId); + createIntrinsicCall(builder, llvm::Intrinsic::nvvm_pm_event_mask, {mId}); + }]; + + let assemblyFormat = "attr-dict (`id` `=` $eventId^)? (`mask` `=` $maskedEventId^)?"; + + let extraClassDeclaration = [{ + bool hasIntrinsic() { if(getEventId()) return false; return true; } + }]; + let extraClassDefinition = [{ + std::string $cppClass::getPtx() { return std::string("pmevent %0;"); } + }]; + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // NVVM Split arrive/wait barrier //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp index e0977f5b616c1..ab0b0d3f754fe 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp @@ -189,6 +189,24 @@ LogicalResult BulkStoreOp::verify() { return success(); } +LogicalResult PMEventOp::verify() { + if (!getMaskedEventId() && !getEventId()) { + return emitOpError() << "either `id` or `mask` must be set"; + } + + if (getMaskedEventId() && getEventId()) { + return emitOpError() << "`id` and `mask` cannot be set at the same time"; + } + + if (getEventId()) { + if (getEventId() < 0 || getEventId() > 15) { + return emitOpError() << "`id` must be between 0 and 15"; + } + } + + return llvm::success(); +} + // Given the element type of an operand and whether or not it is an accumulator, // this function returns the PTX type (`NVVM::MMATypes`) that corresponds to the // operand's element type. diff --git a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir index 580b09d70c480..e50576722e38c 100644 --- a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir +++ b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir @@ -681,3 +681,17 @@ llvm.func @ex2(%input : f32, %pred : i1) { %1 = nvvm.inline_ptx "ex2.approx.ftz.f32 $0, $1;" (%input), predicate = %pred : f32, i1 -> f32 llvm.return } + +// ----- + +// CHECK-LABEL: @nvvm_pmevent +llvm.func @nvvm_pmevent() { + // CHECK: %[[S0:.+]] = llvm.mlir.constant(10 : i32) : i32 + // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "pmevent $0;", "n" %[[S0]] : (i32) -> () + + nvvm.pmevent id = 10 + // CHECK: %[[S1:.+]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "pmevent $0;", "n" %[[S1]] : (i32) -> () + nvvm.pmevent id = 4 + llvm.return +} diff --git a/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir b/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir index 85478cc160064..991222ca29127 100644 --- a/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir +++ b/mlir/test/Target/LLVMIR/nvvmir-invalid.mlir @@ -1,5 +1,24 @@ // RUN: mlir-translate -verify-diagnostics -split-input-file -mlir-to-llvmir %s +llvm.func @pmevent_no_id() { + // expected-error @below {{either `id` or `mask` must be set}} + nvvm.pmevent +} + +// ----- + +llvm.func @pmevent_bigger15() { + // expected-error @below {{`id` must be between 0 and 15}} + nvvm.pmevent id = 141 +} + +// ----- + +llvm.func @pmevent_many_ids() { + // expected-error @below {{`id` and `mask` cannot be set at the same time}} + nvvm.pmevent id = 1 mask = 1 +} + // ----- llvm.func @kernel_func(%numberOfThreads : i32) { diff --git a/mlir/test/Target/LLVMIR/nvvmir.mlir b/mlir/test/Target/LLVMIR/nvvmir.mlir index 5c2cfa4683104..1600216e95c87 100644 --- a/mlir/test/Target/LLVMIR/nvvmir.mlir +++ b/mlir/test/Target/LLVMIR/nvvmir.mlir @@ -918,3 +918,14 @@ llvm.func @nvvm_dot_accumulate_2way(%a: vector<2xi16>, %b: vector<4xi8>, %c: i32 %7 = nvvm.dot.accumulate.2way %a , %b , %c {b_hi = true}: vector<2xi16>, vector<4xi8> llvm.return } + +// ----- + +// CHECK-LABEL: @nvvm_pmevent +llvm.func @nvvm_pmevent() { + // CHECK: call void @llvm.nvvm.pm.event.mask(i16 15000) + nvvm.pmevent mask = 15000 + // CHECK: call void @llvm.nvvm.pm.event.mask(i16 4) + nvvm.pmevent mask = 4 + llvm.return +} \ No newline at end of file From 164e5efcdf9fe63e3da6b7fc76063b365ef4a19e Mon Sep 17 00:00:00 2001 From: Guray Ozen Date: Fri, 8 Aug 2025 07:30:00 +0000 Subject: [PATCH 2/3] fx --- mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td | 4 ++-- mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td index df94f95ced262..8d507268a3a15 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td @@ -418,7 +418,7 @@ def NVVM_PMEventOp : NVVM_PTXBuilder_Op<"pmevent">, immediate operand a, in the range 0..15. With `mask` it triggers one or more of the performance monitor events. Each - bit in the 16-bit immediate operand a controls an event. + bit in the 16-bit immediate operand controls an event. [For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#miscellaneous-instructions-pmevent) }]; @@ -431,7 +431,7 @@ def NVVM_PMEventOp : NVVM_PTXBuilder_Op<"pmevent">, let assemblyFormat = "attr-dict (`id` `=` $eventId^)? (`mask` `=` $maskedEventId^)?"; let extraClassDeclaration = [{ - bool hasIntrinsic() { if(getEventId()) return false; return true; } + bool hasIntrinsic() { return !getEventId(); } }]; let extraClassDefinition = [{ std::string $cppClass::getPtx() { return std::string("pmevent %0;"); } diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp index ab0b0d3f754fe..7ad429efc9fad 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp @@ -190,16 +190,18 @@ LogicalResult BulkStoreOp::verify() { } LogicalResult PMEventOp::verify() { - if (!getMaskedEventId() && !getEventId()) { + auto eventId = getEventId(); + auto maskedEventId = getMaskedEventId(); + if (!maskedEventId && !eventId) { return emitOpError() << "either `id` or `mask` must be set"; } - if (getMaskedEventId() && getEventId()) { + if (maskedEventId && eventId) { return emitOpError() << "`id` and `mask` cannot be set at the same time"; } - if (getEventId()) { - if (getEventId() < 0 || getEventId() > 15) { + if (eventId) { + if (eventId < 0 || eventId > 15) { return emitOpError() << "`id` must be between 0 and 15"; } } From 971539d4941adf93d8cf0d82229e908a18e04d6f Mon Sep 17 00:00:00 2001 From: Guray Ozen Date: Fri, 8 Aug 2025 12:39:58 +0200 Subject: [PATCH 3/3] Update nvvmir.mlir --- mlir/test/Target/LLVMIR/nvvmir.mlir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/test/Target/LLVMIR/nvvmir.mlir b/mlir/test/Target/LLVMIR/nvvmir.mlir index 1600216e95c87..b1800e82f3cd8 100644 --- a/mlir/test/Target/LLVMIR/nvvmir.mlir +++ b/mlir/test/Target/LLVMIR/nvvmir.mlir @@ -928,4 +928,4 @@ llvm.func @nvvm_pmevent() { // CHECK: call void @llvm.nvvm.pm.event.mask(i16 4) nvvm.pmevent mask = 4 llvm.return -} \ No newline at end of file +}