[Mlir-commits] [mlir] edfd360 - [mlir][spirv] Add OpConvertPtrToU and OpConvertUToPtr ops
Lei Zhang
llvmlistbot at llvm.org
Wed May 24 21:40:10 PDT 2023
Author: Md Abdullah Shahneous Bari
Date: 2023-05-24T21:35:30-07:00
New Revision: edfd360d78bc610953053cb2ddf491f4f2b8e8c2
URL: https://github.com/llvm/llvm-project/commit/edfd360d78bc610953053cb2ddf491f4f2b8e8c2
DIFF: https://github.com/llvm/llvm-project/commit/edfd360d78bc610953053cb2ddf491f4f2b8e8c2.diff
LOG: [mlir][spirv] Add OpConvertPtrToU and OpConvertUToPtr ops
Add the definitions and necessary verifications of these Ops.
Reviewed By: antiagainst
Differential Revision: https://reviews.llvm.org/D151074
Added:
Modified:
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
mlir/test/Target/SPIRV/cast-ops.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
index 26e47f49af055..87d1040773948 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td
@@ -4267,6 +4267,8 @@ def SPIRV_OC_OpConvertUToF : I32EnumAttrCase<"OpConvertUToF", 112
def SPIRV_OC_OpUConvert : I32EnumAttrCase<"OpUConvert", 113>;
def SPIRV_OC_OpSConvert : I32EnumAttrCase<"OpSConvert", 114>;
def SPIRV_OC_OpFConvert : I32EnumAttrCase<"OpFConvert", 115>;
+def SPIRV_OC_OpConvertPtrToU : I32EnumAttrCase<"OpConvertPtrToU", 117>;
+def SPIRV_OC_OpConvertUToPtr : I32EnumAttrCase<"OpConvertUToPtr", 120>;
def SPIRV_OC_OpPtrCastToGeneric : I32EnumAttrCase<"OpPtrCastToGeneric", 121>;
def SPIRV_OC_OpGenericCastToPtr : I32EnumAttrCase<"OpGenericCastToPtr", 122>;
def SPIRV_OC_OpGenericCastToPtrExplicit : I32EnumAttrCase<"OpGenericCastToPtrExplicit", 123>;
@@ -4447,6 +4449,7 @@ def SPIRV_OpcodeAttr :
SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize, SPIRV_OC_OpConvertFToU,
SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF, SPIRV_OC_OpConvertUToF,
SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert, SPIRV_OC_OpFConvert,
+ SPIRV_OC_OpConvertPtrToU, SPIRV_OC_OpConvertUToPtr,
SPIRV_OC_OpPtrCastToGeneric, SPIRV_OC_OpGenericCastToPtr,
SPIRV_OC_OpGenericCastToPtrExplicit, SPIRV_OC_OpBitcast, SPIRV_OC_OpSNegate,
SPIRV_OC_OpFNegate, SPIRV_OC_OpIAdd, SPIRV_OC_OpFAdd, SPIRV_OC_OpISub,
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
index 1c9eeab689e4b..9109d41303d83 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td
@@ -332,6 +332,118 @@ def SPIRV_UConvertOp : SPIRV_CastOp<"UConvert",
}
// -----
+
+def SPIRV_ConvertPtrToUOp : SPIRV_Op<"ConvertPtrToU", []> {
+ let summary = [{
+ Bit pattern-preserving conversion of a pointer to
+ an unsigned scalar integer of possibly
diff erent bit width.
+ }];
+
+ let description = [{
+ Result Type must be a scalar of integer type, whose Signedness operand is 0.
+
+ Pointer must be a physical pointer type. If the bit width of Pointer is
+ smaller than that of Result Type, the conversion zero extends Pointer.
+ If the bit width of Pointer is larger than that of Result Type,
+ the conversion truncates Pointer.
+
+ For same bit width Pointer and Result Type, this is the same as OpBitcast.
+
+ <!-- End of AutoGen section -->
+
+ ```
+ ptr-to-u-convert-op ::= ssa-id `=` `spirv.ConvertPtrToUOp` ssa-use
+ `:` operand-type `to` result-type
+ ```
+
+ #### Example:
+
+ ```mlir
+ %1 = spirv.ConvertPtrToU %0 : !spirv.ptr<i32, Generic> to i32
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPIRV_V_1_0>,
+ MaxVersion<SPIRV_V_1_6>,
+ Extension<[]>,
+ Capability<[SPIRV_C_Addresses, SPIRV_C_PhysicalStorageBufferAddresses]>
+ ];
+
+ let arguments = (ins
+ SPIRV_AnyPtr:$pointer
+ );
+
+ let results = (outs
+ SPIRV_Integer:$result
+ );
+
+ let assemblyFormat = [{
+ $pointer attr-dict `:` type($pointer) `to` type($result)
+ }];
+
+ let hasVerifier = 1;
+}
+
+
+// -----
+
+def SPIRV_ConvertUToPtrOp : SPIRV_Op<"ConvertUToPtr", [UnsignedOp]> {
+ let summary = [{
+ Bit pattern-preserving conversion of an unsigned scalar integer
+ to a pointer.
+ }];
+
+ let description = [{
+ Result Type must be a physical pointer type.
+
+ Integer Value must be a scalar of integer type, whose Signedness
+ operand is 0. If the bit width of Integer Value is smaller
+ than that of Result Type, the conversion zero extends Integer Value.
+ If the bit width of Integer Value is larger than that of Result Type,
+ the conversion truncates Integer Value.
+
+ For same-width Integer Value and Result Type, this is the same as OpBitcast.
+
+ <!-- End of AutoGen section -->
+
+ ```
+ u-to-ptr-convert-op ::= ssa-id `=` `spirv.ConvertUToPtr` ssa-use
+ `:` operand-type `to` result-type
+ ```
+
+ #### Example:
+
+ ```mlir
+ %1 = spirv.ConvertUToPtr %0 : i32 to !spirv.ptr<i32, Generic>
+ ```
+ }];
+
+ let availability = [
+ MinVersion<SPIRV_V_1_0>,
+ MaxVersion<SPIRV_V_1_6>,
+ Extension<[]>,
+ Capability<[SPIRV_C_Addresses, SPIRV_C_PhysicalStorageBufferAddresses]>
+ ];
+
+ let arguments = (ins
+ SPIRV_Integer:$operand
+ );
+
+ let results = (outs
+ SPIRV_AnyPtr:$result
+ );
+
+ let assemblyFormat = [{
+ $operand attr-dict `:` type($operand) `to` type($result)
+ }];
+
+ let hasVerifier = 1;
+}
+
+// -----
+
+
def SPIRV_PtrCastToGenericOp : SPIRV_Op<"PtrCastToGeneric", [Pure]> {
let summary = "Convert a pointer’s Storage Class to Generic.";
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
index 2828108072352..16737560362d1 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -1557,6 +1557,48 @@ LogicalResult spirv::BitcastOp::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// spirv.ConvertPtrToUOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::ConvertPtrToUOp::verify() {
+ auto operandType = getPointer().getType().cast<spirv::PointerType>();
+ auto resultType = getResult().getType().cast<spirv::ScalarType>();
+ if (!resultType || !resultType.isSignlessInteger())
+ return emitError("result must be a scalar type of unsigned integer");
+ auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
+ if (!spirvModule)
+ return success();
+ auto addressingModel = spirvModule.getAddressingModel();
+ if ((addressingModel == spirv::AddressingModel::Logical) ||
+ (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
+ operandType.getStorageClass() !=
+ spirv::StorageClass::PhysicalStorageBuffer))
+ return emitError("operand must be a physical pointer");
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.ConvertUToPtrOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult spirv::ConvertUToPtrOp::verify() {
+ auto operandType = getOperand().getType().cast<spirv::ScalarType>();
+ auto resultType = getResult().getType().cast<spirv::PointerType>();
+ if (!operandType || !operandType.isSignlessInteger())
+ return emitError("result must be a scalar type of unsigned integer");
+ auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
+ if (!spirvModule)
+ return success();
+ auto addressingModel = spirvModule.getAddressingModel();
+ if ((addressingModel == spirv::AddressingModel::Logical) ||
+ (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
+ resultType.getStorageClass() !=
+ spirv::StorageClass::PhysicalStorageBuffer))
+ return emitError("result must be a physical pointer");
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// spirv.PtrCastToGenericOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
index 4a7bd603b14dd..cfbbf9494a00e 100644
--- a/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir
@@ -363,3 +363,109 @@ func.func @genericcasttoptrexplicit4(%arg0 : !spirv.ptr<f32, Generic>) {
%0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<vector<2xi32>, Workgroup>
return
}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ConvertPtrToU
+//===----------------------------------------------------------------------===//
+spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
+ spirv.func @covert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
+ spirv.Return
+ }
+ spirv.func @covert_ptr_to_u_truncate(%arg0 : !spirv.ptr<i64, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i64, Generic> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i64, Generic> to i32
+ spirv.Return
+ }
+ spirv.func @covert_ptr_to_u_extend(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i64
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i64
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_ptr_to_u_PhysicalStorageBuffer(%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_ptr_to_u_fail(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // expected-error @+1 {{operand must be a physical pointer}}
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
+ spirv.func @covert_ptr_to_u_fail_2(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // expected-error @+1 {{operand must be a physical pointer}}
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
+ spirv.Return
+ }
+}
+
+// -----
+
+//===----------------------------------------------------------------------===//
+// spirv.ConvertUToPtr
+//===----------------------------------------------------------------------===//
+spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
+ spirv.func @covert_u_to_ptr(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+ spirv.func @covert_u_to_ptr_truncate(%arg0 : i64) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i64 to !spirv.ptr<i32, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i64 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+ spirv.func @covert_u_to_ptr_extend(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i64, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i64, Generic>
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_u_to_ptr_PhysicalStorageBuffer(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_u_to_ptr_fail(%arg0 : i32) "None" {
+ // expected-error @+1 {{result must be a physical pointer}}
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
+ spirv.func @covert_u_to_ptr_fail_2(%arg0 : i32) "None" {
+ // expected-error @+1 {{result must be a physical pointer}}
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+}
diff --git a/mlir/test/Target/SPIRV/cast-ops.mlir b/mlir/test/Target/SPIRV/cast-ops.mlir
index bad7c679950cb..7fe0969497c3e 100644
--- a/mlir/test/Target/SPIRV/cast-ops.mlir
+++ b/mlir/test/Target/SPIRV/cast-ops.mlir
@@ -91,3 +91,63 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Kernel], []> {
spirv.Return
}
}
+
+// -----
+
+spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
+ spirv.func @covert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
+ spirv.Return
+ }
+ spirv.func @covert_ptr_to_u_truncate(%arg0 : !spirv.ptr<i64, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i64, Generic> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i64, Generic> to i32
+ spirv.Return
+ }
+ spirv.func @covert_ptr_to_u_extend(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i64
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i64
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_ptr_to_u_PhysicalStorageBuffer(%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer>) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
+ %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
+ spirv.func @covert_u_to_ptr(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+ spirv.func @covert_u_to_ptr_truncate(%arg0 : i64) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i64 to !spirv.ptr<i32, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i64 to !spirv.ptr<i32, Generic>
+ spirv.Return
+ }
+ spirv.func @covert_u_to_ptr_extend(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i64, Generic>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i64, Generic>
+ spirv.Return
+ }
+}
+
+// -----
+
+spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
+ spirv.func @covert_u_to_ptr_PhysicalStorageBuffer(%arg0 : i32) "None" {
+ // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
+ %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
+ spirv.Return
+ }
+}
More information about the Mlir-commits
mailing list