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) {
38263826 Buf *out_file_o = buf_create_from_buf(g->root_out_name);
38273827 const char *o_ext = target_o_file_ext(&g->zig_target);
38283828 buf_append_str(out_file_o, o_ext);
3829 if (LLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(out_file_o),
3830 LLVMObjectFile, &err_msg))
3829 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(out_file_o),
3830 LLVMObjectFile, &err_msg, !g->is_release_build))
38313831 {
38323832 zig_panic("unable to write object file: %s", err_msg);
38333833 }
src/link.cpp+4-12
......@@ -746,18 +746,10 @@ void codegen_link(CodeGen *g, const char *out_file) {
746746 buf_resize(&lj.out_file, 0);
747747 }
748748
749 bool is_optimized = g->is_release_build;
750 if (is_optimized) {
751 if (g->verbose) {
752 fprintf(stderr, "\nOptimization:\n");
753 fprintf(stderr, "---------------\n");
754 }
755
756 ZigLLVMOptimizeModule(g->target_machine, g->module);
757
758 if (g->verbose) {
759 LLVMDumpModule(g->module);
760 }
749 if (g->verbose) {
750 fprintf(stderr, "\nOptimization:\n");
751 fprintf(stderr, "---------------\n");
752 LLVMDumpModule(g->module);
761753 }
762754 if (g->verbose) {
763755 fprintf(stderr, "\nLink:\n");
src/zig_llvm.cpp+77-34
......@@ -41,6 +41,7 @@
4141#include <llvm/Target/TargetMachine.h>
4242#include <llvm/Transforms/IPO.h>
4343#include <llvm/Transforms/IPO/PassManagerBuilder.h>
44#include <llvm/Transforms/IPO/AlwaysInliner.h>
4445#include <llvm/Transforms/Scalar.h>
4546
4647#include <lld/Driver/Driver.h>
......@@ -72,66 +73,108 @@ char *ZigLLVMGetNativeFeatures(void) {
7273 return strdup(features.getString().c_str());
7374}
7475
75static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
76static void addDiscriminatorsPass(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
7677 PM.add(createAddDiscriminatorsPass());
7778}
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 }
8195 TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
96 target_machine->setO0WantsFastISel(true);
97
8298 Module* module = unwrap(module_ref);
83 TargetLibraryInfoImpl tlii(Triple(module->getTargetTriple()));
8499
85100 PassManagerBuilder *PMBuilder = new PassManagerBuilder();
86101 PMBuilder->OptLevel = target_machine->getOptLevel();
87102 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()));
100122 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
104136 // Set up the per-function pass manager.
105 legacy::FunctionPassManager *FPM = new legacy::FunctionPassManager(module);
106 FPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
107#ifndef NDEBUG
108 bool verify_module = true;
109#else
110 bool verify_module = false;
111#endif
112 if (verify_module) {
113 FPM->add(createVerifierPass());
137 legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
138 FPM.add(new TargetLibraryInfoWrapperPass(tlii));
139 FPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
140 if (assertions_on) {
141 FPM.add(createVerifierPass());
114142 }
115 PMBuilder->populateFunctionPassManager(*FPM);
143 PMBuilder->populateFunctionPassManager(FPM);
116144
117145 // Set up the per-module pass manager.
118 legacy::PassManager *MPM = new legacy::PassManager();
119 MPM->add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
120
121 PMBuilder->populateModulePassManager(*MPM);
122
146 legacy::PassManager MPM;
147 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
148 PMBuilder->populateModulePassManager(MPM);
149
150 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
124164 // run per function optimization passes
125 FPM->doInitialization();
165 FPM.doInitialization();
126166 for (Function &F : *module)
127167 if (!F.isDeclaration())
128 FPM->run(F);
129 FPM->doFinalization();
168 FPM.run(F);
169 FPM.doFinalization();
130170
131 // run per module optimization passes
132 MPM->run(*module);
171 MPM.run(*module);
172
173 dest.flush();
174 return false;
133175}
134176
177
135178LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
136179 unsigned NumArgs, unsigned CC, const char *Name)
137180{
src/zig_llvm.hpp+2-1
......@@ -34,7 +34,8 @@ void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
3434char *ZigLLVMGetHostCPUName(void);
3535char *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
3940LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
4041 unsigned NumArgs, unsigned CC, const char *Name);