-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Add -mlink-builtin-bitcode option to fc1 #94763
Conversation
This patch enables the -mlink-builtin-bitcode flag in fc1 so that bitcode libraries can be linked in. This is needed for OpenMP offloading libraries.
@llvm/pr-subscribers-flang-driver @llvm/pr-subscribers-clang Author: Jan Leyonberg (jsjodin) ChangesThis patch enables the -mlink-builtin-bitcode flag in fc1 so that bitcode libraries can be linked in. This is needed for OpenMP offloading libraries. Full diff: https://github.com/llvm/llvm-project/pull/94763.diff 7 Files Affected:
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d44faa55c456f..490538ce753e0 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7028,6 +7028,12 @@ def as_secure_log_file : Separate<["-"], "as-secure-log-file">,
} // let Visibility = [CC1Option, CC1AsOption]
+let Visibility = [CC1Option, FC1Option] in {
+def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
+ HelpText<"Link and internalize needed symbols from the given bitcode file "
+ "before performing optimizations.">;
+} // let Visibility = [CC1Option, FC1Option]
+
let Visibility = [CC1Option] in {
def llvm_verify_each : Flag<["-"], "llvm-verify-each">,
@@ -7130,9 +7136,6 @@ defm constructor_aliases : BoolMOption<"constructor-aliases",
" emitting complete constructors and destructors as aliases when possible">>;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
-def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
- HelpText<"Link and internalize needed symbols from the given bitcode file "
- "before performing optimizations.">;
defm link_builtin_bitcode_postopt: BoolMOption<"link-builtin-bitcode-postopt",
CodeGenOpts<"LinkBitcodePostopt">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Link builtin bitcodes after the "
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index 918192abae724..3bc5d93c4c43e 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -56,6 +56,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// are offloading binaries containing device images and metadata.
std::vector<std::string> OffloadObjects;
+ /// List of filenames passed in using the -mlink-builtin-bitcode. These
+ /// are bc libraries that should be linked in and internalized;
+ std::vector<std::string> BuiltinBCLibs;
+
/// The directory where temp files are stored if specified by -save-temps
std::optional<std::string> SaveTempsDir;
diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 7823565eb815f..0a9a9c3401d1d 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -223,9 +223,12 @@ class CodeGenAction : public FrontendAction {
std::unique_ptr<llvm::LLVMContext> llvmCtx;
std::unique_ptr<llvm::Module> llvmModule;
- /// Embeds offload objects given with specified with -fembed-offload-object
+ /// Embeds offload objects specified with -fembed-offload-object
void embedOffloadObjects();
+ /// Links in BC libraries spefified with -fmlink-builtin-bitcode
+ void linkBuiltinBCLibs();
+
/// Runs pass pipeline to lower HLFIR into FIR
void lowerHLFIRToFIR();
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f64a939b785ef..f96d72f1ad691 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -347,6 +347,11 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
opts.SaveTempsDir = a->getValue();
+ // -mlink-builtin-bitcode
+ for (auto *a :
+ args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode))
+ opts.BuiltinBCLibs.push_back(a->getValue());
+
// -mrelocation-model option.
if (const llvm::opt::Arg *a =
args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index b1b6391f1439c..c2e6af58ffd79 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -43,6 +43,8 @@
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -54,6 +56,7 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/Linker/Linker.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
@@ -68,6 +71,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
+#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <memory>
#include <system_error>
@@ -1146,6 +1150,54 @@ void CodeGenAction::embedOffloadObjects() {
}
}
+void CodeGenAction::linkBuiltinBCLibs() {
+ auto options = clang::FileSystemOptions();
+ clang::FileManager fileManager(options);
+ CompilerInstance &ci = this->getInstance();
+ const auto &cgOpts = ci.getInvocation().getCodeGenOpts();
+
+ std::vector<std::unique_ptr<llvm::Module>> modules;
+
+ // Load LLVM modules
+ for (llvm::StringRef bcLib : cgOpts.BuiltinBCLibs) {
+ auto BCBuf = fileManager.getBufferForFile(bcLib);
+ if (!BCBuf) {
+ auto diagID = ci.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "could not open '%0' for linking");
+ ci.getDiagnostics().Report(diagID) << bcLib;
+ return;
+ }
+
+ llvm::Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
+ getOwningLazyBitcodeModule(std::move(*BCBuf), *llvmCtx);
+ if (!ModuleOrErr) {
+ auto diagID = ci.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "error loading '%0' for linking");
+ ci.getDiagnostics().Report(diagID) << bcLib;
+ return;
+ }
+ modules.push_back(std::move(ModuleOrErr.get()));
+ }
+
+ // Link modules and internalize functions
+ for (auto &module : modules) {
+ bool Err;
+ Err = llvm::Linker::linkModules(
+ *llvmModule, std::move(module), llvm::Linker::Flags::LinkOnlyNeeded,
+ [](llvm::Module &M, const llvm::StringSet<> &GVS) {
+ llvm::internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
+ return !GV.hasName() || (GVS.count(GV.getName()) == 0);
+ });
+ });
+ if (Err) {
+ auto diagID = ci.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "link error when linking '%0'");
+ ci.getDiagnostics().Report(diagID) << module->getSourceFileName();
+ return;
+ }
+ }
+}
+
static void reportOptRecordError(llvm::Error e, clang::DiagnosticsEngine &diags,
const CodeGenOptions &codeGenOpts) {
handleAllErrors(
@@ -1237,6 +1289,10 @@ void CodeGenAction::executeAction() {
llvmModule->setTargetTriple(theTriple);
llvmModule->setDataLayout(targetMachine.createDataLayout());
+ // Link in builtin bitcode libraries
+ if (!codeGenOpts.BuiltinBCLibs.empty())
+ linkBuiltinBCLibs();
+
// Embed offload objects specified with -fembed-offload-object
if (!codeGenOpts.OffloadObjects.empty())
embedOffloadObjects();
diff --git a/flang/test/Driver/Inputs/bclib.bc b/flang/test/Driver/Inputs/bclib.bc
new file mode 100644
index 0000000000000..bf97a6cd3dbe1
Binary files /dev/null and b/flang/test/Driver/Inputs/bclib.bc differ
diff --git a/flang/test/Driver/mlink-builtin-bc.f90 b/flang/test/Driver/mlink-builtin-bc.f90
new file mode 100644
index 0000000000000..0d655a24a7a63
--- /dev/null
+++ b/flang/test/Driver/mlink-builtin-bc.f90
@@ -0,0 +1,18 @@
+
+!----------
+! RUN lines
+!----------
+! Embed something that can be easily checked
+! RUN: %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu -o - -mlink-builtin-bitcode %S/Inputs/bclib.bc %s 2>&1 | FileCheck %s
+
+! CHECK: define internal void @libfun_
+
+! RUN1: not %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu -o - -mlink-builtin-bitcode %S/Inputs/no-bclib.bc %s 2>&1 | FileCheck %s
+
+! ERROR1: error: could not open {{.*}} no-bclib.bc
+
+external libfun
+parameter(i=1)
+integer :: j
+call libfun(j)
+end program
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. Minor nits on "binary files in repo" and duplication of code [although I couldn't find the corresponding bit in Clang - I didn't spend much time on searching for it].
flang/test/Driver/Inputs/bclib.bc
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to generate this, rather than supply it as a binary - just out of safety-concerns with binaries, really.
I expect the contents isn't particularly complex or time-consuming to build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it should be possible to add a command to generate the .bc file, that is probably a better option anyway since we would avoid specifying the triple.
@@ -1146,6 +1150,54 @@ void CodeGenAction::embedOffloadObjects() { | |||
} | |||
} | |||
|
|||
void CodeGenAction::linkBuiltinBCLibs() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a fairly large chunk of code - does it come from Clang in some way - if so, is it possible to have one common function shared, rather than two copies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does come from clang but it is distributed across a few classes with a lot more options, so there was not simple way to simply re-use the code. I don't know if we want to bring in all that code since it would add a lot more complexity, and I don't know if we need this in the future or not.
|
||
! CHECK: define internal void @libfun_ | ||
|
||
! RUN1: not %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu -o - -mlink-builtin-bitcode %S/Inputs/no-bclib.bc %s 2>&1 | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's RUN1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, I was testing things out and it got in.
|
||
! RUN1: not %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu -o - -mlink-builtin-bitcode %S/Inputs/no-bclib.bc %s 2>&1 | FileCheck %s | ||
|
||
! ERROR1: error: could not open {{.*}} no-bclib.bc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's ERROR1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
!---------- | ||
! RUN lines | ||
!---------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the past, folks asked not to add such comments in tests. Let's stick with that.
! RUN lines | ||
!---------- | ||
! Embed something that can be easily checked | ||
! RUN: %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu -o - -mlink-builtin-bitcode %S/Inputs/bclib.bc %s 2>&1 | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
What's bclib.bc and what makes it easy to check?
-
Does the triple matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The triple matters because when linking the data layout in bclib.bc must match the data layout of the compiled source code, and depending on the host it may not be the same so it is safest to specify the triple to ensure they are the same. However if the .bc file is generated also, then we can avoid specifying the triple.
@@ -1146,6 +1150,54 @@ void CodeGenAction::embedOffloadObjects() { | |||
} | |||
} | |||
|
|||
void CodeGenAction::linkBuiltinBCLibs() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but please do wait on the other more knowledgeable reviewers approvals :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick, otherwise OK by me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Fix comment Co-authored-by: Sergio Afonso <safonsof@amd.com>
This patch enables the -mlink-builtin-bitcode flag in fc1 so that bitcode libraries can be linked in. This is needed for OpenMP offloading libraries.