[Mlir-commits] [mlir] [mlir][gpu] Add an option to represent LLVM bitcode linking flags. (PR #78050)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Jan 13 09:34:28 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-gpu
Author: Fabian Mora (fabianmcg)
<details>
<summary>Changes</summary>
This patch adds an option to `Target/LLVM/ModuleToObject` for specifying the LLVM bitcode linking flags.
One example where this is needed is when compiling OpenMP target offload code, as all the symbols from `libomptarget*.bc` must be imported regardless of usage, because `llvm/Transforms/IPO/OpenMPOpt.cpp` might materialize their use during optimizations.
This patch also adds the `lflags` option to `gpu-module-to-binary` for specifying this linking flags.
---
Full diff: https://github.com/llvm/llvm-project/pull/78050.diff
9 Files Affected:
- (modified) mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h (+12)
- (modified) mlir/include/mlir/Dialect/GPU/Transforms/Passes.td (+3-1)
- (modified) mlir/include/mlir/Target/LLVM/ModuleToObject.h (+6-1)
- (added) mlir/include/mlir/Target/LLVM/Options.h (+39)
- (modified) mlir/lib/Dialect/GPU/IR/GPUDialect.cpp (+14-1)
- (modified) mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp (+13-1)
- (modified) mlir/lib/Target/LLVM/ModuleToObject.cpp (+14-7)
- (modified) mlir/lib/Target/LLVM/NVVM/Target.cpp (+2-1)
- (modified) mlir/lib/Target/LLVM/ROCDL/Target.cpp (+2-1)
``````````diff
diff --git a/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h b/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
index 6d7cb5ca7a7f81..db7e1a7b755896 100644
--- a/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
+++ b/mlir/include/mlir/Dialect/GPU/IR/CompilationInterfaces.h
@@ -23,6 +23,7 @@ namespace mlir {
class SymbolTable;
namespace LLVM {
class ModuleTranslation;
+enum class LinkingFlags : uint32_t;
}
namespace gpu {
enum class CompilationTarget : uint32_t;
@@ -52,6 +53,7 @@ class TargetOptions {
StringRef toolkitPath = {}, ArrayRef<std::string> linkFiles = {},
StringRef cmdOptions = {},
CompilationTarget compilationTarget = getDefaultCompilationTarget(),
+ LLVM::LinkingFlags llvmLinkingFlags = getDefaultLinkingFlags(),
function_ref<SymbolTable *()> getSymbolTableCallback = {});
/// Returns the typeID.
@@ -73,6 +75,9 @@ class TargetOptions {
/// Returns the compilation target.
CompilationTarget getCompilationTarget() const;
+ /// Returns the LLVM linking flags.
+ LLVM::LinkingFlags getLinkingFlags() const;
+
/// Returns the result of the `getSymbolTableCallback` callback or a nullptr
/// if no callback was provided.
/// Note: The callback itself can return nullptr. It is up to the target how
@@ -83,6 +88,9 @@ class TargetOptions {
/// Returns the default compilation target: `CompilationTarget::Fatbin`.
static CompilationTarget getDefaultCompilationTarget();
+ /// Returns the default LLVM linking flags: `LLVM::LinkingFlags::onlyNeeded`.
+ static LLVM::LinkingFlags getDefaultLinkingFlags();
+
protected:
/// Derived classes must use this constructor to initialize `typeID` to the
/// appropiate value: ie. `TargetOptions(TypeID::get<DerivedClass>())`.
@@ -90,6 +98,7 @@ class TargetOptions {
TypeID typeID, StringRef toolkitPath = {},
ArrayRef<std::string> linkFiles = {}, StringRef cmdOptions = {},
CompilationTarget compilationTarget = getDefaultCompilationTarget(),
+ LLVM::LinkingFlags llvmLinkingFlags = getDefaultLinkingFlags(),
function_ref<SymbolTable *()> getSymbolTableCallback = {});
/// Path to the target toolkit.
@@ -105,6 +114,9 @@ class TargetOptions {
/// Compilation process target format.
CompilationTarget compilationTarget;
+ /// LLVM bitcode linker flags.
+ LLVM::LinkingFlags llvmLinkingFlags;
+
/// Callback for obtaining the parent symbol table of all the GPU modules
/// being serialized.
function_ref<SymbolTable *()> getSymbolTableCallback;
diff --git a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
index 3e0f6a3022f935..601f0fec49a0a3 100644
--- a/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/GPU/Transforms/Passes.td
@@ -97,7 +97,9 @@ def GpuModuleToBinaryPass
Option<"cmdOptions", "opts", "std::string", [{""}],
"Command line options to pass to the tools.">,
Option<"compilationTarget", "format", "std::string", [{"fatbin"}],
- "The target representation of the compilation process.">
+ "The target representation of the compilation process.">,
+ Option<"linkingFlags", "lflags", "std::string", [{"only-needed"}],
+ "The LLVM bitcode linking flags.">
];
}
diff --git a/mlir/include/mlir/Target/LLVM/ModuleToObject.h b/mlir/include/mlir/Target/LLVM/ModuleToObject.h
index e40d7e9a43dd6b..8b468aafdfac40 100644
--- a/mlir/include/mlir/Target/LLVM/ModuleToObject.h
+++ b/mlir/include/mlir/Target/LLVM/ModuleToObject.h
@@ -15,6 +15,7 @@
#define MLIR_TARGET_LLVM_MODULETOOBJECT_H
#include "mlir/IR/Operation.h"
+#include "mlir/Target/LLVM/Options.h"
#include "llvm/IR/Module.h"
namespace llvm {
@@ -30,7 +31,8 @@ class ModuleTranslation;
class ModuleToObject {
public:
ModuleToObject(Operation &module, StringRef triple, StringRef chip,
- StringRef features = {}, int optLevel = 3);
+ StringRef features = {}, int optLevel = 3,
+ LinkingFlags linkingFlags = LinkingFlags::onlyNeeded);
virtual ~ModuleToObject();
/// Returns the operation being serialized.
@@ -114,6 +116,9 @@ class ModuleToObject {
/// Optimization level.
int optLevel;
+ /// Linker flags.
+ LinkingFlags linkingFlags;
+
private:
/// The TargetMachine created for the given Triple, if available.
/// Accessible through `getOrCreateTargetMachine()`.
diff --git a/mlir/include/mlir/Target/LLVM/Options.h b/mlir/include/mlir/Target/LLVM/Options.h
new file mode 100644
index 00000000000000..a370fca0f08c00
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVM/Options.h
@@ -0,0 +1,39 @@
+//===- Options.h - LLVM Target Options --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares LLVM target options.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVM_OPTIONS_H
+#define MLIR_TARGET_LLVM_OPTIONS_H
+
+#include <cstdint>
+
+namespace mlir {
+namespace LLVM {
+/// This enumeration represents LLVM bitcode linking flags.
+enum class LinkingFlags : uint32_t {
+ none = 0,
+ overrideFromSrc = 1, /// Override symbols using the source definition.
+ onlyNeeded = 2, /// Add only symbols referenced by the destination module.
+};
+
+/// LinkingFlags bitwise operators.
+inline LinkingFlags operator|(LinkingFlags x, LinkingFlags y) {
+ return static_cast<LinkingFlags>(static_cast<uint32_t>(x) |
+ static_cast<uint32_t>(y));
+}
+inline LinkingFlags operator&(LinkingFlags x, LinkingFlags y) {
+ return static_cast<LinkingFlags>(static_cast<uint32_t>(x) &
+ static_cast<uint32_t>(y));
+}
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVM_OPTIONS_H
diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
index 020900934c9f72..45ac56cf2fca04 100644
--- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
+++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
@@ -29,6 +29,7 @@
#include "mlir/Interfaces/FunctionImplementation.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Support/LogicalResult.h"
+#include "mlir/Target/LLVM/Options.h"
#include "mlir/Transforms/InliningUtils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/TypeSwitch.h"
@@ -2211,16 +2212,20 @@ LogicalResult gpu::DynamicSharedMemoryOp::verify() {
TargetOptions::TargetOptions(
StringRef toolkitPath, ArrayRef<std::string> linkFiles,
StringRef cmdOptions, CompilationTarget compilationTarget,
+ LLVM::LinkingFlags llvmLinkingFlags,
function_ref<SymbolTable *()> getSymbolTableCallback)
: TargetOptions(TypeID::get<TargetOptions>(), toolkitPath, linkFiles,
- cmdOptions, compilationTarget, getSymbolTableCallback) {}
+ cmdOptions, compilationTarget, llvmLinkingFlags,
+ getSymbolTableCallback) {}
TargetOptions::TargetOptions(
TypeID typeID, StringRef toolkitPath, ArrayRef<std::string> linkFiles,
StringRef cmdOptions, CompilationTarget compilationTarget,
+ LLVM::LinkingFlags llvmLinkingFlags,
function_ref<SymbolTable *()> getSymbolTableCallback)
: toolkitPath(toolkitPath.str()), linkFiles(linkFiles),
cmdOptions(cmdOptions.str()), compilationTarget(compilationTarget),
+ llvmLinkingFlags(llvmLinkingFlags),
getSymbolTableCallback(getSymbolTableCallback), typeID(typeID) {}
TypeID TargetOptions::getTypeID() const { return typeID; }
@@ -2243,6 +2248,14 @@ CompilationTarget TargetOptions::getDefaultCompilationTarget() {
return CompilationTarget::Fatbin;
}
+LLVM::LinkingFlags TargetOptions::getLinkingFlags() const {
+ return llvmLinkingFlags;
+}
+
+LLVM::LinkingFlags TargetOptions::getDefaultLinkingFlags() {
+ return LLVM::LinkingFlags::onlyNeeded;
+}
+
std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>>
TargetOptions::tokenizeCmdOptions() const {
std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> options;
diff --git a/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp b/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
index 70d36297e103f3..91d545ce380488 100644
--- a/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
+++ b/mlir/lib/Dialect/GPU/Transforms/ModuleToBinary.cpp
@@ -20,6 +20,7 @@
#include "mlir/Dialect/LLVMIR/ROCDLDialect.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/Target/LLVM/Options.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "llvm/ADT/STLExtras.h"
@@ -69,6 +70,17 @@ void GpuModuleToBinaryPass::runOnOperation() {
if (!targetFormat)
getOperation()->emitError() << "Invalid format specified.";
+ auto lFlags =
+ llvm::StringSwitch<std::optional<LLVM::LinkingFlags>>(linkingFlags)
+ .Case("only-needed", LLVM::LinkingFlags::onlyNeeded)
+ .Case("override", LLVM::LinkingFlags::overrideFromSrc)
+ .Cases("none", "", LLVM::LinkingFlags::none)
+ .Case("override-only-needed", LLVM::LinkingFlags::overrideFromSrc |
+ LLVM::LinkingFlags::onlyNeeded)
+ .Default(std::nullopt);
+ if (!lFlags)
+ getOperation()->emitError() << "Invalid linking options specified.";
+
// Lazy symbol table builder callback.
std::optional<SymbolTable> parentTable;
auto lazyTableBuilder = [&]() -> SymbolTable * {
@@ -85,7 +97,7 @@ void GpuModuleToBinaryPass::runOnOperation() {
};
TargetOptions targetOptions(toolkitPath, linkFiles, cmdOptions, *targetFormat,
- lazyTableBuilder);
+ *lFlags, lazyTableBuilder);
if (failed(transformGpuModulesToBinaries(
getOperation(),
offloadingHandler ? dyn_cast<OffloadingLLVMTranslationAttrInterface>(
diff --git a/mlir/lib/Target/LLVM/ModuleToObject.cpp b/mlir/lib/Target/LLVM/ModuleToObject.cpp
index d94c10de8d7c42..258656173c7239 100644
--- a/mlir/lib/Target/LLVM/ModuleToObject.cpp
+++ b/mlir/lib/Target/LLVM/ModuleToObject.cpp
@@ -35,9 +35,10 @@ using namespace mlir;
using namespace mlir::LLVM;
ModuleToObject::ModuleToObject(Operation &module, StringRef triple,
- StringRef chip, StringRef features, int optLevel)
+ StringRef chip, StringRef features, int optLevel,
+ LinkingFlags linkingFlags)
: module(module), triple(triple), chip(chip), features(features),
- optLevel(optLevel) {}
+ optLevel(optLevel), linkingFlags(linkingFlags) {}
ModuleToObject::~ModuleToObject() = default;
@@ -107,6 +108,15 @@ ModuleToObject::translateToLLVMIR(llvm::LLVMContext &llvmContext) {
return translateModuleToLLVMIR(&getOperation(), llvmContext);
}
+static unsigned convertFlags(LinkingFlags flags) {
+ unsigned res = llvm::Linker::Flags::None;
+ if ((flags & LinkingFlags::onlyNeeded) == LinkingFlags::onlyNeeded)
+ res |= llvm::Linker::Flags::LinkOnlyNeeded;
+ if ((flags & LinkingFlags::overrideFromSrc) == LinkingFlags::overrideFromSrc)
+ res |= llvm::Linker::Flags::OverrideFromSrc;
+ return res;
+}
+
LogicalResult
ModuleToObject::linkFiles(llvm::Module &module,
SmallVector<std::unique_ptr<llvm::Module>> &&libs) {
@@ -116,12 +126,9 @@ ModuleToObject::linkFiles(llvm::Module &module,
for (std::unique_ptr<llvm::Module> &libModule : libs) {
// This bitcode linking imports the library functions into the module,
// allowing LLVM optimization passes (which must run after linking) to
- // optimize across the libraries and the module's code. We also only import
- // symbols if they are referenced by the module or a previous library since
- // there will be no other source of references to those symbols in this
- // compilation and since we don't want to bloat the resulting code object.
+ // optimize across the libraries and the module's code.
bool err = linker.linkInModule(
- std::move(libModule), llvm::Linker::Flags::LinkOnlyNeeded,
+ std::move(libModule), convertFlags(linkingFlags),
[](llvm::Module &m, const StringSet<> &gvs) {
llvm::internalizeModule(m, [&gvs](const llvm::GlobalValue &gv) {
return !gv.hasName() || (gvs.count(gv.getName()) == 0);
diff --git a/mlir/lib/Target/LLVM/NVVM/Target.cpp b/mlir/lib/Target/LLVM/NVVM/Target.cpp
index eaf94147e2a6f1..4782158af102de 100644
--- a/mlir/lib/Target/LLVM/NVVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/NVVM/Target.cpp
@@ -84,7 +84,8 @@ SerializeGPUModuleBase::SerializeGPUModuleBase(
Operation &module, NVVMTargetAttr target,
const gpu::TargetOptions &targetOptions)
: ModuleToObject(module, target.getTriple(), target.getChip(),
- target.getFeatures(), target.getO()),
+ target.getFeatures(), target.getO(),
+ targetOptions.getLinkingFlags()),
target(target), toolkitPath(targetOptions.getToolkitPath()),
fileList(targetOptions.getLinkFiles()) {
diff --git a/mlir/lib/Target/LLVM/ROCDL/Target.cpp b/mlir/lib/Target/LLVM/ROCDL/Target.cpp
index a589e5cbbb6198..94d97242d1023d 100644
--- a/mlir/lib/Target/LLVM/ROCDL/Target.cpp
+++ b/mlir/lib/Target/LLVM/ROCDL/Target.cpp
@@ -98,7 +98,8 @@ SerializeGPUModuleBase::SerializeGPUModuleBase(
Operation &module, ROCDLTargetAttr target,
const gpu::TargetOptions &targetOptions)
: ModuleToObject(module, target.getTriple(), target.getChip(),
- target.getFeatures(), target.getO()),
+ target.getFeatures(), target.getO(),
+ targetOptions.getLinkingFlags()),
target(target), toolkitPath(targetOptions.getToolkitPath()),
fileList(targetOptions.getLinkFiles()) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/78050
More information about the Mlir-commits
mailing list