Skip to content

Commit 63e4581

Browse files
IgWod-IMGrorth
authored andcommitted
[mlir][spirv] Allow disabling control flow structurization (llvm#140561)
Currently some control flow patterns cannot be structurized into existing SPIR-V MLIR constructs, e.g., conditional early exits (break). Since the support for early exit cannot be currently added (llvm#138688 (review)) this patch enables structurizer to be disabled to keep the control flow unstructurized. By default, the control flow is structurized.
1 parent bd1a3ea commit 63e4581

File tree

5 files changed

+45
-11
lines changed

5 files changed

+45
-11
lines changed

mlir/include/mlir/Target/SPIRV/Deserialization.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ class MLIRContext;
2323
namespace spirv {
2424
class ModuleOp;
2525

26+
struct DeserializationOptions {
27+
// Whether to structurize control flow into `spirv.mlir.selection` and
28+
// `spirv.mlir.loop`.
29+
bool enableControlFlowStructurization = true;
30+
};
31+
2632
/// Deserializes the given SPIR-V `binary` module and creates a MLIR ModuleOp
2733
/// in the given `context`. Returns the ModuleOp on success; otherwise, reports
2834
/// errors to the error handler registered with `context` and returns a null
2935
/// module.
30-
OwningOpRef<spirv::ModuleOp> deserialize(ArrayRef<uint32_t> binary,
31-
MLIRContext *context);
36+
OwningOpRef<spirv::ModuleOp>
37+
deserialize(ArrayRef<uint32_t> binary, MLIRContext *context,
38+
const DeserializationOptions &options = {});
3239

3340
} // namespace spirv
3441
} // namespace mlir

mlir/lib/Target/SPIRV/Deserialization/Deserialization.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212

1313
using namespace mlir;
1414

15-
OwningOpRef<spirv::ModuleOp> spirv::deserialize(ArrayRef<uint32_t> binary,
16-
MLIRContext *context) {
17-
Deserializer deserializer(binary, context);
15+
OwningOpRef<spirv::ModuleOp>
16+
spirv::deserialize(ArrayRef<uint32_t> binary, MLIRContext *context,
17+
const DeserializationOptions &options) {
18+
Deserializer deserializer(binary, context, options);
1819

1920
if (failed(deserializer.deserialize()))
2021
return nullptr;

mlir/lib/Target/SPIRV/Deserialization/Deserializer.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ static inline bool isFnEntryBlock(Block *block) {
4949
//===----------------------------------------------------------------------===//
5050

5151
spirv::Deserializer::Deserializer(ArrayRef<uint32_t> binary,
52-
MLIRContext *context)
52+
MLIRContext *context,
53+
const spirv::DeserializationOptions &options)
5354
: binary(binary), context(context), unknownLoc(UnknownLoc::get(context)),
54-
module(createModuleOp()), opBuilder(module->getRegion())
55+
module(createModuleOp()), opBuilder(module->getRegion()), options(options)
5556
#ifndef NDEBUG
5657
,
5758
logger(llvm::dbgs())
@@ -2361,6 +2362,16 @@ LogicalResult spirv::Deserializer::splitConditionalBlocks() {
23612362
}
23622363

23632364
LogicalResult spirv::Deserializer::structurizeControlFlow() {
2365+
if (!options.enableControlFlowStructurization) {
2366+
LLVM_DEBUG(
2367+
{
2368+
logger.startLine()
2369+
<< "//----- [cf] skip structurizing control flow -----//\n";
2370+
logger.indent();
2371+
});
2372+
return success();
2373+
}
2374+
23642375
LLVM_DEBUG({
23652376
logger.startLine()
23662377
<< "//----- [cf] start structurizing control flow -----//\n";

mlir/lib/Target/SPIRV/Deserialization/Deserializer.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mlir/Dialect/SPIRV/IR/SPIRVEnums.h"
1717
#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
1818
#include "mlir/IR/Builders.h"
19+
#include "mlir/Target/SPIRV/Deserialization.h"
1920
#include "llvm/ADT/ArrayRef.h"
2021
#include "llvm/ADT/SetVector.h"
2122
#include "llvm/ADT/StringRef.h"
@@ -121,7 +122,8 @@ class Deserializer {
121122
public:
122123
/// Creates a deserializer for the given SPIR-V `binary` module.
123124
/// The SPIR-V ModuleOp will be created into `context.
124-
explicit Deserializer(ArrayRef<uint32_t> binary, MLIRContext *context);
125+
explicit Deserializer(ArrayRef<uint32_t> binary, MLIRContext *context,
126+
const DeserializationOptions &options);
125127

126128
/// Deserializes the remembered SPIR-V binary module.
127129
LogicalResult deserialize();
@@ -622,6 +624,9 @@ class Deserializer {
622624
/// A list of all structs which have unresolved member types.
623625
SmallVector<DeferredStructTypeInfo, 0> deferredStructTypesInfos;
624626

627+
/// Deserialization options.
628+
DeserializationOptions options;
629+
625630
#ifndef NDEBUG
626631
/// A logger used to emit information during the deserialzation process.
627632
llvm::ScopedPrinter logger;

mlir/lib/Target/SPIRV/TranslateRegistration.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ using namespace mlir;
3737
// Deserializes the SPIR-V binary module stored in the file named as
3838
// `inputFilename` and returns a module containing the SPIR-V module.
3939
static OwningOpRef<Operation *>
40-
deserializeModule(const llvm::MemoryBuffer *input, MLIRContext *context) {
40+
deserializeModule(const llvm::MemoryBuffer *input, MLIRContext *context,
41+
const spirv::DeserializationOptions &options) {
4142
context->loadDialect<spirv::SPIRVDialect>();
4243

4344
// Make sure the input stream can be treated as a stream of SPIR-V words
@@ -51,17 +52,26 @@ deserializeModule(const llvm::MemoryBuffer *input, MLIRContext *context) {
5152

5253
auto binary = llvm::ArrayRef(reinterpret_cast<const uint32_t *>(start),
5354
size / sizeof(uint32_t));
54-
return spirv::deserialize(binary, context);
55+
return spirv::deserialize(binary, context, options);
5556
}
5657

5758
namespace mlir {
5859
void registerFromSPIRVTranslation() {
60+
static llvm::cl::opt<bool> enableControlFlowStructurization(
61+
"spirv-structurize-control-flow",
62+
llvm::cl::desc(
63+
"Enable control flow structurization into `spirv.mlir.selection` and "
64+
"`spirv.mlir.loop`. This may need to be disabled to support "
65+
"deserialization of early exits (see #138688)"),
66+
llvm::cl::init(true));
67+
5968
TranslateToMLIRRegistration fromBinary(
6069
"deserialize-spirv", "deserializes the SPIR-V module",
6170
[](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
6271
assert(sourceMgr.getNumBuffers() == 1 && "expected one buffer");
6372
return deserializeModule(
64-
sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()), context);
73+
sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()), context,
74+
{enableControlFlowStructurization});
6575
});
6676
}
6777
} // namespace mlir

0 commit comments

Comments
 (0)