Skip to content

Commit f609afa

Browse files
committed
Add --funified-lto command-line option, same as clang.
1 parent da9e190 commit f609afa

5 files changed

Lines changed: 85 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- `clang --target=aarch64-linux-gnu`
1717
- The prebuilt arm64/universal macOS packages additionally bundle the arm64 iOS-*simulator* libraries, for out-of-the-box cross-compilation support via e.g. `-mtriple=arm64-apple-ios12.0-simulator`. (#4974)
1818
- New `--fdebug-prefix-map` command-line option and changed debuginfo file/directory name splitting logic (both now similar to clang), to aid reproducible builds. (#5039)
19+
- New `--funified-lto` command-line option, same as clang.
1920

2021
#### Platform support
2122
- Supports LLVM 15 - 21.

driver/cl_options.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,8 @@ cl::opt<bool> ltoFatObjects(
732732
"ffat-lto-objects", cl::ZeroOrMore,
733733
cl::desc("Include both IR and object code in object file output; only "
734734
"effective when compiling with -flto."));
735+
cl::opt<bool> ltoUnified("funified-lto", cl::ZeroOrMore,
736+
cl::desc("Use unified LTO pipeline."));
735737

736738
cl::opt<std::string>
737739
saveOptimizationRecord("fsave-optimization-record",

driver/cl_options.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,11 @@ enum LTOKind {
131131
LTO_Thin,
132132
};
133133
extern cl::opt<LTOKind> ltoMode;
134+
extern cl::opt<bool> ltoFatObjects;
135+
extern cl::opt<bool> ltoUnified;
134136
inline bool isUsingLTO() { return ltoMode != LTO_None; }
135137
inline bool isUsingThinLTO() { return ltoMode == LTO_Thin; }
136-
extern cl::opt<bool> ltoFatObjects;
138+
inline bool prepareForThinLTO() { return isUsingThinLTO() || opts::ltoUnified; }
137139

138140
extern cl::opt<std::string> saveOptimizationRecord;
139141

gen/optimizer.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,24 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#ifdef IN_JITRT
14-
#include "runtime/jit-rt/cpp-so/optimizer.h"
15-
#include "runtime/jit-rt/cpp-so/valueparser.h"
16-
#include "runtime/jit-rt/cpp-so/utils.h"
17-
#endif
18-
1913
#include "gen/optimizer.h"
20-
21-
#ifndef IN_JITRT
22-
#include "dmd/errors.h"
23-
#include "gen/logger.h"
24-
#endif
25-
2614
#include "gen/passes/GarbageCollect2Stack.h"
2715
#include "gen/passes/StripExternals.h"
2816
#include "gen/passes/SimplifyDRuntimeCalls.h"
2917
#include "gen/passes/Passes.h"
3018

31-
#ifndef IN_JITRT
19+
#ifdef IN_JITRT
20+
#include "runtime/jit-rt/cpp-so/optimizer.h"
21+
#include "runtime/jit-rt/cpp-so/valueparser.h"
22+
#include "runtime/jit-rt/cpp-so/utils.h"
23+
#else
24+
#include "dmd/errors.h"
3225
#include "driver/cl_options.h"
3326
#include "driver/cl_options_instrumentation.h"
3427
#include "driver/cl_options_sanitizers.h"
3528
#include "driver/plugins.h"
3629
#include "driver/targetmachine.h"
30+
#include "gen/logger.h"
3731
#endif
3832

3933
#if LDC_LLVM_VER < 1700
@@ -355,7 +349,9 @@ static void addGarbageCollect2StackPass(ModulePassManager &mpm,
355349
}
356350
}
357351

352+
// Exclude these functions, that access cmdline options, from the JIT RT.
358353
#ifndef IN_JITRT
354+
359355
static llvm::Optional<PGOOptions> getPGOOptions() {
360356
// FIXME: Do we have these anywhere?
361357
bool debugInfoForProfiling = false;
@@ -409,6 +405,44 @@ static llvm::Optional<PGOOptions> getPGOOptions() {
409405
return std::nullopt;
410406
#endif
411407
}
408+
409+
// Imitate behavior of clang
410+
static bool shouldEmitRegularLTOSummary(llvm::Module const &M) {
411+
return opts::isUsingLTO() &&
412+
llvm::Triple(M.getTargetTriple()).getVendor() != llvm::Triple::Apple;
413+
}
414+
415+
/// Check whether we should emit a flag for UnifiedLTO.
416+
/// The UnifiedLTO module flag should be set when UnifiedLTO is enabled for
417+
/// ThinLTO or Full LTO with module summaries.
418+
static bool shouldEmitUnifiedLTOModuleFlag(llvm::Module const &M) {
419+
return opts::ltoUnified &&
420+
(opts::prepareForThinLTO() || shouldEmitRegularLTOSummary(M));
421+
}
422+
423+
static void addLTOModuleFlags(llvm::Module *M) {
424+
if (opts::ltoFatObjects) {
425+
if (opts::prepareForThinLTO()) {
426+
// TODO: implement support for EnableSplitLTOUnit
427+
// if (!M->getModuleFlag("EnableSplitLTOUnit"))
428+
// M->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
429+
// CodeGenOpts.EnableSplitLTOUnit);
430+
} else {
431+
if (shouldEmitRegularLTOSummary(*M)) {
432+
if (!M->getModuleFlag("ThinLTO") && !opts::ltoUnified)
433+
M->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0));
434+
if (!M->getModuleFlag("EnableSplitLTOUnit"))
435+
M->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
436+
uint32_t(1));
437+
}
438+
}
439+
440+
if (shouldEmitUnifiedLTOModuleFlag(*M) &&
441+
!M->getModuleFlag("UnifiedLTO"))
442+
M->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
443+
}
444+
}
445+
412446
#endif // !IN_JITRT
413447

