Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -4035,6 +4035,116 @@ def NVVM_DotAccumulate2WayOp : NVVM_Op<"dot.accumulate.2way"> {
}];
}

//===----------------------------------------------------------------------===//
// NVVM clusterlaunchcontrol Ops.
//===----------------------------------------------------------------------===//

def NVVM_ClusterLaunchControlTryCancelOp
: NVVM_Op<"clusterlaunchcontrol.try.cancel", [NVVMRequiresSM<100>]> {
let summary = "Request atomically canceling the launch of a cluster that has not started running yet";
let description = [{
`clusterlaunchcontrol.try.cancel` requests atomically canceling the launch
of a cluster that has not started running yet. It asynchronously writes an
opaque response to shared memory indicating whether the operation succeeded
or failed.

Operand `smemAddress` specifies the naturally aligned address of the
16-byte wide shared memory location where the request's response is written.

Operand `mbarrier` specifies the mbarrier object used to track the
completion of the asynchronous operation.

If `multicast` is specified, the response is asynchronously written to the
corresponding local shared memory location (specifed by `addr`) of each CTA
in the requesting cluster.

[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-clusterlaunchcontrol-try-cancel)
}];

let arguments = (ins UnitAttr:$multicast,
LLVM_PointerShared: $smemAddress,
LLVM_PointerShared: $mbarrier);

let assemblyFormat = "(`multicast` $multicast^ `,`)? $smemAddress `,` $mbarrier attr-dict";

let extraClassDeclaration = [{
static mlir::NVVM::IDArgPair
getIntrinsicIDAndArgs(Operation &op, LLVM::ModuleTranslation &mt,
llvm::IRBuilderBase &builder);
}];

string llvmBuilder = [{
auto [id, args] =
NVVM::ClusterLaunchControlTryCancelOp::getIntrinsicIDAndArgs(
*op, moduleTranslation, builder);
createIntrinsicCall(builder, id, args);
}];
}

def ClusterLaunchControlIsCanceled
: I32EnumCase<"IS_CANCELED", 0, "is_canceled">;
def ClusterLaunchControlGetFirstCTAIDX
: I32EnumCase<"GET_FIRST_CTA_ID_X", 1, "get_first_cta_id_x">;
def ClusterLaunchControlGetFirstCTAIDY
: I32EnumCase<"GET_FIRST_CTA_ID_Y", 2, "get_first_cta_id_y">;
def ClusterLaunchControlGetFirstCTAIDZ
: I32EnumCase<"GET_FIRST_CTA_ID_Z", 3, "get_first_cta_id_z">;

def ClusterLaunchControlQueryType
: I32Enum<"ClusterLaunchControlQueryType",
"NVVM ClusterLaunchControlQueryType",
[ClusterLaunchControlIsCanceled, ClusterLaunchControlGetFirstCTAIDX,
ClusterLaunchControlGetFirstCTAIDY, ClusterLaunchControlGetFirstCTAIDZ]> {
let cppNamespace = "::mlir::NVVM";
}

def ClusterLaunchControlQueryTypeAttr
: EnumAttr<NVVM_Dialect,
ClusterLaunchControlQueryType, "cluster_launch_control_query_type"> {
let assemblyFormat = "$value";
}

def NVVM_ClusterLaunchControlQueryCancelOp
: NVVM_Op<"clusterlaunchcontrol.query.cancel", [NVVMRequiresSM<100>]> {
let summary = "Query the response of a clusterlaunchcontrol.try.cancel operation";
let description = [{
`clusterlaunchcontrol.query.cancel` queries the response of a
`clusterlaunchcontrol.try.cancel` operation specified by operand
`try_cancel_response`.

Operand `query_type` specifies the type of query to perform and can be one
of the following:
- `is_canceled` : Returns true if the try cancel request succeeded,
and false otherwise.
- `get_first_cta_id_{x/y/z}` : Returns the x, y, or z coordinate of the
first CTA in the canceled cluster. Behaviour is defined only if the try
cancel request succeeded.

[For more information, see PTX ISA](https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-clusterlaunchcontrol-query-cancel)
}];

let arguments = (ins ClusterLaunchControlQueryTypeAttr:$query_type,
I128:$try_cancel_response);
let results = (outs AnyTypeOf<[I1, I32]>:$res);

let assemblyFormat = "`query` `=` $query_type `,` $try_cancel_response attr-dict `:` type($res)";

let hasVerifier = 1;

let extraClassDeclaration = [{
static mlir::NVVM::IDArgPair
getIntrinsicIDAndArgs(Operation &op, LLVM::ModuleTranslation &mt,
llvm::IRBuilderBase &builder);
}];

string llvmBuilder = [{
auto [id, args] =
NVVM::ClusterLaunchControlQueryCancelOp::getIntrinsicIDAndArgs(
*op, moduleTranslation, builder);
$res = createIntrinsicCall(builder, id, args);
}];
}

