authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-11 03:37:44-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-11 03:37:44-04:00
log7f47b0c271931466d8ce88c0928ff2bef8f8109f
tree18e3aa9436bd8d4ae543e13c5e6955b20c95b49e
parent11a655032400fda22132c54131546f3e671476a9

run alwaysinline pass in debug mode

before this commit, the optimized IR code that is displayed in --verbose mode is not actually what gets emitted to an object file. that is now corrected, and we make sure to run the alwaysinliner pass even in debug mode, so you can rely on "inline" keyword inlining a function, guaranteed. See #306

4 files changed, 85 insertions(+), 49 deletions(-)

src/codegen.cpp+2-2
...@@ -3826,8 +3826,8 @@ static void do_code_gen(CodeGen *g) {...@@ -3826,8 +3826,8 @@ static void do_code_gen(CodeGen *g) {
3826 Buf *out_file_o = buf_create_from_buf(g->root_out_name);3826 Buf *out_file_o = buf_create_from_buf(g->root_out_name);
3827 const char *o_ext = target_o_file_ext(&g->zig_target);3827 const char *o_ext = target_o_file_ext(&g->zig_target);
3828 buf_append_str(out_file_o, o_ext);3828 buf_append_str(out_file_o, o_ext);
3829 if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(out_file_o),3829 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(out_file_o),
3830 LLVMObjectFile, &err_msg))3830 LLVMObjectFile, &err_msg, !g->is_release_build))
3831 {3831 {
3832 zig_panic("unable to write object file: %s", err_msg);3832 zig_panic("unable to write object file: %s", err_msg);
3833 }3833 }
src/link.cpp+4-12
...@@ -746,18 +746,10 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -746,18 +746,10 @@ void codegen_link(CodeGen *g, const char *out_file) {
746 buf_resize(&lj.out_file, 0);746 buf_resize(&lj.out_file, 0);
747 }747 }
748748
749 bool is_optimized = g->is_release_build;749 if (g->verbose) {
750 if (is_optimized) {750 fprintf(stderr, "\nOptimization:\n");
751 if (g->verbose) {751 fprintf(stderr, "---------------\n");
752 fprintf(stderr, "\nOptimization:\n");752 LLVMDumpModule(g->module);
753 fprintf(stderr, "---------------\n");
754 }
755
756 ZigLLVMOptimizeModule(g->target_machine, g->module);
757
758 if (g->verbose) {
759 LLVMDumpModule(g->module);
760 }
761 }753 }
762 if (g->verbose) {754 if (g->verbose) {
763 fprintf(stderr, "\nLink:\n");755 fprintf(stderr, "\nLink:\n");
src/zig_llvm.cpp+77-34
...@@ -41,6 +41,7 @@...@@ -41,6 +41,7 @@
41#include <llvm/Target/TargetMachine.h>41#include <llvm/Target/TargetMachine.h>
42#include <llvm/Transforms/IPO.h>42#include <llvm/Transforms/IPO.h>
43#include <llvm/Transforms/IPO/PassManagerBuilder.h>43#include <llvm/Transforms/IPO/PassManagerBuilder.h>
44#include <llvm/Transforms/IPO/AlwaysInliner.h>
44#include <llvm/Transforms/Scalar.h>45#include <llvm/Transforms/Scalar.h>
4546
46#include <lld/Driver/Driver.h>47#include <lld/Driver/Driver.h>
...@@ -72,66 +73,108 @@ char *ZigLLVMGetNativeFeatures(void) {...@@ -72,66 +73,108 @@ char *ZigLLVMGetNativeFeatures(void) {
72 return strdup(features.getString().c_str());73 return strdup(features.getString().c_str());
73}74}
7475
75static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {76static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
76 PM.add(createAddDiscriminatorsPass());77 PM.add(createAddDiscriminatorsPass());
77}78}
7879
80#ifndef NDEBUG
81static const bool assertions_on = true;
82#else
83static const bool assertions_on = false;
84#endif
7985
80void ZigLLVMOptimizeModule(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref) {86bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
87 const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug)
88{
89 std::error_code EC;
90 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
91 if (EC) {
92 *error_message = strdup(EC.message().c_str());
93 return true;
94 }
81 TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);95 TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
96 target_machine->setO0WantsFastISel(true);
97
82 Module* module = unwrap(module_ref);98 Module* module = unwrap(module_ref);
83 TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple()));
8499
85 PassManagerBuilder *PMBuilder = new PassManagerBuilder();100 PassManagerBuilder *PMBuilder = new PassManagerBuilder();
86 PMBuilder->OptLevel = target_machine->getOptLevel();101 PMBuilder->OptLevel = target_machine->getOptLevel();
87 PMBuilder->SizeLevel = 0;102 PMBuilder->SizeLevel = 0;
88 PMBuilder->BBVectorize = true;
89 PMBuilder->SLPVectorize = true;
90 PMBuilder->LoopVectorize = true;
91
92 PMBuilder->DisableUnitAtATime = false;
93 PMBuilder->DisableUnrollLoops = false;
94 PMBuilder->MergeFunctions = true;
95 PMBuilder->PrepareForLTO = true;
96 PMBuilder->RerollLoops = true;
97103
98 PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addAddDiscriminatorsPass);104 PMBuilder->DisableTailCalls = is_debug;
105 PMBuilder->DisableUnitAtATime = is_debug;
106 PMBuilder->DisableUnrollLoops = is_debug;
107 PMBuilder->BBVectorize = !is_debug;
108 PMBuilder->SLPVectorize = !is_debug;
109 PMBuilder->LoopVectorize = !is_debug;
110 PMBuilder->RerollLoops = !is_debug;
111 PMBuilder->LoadCombine = !is_debug;
112 PMBuilder->NewGVN = !is_debug;
113 PMBuilder->DisableGVNLoadPRE = is_debug;
114 PMBuilder->VerifyInput = assertions_on;
115 PMBuilder->VerifyOutput = assertions_on;
116 PMBuilder->MergeFunctions = !is_debug;
117 PMBuilder->PrepareForLTO = false;
118 PMBuilder->PrepareForThinLTO = false;
119 PMBuilder->PerformThinLTO = false;
99120
121 TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple()));
100 PMBuilder->LibraryInfo = &tlii;122 PMBuilder->LibraryInfo = &tlii;
101123
102 PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel);124 if (is_debug) {
125 PMBuilder->Inliner = createAlwaysInlinerLegacyPass(false);
126 } else {
127 PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible,
128 [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
129 target_machine->addEarlyAsPossiblePasses(PM);
130 });
131
132 PMBuilder->addExtension(PassManagerBuilder::EP_EarlyAsPossible, addDiscriminatorsPass);
133 PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel);
134 }
103135
104 // Set up the per-function pass manager.136 // Set up the per-function pass manager.
105 legacy::FunctionPassManager *FPM = new legacy::FunctionPassManager(module);137 legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
106 FPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));138 FPM.add(new TargetLibraryInfoWrapperPass(tlii));
107#ifndef NDEBUG139 FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
108 bool verify_module = true;140 if (assertions_on) {
109#else141 FPM.add(createVerifierPass());
110 bool verify_module = false;
111#endif
112 if (verify_module) {
113 FPM->add(createVerifierPass());
114 }142 }
115 PMBuilder->populateFunctionPassManager(*FPM);143 PMBuilder->populateFunctionPassManager(FPM);
116144
117 // Set up the per-module pass manager.145 // Set up the per-module pass manager.
118 legacy::PassManager *MPM = new legacy::PassManager();146 legacy::PassManager MPM;
119 MPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));147 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
120148 PMBuilder->populateModulePassManager(MPM);
121 PMBuilder->populateModulePassManager(*MPM);149
122150 TargetMachine::CodeGenFileType ft;
151 switch (file_type) {
152 case LLVMAssemblyFile:
153 ft = TargetMachine::CGFT_AssemblyFile;
154 break;
155 default:
156 ft = TargetMachine::CGFT_ObjectFile;
157 break;
158 }
159 if (target_machine->addPassesToEmitFile(MPM, dest, ft)) {
160 *error_message = strdup("TargetMachine can't emit a file of this type");
161 return true;
162 }
123163
124 // run per function optimization passes164 // run per function optimization passes
125 FPM->doInitialization();165 FPM.doInitialization();
126 for (Function &F : *module)166 for (Function &F : *module)
127 if (!F.isDeclaration())167 if (!F.isDeclaration())
128 FPM->run(F);168 FPM.run(F);
129 FPM->doFinalization();169 FPM.doFinalization();
130170
131 // run per module optimization passes171 MPM.run(*module);
132 MPM->run(*module);172
173 dest.flush();
174 return false;
133}175}
134176
177
135LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,178LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
136 unsigned NumArgs, unsigned CC, const char *Name)179 unsigned NumArgs, unsigned CC, const char *Name)
137{180{
src/zig_llvm.hpp+2-1
...@@ -34,7 +34,8 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);...@@ -34,7 +34,8 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
34char *ZigLLVMGetHostCPUName(void);34char *ZigLLVMGetHostCPUName(void);
35char *ZigLLVMGetNativeFeatures(void);35char *ZigLLVMGetNativeFeatures(void);
3636
37void ZigLLVMOptimizeModule(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref);37bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
38 const char *filename, LLVMCodeGenFileType file_type, char **error_message, bool is_debug);
3839
39LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,40LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
40 unsigned NumArgs, unsigned CC, const char *Name);41 unsigned NumArgs, unsigned CC, const char *Name);