Skip to content

Commit 1a91aae

Browse files
IgWod-IMGgithub-actions[bot]
authored andcommitted
Automerge: [mlir][spirv] Ensure function declarations precede definitions (#164956)
SPIR-V spec requires that any calls to external functions are preceded by declarations of those external functions. To simplify the implementation, we sort functions in the serializer using a stronger condition: any functions declarations are moved before any functions definitions - this ensures that external functions are always declared before being used.
2 parents 20f037d + 046ed90 commit 1a91aae

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

mlir/lib/Target/SPIRV/Serialization/Serializer.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,22 @@ static bool isZeroValue(Attribute attr) {
8989
return false;
9090
}
9191

92+
/// Move all functions declaration before functions definitions. In SPIR-V
93+
/// "declarations" are functions without a body and "definitions" functions
94+
/// with a body. This is stronger than necessary. It should be sufficient to
95+
/// ensure any declarations precede their uses and not all definitions, however
96+
/// this allows to avoid analysing every function in the module this way.
97+
static void moveFuncDeclarationsToTop(spirv::ModuleOp moduleOp) {
98+
Block::OpListType &ops = moduleOp.getBody()->getOperations();
99+
if (ops.empty())
100+
return;
101+
Operation &firstOp = ops.front();
102+
for (Operation &op : llvm::drop_begin(ops))
103+
if (auto funcOp = dyn_cast<spirv::FuncOp>(op))
104+
if (funcOp.getBody().empty())
105+
funcOp->moveBefore(&firstOp);
106+
}
107+
92108
namespace mlir {
93109
namespace spirv {
94110

@@ -119,6 +135,8 @@ LogicalResult Serializer::serialize() {
119135
processMemoryModel();
120136
processDebugInfo();
121137

138+
moveFuncDeclarationsToTop(module);
139+
122140
// Iterate over the module body to serialize it. Assumptions are that there is
123141
// only one basic block in the moduleOp
124142
for (auto &op : *module.getBody()) {

mlir/test/Target/SPIRV/function-decorations.mlir

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
// RUN: mlir-translate --no-implicit-module --test-spirv-roundtrip --split-input-file %s | FileCheck %s
22

3-
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
3+
// RUN: %if spirv-tools %{ rm -rf %t %}
4+
// RUN: %if spirv-tools %{ mkdir %t %}
5+
// RUN: %if spirv-tools %{ mlir-translate --no-implicit-module --serialize-spirv --split-input-file --spirv-save-validation-files-with-prefix=%t/module %s %}
6+
// RUN: %if spirv-tools %{ spirv-val %t %}
7+
8+
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, Int8, Int16], []> {
9+
// CHECK: spirv.func @outside.func.with.linkage(i8) "Pure" attributes
10+
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
11+
// CHECK: spirv.func @linkage_attr_test_kernel() "DontInline" {
12+
// CHECK: spirv.func @inside.func() "Pure" {
413
spirv.func @linkage_attr_test_kernel() "DontInline" attributes {} {
514
%uchar_0 = spirv.Constant 0 : i8
615
%ushort_1 = spirv.Constant 1 : i16
716
%uint_0 = spirv.Constant 0 : i32
817
spirv.FunctionCall @outside.func.with.linkage(%uchar_0):(i8) -> ()
918
spirv.Return
1019
}
11-
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
1220
spirv.func @outside.func.with.linkage(%arg0 : i8) -> () "Pure" attributes {
1321
linkage_attributes=#spirv.linkage_attributes<
1422
linkage_name="outside.func",
@@ -21,7 +29,7 @@ spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
2129
// -----
2230

2331
spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
24-
[Shader, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]> {
32+
[Shader, PhysicalStorageBufferAddresses, Linkage], [SPV_KHR_physical_storage_buffer]> {
2533
// CHECK-LABEL: spirv.func @func_arg_decoration_aliased(%{{.*}}: !spirv.ptr<i32, PhysicalStorageBuffer> {spirv.decoration = #spirv.decoration<Aliased>})
2634
spirv.func @func_arg_decoration_aliased(
2735
%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> { spirv.decoration = #spirv.decoration<Aliased> }
@@ -33,7 +41,7 @@ spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
3341
// -----
3442

3543
spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
36-
[Shader, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]> {
44+
[Shader, PhysicalStorageBufferAddresses, Linkage], [SPV_KHR_physical_storage_buffer]> {
3745
// CHECK-LABEL: spirv.func @func_arg_decoration_restrict(%{{.*}}: !spirv.ptr<i32, PhysicalStorageBuffer> {spirv.decoration = #spirv.decoration<Restrict>})
3846
spirv.func @func_arg_decoration_restrict(
3947
%arg0 : !spirv.ptr<i32,PhysicalStorageBuffer> { spirv.decoration = #spirv.decoration<Restrict> }
@@ -45,7 +53,7 @@ spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
4553
// -----
4654

4755
spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
48-
[Shader, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]> {
56+
[Shader, PhysicalStorageBufferAddresses, Linkage, GenericPointer], [SPV_KHR_physical_storage_buffer]> {
4957
// CHECK-LABEL: spirv.func @func_arg_decoration_aliased_pointer(%{{.*}}: !spirv.ptr<!spirv.ptr<i32, PhysicalStorageBuffer>, Generic> {spirv.decoration = #spirv.decoration<AliasedPointer>})
5058
spirv.func @func_arg_decoration_aliased_pointer(
5159
%arg0 : !spirv.ptr<!spirv.ptr<i32,PhysicalStorageBuffer>, Generic> { spirv.decoration = #spirv.decoration<AliasedPointer> }
@@ -57,7 +65,7 @@ spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
5765
// -----
5866

5967
spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
60-
[Shader, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]> {
68+
[Shader, PhysicalStorageBufferAddresses, Linkage, GenericPointer], [SPV_KHR_physical_storage_buffer]> {
6169
// CHECK-LABEL: spirv.func @func_arg_decoration_restrict_pointer(%{{.*}}: !spirv.ptr<!spirv.ptr<i32, PhysicalStorageBuffer>, Generic> {spirv.decoration = #spirv.decoration<RestrictPointer>})
6270
spirv.func @func_arg_decoration_restrict_pointer(
6371
%arg0 : !spirv.ptr<!spirv.ptr<i32,PhysicalStorageBuffer>, Generic> { spirv.decoration = #spirv.decoration<RestrictPointer> }
@@ -69,7 +77,7 @@ spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
6977
// -----
7078

7179
spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce<v1.0,
72-
[Shader, PhysicalStorageBufferAddresses], [SPV_KHR_physical_storage_buffer]> {
80+
[Shader, PhysicalStorageBufferAddresses, Linkage], [SPV_KHR_physical_storage_buffer]> {
7381
// CHECK-LABEL: spirv.func @fn1(%{{.*}}: i32, %{{.*}}: !spirv.ptr<i32, PhysicalStorageBuffer> {spirv.decoration = #spirv.decoration<Aliased>})
7482
spirv.func @fn1(
7583
%arg0: i32,

0 commit comments

Comments
 (0)