//===----------------------------------------------------------------------===//
// NVVM target attribute.
//===----------------------------------------------------------------------===//
Expand Down
63 changes: 63 additions & 0 deletions mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,24 @@ LogicalResult NVVM::PrefetchOp::verify() {
return success();
}

LogicalResult NVVM::ClusterLaunchControlQueryCancelOp::verify() {
switch (getQueryType()) {
case NVVM::ClusterLaunchControlQueryType::IS_CANCELED:
if (!getType().isInteger(1))
return emitOpError("is_canceled query type returns an i1");
break;
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_X:
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_Y:
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_Z:
if (!getType().isInteger(32)) {
return emitOpError("get_first_cta_id_x, get_first_cta_id_y, "
"get_first_cta_id_z query types return an i32");
}
break;
}
return success();
}

/// Packs the given `field` into the `result`.
/// The `result` is 64-bits and each `field` can be 32-bits or narrower.
static llvm::Value *
Expand Down Expand Up @@ -2088,6 +2106,51 @@ bool NVVM::InlinePtxOp::getAsmValues(
return false; // No manual mapping needed
}

NVVM::IDArgPair ClusterLaunchControlTryCancelOp::getIntrinsicIDAndArgs(
Operation &op, LLVM::ModuleTranslation &mt, llvm::IRBuilderBase &builder) {
auto curOp = cast<NVVM::ClusterLaunchControlTryCancelOp>(op);
llvm::SmallVector<llvm::Value *> args;
args.push_back(mt.lookupValue(curOp.getSmemAddress()));
args.push_back(mt.lookupValue(curOp.getMbarrier()));

llvm::Intrinsic::ID intrinsicID =
curOp.getMulticast()
? llvm::Intrinsic::
nvvm_clusterlaunchcontrol_try_cancel_async_multicast_shared
: llvm::Intrinsic::nvvm_clusterlaunchcontrol_try_cancel_async_shared;

return {intrinsicID, args};
}

NVVM::IDArgPair ClusterLaunchControlQueryCancelOp::getIntrinsicIDAndArgs(
Operation &op, LLVM::ModuleTranslation &mt, llvm::IRBuilderBase &builder) {
auto curOp = cast<NVVM::ClusterLaunchControlQueryCancelOp>(op);
llvm::SmallVector<llvm::Value *> args;
args.push_back(mt.lookupValue(curOp.getTryCancelResponse()));

llvm::Intrinsic::ID intrinsicID;

switch (curOp.getQueryType()) {
case NVVM::ClusterLaunchControlQueryType::IS_CANCELED:
intrinsicID =
llvm::Intrinsic::nvvm_clusterlaunchcontrol_query_cancel_is_canceled;
break;
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_X:
intrinsicID = llvm::Intrinsic::
nvvm_clusterlaunchcontrol_query_cancel_get_first_ctaid_x;
break;
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_Y:
intrinsicID = llvm::Intrinsic::
nvvm_clusterlaunchcontrol_query_cancel_get_first_ctaid_y;
break;
case NVVM::ClusterLaunchControlQueryType::GET_FIRST_CTA_ID_Z:
intrinsicID = llvm::Intrinsic::
nvvm_clusterlaunchcontrol_query_cancel_get_first_ctaid_z;
break;
}
return {intrinsicID, args};
}

//===----------------------------------------------------------------------===//
// NVVMDialect initialization, type parsing, and registration.
//===----------------------------------------------------------------------===//
Expand Down
55 changes: 55 additions & 0 deletions mlir/test/Target/LLVMIR/nvvm/clusterlaunchcontrol.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s

