A high-performance LLVM plugin designed to perform custom IR-level optimizations including Constant Folding, Algebraic Identity Elimination, and Trivial Dead Code Elimination (DCE). This project demonstrates the usage of the LLVM New Pass Manager (NPM) and pattern matching for hardware-aware code optimization.
The pass implements a three-stage optimization suite targeted at reducing redundant CPU cycles:
- Constant Folding: Identifies instructions where all operands are constants and pre-calculates the result at compile-time.
-
Algebraic Identity: Detects and simplifies mathematical redundancies such as:
-
x + 0$\rightarrow$ x -
x * 1$\rightarrow$ x -
x ^ x$\rightarrow$ 0
-
- Dead Code Elimination (DCE): Recursively removes instructions that have no side effects and no remaining users, reducing binary size and memory footprint.
- LLVM/Clang 15+ (Tested on LLVM 20.0.0git)
- CMake 3.15+
- Build Essentials (gcc, g++, make)
sudo apt update
sudo apt install llvm clang cmake build-essential
llvm-cpu-optimization-pass/
├── CMakeLists.txt # Root CMake configuration
├── include/
│ └── MyCPUPass.h # Pass declaration
├── src/
│ ├── CMakeLists.txt # Subdirectory build rules
│ └── MyCPUPass.cpp # Pass implementation & Registration
└── tests/
└── test.c # Sample C code for validation
Clone the repository:
git clone https://github.com/atharva0300/llvm-cpu-optimization-pass
cd llvm-cpu-optimization-pass
Configure and Build:
mkdir build
cd build
cmake ..
make
After a successful build, the shared object plugin libMyCPUPass.so (Linux)
To run the pass against a C program, follow the LLVM pipeline:
-
Generate LLVM IR
Compile your C code to unoptimized LLVM bitcode:
clang -O0 -S -emit-llvm ../tests/test.c -o test.ll -
Run the Optimization Pass
Use the opt tool to load the plugin and execute the custom pipeline: Bash
opt -load-pass-plugin src/libMyCPUPass.so \ -passes="my-cpu-pass" \ -S test.ll -o output.ll -
Verify Results
Check the terminal for optimization logs:
Running CPU optimization suite on: main [FOLD] %5 = add i32 10, 5 -> i32 15 [IDENTITY] %7 = add nsw i32 %6, 0 -> %6 [DCE] Removing: %7 = add nsw i32 %6, 0
The pass utilizes llvm/IR/PatternMatch.h for robust instruction identification.
if (match(&I, m_Add(m_Value(LHS), m_Zero()))) {
I.replaceAllUsesWith(LHS);
}
The pass is registered using the llvmGetPassPluginInfo entry point, allowing it to be called via the -passes="my-cpu-pass" flag in modern LLVM tools.
To see exactly how the CPU instructions were transformed, compare the function body of the original IR versus the optimized IR using grep.
-
Check the Original IR Run this command to see the unoptimized code (with redundant math and dead code):
grep -A 15 "define dso_local i32 @main" test_pre.llExpected Output snippet:
%5 = load i32, ptr %2, align 4 %6 = add nsw i32 %5, 0 ; <--- Redundant addition store i32 %6, ptr %3, align 4 %7 = mul nsw i32 100, 2 ; <--- Dead code (if unused) -
Check the Optimized IR
Run this command to see the results of the my-cpu-pass:
grep -A 15 "define dso_local i32 @main" test_post.llExpected Output snippet:
%5 = load i32, ptr %2, align 4 store i32 %5, ptr %3, align 4 ; <--- Pass replaced %6 with %5 and deleted the 'add' ; <--- 'mul' instruction was completely removed by DCE -
Visual Side-by-Side (Linux)
For a cleaner view of every single change made by the pass, use the diff tool:
diff -y test_pre.ll test_post.ll
| Optimization Strategy | LLVM IR Transformation | CPU/Hardware Benefit |
|---|---|---|
| Constant Folding | "add i32 10, 5 → 15" | Zero runtime math: Eliminates ALU execution latency for static values. |
| Algebraic Identity | "add i32 %x, 0 → %x" | Reduces Op Count: Removes redundant instructions before they reach the execution pipeline. |
| Dead Code Elimination | Removes unused %y = ... | Lower Register Pressure: Reduces the work for the Register Allocator minimizing stack spills. |
Atharva Pingale ( https://github.com/atharva0300 )