IRGen: Introduce the option to use the new llvm pass manager

This commit is contained in:
Arnold Schwaighofer
2022-07-15 08:16:45 -07:00
parent 5c9eab0f6c
commit 3dac6c9f90

View File

@@ -14,7 +14,7 @@
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "irgen"
#include "../Serialization/ModuleFormat.h"
#include "IRGenModule.h"
#include "swift/ABI/MetadataValues.h"
#include "swift/AST/DiagnosticsIRGen.h"
@@ -44,7 +44,6 @@
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/Subsystems.h"
#include "swift/TBDGen/TBDGen.h"
#include "../Serialization/ModuleFormat.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/ADT/StringSet.h"
@@ -59,12 +58,15 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Linker/Linker.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -79,6 +81,7 @@
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
@@ -93,6 +96,8 @@ using namespace swift;
using namespace irgen;
using namespace llvm;
#define DEBUG_TYPE "irgen"
static cl::opt<bool> DisableObjCARCContract(
"disable-objc-arc-contract", cl::Hidden,
cl::desc("Disable running objc arc contract for testing purposes"));
@@ -216,6 +221,22 @@ void setModuleFlags(IRGenModule &IGM) {
}
}
static void align(llvm::Module *Module) {
// For performance benchmarking: Align the module to the page size by
// aligning the first function of the module.
unsigned pageSize =
#if HAVE_UNISTD_H
sysconf(_SC_PAGESIZE));
#else
4096; // Use a default value
#endif
for (auto I = Module->begin(), E = Module->end(); I != E; ++I) {
if (!I->isDeclaration()) {
I->setAlignment(llvm::MaybeAlign(pageSize));
break;
}
}
}
static void
performOptimizationsUsingLegacyPassManger(const IRGenOptions &Opts,
llvm::Module *Module,
@@ -373,27 +394,197 @@ performOptimizationsUsingLegacyPassManger(const IRGenOptions &Opts,
ModulePasses.run(*Module);
if (AlignModuleToPageSize) {
// For performance benchmarking: Align the module to the page size by
// aligning the first function of the module.
unsigned pageSize =
#if HAVE_UNISTD_H
sysconf(_SC_PAGESIZE));
#else
4096; // Use a default value
#endif
for (auto I = Module->begin(), E = Module->end(); I != E; ++I) {
if (!I->isDeclaration()) {
I->setAlignment(llvm::MaybeAlign(pageSize));
break;
}
}
align(Module);
}
}
static void
performOptimizationsUsingNewPassManger(const IRGenOptions &Opts,
llvm::Module *Module,
llvm::TargetMachine *TargetMachine) {}
llvm::TargetMachine *TargetMachine) {
Optional<PGOOptions> PGOOpt;
PipelineTuningOptions PTO;
bool RunSwiftMergeFunctions = true;
// LLVM MergeFunctions and SwiftMergeFunctions don't understand that the
// string in the metadata on calls in @llvm.type.checked.load intrinsics is
// semantically meaningful, and mis-compile (mis-merge) unrelated functions.
if (Opts.VirtualFunctionElimination || Opts.WitnessMethodElimination) {
RunSwiftMergeFunctions = false;
}
bool RunSwiftSpecificLLVMOptzns =
!Opts.DisableSwiftSpecificLLVMOptzns && !Opts.DisableLLVMOptzns;
PTO.CallGraphProfile = false;
llvm::OptimizationLevel level = llvm::OptimizationLevel::O0;
if (Opts.shouldOptimize() && !Opts.DisableLLVMOptzns) {
// For historical reasons, loop interleaving is set to mirror setting for
// loop unrolling.
PTO.LoopInterleaving = true;
PTO.LoopVectorization = true;
PTO.SLPVectorization = true;
PTO.MergeFunctions = RunSwiftMergeFunctions;
level = llvm::OptimizationLevel::Os;
} else {
level = llvm::OptimizationLevel::O0;
}
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
bool DebugPassStructure = false;
PassInstrumentationCallbacks PIC;
PrintPassOptions PrintPassOpts;
PrintPassOpts.Indent = DebugPassStructure;
PrintPassOpts.SkipAnalyses = DebugPassStructure;
StandardInstrumentations SI(DebugPassStructure, /*VerifyEach*/ false,
PrintPassOpts);
SI.registerCallbacks(PIC, &FAM);
PassBuilder PB(TargetMachine, PTO, PGOOpt, &PIC);
// Register the AA manager first so that our version is the one used.
FAM.registerPass([&] {
auto AA = PB.buildDefaultAAPipeline();
if (RunSwiftSpecificLLVMOptzns)
AA.registerFunctionAnalysis<SwiftAA>();
return AA;
});
FAM.registerPass([&] { return SwiftAA(); });
// Register all the basic analyses with the managers.
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
ModulePassManager MPM;
if (RunSwiftSpecificLLVMOptzns) {
PB.registerScalarOptimizerLateEPCallback(
[](FunctionPassManager &FPM, OptimizationLevel Level) {
if (Level != OptimizationLevel::O0)
FPM.addPass(SwiftARCOptPass());
});
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level) {
if (Level != OptimizationLevel::O0)
MPM.addPass(createModuleToFunctionPassAdaptor(SwiftARCContractPass()));
});
}
// PassBuilder adds coroutine passes per default.
//
if (Opts.Sanitizers & SanitizerKind::Address) {
PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM,
OptimizationLevel Level) {
auto Recover = bool(Opts.SanitizersWithRecoveryInstrumentation &
SanitizerKind::Address);
bool UseAfterScope = false;
bool ModuleUseAfterScope = true;
bool UseOdrIndicator = Opts.SanitizeAddressUseODRIndicator;
llvm::AsanDtorKind DestructorKind = llvm::AsanDtorKind::Global;
llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
llvm::AsanDetectStackUseAfterReturnMode::Runtime;
MPM.addPass(
RequireAnalysisPass<ASanGlobalsMetadataAnalysis, llvm::Module>());
MPM.addPass(ModuleAddressSanitizerPass(false, Recover,
ModuleUseAfterScope,
UseOdrIndicator, DestructorKind));
MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
{false, Recover, UseAfterScope, UseAfterReturn})));
});
}
if (Opts.Sanitizers & SanitizerKind::Thread) {
PB.registerOptimizerLastEPCallback(
[&](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(ModuleThreadSanitizerPass());
MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
});
}
if (Opts.SanitizeCoverage.CoverageType !=
llvm::SanitizerCoverageOptions::SCK_None) {
PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM,
OptimizationLevel Level) {
std::vector<std::string> allowlistFiles;
std::vector<std::string> ignorelistFiles;
MPM.addPass(ModuleSanitizerCoveragePass(Opts.SanitizeCoverage,
allowlistFiles, ignorelistFiles));
});
}
if (RunSwiftSpecificLLVMOptzns && RunSwiftMergeFunctions) {
PB.registerOptimizerLastEPCallback(
[&](ModulePassManager &MPM, OptimizationLevel Level) {
if (Level != OptimizationLevel::O0) {
const PointerAuthSchema &schema = Opts.PointerAuth.FunctionPointers;
unsigned key = (schema.isEnabled() ? schema.getKey() : 0);
MPM.addPass(SwiftMergeFunctionsPass(schema.isEnabled(), key));
}
});
}
if (RunSwiftSpecificLLVMOptzns) {
PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM,
OptimizationLevel Level) {
MPM.addPass(
createModuleToFunctionPassAdaptor(SwiftDbgAddrBlockSplitterPass()));
});
}
if (Opts.GenerateProfile) {
InstrProfOptions options;
options.Atomic = bool(Opts.Sanitizers & SanitizerKind::Thread);
PB.registerPipelineStartEPCallback(
[options](ModulePassManager &MPM, OptimizationLevel level) {
MPM.addPass(InstrProfiling(options, false));
});
}
if (!Opts.shouldOptimize() || Opts.DisableLLVMOptzns) {
MPM = PB.buildO0DefaultPipeline(level, false);
} else {
MPM = PB.buildPerModuleDefaultPipeline(level);
}
// Make sure we do ARC contraction under optimization. We don't
// rely on any other LLVM ARC transformations, but we do need ARC
// contraction to add the objc_retainAutoreleasedReturnValue
// assembly markers and remove clang.arc.used.
if (Opts.shouldOptimize() && !DisableObjCARCContract &&
!Opts.DisableLLVMOptzns)
MPM.addPass(createModuleToFunctionPassAdaptor(ObjCARCContractPass()));
if (Opts.Verify) {
// Run verification before we run the pipeline.
ModulePassManager VerifyPM;
VerifyPM.addPass(VerifierPass());
VerifyPM.run(*Module, MAM);
// PB.registerPipelineStartEPCallback(
// [](ModulePassManager &MPM, OptimizationLevel Level) {
// MPM.addPass(VerifierPass());
// });
// Run verification after we ran the pipeline;
MPM.addPass(VerifierPass());
}
if (Opts.PrintInlineTree)
MPM.addPass(InlineTreePrinterPass());
if (!Opts.DisableLLVMOptzns)
MPM.run(*Module, MAM);
if (AlignModuleToPageSize) {
align(Module);
}
}
void swift::performLLVMOptimizations(const IRGenOptions &Opts,
llvm::Module *Module,