aboutsummaryrefslogtreecommitdiff
path: root/src/zig_llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zig_llvm.cpp')
-rw-r--r--src/zig_llvm.cpp231
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;
}