MLIR  22.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 
21 using namespace mlir;
22 using namespace mlir::gpu;
23 
24 namespace mlir {
25 #define GEN_PASS_DEF_GPUMODULETOBINARYPASS
26 #include "mlir/Dialect/GPU/Transforms/Passes.h.inc"
27 } // namespace mlir
28 
29 namespace {
30 class GpuModuleToBinaryPass
31  : public impl::GpuModuleToBinaryPassBase<GpuModuleToBinaryPass> {
32 public:
33  using Base::Base;
34  void runOnOperation() final;
35 };
36 } // namespace
37 
38 void GpuModuleToBinaryPass::runOnOperation() {
40  auto targetFormat =
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() << "Invalid format specified.";
49 
50  // Lazy symbol table builder callback.
51  std::optional<SymbolTable> parentTable;
52  auto lazyTableBuilder = [&]() -> SymbolTable * {
53  // Build the table if it has not been built.
54  if (!parentTable) {
56  // It's up to the target attribute to determine if failing to find a
57  // symbol table is an error.
58  if (!table)
59  return nullptr;
60  parentTable = SymbolTable(table);
61  }
62  return &parentTable.value();
63  };
64  SmallVector<Attribute> librariesToLink;
65  for (const std::string &path : linkFiles)
66  librariesToLink.push_back(StringAttr::get(&getContext(), path));
67  TargetOptions targetOptions(toolkitPath, librariesToLink, cmdOptions,
68  elfSection, *targetFormat, lazyTableBuilder);
70  getOperation(), OffloadingLLVMTranslationAttrInterface(nullptr),
71  targetOptions)))
72  return signalPassFailure();
73 }
74 
75 namespace {
76 LogicalResult moduleSerializer(GPUModuleOp op,
77  OffloadingLLVMTranslationAttrInterface handler,
78  const TargetOptions &targetOptions) {
79  OpBuilder builder(op->getContext());
80  SmallVector<Attribute> objects;
81  // Fail if there are no target attributes
82  if (!op.getTargetsAttr())
83  return op.emitError("the module has no target attributes");
84  // Serialize all targets.
85  for (auto targetAttr : op.getTargetsAttr()) {
86  assert(targetAttr && "Target attribute cannot be null.");
87  auto target = dyn_cast<gpu::TargetAttrInterface>(targetAttr);
88  assert(target &&
89  "Target attribute doesn't implements `TargetAttrInterface`.");
90  std::optional<SmallVector<char, 0>> serializedModule =
91  target.serializeToObject(op, targetOptions);
92  if (!serializedModule) {
93  op.emitError("An error happened while serializing the module.");
94  return failure();
95  }
96 
97  Attribute object =
98  target.createObject(op, *serializedModule, targetOptions);
99  if (!object) {
100  op.emitError("An error happened while creating the object.");
101  return failure();
102  }
103  objects.push_back(object);
104  }
105  if (auto moduleHandler =
106  dyn_cast_or_null<OffloadingLLVMTranslationAttrInterface>(
107  op.getOffloadingHandlerAttr());
108  !handler && moduleHandler)
109  handler = moduleHandler;
110  builder.setInsertionPointAfter(op);
111  gpu::BinaryOp::create(builder, op.getLoc(), op.getName(), handler,
112  builder.getArrayAttr(objects));
113  op->erase();
114  return success();
115 }
116 } // namespace
117 
119  Operation *op, OffloadingLLVMTranslationAttrInterface handler,
120  const gpu::TargetOptions &targetOptions) {
121  for (Region &region : op->getRegions())
122  for (Block &block : region.getBlocks())
123  for (auto module :
124  llvm::make_early_inc_range(block.getOps<GPUModuleOp>()))
125  if (failed(moduleSerializer(module, handler, targetOptions)))
126  return failure();
127  return success();
128 }
static MLIRContext * getContext(OpFoldResult val)
const float * table
Attributes are known-constant values of operations.
Definition: Attributes.h:25
Block represents an ordered list of Operations.
Definition: Block.h:33
This class helps build Operations.
Definition: Builders.h:207
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:677
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.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition: Remarks.h:491
Include the generated interface declarations.
const FrozenRewritePatternSet & patterns
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...