Creating an optimization pipeline – Optimizing IR-3
- For the code generation process, we have to use the old pass manager. We must simply declare the CodeGenPM instances and add the pass, which makes target-specific information available at the IR transformation level: legacy::PassManager CodeGenPM;
CodeGenPM.add(createTargetTransformInfoWrapperPass(
TM->getTargetIRAnalysis())); - To output LLVM IR, we must add a pass that prints the IR into a stream: if (FileType == CGFT_AssemblyFile && EmitLLVM) {
CodeGenPM.add(createPrintModulePass(Out->os()));
} - Otherwise, we must let the TargetMachine instance add the required code generation passes, directed by the FileType value we pass as an argument: else {
if (TM->addPassesToEmitFile(CodeGenPM, Out->os(),
nullptr, FileType)) {
WithColor::error()
<< “No support for file type\n”;
return false;
}
} - After all this preparation, we are now ready to execute the passes. First, we must run the optimization pipeline on the IR module. Next, the code generation passes are run. Of course, after all this work, we want to keep the output file: MPM.run(M, MAM); CodeGenPM.run(M);
Out->keep();
return true;
} - That was a lot of code, but the process was straightforward. Of course, we have to update the dependencies in the tools/driver/CMakeLists.txt build file too. Besides adding the target components, we must add all the transformation and code generation components from LLVM. The names roughly resemble the directory names where the source is located. The component name is translated into the link library name during the configuration process:
set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD}
AggressiveInstCombine Analysis AsmParser
BitWriter CodeGen Core Coroutines IPO IRReader
InstCombine Instrumentation MC ObjCARCOpts Remarks
ScalarOpts Support Target TransformUtils Vectorize
Passes)
- Our compiler driver supports plugins, and we must announce this support:
add_tinylang_tool(tinylang Driver.cpp SUPPORT_PLUGINS)
- As before, we have to link against our own libraries:
target_link_libraries(tinylang
PRIVATE tinylangBasic tinylangCodeGen
tinylangLexer tinylangParser tinylangSema)
These are necessary additions to the source code and the build system.
- To build the extended compiler, you must change into your build directory and type the following:
$ ninja
Changes to the files of the build system are automatically detected, and cmake is run before compiling and linking our changed source. If you need to re-run the configuration step, please follow the instructions in Chapter 1, Installing LLVM, the Compiling the tinylang application section.
As we have used the options for the opt tool as a blueprint, you should try running tinylang with the options to load a pass plugin and run the pass, as we did in the previous sections.
With the current implementation, we can either run a default pass pipeline or we can construct one ourselves. The latter is very flexible, but in almost all cases, it would be overkill. The default pipeline runs very well for C-like languages. However, what is missing is a way to extend the pass pipeline. We’ll look at how to implement this in the next section.