Skip to content

Commit e32eab5

Browse files
committed
WIP NewPM
1 parent fe79fa8 commit e32eab5

File tree

3 files changed

+178
-0
lines changed

3 files changed

+178
-0
lines changed

src/librustc_codegen_llvm/back/write.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,18 @@ pub fn to_llvm_opt_settings(
111111
}
112112
}
113113

114+
pub fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel {
115+
use config::OptLevel::*;
116+
match cfg {
117+
No => llvm::PassBuilderOptLevel::O0,
118+
Less => llvm::PassBuilderOptLevel::O1,
119+
Default => llvm::PassBuilderOptLevel::O2,
120+
Aggressive => llvm::PassBuilderOptLevel::O3,
121+
Size => llvm::PassBuilderOptLevel::Os,
122+
SizeMin => llvm::PassBuilderOptLevel::Oz,
123+
}
124+
}
125+
114126
// If find_features is true this won't access `sess.crate_types` by assuming
115127
// that `is_pie_binary` is false. When we discover LLVM target features
116128
// `sess.crate_types` is uninitialized so we cannot access it.
@@ -327,6 +339,34 @@ pub(crate) unsafe fn optimize(
327339
}
328340

329341
if let Some(opt_level) = config.opt_level {
342+
let use_new_pm = true;
343+
if use_new_pm {
344+
let unroll_loops =
345+
opt_level != config::OptLevel::Size && opt_level != config::OptLevel::SizeMin;
346+
let prepare_for_thin_lto = cgcx.lto == Lto::Thin
347+
|| cgcx.lto == Lto::ThinLocal
348+
|| (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
349+
let using_thin_buffers = prepare_for_thin_lto || config.bitcode_needed();
350+
// FIXME: NewPM doesn't seem to have a facility to provide custom InlineParams.
351+
// FIXME: Extra passes.
352+
llvm::LLVMRustOptimizeWithNewPassManager(
353+
llmod,
354+
tm,
355+
to_pass_builder_opt_level(opt_level),
356+
config.no_prepopulate_passes,
357+
config.verify_llvm_ir,
358+
prepare_for_thin_lto,
359+
/* prepare_for_lto */ false, // FIXME: Actually differentiate this?
360+
using_thin_buffers,
361+
config.merge_functions,
362+
unroll_loops,
363+
config.vectorize_slp,
364+
config.vectorize_loop,
365+
config.no_builtins,
366+
);
367+
return Ok(());
368+
}
369+
330370
// Create the two optimizing pass managers. These mirror what clang
331371
// does, and are by populated by LLVM's default PassManagerBuilder.
332372
// Each manager has a different set of passes, but they also share

src/librustc_codegen_llvm/llvm/ffi.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,17 @@ pub enum CodeGenOptLevel {
402402
Aggressive,
403403
}
404404

405+
/// LLVMPassBuilderOptLevel
406+
#[repr(C)]
407+
pub enum PassBuilderOptLevel {
408+
O0,
409+
O1,
410+
O2,
411+
O3,
412+
Os,
413+
Oz,
414+
}
415+
405416
/// LLVMRelocMode
406417
#[derive(Copy, Clone, PartialEq)]
407418
#[repr(C)]
@@ -1894,6 +1905,21 @@ extern "C" {
18941905
Output: *const c_char,
18951906
FileType: FileType,
18961907
) -> LLVMRustResult;
1908+
pub fn LLVMRustOptimizeWithNewPassManager(
1909+
M: &'a Module,
1910+
TM: &'a TargetMachine,
1911+
OptLevel: PassBuilderOptLevel,
1912+
NoPrepopulatePasses: bool,
1913+
VerifyIR: bool,
1914+
PrepareForThinLTO: bool,
1915+
PrepareForLTO: bool,
1916+
UseThinLTOBuffers: bool,
1917+
MergeFunctions: bool,
1918+
UnrollLoops: bool,
1919+
SLPVectorize: bool,
1920+
LoopVectorize: bool,
1921+
DisableSimplifyLibCalls: bool,
1922+
);
18971923
pub fn LLVMRustPrintModule(
18981924
M: &'a Module,
18991925
Output: *const c_char,

src/rustllvm/PassWrapper.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "llvm/IR/AutoUpgrade.h"
1212
#include "llvm/IR/AssemblyAnnotationWriter.h"
1313
#include "llvm/IR/IntrinsicInst.h"
14+
#include "llvm/IR/Verifier.h"
15+
#include "llvm/Passes/PassBuilder.h"
16+
#include "llvm/Passes/StandardInstrumentations.h"
1417
#include "llvm/Support/CBindingWrapping.h"
1518
#include "llvm/Support/FileSystem.h"
1619
#include "llvm/Support/Host.h"
@@ -30,6 +33,8 @@
3033
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
3134
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
3235
#endif
36+
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
37+
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
3338

3439
using namespace llvm;
3540
using namespace llvm::legacy;
@@ -294,6 +299,34 @@ static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
294299
}
295300
}
296301

302+
enum class LLVMRustPassBuilderOptLevel {
303+
O0,
304+
O1,
305+
O2,
306+
O3,
307+
Os,
308+
Oz,
309+
};
310+
311+
static PassBuilder::OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
312+
switch (Level) {
313+
case LLVMRustPassBuilderOptLevel::O0:
314+
return PassBuilder::O0;
315+
case LLVMRustPassBuilderOptLevel::O1:
316+
return PassBuilder::O1;
317+
case LLVMRustPassBuilderOptLevel::O2:
318+
return PassBuilder::O2;
319+
case LLVMRustPassBuilderOptLevel::O3:
320+
return PassBuilder::O3;
321+
case LLVMRustPassBuilderOptLevel::Os:
322+
return PassBuilder::Os;
323+
case LLVMRustPassBuilderOptLevel::Oz:
324+
return PassBuilder::Oz;
325+
default:
326+
report_fatal_error("Bad PassBuilderOptLevel.");
327+
}
328+
}
329+
297330
enum class LLVMRustRelocMode {
298331
Default,
299332
Static,
@@ -571,6 +604,85 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
571604
return LLVMRustResult::Success;
572605
}
573606