414448
static PipelineTuningOptions getPipelineTuningOptions(unsigned optLevelVal, unsigned sizeLevelVal) {
@@ -585,12 +619,11 @@ void runOptimizationPasses(llvm::Module *M, llvm::TargetMachine *TM) {
585619
mpm = pb.buildO0DefaultPipeline(level, ltoPrelink);
586620
#if LDC_LLVM_VER >= 1700
587621
} else if (opts::ltoFatObjects && opts::isUsingLTO()) {
588-
mpm = pb.buildFatLTODefaultPipeline(level,
589-
opts::isUsingThinLTO(),
590-
opts::isUsingThinLTO()
591-
);
622+
mpm = pb.buildFatLTODefaultPipeline(level, opts::prepareForThinLTO(),
623+
opts::prepareForThinLTO() ||
624+
shouldEmitRegularLTOSummary(*M));
592625
#endif
593-
} else if (opts::isUsingThinLTO()) {
626+
} else if (opts::prepareForThinLTO()) {
594627
mpm = pb.buildThinLTOPreLinkDefaultPipeline(level);
595628
} else if (opts::isUsingLTO()) {
596629
mpm = pb.buildLTOPreLinkDefaultPipeline(level);
@@ -599,6 +632,9 @@ void runOptimizationPasses(llvm::Module *M, llvm::TargetMachine *TM) {
599632
mpm = pb.buildPerModuleDefaultPipeline(level);
600633
}
601634

635+
#ifndef IN_JITRT
636+
addLTOModuleFlags(M);
637+
#endif
602638

603639
mpm.run(*M,mam);
604640
}

tests/linking/lto_unified.d

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Test unified lto commandline flag
2+
3+
// REQUIRES: LTO
4+
// REQUIRES: atleast_llvm1800
5+
6+
// RUN: split-file %s %t
7+
8+
// RUN: %ldc %t/second.d -of=%t/second_thin%obj -c -flto=thin
9+
// RUN: %ldc %t/third.d -of=%t/third_full%obj -c -flto=full
10+
// RUN: %ldc -I%t %t/main.d %t/second_thin%obj %t/third_full%obj -flto=full -O
11+
12+
//--- main.d
13+
import second;
14+
import third;
15+
void main()
16+
{
17+
foo();
18+
g();
19+
}
20+
21+
//--- second.d
22+
void foo() {}
23+
24+
//--- third.d
25+
void g() {}

0 commit comments

Comments
 (0)