Skip to content

Commit edfd360

Browse files
mshahneoantiagainst
authored andcommitted
[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
1 parent 9289b64 commit edfd360

File tree

5 files changed

+323
-0
lines changed

5 files changed

+323
-0
lines changed

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBase.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4267,6 +4267,8 @@ def SPIRV_OC_OpConvertUToF : I32EnumAttrCase<"OpConvertUToF", 112
42674267
def SPIRV_OC_OpUConvert : I32EnumAttrCase<"OpUConvert", 113>;
42684268
def SPIRV_OC_OpSConvert : I32EnumAttrCase<"OpSConvert", 114>;
42694269
def SPIRV_OC_OpFConvert : I32EnumAttrCase<"OpFConvert", 115>;
4270+
def SPIRV_OC_OpConvertPtrToU : I32EnumAttrCase<"OpConvertPtrToU", 117>;
4271+
def SPIRV_OC_OpConvertUToPtr : I32EnumAttrCase<"OpConvertUToPtr", 120>;
42704272
def SPIRV_OC_OpPtrCastToGeneric : I32EnumAttrCase<"OpPtrCastToGeneric", 121>;
42714273
def SPIRV_OC_OpGenericCastToPtr : I32EnumAttrCase<"OpGenericCastToPtr", 122>;
42724274
def SPIRV_OC_OpGenericCastToPtrExplicit : I32EnumAttrCase<"OpGenericCastToPtrExplicit", 123>;
@@ -4447,6 +4449,7 @@ def SPIRV_OpcodeAttr :
44474449
SPIRV_OC_OpImage, SPIRV_OC_OpImageQuerySize, SPIRV_OC_OpConvertFToU,
44484450
SPIRV_OC_OpConvertFToS, SPIRV_OC_OpConvertSToF, SPIRV_OC_OpConvertUToF,
44494451
SPIRV_OC_OpUConvert, SPIRV_OC_OpSConvert, SPIRV_OC_OpFConvert,
4452+
SPIRV_OC_OpConvertPtrToU, SPIRV_OC_OpConvertUToPtr,
44504453
SPIRV_OC_OpPtrCastToGeneric, SPIRV_OC_OpGenericCastToPtr,
44514454
SPIRV_OC_OpGenericCastToPtrExplicit, SPIRV_OC_OpBitcast, SPIRV_OC_OpSNegate,
44524455
SPIRV_OC_OpFNegate, SPIRV_OC_OpIAdd, SPIRV_OC_OpFAdd, SPIRV_OC_OpISub,

mlir/include/mlir/Dialect/SPIRV/IR/SPIRVCastOps.td

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,118 @@ def SPIRV_UConvertOp : SPIRV_CastOp<"UConvert",
332332
}
333333

