mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
IRGen: Introduce the option to use the new llvm pass manager
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user