llvm.func @clusterlaunchcontrol_try_cancel(%addr: !llvm.ptr<3>, %mbar: !llvm.ptr<3>) {
// CHECK-LABEL: define void @clusterlaunchcontrol_try_cancel(ptr addrspace(3) %0, ptr addrspace(3) %1) {
// CHECK-NEXT: call void @llvm.nvvm.clusterlaunchcontrol.try_cancel.async.shared(ptr addrspace(3) %0, ptr addrspace(3) %1)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
nvvm.clusterlaunchcontrol.try.cancel %addr, %mbar
llvm.return
}

llvm.func @clusterlaunchcontrol_try_cancel_multicast(%addr: !llvm.ptr<3>, %mbar: !llvm.ptr<3>) {
// CHECK-LABEL: define void @clusterlaunchcontrol_try_cancel_multicast(ptr addrspace(3) %0, ptr addrspace(3) %1) {
// CHECK-NEXT: call void @llvm.nvvm.clusterlaunchcontrol.try_cancel.async.multicast.shared(ptr addrspace(3) %0, ptr addrspace(3) %1)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
nvvm.clusterlaunchcontrol.try.cancel multicast, %addr, %mbar
llvm.return
}

llvm.func @clusterlaunchcontrol_query_cancel_is_canceled(%try_cancel_response: i128) {
// CHECK-LABEL: define void @clusterlaunchcontrol_query_cancel_is_canceled(i128 %0) {
// CHECK-NEXT: %2 = call i1 @llvm.nvvm.clusterlaunchcontrol.query_cancel.is_canceled(i128 %0)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
%res = nvvm.clusterlaunchcontrol.query.cancel query = is_canceled, %try_cancel_response : i1
llvm.return
}

llvm.func @clusterlaunchcontrol_query_cancel_get_first_cta_id_x(%try_cancel_response: i128) {
// CHECK-LABEL: define void @clusterlaunchcontrol_query_cancel_get_first_cta_id_x(i128 %0) {
// CHECK-NEXT: %2 = call i32 @llvm.nvvm.clusterlaunchcontrol.query_cancel.get_first_ctaid.x(i128 %0)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
%res = nvvm.clusterlaunchcontrol.query.cancel query = get_first_cta_id_x, %try_cancel_response : i32
llvm.return
}

llvm.func @clusterlaunchcontrol_query_cancel_get_first_cta_id_y(%try_cancel_response: i128) {
// CHECK-LABEL: define void @clusterlaunchcontrol_query_cancel_get_first_cta_id_y(i128 %0) {
// CHECK-NEXT: %2 = call i32 @llvm.nvvm.clusterlaunchcontrol.query_cancel.get_first_ctaid.y(i128 %0)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
%res = nvvm.clusterlaunchcontrol.query.cancel query = get_first_cta_id_y, %try_cancel_response : i32
llvm.return
}

llvm.func @clusterlaunchcontrol_query_cancel_get_first_cta_id_z(%try_cancel_response: i128) {
// CHECK-LABEL: define void @clusterlaunchcontrol_query_cancel_get_first_cta_id_z(i128 %0) {
// CHECK-NEXT: %2 = call i32 @llvm.nvvm.clusterlaunchcontrol.query_cancel.get_first_ctaid.z(i128 %0)
// CHECK-NEXT: ret void
// CHECK-NEXT: }
%res = nvvm.clusterlaunchcontrol.query.cancel query = get_first_cta_id_z, %try_cancel_response : i32
llvm.return
}
16 changes: 16 additions & 0 deletions mlir/test/Target/LLVMIR/nvvmir-invalid.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,19 @@ llvm.func @nanosleep() {
nvvm.nanosleep 100000000000000
llvm.return
}

// -----

llvm.func @clusterlaunchcontrol_query_cancel_is_canceled_invalid_return_type(%try_cancel_response: i128) {
// expected-error@+1 {{'nvvm.clusterlaunchcontrol.query.cancel' op is_canceled query type returns an i1}}
%res = nvvm.clusterlaunchcontrol.query.cancel query = is_canceled, %try_cancel_response : i32
llvm.return
}

// -----

llvm.func @clusterlaunchcontrol_query_cancel_get_first_cta_id_invalid_return_type(%try_cancel_response: i128) {
// expected-error@+1 {{'nvvm.clusterlaunchcontrol.query.cancel' op get_first_cta_id_x, get_first_cta_id_y, get_first_cta_id_z query types return an i32}}
%res = nvvm.clusterlaunchcontrol.query.cancel query = get_first_cta_id_x, %try_cancel_response : i1
llvm.return
}