- LLVM 50%
- C++ 32.9%
- Shell 7.9%
- C 5.5%
- CMake 3.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| CMakeLists.txt | ||
| LICENSE | ||
| README.md | ||
LLVM Loop Unroll Analyzer
Status: not actively maintained. Left up as a reference.
Custom LLVM pass that analyzes loop structures and identifies unroll opportunities.
Function
This pass traverses all functions in LLVM IR and reports the following:
- Detected loops and their nesting depth
- Loop trip-count analysis (via ScalarEvolution)
- Unroll recommendations
- Metadata attachment for unroll recommendations (
llvm.loop.unroll.full/llvm.loop.unroll.partial)
Recommendation rules (innermost loops only):
- Trip count unknown -> "Cannot determine unroll strategy"
- Trip count <= 16 -> full unroll
- Trip count > 16 -> partial unroll by factor of 4
- Non-innermost loops are reported but never marked.
Prerequisites
- LLVM 18 and Clang 18 (
opt-18,clang-18) - CMake
Build
cmake -S . -B build
cmake --build build
This produces build/libUnrollAnalyzerPass.so. The plugin deliberately does
not link the LLVM libraries; opt/clang supply them at load time.
Usage
The pass relies on ScalarEvolution to compute trip counts, which needs the loop
in canonical (rotated, indvar-simplified) form. -O0 IR is not canonical, so
trip counts come back "unknown" and nothing gets recommended. Compile the input
at -O1 (or higher):
# 1. Compile C to canonical LLVM IR
clang-18 -O1 -emit-llvm -S tests/test.c -o tests/test.ll
# 2. Run the pass (report goes to stderr; transformed IR to output.ll)
opt-18 -load-pass-plugin=build/libUnrollAnalyzerPass.so \
-passes="unroll-analyzer" tests/test.ll -S -o output.ll
If you must start from -O0 IR, run the canonicalization passes first:
opt-18 -load-pass-plugin=build/libUnrollAnalyzerPass.so \
-passes="loop-rotate,indvars,unroll-analyzer" input.ll -S -o output.ll
Tests
tests/run_tests.sh runs the pass on the committed fixtures and checks both the
analysis report and the attached metadata with FileCheck:
tests/run_tests.sh build/libUnrollAnalyzerPass.so
Requires FileCheck-18 on PATH. The expected output lives in tests/checks/.
Regenerate the fixtures after changing the C sources with the clang-18 -O1
command above.
Project structure
unroll-analyzer
├── README.md
├── CMakeLists.txt
├── src
│ └── UnrollAnalyzer.cpp
└── tests
├── test.c / test.ll
├── test_edge_cases.c / test_edge_cases.ll
├── checks/ FileCheck expectations
└── run_tests.sh
Notes
- New pass manager: required for the
-load-pass-plugin/-passesinterface used here (LLVM 18). - ScalarEvolution: computes the loop trip count used for the unroll decision;
getSmallConstantTripCountreturns 0 when the count is not a known small constant, which the pass reports as "unknown".