Skip to content

Commit 3159c93

Browse files
committed
Sort functions inside the serializer.
1 parent ba85d0d commit 3159c93

File tree

4 files changed

+30
-46
lines changed

4 files changed

+30
-46
lines changed

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

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,7 +1516,6 @@ LogicalResult spirv::ModuleOp::verifyRegions() {
15161516
DenseMap<std::pair<spirv::FuncOp, spirv::ExecutionModel>, spirv::EntryPointOp>
15171517
entryPoints;
15181518
mlir::SymbolTable table(*this);
1519-
bool encounteredFuncDefinition = false;
15201519

15211520
for (auto &op : *getBody()) {
15221521
if (op.getDialect() != dialect)
@@ -1562,23 +1561,10 @@ LogicalResult spirv::ModuleOp::verifyRegions() {
15621561
auto hasImportLinkage =
15631562
linkageAttr && (linkageAttr.value().getLinkageType().getValue() ==
15641563
spirv::LinkageType::Import);
1565-
if (funcOp.isExternal()) {
1566-
if (!hasImportLinkage)
1567-
return op.emitError(
1568-
"'spirv.module' cannot contain external functions "
1569-
"without 'Import' linkage_attributes (LinkageAttributes)");
1570-
// This is stronger than necessary. It should be sufficient to
1571-
// ensure any declarations precede their uses and not all definitions,
1572-
// however this allows to avoid analysing every function in the module
1573-
// this way.
1574-
if (encounteredFuncDefinition)
1575-
return op.emitError("all functions declarations in 'spirv.module' "
1576-
"must happen before any definitions");
1577-
}
1578-
1579-
// In SPIR-V "declarations" are functions without a body and "definitions"
1580-
// functions with a body.
1581-
encounteredFuncDefinition |= !funcOp.getBody().empty();
1564+
if (funcOp.isExternal() && !hasImportLinkage)
1565+
return op.emitError(
1566+
"'spirv.module' cannot contain external functions "
1567+
"without 'Import' linkage_attributes (LinkageAttributes)");
15821568

15831569
// TODO: move this check to spirv.func.
15841570
for (auto &block : funcOp)

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+
Operation &firstOp = ops.front();
101+
for (Operation &op : llvm::drop_begin(ops))
102+
if (auto funcOp = dyn_cast<spirv::FuncOp>(op))
103+
if (funcOp.getBody().empty())
104+
funcOp->moveBefore(&firstOp);
105+
}
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/Dialect/SPIRV/IR/function-decorations.mlir

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,14 @@
11
// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
22

33
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage], []> {
4-
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
5-
spirv.func @outside.func.with.linkage(%arg0 : i8) -> () "Pure" attributes {
6-
linkage_attributes=#spirv.linkage_attributes<
7-
linkage_name="outside.func",
8-
linkage_type=<Import>
9-
>
10-
}
11-
spirv.func @linkage_attr_test_kernel() "DontInline" attributes {} {
12-
%uchar_0 = spirv.Constant 0 : i8
13-
%ushort_1 = spirv.Constant 1 : i16
14-
%uint_0 = spirv.Constant 0 : i32
15-
spirv.FunctionCall @outside.func.with.linkage(%uchar_0):(i8) -> ()
16-
spirv.Return
17-
}
18-
spirv.func @inside.func() -> () "Pure" attributes {} {spirv.Return}
19-
}
20-
21-
// -----
22-
23-
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, Int8, Int16], []> {
244
spirv.func @linkage_attr_test_kernel() "DontInline" attributes {} {
255
%uchar_0 = spirv.Constant 0 : i8
266
%ushort_1 = spirv.Constant 1 : i16
277
%uint_0 = spirv.Constant 0 : i32
288
spirv.FunctionCall @outside.func.with.linkage(%uchar_0):(i8) -> ()
299
spirv.Return
3010
}
31-
// expected-error@+1 {{all functions declarations in 'spirv.module' must happen before any definitions}}
11+
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
3212
spirv.func @outside.func.with.linkage(%arg0 : i8) -> () "Pure" attributes {
3313
linkage_attributes=#spirv.linkage_attributes<
3414
linkage_name="outside.func",

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@
66
// RUN: %if spirv-tools %{ spirv-val %t %}
77

88
spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader, Linkage, Int8, Int16], []> {
9-
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
10-
spirv.func @outside.func.with.linkage(%arg0 : i8) -> () "Pure" attributes {
11-
linkage_attributes=#spirv.linkage_attributes<
12-
linkage_name="outside.func",
13-
linkage_type=<Import>
14-
>
15-
}
169
spirv.func @linkage_attr_test_kernel() "DontInline" attributes {} {
1710
%uchar_0 = spirv.Constant 0 : i8
1811
%ushort_1 = spirv.Constant 1 : i16
1912
%uint_0 = spirv.Constant 0 : i32
2013
spirv.FunctionCall @outside.func.with.linkage(%uchar_0):(i8) -> ()
2114
spirv.Return
2215
}
16+
// CHECK: linkage_attributes = #spirv.linkage_attributes<linkage_name = "outside.func", linkage_type = <Import>>
17+
spirv.func @outside.func.with.linkage(%arg0 : i8) -> () "Pure" attributes {
18+
linkage_attributes=#spirv.linkage_attributes<
19+
linkage_name="outside.func",
20+
linkage_type=<Import>
21+
>
22+
}
2323
spirv.func @inside.func() -> () "Pure" attributes {} {spirv.Return}
2424
}
2525

0 commit comments

Comments
 (0)