MLIR  20.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 runOnOperation() final;
42 };
43 } // namespace
44 
45 void GpuModuleToBinaryPass::runOnOperation() {
46  RewritePatternSet patterns(&getContext());
47  auto targetFormat =
49  .Cases("offloading", "llvm", CompilationTarget::Offload)
50  .Cases("assembly", "isa", CompilationTarget::Assembly)
51  .Cases("binary", "bin", CompilationTarget::Binary)
52  .Cases("fatbinary", "fatbin", CompilationTarget::Fatbin)
53  .Default(std::nullopt);
54  if (!targetFormat)
55  getOperation()->emitError() << "Invalid format specified.";
56 
57  // Lazy symbol table builder callback.
58  std::optional<SymbolTable> parentTable;
59  auto lazyTableBuilder = [&]() -> SymbolTable * {
60  // Build the table if it has not been built.
61  if (!parentTable) {
63  // It's up to the target attribute to determine if failing to find a
64  // symbol table is an error.
65  if (!table)
66  return nullptr;
67  parentTable = SymbolTable(table);
68  }
69  return &parentTable.value();
70  };
71 
72  TargetOptions targetOptions(toolkitPath, linkFiles, cmdOptions, *targetFormat,
73  lazyTableBuilder);
75  getOperation(), OffloadingLLVMTranslationAttrInterface(nullptr),
76  targetOptions)))
77  return signalPassFailure();
78 }
79 
80 namespace {
81 LogicalResult 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<SmallVector<char, 0>> 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  builder.create<gpu::BinaryOp>(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 }
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:215
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:672
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.