334334
// -----
335+
336+
def SPIRV_ConvertPtrToUOp : SPIRV_Op<"ConvertPtrToU", []> {
337+
let summary = [{
338+
Bit pattern-preserving conversion of a pointer to
339+
an unsigned scalar integer of possibly different bit width.
340+
}];
341+
342+
let description = [{
343+
Result Type must be a scalar of integer type, whose Signedness operand is 0.
344+
345+
Pointer must be a physical pointer type. If the bit width of Pointer is
346+
smaller than that of Result Type, the conversion zero extends Pointer.
347+
If the bit width of Pointer is larger than that of Result Type,
348+
the conversion truncates Pointer.
349+
350+
For same bit width Pointer and Result Type, this is the same as OpBitcast.
351+
352+
<!-- End of AutoGen section -->
353+
354+
```
355+
ptr-to-u-convert-op ::= ssa-id `=` `spirv.ConvertPtrToUOp` ssa-use
356+
`:` operand-type `to` result-type
357+
```
358+
359+
#### Example:
360+
361+
```mlir
362+
%1 = spirv.ConvertPtrToU %0 : !spirv.ptr<i32, Generic> to i32
363+
```
364+
}];
365+
366+
let availability = [
367+
MinVersion<SPIRV_V_1_0>,
368+
MaxVersion<SPIRV_V_1_6>,
369+
Extension<[]>,
370+
Capability<[SPIRV_C_Addresses, SPIRV_C_PhysicalStorageBufferAddresses]>
371+
];
372+
373+
let arguments = (ins
374+
SPIRV_AnyPtr:$pointer
375+
);
376+
377+
let results = (outs
378+
SPIRV_Integer:$result
379+
);
380+
381+
let assemblyFormat = [{
382+
$pointer attr-dict `:` type($pointer) `to` type($result)
383+
}];
384+
385+
let hasVerifier = 1;
386+
}
387+
388+
389+
// -----
390+
391+
def SPIRV_ConvertUToPtrOp : SPIRV_Op<"ConvertUToPtr", [UnsignedOp]> {
392+
let summary = [{
393+
Bit pattern-preserving conversion of an unsigned scalar integer
394+
to a pointer.
395+
}];
396+
397+
let description = [{
398+
Result Type must be a physical pointer type.
399+
400+
Integer Value must be a scalar of integer type, whose Signedness
401+
operand is 0. If the bit width of Integer Value is smaller
402+
than that of Result Type, the conversion zero extends Integer Value.
403+
If the bit width of Integer Value is larger than that of Result Type,
404+
the conversion truncates Integer Value.
405+
406+
For same-width Integer Value and Result Type, this is the same as OpBitcast.
407+
408+
<!-- End of AutoGen section -->
409+
410+
```
411+
u-to-ptr-convert-op ::= ssa-id `=` `spirv.ConvertUToPtr` ssa-use
412+
`:` operand-type `to` result-type
413+
```
414+
415+
#### Example:
416+
417+
```mlir
418+
%1 = spirv.ConvertUToPtr %0 : i32 to !spirv.ptr<i32, Generic>
419+
```
420+
}];
421+
422+
let availability = [
423+
MinVersion<SPIRV_V_1_0>,
424+
MaxVersion<SPIRV_V_1_6>,
425+
Extension<[]>,
426+
Capability<[SPIRV_C_Addresses, SPIRV_C_PhysicalStorageBufferAddresses]>
427+
];
428+
429+
let arguments = (ins
430+
SPIRV_Integer:$operand
431+
);
432+
433+
let results = (outs
434+
SPIRV_AnyPtr:$result
435+
);
436+
437+
let assemblyFormat = [{
438+
$operand attr-dict `:` type($operand) `to` type($result)
439+
}];
440+
441+
let hasVerifier = 1;
442+
}
443+
444+
// -----
445+
446+
335447
def SPIRV_PtrCastToGenericOp : SPIRV_Op<"PtrCastToGeneric", [Pure]> {
336448
let summary = "Convert a pointer’s Storage Class to Generic.";
337449

mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,48 @@ LogicalResult spirv::BitcastOp::verify() {
15571557
return success();
15581558
}
15591559

1560+
//===----------------------------------------------------------------------===//
1561+
// spirv.ConvertPtrToUOp
1562+
//===----------------------------------------------------------------------===//
1563+
1564+
LogicalResult spirv::ConvertPtrToUOp::verify() {
1565+
auto operandType = getPointer().getType().cast<spirv::PointerType>();
1566+
auto resultType = getResult().getType().cast<spirv::ScalarType>();
1567+
if (!resultType || !resultType.isSignlessInteger())
1568+
return emitError("result must be a scalar type of unsigned integer");
1569+
auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
1570+
if (!spirvModule)
1571+
return success();
1572+
auto addressingModel = spirvModule.getAddressingModel();
1573+
if ((addressingModel == spirv::AddressingModel::Logical) ||
1574+
(addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
1575+
operandType.getStorageClass() !=
1576+
spirv::StorageClass::PhysicalStorageBuffer))
1577+
return emitError("operand must be a physical pointer");
1578+
return success();
1579+
}
1580+
1581+
//===----------------------------------------------------------------------===//
1582+
// spirv.ConvertUToPtrOp
1583+
//===----------------------------------------------------------------------===//
1584+
1585+
LogicalResult spirv::ConvertUToPtrOp::verify() {
1586+
auto operandType = getOperand().getType().cast<spirv::ScalarType>();
1587+
auto resultType = getResult().getType().cast<spirv::PointerType>();
1588+
if (!operandType || !operandType.isSignlessInteger())
1589+
return emitError("result must be a scalar type of unsigned integer");
1590+
auto spirvModule = (*this)->getParentOfType<spirv::ModuleOp>();
1591+
if (!spirvModule)
1592+
return success();
1593+
auto addressingModel = spirvModule.getAddressingModel();
1594+
if ((addressingModel == spirv::AddressingModel::Logical) ||
1595+
(addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64 &&
1596+
resultType.getStorageClass() !=
1597+
spirv::StorageClass::PhysicalStorageBuffer))
1598+
return emitError("result must be a physical pointer");
1599+
return success();
1600+
}
1601+
15601602
//===----------------------------------------------------------------------===//
15611603
// spirv.PtrCastToGenericOp
15621604
//===----------------------------------------------------------------------===//

mlir/test/Dialect/SPIRV/IR/cast-ops.mlir

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,3 +363,109 @@ func.func @genericcasttoptrexplicit4(%arg0 : !spirv.ptr<f32, Generic>) {
363363
%0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<vector<2xi32>, Workgroup>
364364
return
365365
}
366+
367+
// -----
368+
369+
//===----------------------------------------------------------------------===//
370+
// spirv.ConvertPtrToU
371+
//===----------------------------------------------------------------------===//
372+
spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
373+
spirv.func @covert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
374+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i32
375+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
376+
spirv.Return
377+
}
378+
spirv.func @covert_ptr_to_u_truncate(%arg0 : !spirv.ptr<i64, Generic>) "None" {
379+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i64, Generic> to i32
380+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i64, Generic> to i32
381+
spirv.Return
382+
}
383+
spirv.func @covert_ptr_to_u_extend(%arg0 : !spirv.ptr<i32, Generic>) "None" {
384+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i64
385+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i64
386+
spirv.Return
387+
}
388+
}
389+
390+
// -----
391+
392+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
393+
spirv.func @covert_ptr_to_u_PhysicalStorageBuffer(%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer>) "None" {
394+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
395+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
396+
spirv.Return
397+
}
398+
}
399+
400+
// -----
401+
402+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
403+
spirv.func @covert_ptr_to_u_fail(%arg0 : !spirv.ptr<i32, Generic>) "None" {
404+
// expected-error @+1 {{operand must be a physical pointer}}
405+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
406+
spirv.Return
407+
}
408+
}
409+
410+
// -----
411+
412+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
413+
spirv.func @covert_ptr_to_u_fail_2(%arg0 : !spirv.ptr<i32, Generic>) "None" {
414+
// expected-error @+1 {{operand must be a physical pointer}}
415+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
416+
spirv.Return
417+
}
418+
}
419+
420+
// -----
421+
422+
//===----------------------------------------------------------------------===//
423+
// spirv.ConvertUToPtr
424+
//===----------------------------------------------------------------------===//
425+
spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
426+
spirv.func @covert_u_to_ptr(%arg0 : i32) "None" {
427+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, Generic>
428+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
429+
spirv.Return
430+
}
431+
spirv.func @covert_u_to_ptr_truncate(%arg0 : i64) "None" {
432+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i64 to !spirv.ptr<i32, Generic>
433+
%0 = spirv.ConvertUToPtr %arg0 : i64 to !spirv.ptr<i32, Generic>
434+
spirv.Return
435+
}
436+
spirv.func @covert_u_to_ptr_extend(%arg0 : i32) "None" {
437+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i64, Generic>
438+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i64, Generic>
439+
spirv.Return
440+
}
441+
}
442+
443+
// -----
444+
445+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
446+
spirv.func @covert_u_to_ptr_PhysicalStorageBuffer(%arg0 : i32) "None" {
447+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
448+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
449+
spirv.Return
450+
}
451+
}
452+
453+
// -----
454+
455+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
456+
spirv.func @covert_u_to_ptr_fail(%arg0 : i32) "None" {
457+
// expected-error @+1 {{result must be a physical pointer}}
458+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
459+
spirv.Return
460+
}
461+
}
462+
463+
// -----
464+
465+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
466+
spirv.func @covert_u_to_ptr_fail_2(%arg0 : i32) "None" {
467+
// expected-error @+1 {{result must be a physical pointer}}
468+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
469+
spirv.Return
470+
}
471+
}

