diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-04-02 14:35:01 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-04-02 14:35:45 -0700 |
| commit | 09008125e7944ae01bb907f2eb8dbff41d7a0715 (patch) | |
| tree | 67aa1d250bfe9dda56632ce6eb2fcbb1929cc5c7 /src/zig_llvm.cpp | |
| parent | ba1bea2fe87b73a53a3ecd729789853dcc56affe (diff) | |
| download | zig-09008125e7944ae01bb907f2eb8dbff41d7a0715.tar.gz zig-09008125e7944ae01bb907f2eb8dbff41d7a0715.zip | |
Revert back to the old LLVM PassManager
See #8418
This reverts commit ba1bea2fe87b73a53a3ecd729789853dcc56affe.
This reverts commit 94383d14df77fa638dac14f4b2bda5a2e3f21c5c.
This reverts commit 0d53a2bff01750f9220bcc861d662b2c5f304506.
Diffstat (limited to 'src/zig_llvm.cpp')
| -rw-r--r-- | src/zig_llvm.cpp | 231 |
1 files changed, 96 insertions, 135 deletions
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index d26dc97874..5a7d60f83b 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -20,7 +20,6 @@ #pragma GCC diagnostic ignored "-Winit-list-lifetime" #endif -#include <llvm/Analysis/AliasAnalysis.h> #include <llvm/Analysis/TargetLibraryInfo.h> #include <llvm/Analysis/TargetTransformInfo.h> #include <llvm/Bitcode/BitcodeWriter.h> @@ -31,12 +30,9 @@ #include <llvm/IR/Instructions.h> #include <llvm/IR/LegacyPassManager.h> #include <llvm/IR/Module.h> -#include <llvm/IR/PassManager.h> #include <llvm/IR/Verifier.h> #include <llvm/InitializePasses.h> #include <llvm/MC/SubtargetFeature.h> -#include <llvm/Passes/PassBuilder.h> -#include <llvm/Passes/StandardInstrumentations.h> #include <llvm/Object/Archive.h> #include <llvm/Object/ArchiveWriter.h> #include <llvm/Object/COFF.h> @@ -58,9 +54,6 @@ #include <llvm/Transforms/Instrumentation/ThreadSanitizer.h> #include <llvm/Transforms/Scalar.h> #include <llvm/Transforms/Utils.h> -#include <llvm/Transforms/Utils/AddDiscriminators.h> -#include <llvm/Transforms/Utils/CanonicalizeAliases.h> -#include <llvm/Transforms/Utils/NameAnonGlobals.h> #include <lld/Common/Driver.h> @@ -98,6 +91,14 @@ char *ZigLLVMGetNativeFeatures(void) { return strdup((const char *)StringRef(features.getString()).bytes_begin()); } +static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { + PM.add(createAddDiscriminatorsPass()); +} + +static void addThreadSanitizerPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { + PM.add(createThreadSanitizerLegacyPassPass()); +} + #ifndef NDEBUG static const bool assertions_on = true; #else @@ -187,16 +188,14 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM bool is_small, bool time_report, bool tsan, bool lto, const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename) { - // TODO: Maybe we should collect time trace rather than using timer - // to get a more hierarchical timeline view TimePassesIsEnabled = time_report; - raw_fd_ostream *dest_asm_ptr = nullptr; - raw_fd_ostream *dest_bin_ptr = nullptr; + raw_fd_ostream *dest_asm = nullptr; + raw_fd_ostream *dest_bin = nullptr; if (asm_filename) { std::error_code EC; - dest_asm_ptr = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); + dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; @@ -204,155 +203,117 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM } if (bin_filename) { std::error_code EC; - dest_bin_ptr = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); + dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); if (EC) { *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); return true; } } - std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr), - dest_bin(dest_bin_ptr); - - TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref); - target_machine.setO0WantsFastISel(true); - - Module &module = *unwrap(module_ref); - - // Pipeline configurations - PipelineTuningOptions pipeline_opts; - pipeline_opts.LoopUnrolling = !is_debug; - pipeline_opts.SLPVectorization = !is_debug; - pipeline_opts.LoopVectorization = !is_debug; - pipeline_opts.LoopInterleaving = !is_debug; - pipeline_opts.MergeFunctions = !is_debug; - - // Instrumentations - PassInstrumentationCallbacks instr_callbacks; - StandardInstrumentations std_instrumentations(false); - std_instrumentations.registerCallbacks(instr_callbacks); - - PassBuilder pass_builder(false, &target_machine, pipeline_opts, - None, &instr_callbacks); - using OptimizationLevel = typename PassBuilder::OptimizationLevel; - - LoopAnalysisManager loop_am; - FunctionAnalysisManager function_am; - CGSCCAnalysisManager cgscc_am; - ModuleAnalysisManager module_am; - - // Register the AA manager first so that our version is the one used - function_am.registerPass([&] { - return pass_builder.buildDefaultAAPipeline(); - }); - - Triple target_triple(module.getTargetTriple()); - auto tlii = std::make_unique<TargetLibraryInfoImpl>(target_triple); - function_am.registerPass([&] { return TargetLibraryAnalysis(*tlii); }); - - // Initialize the AnalysisManagers - pass_builder.registerModuleAnalyses(module_am); - pass_builder.registerCGSCCAnalyses(cgscc_am); - pass_builder.registerFunctionAnalyses(function_am); - pass_builder.registerLoopAnalyses(loop_am); - pass_builder.crossRegisterProxies(loop_am, function_am, - cgscc_am, module_am); - - // IR verification - if (assertions_on) { - // Verify the input - pass_builder.registerPipelineStartEPCallback( - [](ModulePassManager &module_pm, OptimizationLevel OL) { - module_pm.addPass(VerifierPass()); - }); - // Verify the output - pass_builder.registerOptimizerLastEPCallback( - [](ModulePassManager &module_pm, OptimizationLevel OL) { - module_pm.addPass(VerifierPass()); - }); + TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref); + target_machine->setO0WantsFastISel(true); + + Module* module = unwrap(module_ref); + + PassManagerBuilder *PMBuilder = new(std::nothrow) PassManagerBuilder(); + if (PMBuilder == nullptr) { + *error_message = strdup("memory allocation failure"); + return true; } + PMBuilder->OptLevel = target_machine->getOptLevel(); + PMBuilder->SizeLevel = is_small ? 2 : 0; + + PMBuilder->DisableTailCalls = is_debug; + PMBuilder->DisableUnrollLoops = is_debug; + PMBuilder->SLPVectorize = !is_debug; + PMBuilder->LoopVectorize = !is_debug; + PMBuilder->LoopsInterleaved = !PMBuilder->DisableUnrollLoops; + PMBuilder->RerollLoops = !is_debug; + // Leaving NewGVN as default (off) because when on it caused issue #673 + //PMBuilder->NewGVN = !is_debug; + PMBuilder->DisableGVNLoadPRE = is_debug; + PMBuilder->VerifyInput = assertions_on; + PMBuilder->VerifyOutput = assertions_on; + PMBuilder->MergeFunctions = !is_debug; + PMBuilder->PrepareForLTO = lto; + PMBuilder->PrepareForThinLTO = false; + PMBuilder->PerformThinLTO = false; + + TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple())); + PMBuilder->LibraryInfo = &tlii; - // Passes for either debug or release build if (is_debug) { - // NOTE: Always inliner will go away (in debug build) - // when the self-hosted compiler becomes mature. - pass_builder.registerPipelineStartEPCallback( - [](ModulePassManager &module_pm, OptimizationLevel OL) { - module_pm.addPass(AlwaysInlinerPass()); - }); + PMBuilder->Inliner = createAlwaysInlinerLegacyPass(false); } else { - pass_builder.registerPipelineStartEPCallback( - [](ModulePassManager &module_pm, OptimizationLevel OL) { - module_pm.addPass( - createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); - }); + target_machine->adjustPassManager(*PMBuilder); + + PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addDiscriminatorsPass); + PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false); } - // Thread sanitizer if (tsan) { - pass_builder.registerOptimizerLastEPCallback( - [](ModulePassManager &module_pm, OptimizationLevel level) { - module_pm.addPass(ThreadSanitizerPass()); - }); + PMBuilder->addExtension(PassManagerBuilder::EP_OptimizerLast, addThreadSanitizerPass); + PMBuilder->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, addThreadSanitizerPass); } - ModulePassManager module_pm; - OptimizationLevel opt_level; - // Setting up the optimization level - if (is_debug) - opt_level = OptimizationLevel::O0; - else if (is_small) - opt_level = OptimizationLevel::Oz; - else - opt_level = OptimizationLevel::O3; - - // Initialize the PassManager - if (lto) { - module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level); - module_pm.addPass(CanonicalizeAliasesPass()); - module_pm.addPass(NameAnonGlobalPass()); - } else { - module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level); + // Set up the per-function pass manager. + legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module); + auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii); + FPM.add(tliwp); + FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); + if (assertions_on) { + FPM.add(createVerifierPass()); } - - // Unfortunately we don't have new PM for code generation - legacy::PassManager codegen_pm; - codegen_pm.add( - createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis())); - - if (dest_bin && !lto) { - if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CGFT_ObjectFile)) { - *error_message = strdup("TargetMachine can't emit an object file"); - return true; + PMBuilder->populateFunctionPassManager(FPM); + + { + // Set up the per-module pass manager. + legacy::PassManager MPM; + MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); + PMBuilder->populateModulePassManager(MPM); + + // Set output passes. + if (dest_bin && !lto) { + if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, CGFT_ObjectFile)) { + *error_message = strdup("TargetMachine can't emit an object file"); + return true; + } } - } - if (dest_asm) { - if (target_machine.addPassesToEmitFile(codegen_pm, *dest_asm, nullptr, CGFT_AssemblyFile)) { - *error_message = strdup("TargetMachine can't emit an assembly file"); - return true; + if (dest_asm) { + if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, CGFT_AssemblyFile)) { + *error_message = strdup("TargetMachine can't emit an assembly file"); + return true; + } } - } - // Optimization phase - module_pm.run(module, module_am); + // run per function optimization passes + FPM.doInitialization(); + for (Function &F : *module) + if (!F.isDeclaration()) + FPM.run(F); + FPM.doFinalization(); - // Code generation phase - codegen_pm.run(module); + MPM.run(*module); - if (llvm_ir_filename) { - if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { - return true; + if (llvm_ir_filename) { + if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { + return true; + } + } + if (dest_bin && lto) { + WriteBitcodeToFile(*module, *dest_bin); } - } - if (dest_bin && lto) { - WriteBitcodeToFile(module, *dest_bin); - } + if (time_report) { + TimerGroup::printAll(errs()); + } - if (time_report) { - TimerGroup::printAll(errs()); + // MPM goes out of scope and writes to the out streams } + delete dest_asm; + delete dest_bin; + return false; } |
