# llvm-optimization-passes **Repository Path**: Ivanmax/llvm-optimization-passes ## Basic Information - **Project Name**: llvm-optimization-passes - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-05 - **Last Updated**: 2026-09-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LLVM Custom Optimization Passes This is a collection of out-of-tree optimization and analysis passes for the modern LLVM infrastructure, built using the **New Pass Manager (NPM)**. > [!NOTE] > This is part of an assignment for the Compilers course at IIITH, done with @GnanaPrakashSG2004. Some of this readme is LLM generated. ## Features - **Modern LLVM:** Uses the New Pass Manager (for LLVM 19+). - **Out-of-Tree Build:** Compiles against an existing LLVM installation without modifying its source code. - **Cross-Platform:** Includes build instructions for both macOS (with Homebrew) and generic Linux setups. - **Diverse Examples:** Contains a variety of passes, from simple "Hello World" to lite versions of classic optimizations like Constant Propagation and Dead Code Elimination. ## Prerequisites Before you begin, ensure you have the following installed on your system: - **LLVM >= 19.0:** The project relies on APIs available in LLVM 19 and later. - **CMake >= 3.20:** Used for the build system. - **C++ Compiler:** A modern C++ compiler like Clang. - **Make:** Or another build tool like Ninja. ### Installing LLVM The easiest way to install the dependencies on macOS is with [Homebrew](https://brew.sh/). See the [LLVM Github](https://github.com/llvm/llvm-project) and the [LLVM Getting Started](https://llvm.org/docs/GettingStarted.html) page on installing LLVM. Homebrew (and possibly your distro's package manager) installs LLVM and clang in a non-standard path to avoid conflicts with the system's tools. You need to export some environment variables so that CMake can find the correct LLVM installation. The following are the ones I used, ymmv. ```sh export LDFLAGS="-L/opt/homebrew/opt/llvm/lib/clang/19 -L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind" export PATH="/opt/homebrew/opt/llvm/bin:$PATH" ``` --- ## Building the Project ### Configure and Build The method for configuring CMake depends on your operating system and how you installed LLVM. A convenience script `build.sh` is provided for this common setup. It correctly sets the necessary environment variables to find the Homebrew-installed LLVM. The script automates the following steps: 1. Creates a `build` directory. 2. Sets environment variables (`PATH`, `LDFLAGS`). 3. Runs `cmake` with the correct compiler paths. 4. Runs `make`. 5. On Linux, you will need to add `-DLLVM_DIR=` to the cmake command in the build script. After a successful build, all compiled pass plugins (as shared libraries) will be located in the `build/lib/` directory. To manually build, run: ```sh mkdir build && cd build ``` Replace the paths according to your installation for all further commands: ```sh export LDFLAGS="-L/opt/homebrew/opt/llvm/lib/clang/19 -L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind" export PATH="/opt/homebrew/opt/llvm/bin:$PATH" ``` For macOS: ```sh cmake ../ -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-fno-rtti" -DCMAKE_SYSTEM_NAME=Darwin -DLLVM_BIN_DIR=/opt/homebrew/opt/llvm/bin && make ``` For linux: ```sh cmake ../ -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm/bin/clang -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-fno-rtti" -DLLVM_DIR=/opt/homebrew/opt/llvm/bin && make ``` --- ## Included Passes This project includes several passes, each demonstrating a different aspect of LLVM pass development. | Pass Name | Shared Library (`.so`/`.dylib`) | Registered Name (`-passes=...`) | Type (Level, Kind) | | ------------------------- | -------------------------- | ------------------------------- | ---------------------------- | | **HelloWorld** | `libHelloWorld` | `hello-world` | Module, Utility | | **OpcodeCounter** | `libOpcodeCounter` | `print` | Function, Analysis + Printer | | **ArithmeticSimplifier** | `libArithmeticSimplifier`| `arithmetic-simplifier` | Function, Transformation | | **CFG Printer** | `libCFGPrinter` | `cfg-printer` | Module, Analysis + Printer | | **Function Call Counter** | `libFunctionCallCounter`| `print` | Module, Analysis + Printer | | **Instruction Replacer** | `libInstructionReplacer`| `inst-replace` | Function, Transformation | | **Constant Propagation** | `libConstantPropagation`| `constant-propagation` | Function, Transformation | | **Dead Code Elimination** | `libDeadCodeElimination`| `dead-code-elimination` | Function, Transformation | ### Pass Details & Usage First, generate LLVM Intermediate Representation (IR) from a source file. The `-O0` flag is used to prevent the compiler from running its own optimizations, ensuring our passes have code to work on. ```sh clang -O0 -S -emit-llvm inputs/hello.c -o hello.ll ``` Now you can run any of the passes using `opt`. By default, they output the new program to stdout. To stop this behavior, redirect the output using `-o /dev/null` #### HelloWorld - **Description:** A simple module pass that prints "Hello, World!" to the console. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libHelloWorld.so -passes="hello-world" -S hello.ll -o /dev/null ``` #### OpcodeCounter - **Description:** An analysis pass that counts the occurrences of each opcode within a function. A separate printer pass displays the results. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libOpcodeCounter.so -passes="print" -S hello.ll -o /dev/null ``` #### ArithmeticSimplifier - **Description:** A transformation pass that performs simple algebraic simplifications (`x * 1 -> x`, `x + 0 -> x`). It does not preserve analysis results. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libArithmeticSimplifier.so -passes="arithmetic-simplifier" -S hello.ll ``` #### CFG Printer - **Description:** An analysis pass that prints the Control Flow Graph (CFG) for each function in a module in DOT format. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libCFGPrinter.so -passes="cfg-printer" -S hello.ll -o /dev/null ``` #### Function Call Counter - **Description:** An analysis pass that counts the number of direct calls to each function within a module. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libFunctionCallCounter.so -passes="print" -S hello.ll -o /dev/null ``` #### Instruction Replacer - **Description:** A transformation pass that replaces `add` instructions with `sub` instructions where both operands are identical (e.g., `%x = add i32 %a, %a` becomes `%x = sub i32 %a, %a`). This is primarily for demonstrating instruction modification and does not maintain semantic correctness. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libInstructionReplacer.so -passes="inst-replace" -S hello.ll -o replaced.ll ``` #### Constant Propagation Lite - **Description:** A transformation pass that performs simple constant folding for binary operations (e.g., `%x = add i32 5, 3` becomes `%x = 8`). - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libConstantPropagation.so -passes="constant-propagation" -S hello.ll -o constproped.ll ``` #### Dead Code Elimination Lite - **Description:** A transformation pass that removes instructions that have no users and no side effects. - **Usage:** ```sh opt -load-pass-plugin ./build/lib/libDeadCodeElimination.so -passes="dead-code-elimination" -S hello.ll -o dce.ll ``` ---