MLIR  19.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 
22 #include "mlir/IR/BuiltinOps.h"
24 
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/StringSwitch.h"
27 
28 using namespace mlir;
29 using namespace mlir::gpu;
30 
31 namespace mlir {
32 #define GEN_PASS_DEF_GPUMODULETOBINARYPASS
33 #include "mlir/Dialect/GPU/Transforms/Passes.h.inc"
34 } // namespace mlir
35 
36 namespace {
37 class GpuModuleToBinaryPass
38  : public impl::GpuModuleToBinaryPassBase<GpuModuleToBinaryPass> {
39 public:
40  using Base::Base;
41  void getDependentDialects(DialectRegistry &registry) const override;
42  void runOnOperation() final;
43 };
44 } // namespace
45 
46 void GpuModuleToBinaryPass::getDependentDialects(
47  DialectRegistry &registry) const {
48  // Register all GPU related translations.
49  registry.insert<gpu::GPUDialect>();
50  registry.insert<LLVM::LLVMDialect>();
51 #if LLVM_HAS_NVPTX_TARGET
52  registry.insert<NVVM::NVVMDialect>();
53 #endif
54 #if MLIR_ENABLE_ROCM_CONVERSIONS
55  registry.insert<ROCDL::ROCDLDialect>();
56 #endif
57  registry.insert<spirv::SPIRVDialect>();
58 }
59 
60 void GpuModuleToBinaryPass::runOnOperation() {
61  RewritePatternSet patterns(&getContext());
62  auto targetFormat =
64  .Cases("offloading", "llvm", CompilationTarget::Offload)
65  .Cases("assembly", "isa", CompilationTarget::Assembly)
66  .Cases("binary", "bin", CompilationTarget::Binary)
67  .Cases("fatbinary", "fatbin", CompilationTarget::Fatbin)
68  .Default(std::nullopt);
69  if (!targetFormat)
70  getOperation()->emitError() << "Invalid format specified.";
71 
72  // Lazy symbol table builder callback.
73  std::optional<SymbolTable> parentTable;
74  auto lazyTableBuilder = [&]() -> SymbolTable * {
75  // Build the table if it has not been built.
76  if (!parentTable) {
77  Operation *table = SymbolTable::getNearestSymbolTable(getOperation());
78  // It's up to the target attribute to determine if failing to find a
79  // symbol table is an error.
80  if (!table)
81  return nullptr;
82  parentTable = SymbolTable(table);
83  }
84  return &parentTable.value();
85  };
86 
87  TargetOptions targetOptions(toolkitPath, linkFiles, cmdOptions, *targetFormat,
88  lazyTableBuilder);
90  getOperation(), OffloadingLLVMTranslationAttrInterface(nullptr),
91  targetOptions)))
92  return signalPassFailure();
93 }
94 
95 namespace {
96 LogicalResult moduleSerializer(GPUModuleOp op,
97  OffloadingLLVMTranslationAttrInterface handler,
98  const TargetOptions &targetOptions) {
99  OpBuilder builder(op->getContext());
100  SmallVector<Attribute> objects;
101  // Fail if there are no target attributes
102  if (!op.getTargetsAttr())
103  return op.emitError("the module has no target attributes");
104  // Serialize all targets.
105  for (auto targetAttr : op.getTargetsAttr()) {
106  assert(targetAttr && "Target attribute cannot be null.");
107  auto target = dyn_cast<gpu::TargetAttrInterface>(targetAttr);
108  assert(target &&
109  "Target attribute doesn't implements `TargetAttrInterface`.");
110  std::optional<SmallVector<char, 0>> serializedModule =
111  target.serializeToObject(op, targetOptions);
112  if (!serializedModule) {
113  op.emitError("An error happened while serializing the module.");
114  return failure();
115  }
116 
117  Attribute object = target.createObject(*serializedModule, targetOptions);
118  if (!object) {
119  op.emitError("An error happened while creating the object.");
120  return failure();
121  }
122  objects.push_back(object);
123  }
124  if (auto moduleHandler =
125  dyn_cast_or_null<OffloadingLLVMTranslationAttrInterface>(
126  op.getOffloadingHandlerAttr());
127  !handler && moduleHandler)
128  handler = moduleHandler;
129  builder.setInsertionPointAfter(op);
130  builder.create<gpu::BinaryOp>(op.getLoc(), op.getName(), handler,
131  builder.getArrayAttr(objects));
132  op->erase();
133  return success();
134 }
135 } // namespace
136 
138  Operation *op, OffloadingLLVMTranslationAttrInterface handler,
139  const gpu::TargetOptions &targetOptions) {
140  for (Region &region : op->getRegions())
141  for (Block &block : region.getBlocks())
142  for (auto module :
143  llvm::make_early_inc_range(block.getOps<GPUModuleOp>()))
144  if (failed(moduleSerializer(module, handler, targetOptions)))
145  return failure();
146  return success();
147 }
static MLIRContext * getContext(OpFoldResult val)
Attributes are known-constant values of operations.
Definition: Attributes.h:25
Block represents an ordered list of Operations.
Definition: Block.h:31
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
This class helps build Operations.
Definition: Builders.h:209
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:672
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:119
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:539
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Definition: SymbolTable.h:24
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.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26