MLIR 23.0.0git
ModuleToBinary.cpp
Go to the documentation of this file.
1//===- ModuleToBinary.cpp - Transforms GPU modules to GPU binaries ----------=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the `GpuModuleToBinaryPass` pass, transforming GPU
10// modules into GPU binaries.
11//
12//===----------------------------------------------------------------------===//
13
15
17
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringSwitch.h"
20
21using namespace mlir;
22using namespace mlir::gpu;
23
24namespace mlir {
25#define GEN_PASS_DEF_GPUMODULETOBINARYPASS
26#include "mlir/Dialect/GPU/Transforms/Passes.h.inc"
27} // namespace mlir
28
29namespace {
30class GpuModuleToBinaryPass
31 : public impl::GpuModuleToBinaryPassBase<GpuModuleToBinaryPass> {
32public:
33 using Base::Base;
34 void runOnOperation() final;
35};
36} // namespace
37
38void GpuModuleToBinaryPass::runOnOperation() {
39 RewritePatternSet patterns(&getContext());
40 auto targetFormat =
41 llvm::StringSwitch<std::optional<CompilationTarget>>(compilationTarget)
42 .Cases({"offloading", "llvm"}, CompilationTarget::Offload)
43 .Cases({"assembly", "isa"}, CompilationTarget::Assembly)
44 .Cases({"binary", "bin"}, CompilationTarget::Binary)
45 .Cases({"fatbinary", "fatbin"}, CompilationTarget::Fatbin)
46 .Default(std::nullopt);
47 if (!targetFormat) {
48 getOperation()->emitError()
49 << "Invalid format specified: '" << compilationTarget
50 << "' (expected one of: offloading, llvm, assembly, isa, binary, bin, "
51 "fatbinary, fatbin)";
52 return signalPassFailure();
53 }
54
55 // Lazy symbol table builder callback.
56 std::optional<SymbolTable> parentTable;
57 auto lazyTableBuilder = [&]() -> SymbolTable * {
58 // Build the table if it has not been built.
59 if (!parentTable) {
60 Operation *table = SymbolTable::getNearestSymbolTable(getOperation());
61 // It's up to the target attribute to determine if failing to find a
62 // symbol table is an error.
63 if (!table)
64 return nullptr;
65 parentTable = SymbolTable(table);
66 }
67 return &parentTable.value();
68 };
69 SmallVector<Attribute> librariesToLink;
70 for (const std::string &path : linkFiles)
71 librariesToLink.push_back(StringAttr::get(&getContext(), path));
72 TargetOptions targetOptions(toolkitPath, librariesToLink, cmdOptions,
73 elfSection, *targetFormat, lazyTableBuilder);
75 getOperation(), OffloadingLLVMTranslationAttrInterface(nullptr),
76 targetOptions)))
77 return signalPassFailure();
78}
79
80namespace {
81LogicalResult moduleSerializer(GPUModuleOp op,
82 OffloadingLLVMTranslationAttrInterface handler,
83 const TargetOptions &targetOptions) {
84 OpBuilder builder(op->getContext());
85 SmallVector<Attribute> objects;
86 // Fail if there are no target attributes
87 if (!op.getTargetsAttr())
88 return op.emitError("the module has no target attributes");
89 // Serialize all targets.
90 for (auto targetAttr : op.getTargetsAttr()) {
91 assert(targetAttr && "Target attribute cannot be null.");
92 auto target = dyn_cast<gpu::TargetAttrInterface>(targetAttr);
93 assert(target &&
94 "Target attribute doesn't implements `TargetAttrInterface`.");
95 std::optional<SerializedObject> serializedModule =
96 target.serializeToObject(op, targetOptions);
97 if (!serializedModule) {
98 op.emitError("An error happened while serializing the module.");
99 return failure();
100 }
101
102 Attribute object =
103 target.createObject(op, *serializedModule, targetOptions);
104 if (!object) {
105 op.emitError("An error happened while creating the object.");
106 return failure();
107 }
108 objects.push_back(object);
109 }
110 if (auto moduleHandler =
111 dyn_cast_or_null<OffloadingLLVMTranslationAttrInterface>(
112 op.getOffloadingHandlerAttr());
113 !handler && moduleHandler)
114 handler = moduleHandler;
115 builder.setInsertionPointAfter(op);
116 gpu::BinaryOp::create(builder, op.getLoc(), op.getName(), handler,
117 builder.getArrayAttr(objects));
118 op->erase();
119 return success();
120}
121} // namespace
122
124 Operation *op, OffloadingLLVMTranslationAttrInterface handler,
125 const gpu::TargetOptions &targetOptions) {
126 for (Region &region : op->getRegions())
127 for (Block &block : region.getBlocks())
128 for (auto module :
129 llvm::make_early_inc_range(block.getOps<GPUModuleOp>()))
130 if (failed(moduleSerializer(module, handler, targetOptions)))
131 return failure();
132 return success();
133}
return success()
b getContext())
Block represents an ordered list of Operations.
Definition Block.h:33
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition Operation.h:706
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
static Operation * getNearestSymbolTable(Operation *from)
Returns the nearest symbol table from a given operation from.
This class serves as an opaque interface for passing options to the TargetAttrInterface methods.
LogicalResult transformGpuModulesToBinaries(Operation *op, OffloadingLLVMTranslationAttrInterface handler=nullptr, const gpu::TargetOptions &options={})
Searches for all GPU modules in op and transforms them into GPU binary operations.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:717
Include the generated interface declarations.