607+
extern "C" void
608+
LLVMRustOptimizeWithNewPassManager(
609+
LLVMModuleRef ModuleRef,
610+
LLVMTargetMachineRef TMRef,
611+
LLVMRustPassBuilderOptLevel OptLevelRust,
612+
bool NoPrepopulatePasses, bool VerifyIR,
613+
bool PrepareForThinLTO, bool PrepareForLTO, bool UseThinLTOBuffers,
614+
bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
615+
bool DisableSimplifyLibCalls) {
616+
Module *TheModule = unwrap(ModuleRef);
617+
TargetMachine *TM = unwrap(TMRef);
618+
PassBuilder::OptimizationLevel OptLevel = fromRust(OptLevelRust);
619+
620+
// FIXME: MergeFunctions not supported by NewPM.
621+
(void) MergeFunctions;
622+
623+
PipelineTuningOptions PTO;
624+
PTO.LoopUnrolling = UnrollLoops;
625+
PTO.LoopInterleaving = UnrollLoops;
626+
PTO.LoopVectorization = LoopVectorize;
627+
PTO.SLPVectorization = SLPVectorize;
628+
629+
// FIXME: What's this?
630+
PassInstrumentationCallbacks PIC;
631+
StandardInstrumentations SI;
632+
SI.registerCallbacks(PIC);
633+
634+
// FIXME: PGOOpt
635+
Optional<PGOOptions> PGOOpt;
636+
PassBuilder PB(TM, PTO, PGOOpt, &PIC);
637+
638+
bool DebugPassManager = false;
639+
LoopAnalysisManager LAM(DebugPassManager);
640+
FunctionAnalysisManager FAM(DebugPassManager);
641+
CGSCCAnalysisManager CGAM(DebugPassManager);
642+
ModuleAnalysisManager MAM(DebugPassManager);
643+
644+
FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
645+
646+
Triple TargetTriple(TheModule->getTargetTriple());
647+
std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
648+
if (DisableSimplifyLibCalls)
649+
TLII->disableAllFunctions();
650+
FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
651+
652+
PB.registerModuleAnalyses(MAM);
653+
PB.registerCGSCCAnalyses(CGAM);
654+
PB.registerFunctionAnalyses(FAM);
655+
PB.registerLoopAnalyses(LAM);
656+
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
657+
PB.registerPipelineStartEPCallback([VerifyIR](ModulePassManager &MPM) {
658+
if (VerifyIR)
659+
MPM.addPass(VerifierPass());
660+
});
661+
662+
ModulePassManager MPM(DebugPassManager);
663+
if (!NoPrepopulatePasses) {
664+
if (OptLevel == PassBuilder::O0) {
665+
MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/false));
666+
// FIXME: PGO?
667+
} else {
668+
// FIXME: Sanitizers? PGO?
669+
if (PrepareForThinLTO) {
670+
MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
671+
} else if (PrepareForLTO) {
672+
MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager);
673+
} else {
674+
MPM = PB.buildPerModuleDefaultPipeline(OptLevel, DebugPassManager);
675+
}
676+
}
677+
}
678+
679+
if (UseThinLTOBuffers) {
680+
MPM.addPass(CanonicalizeAliasesPass());
681+
MPM.addPass(NameAnonGlobalPass());
682+
}
683+
684+
MPM.run(*TheModule, MAM);
685+
}
574686

575687
// Callback to demangle function name
576688
// Parameters:

0 commit comments

Comments
 (0)