mlir/test/Target/SPIRV/cast-ops.mlir

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,63 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Kernel], []> {
9191
spirv.Return
9292
}
9393
}
94+
95+
// -----
96+
97+
spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
98+
spirv.func @covert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
99+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i32
100+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
101+
spirv.Return
102+
}
103+
spirv.func @covert_ptr_to_u_truncate(%arg0 : !spirv.ptr<i64, Generic>) "None" {
104+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i64, Generic> to i32
105+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i64, Generic> to i32
106+
spirv.Return
107+
}
108+
spirv.func @covert_ptr_to_u_extend(%arg0 : !spirv.ptr<i32, Generic>) "None" {
109+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i64
110+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i64
111+
spirv.Return
112+
}
113+
}
114+
115+
// -----
116+
117+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
118+
spirv.func @covert_ptr_to_u_PhysicalStorageBuffer(%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer>) "None" {
119+
// CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
120+
%0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
121+
spirv.Return
122+
}
123+
}
124+
125+
// -----
126+
127+
spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
128+
spirv.func @covert_u_to_ptr(%arg0 : i32) "None" {
129+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, Generic>
130+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
131+
spirv.Return
132+
}
133+
spirv.func @covert_u_to_ptr_truncate(%arg0 : i64) "None" {
134+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i64 to !spirv.ptr<i32, Generic>
135+
%0 = spirv.ConvertUToPtr %arg0 : i64 to !spirv.ptr<i32, Generic>
136+
spirv.Return
137+
}
138+
spirv.func @covert_u_to_ptr_extend(%arg0 : i32) "None" {
139+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i64, Generic>
140+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i64, Generic>
141+
spirv.Return
142+
}
143+
}
144+
145+
// -----
146+
147+
spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
148+
spirv.func @covert_u_to_ptr_PhysicalStorageBuffer(%arg0 : i32) "None" {
149+
// CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
150+
%0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
151+
spirv.Return
152+
}
153+
}

0 commit comments

Comments
 (0)