authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-02 14:35:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-02 14:35:45-07:00
log09008125e7944ae01bb907f2eb8dbff41d7a0715
tree67aa1d250bfe9dda56632ce6eb2fcbb1929cc5c7
parentba1bea2fe87b73a53a3ecd729789853dcc56affe

Revert back to the old LLVM PassManager

See #8418 This reverts commit ba1bea2fe87b73a53a3ecd729789853dcc56affe. This reverts commit 94383d14df77fa638dac14f4b2bda5a2e3f21c5c. This reverts commit 0d53a2bff01750f9220bcc861d662b2c5f304506.

1 files changed, 96 insertions(+), 135 deletions(-)

src/zig_llvm.cpp+96-135
...@@ -20,7 +20,6 @@...@@ -20,7 +20,6 @@
20#pragma GCC diagnostic ignored "-Winit-list-lifetime"20#pragma GCC diagnostic ignored "-Winit-list-lifetime"
21#endif21#endif
2222
23#include <llvm/Analysis/AliasAnalysis.h>
24#include <llvm/Analysis/TargetLibraryInfo.h>23#include <llvm/Analysis/TargetLibraryInfo.h>
25#include <llvm/Analysis/TargetTransformInfo.h>24#include <llvm/Analysis/TargetTransformInfo.h>
26#include <llvm/Bitcode/BitcodeWriter.h>25#include <llvm/Bitcode/BitcodeWriter.h>
...@@ -31,12 +30,9 @@...@@ -31,12 +30,9 @@
31#include <llvm/IR/Instructions.h>30#include <llvm/IR/Instructions.h>
32#include <llvm/IR/LegacyPassManager.h>31#include <llvm/IR/LegacyPassManager.h>
33#include <llvm/IR/Module.h>32#include <llvm/IR/Module.h>
34#include <llvm/IR/PassManager.h>
35#include <llvm/IR/Verifier.h>33#include <llvm/IR/Verifier.h>
36#include <llvm/InitializePasses.h>34#include <llvm/InitializePasses.h>
37#include <llvm/MC/SubtargetFeature.h>35#include <llvm/MC/SubtargetFeature.h>
38#include <llvm/Passes/PassBuilder.h>
39#include <llvm/Passes/StandardInstrumentations.h>
40#include <llvm/Object/Archive.h>36#include <llvm/Object/Archive.h>
41#include <llvm/Object/ArchiveWriter.h>37#include <llvm/Object/ArchiveWriter.h>
42#include <llvm/Object/COFF.h>38#include <llvm/Object/COFF.h>
...@@ -58,9 +54,6 @@...@@ -58,9 +54,6 @@
58#include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>54#include <llvm/Transforms/Instrumentation/ThreadSanitizer.h>
59#include <llvm/Transforms/Scalar.h>55#include <llvm/Transforms/Scalar.h>
60#include <llvm/Transforms/Utils.h>56#include <llvm/Transforms/Utils.h>
61#include <llvm/Transforms/Utils/AddDiscriminators.h>
62#include <llvm/Transforms/Utils/CanonicalizeAliases.h>
63#include <llvm/Transforms/Utils/NameAnonGlobals.h>
6457
65#include <lld/Common/Driver.h>58#include <lld/Common/Driver.h>
6659
...@@ -98,6 +91,14 @@ char *ZigLLVMGetNativeFeatures(void) {...@@ -98,6 +91,14 @@ char *ZigLLVMGetNativeFeatures(void) {
98 return strdup((const char *)StringRef(features.getString()).bytes_begin());91 return strdup((const char *)StringRef(features.getString()).bytes_begin());
99}92}
10093
94static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
95 PM.add(createAddDiscriminatorsPass());
96}
97
98static void addThreadSanitizerPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
99 PM.add(createThreadSanitizerLegacyPassPass());
100}
101
101#ifndef NDEBUG102#ifndef NDEBUG
102static const bool assertions_on = true;103static const bool assertions_on = true;
103#else104#else
...@@ -187,16 +188,14 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -187,16 +188,14 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
187 bool is_small, bool time_report, bool tsan, bool lto,188 bool is_small, bool time_report, bool tsan, bool lto,
188 const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)189 const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)
189{190{
190 // TODO: Maybe we should collect time trace rather than using timer
191 // to get a more hierarchical timeline view
192 TimePassesIsEnabled = time_report;191 TimePassesIsEnabled = time_report;
193192
194 raw_fd_ostream *dest_asm_ptr = nullptr;193 raw_fd_ostream *dest_asm = nullptr;
195 raw_fd_ostream *dest_bin_ptr = nullptr;194 raw_fd_ostream *dest_bin = nullptr;
196195
197 if (asm_filename) {196 if (asm_filename) {
198 std::error_code EC;197 std::error_code EC;
199 dest_asm_ptr = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None);198 dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None);
200 if (EC) {199 if (EC) {
201 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());200 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
202 return true;201 return true;
...@@ -204,155 +203,117 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM...@@ -204,155 +203,117 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
204 }203 }
205 if (bin_filename) {204 if (bin_filename) {
206 std::error_code EC;205 std::error_code EC;
207 dest_bin_ptr = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None);206 dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None);
208 if (EC) {207 if (EC) {
209 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());208 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
210 return true;209 return true;
211 }210 }
212 }211 }
213212
214 std::unique_ptr<raw_fd_ostream> dest_asm(dest_asm_ptr),213 TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
215 dest_bin(dest_bin_ptr);214 target_machine->setO0WantsFastISel(true);
216215
217 TargetMachine &target_machine = *reinterpret_cast<TargetMachine*>(targ_machine_ref);216 Module* module = unwrap(module_ref);
218 target_machine.setO0WantsFastISel(true);217
219218 PassManagerBuilder *PMBuilder = new(std::nothrow) PassManagerBuilder();
220 Module &module = *unwrap(module_ref);219 if (PMBuilder == nullptr) {
221220 *error_message = strdup("memory allocation failure");
222 // Pipeline configurations221 return true;
223 PipelineTuningOptions pipeline_opts;
224 pipeline_opts.LoopUnrolling = !is_debug;
225 pipeline_opts.SLPVectorization = !is_debug;
226 pipeline_opts.LoopVectorization = !is_debug;
227 pipeline_opts.LoopInterleaving = !is_debug;
228 pipeline_opts.MergeFunctions = !is_debug;
229
230 // Instrumentations
231 PassInstrumentationCallbacks instr_callbacks;
232 StandardInstrumentations std_instrumentations(false);
233 std_instrumentations.registerCallbacks(instr_callbacks);
234
235 PassBuilder pass_builder(false, &target_machine, pipeline_opts,
236 None, &instr_callbacks);
237 using OptimizationLevel = typename PassBuilder::OptimizationLevel;
238
239 LoopAnalysisManager loop_am;
240 FunctionAnalysisManager function_am;
241 CGSCCAnalysisManager cgscc_am;
242 ModuleAnalysisManager module_am;
243
244 // Register the AA manager first so that our version is the one used
245 function_am.registerPass([&] {
246 return pass_builder.buildDefaultAAPipeline();
247 });
248
249 Triple target_triple(module.getTargetTriple());
250 auto tlii = std::make_unique<TargetLibraryInfoImpl>(target_triple);
251 function_am.registerPass([&] { return TargetLibraryAnalysis(*tlii); });
252
253 // Initialize the AnalysisManagers
254 pass_builder.registerModuleAnalyses(module_am);
255 pass_builder.registerCGSCCAnalyses(cgscc_am);
256 pass_builder.registerFunctionAnalyses(function_am);
257 pass_builder.registerLoopAnalyses(loop_am);
258 pass_builder.crossRegisterProxies(loop_am, function_am,
259 cgscc_am, module_am);
260
261 // IR verification
262 if (assertions_on) {
263 // Verify the input
264 pass_builder.registerPipelineStartEPCallback(
265 [](ModulePassManager &module_pm, OptimizationLevel OL) {
266 module_pm.addPass(VerifierPass());
267 });
268 // Verify the output
269 pass_builder.registerOptimizerLastEPCallback(
270 [](ModulePassManager &module_pm, OptimizationLevel OL) {
271 module_pm.addPass(VerifierPass());
272 });
273 }222 }
223 PMBuilder->OptLevel = target_machine->getOptLevel();
224 PMBuilder->SizeLevel = is_small ? 2 : 0;
225
226 PMBuilder->DisableTailCalls = is_debug;
227 PMBuilder->DisableUnrollLoops = is_debug;
228 PMBuilder->SLPVectorize = !is_debug;
229 PMBuilder->LoopVectorize = !is_debug;
230 PMBuilder->LoopsInterleaved = !PMBuilder->DisableUnrollLoops;
231 PMBuilder->RerollLoops = !is_debug;
232 // Leaving NewGVN as default (off) because when on it caused issue #673
233 //PMBuilder->NewGVN = !is_debug;
234 PMBuilder->DisableGVNLoadPRE = is_debug;
235 PMBuilder->VerifyInput = assertions_on;
236 PMBuilder->VerifyOutput = assertions_on;
237 PMBuilder->MergeFunctions = !is_debug;
238 PMBuilder->PrepareForLTO = lto;
239 PMBuilder->PrepareForThinLTO = false;
240 PMBuilder->PerformThinLTO = false;
241
242 TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple()));
243 PMBuilder->LibraryInfo = &tlii;
274244
275 // Passes for either debug or release build
276 if (is_debug) {245 if (is_debug) {
277 // NOTE: Always inliner will go away (in debug build)246 PMBuilder->Inliner = createAlwaysInlinerLegacyPass(false);
278 // when the self-hosted compiler becomes mature.
279 pass_builder.registerPipelineStartEPCallback(
280 [](ModulePassManager &module_pm, OptimizationLevel OL) {
281 module_pm.addPass(AlwaysInlinerPass());
282 });
283 } else {247 } else {
284 pass_builder.registerPipelineStartEPCallback(248 target_machine->adjustPassManager(*PMBuilder);
285 [](ModulePassManager &module_pm, OptimizationLevel OL) {249
286 module_pm.addPass(250 PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addDiscriminatorsPass);
287 createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));251 PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false);
288 });
289 }252 }
290253
291 // Thread sanitizer
292 if (tsan) {254 if (tsan) {
293 pass_builder.registerOptimizerLastEPCallback(255 PMBuilder->addExtension(PassManagerBuilder::EP_OptimizerLast, addThreadSanitizerPass);
294 [](ModulePassManager &module_pm, OptimizationLevel level) {256 PMBuilder->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, addThreadSanitizerPass);
295 module_pm.addPass(ThreadSanitizerPass());
296 });
297 }257 }
298258
299 ModulePassManager module_pm;259 // Set up the per-function pass manager.
300 OptimizationLevel opt_level;260 legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
301 // Setting up the optimization level261 auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii);
302 if (is_debug)262 FPM.add(tliwp);
303 opt_level = OptimizationLevel::O0;263 FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
304 else if (is_small)264 if (assertions_on) {
305 opt_level = OptimizationLevel::Oz;265 FPM.add(createVerifierPass());
306 else
307 opt_level = OptimizationLevel::O3;
308
309 // Initialize the PassManager
310 if (lto) {
311 module_pm = pass_builder.buildLTOPreLinkDefaultPipeline(opt_level);
312 module_pm.addPass(CanonicalizeAliasesPass());
313 module_pm.addPass(NameAnonGlobalPass());
314 } else {
315 module_pm = pass_builder.buildPerModuleDefaultPipeline(opt_level);
316 }266 }
317267 PMBuilder->populateFunctionPassManager(FPM);
318 // Unfortunately we don't have new PM for code generation268
319 legacy::PassManager codegen_pm;269 {
320 codegen_pm.add(270 // Set up the per-module pass manager.
321 createTargetTransformInfoWrapperPass(target_machine.getTargetIRAnalysis()));271 legacy::PassManager MPM;
322272 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
323 if (dest_bin && !lto) {273 PMBuilder->populateModulePassManager(MPM);
324 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_bin, nullptr, CGFT_ObjectFile)) {274
325 *error_message = strdup("TargetMachine can't emit an object file");275 // Set output passes.
326 return true;276 if (dest_bin && !lto) {
277 if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, CGFT_ObjectFile)) {
278 *error_message = strdup("TargetMachine can't emit an object file");
279 return true;
280 }
327 }281 }
328 }282 if (dest_asm) {
329 if (dest_asm) {283 if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, CGFT_AssemblyFile)) {
330 if (target_machine.addPassesToEmitFile(codegen_pm, *dest_asm, nullptr, CGFT_AssemblyFile)) {284 *error_message = strdup("TargetMachine can't emit an assembly file");
331 *error_message = strdup("TargetMachine can't emit an assembly file");285 return true;
332 return true;286 }
333 }287 }
334 }
335288
336 // Optimization phase289 // run per function optimization passes
337 module_pm.run(module, module_am);290 FPM.doInitialization();
291 for (Function &F : *module)
292 if (!F.isDeclaration())
293 FPM.run(F);
294 FPM.doFinalization();
338295
339 // Code generation phase296 MPM.run(*module);
340 codegen_pm.run(module);
341297
342 if (llvm_ir_filename) {298 if (llvm_ir_filename) {
343 if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {299 if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {
344 return true;300 return true;
301 }
302 }
303 if (dest_bin && lto) {
304 WriteBitcodeToFile(*module, *dest_bin);
345 }305 }
346 }
347306
348 if (dest_bin && lto) {307 if (time_report) {
349 WriteBitcodeToFile(module, *dest_bin);308 TimerGroup::printAll(errs());
350 }309 }
351310
352 if (time_report) {311 // MPM goes out of scope and writes to the out streams
353 TimerGroup::printAll(errs());
354 }312 }
355313
314 delete dest_asm;
315 delete dest_bin;
316
356 return false;317 return false;
357}318}
358319