git clone https://github.com/m7nu3l/llvm-tutor.git llvm-tutor
cd llvm-tutor
docker build -t llvm-challenge/llvm-challenge .
docker run --rm -ti llvm-challenge/llvm-challenge
This creates an interactive and temporal docker image where this project is already compiled and tested. Below, it is explained how to use the passes.
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main"
sudo apt-get update
sudo apt-get install -y gnuplot cmake llvm-12 llvm-12-dev clang-12 llvm-12-tools python3-setuptools
sudo pip3 install lit
sudo pip3 install py-gnuplot
git clone https://github.com/m7nu3l/llvm-tutor.git llvm-tutor
cd llvm-tutor
mkdir build
cd build
export LLVM_DIR=<installation/dir/of/llvm/12> # /usr/lib/llvm-12
cmake -DLT_LLVM_INSTALL_DIR=$LLVM_DIR ..
make -j4
rm -r -f test/ && lit -vv test/
Given a function, the pass appends to a file F the number of instructions in each basic block. Then, that file can be processed by a python script (repo/scripts/draw_histogram.py
) which draws the histogram. Under the hood, gnuplot is invoked.
opt -load repo/build/lib/libHistogram.so -legacy-histogram -histogram-output-file=path/to/histogram.data
python3 repo/scripts/draw_histogram.py path/to/histogram.data path/to/histogram.png
In this case, the pass is applied to every function processed by this clang call. All basic block sizes are appended to the same file.
clang-12 -O2 -fexperimental-new-pass-manager -fpass-plugin=/repo/build/lib/libHistogram.so
python3 repo/scripts/draw_histogram.py $(pwd)/histogram.data path/to/histogram.png
Using the -histogram-output
option, the output file path can be specified. However, this is only available for opt
. The default path is $(pwd)/histogram.data
.
The pass entry point is lib/Histogram.cpp::runOnFunction.
Single-file program test is test/Histogram-test.ll.
Source-code project test is here. The zip project is analyzed by the Histogram pass. Output files are in /repo/histogram-sample.
Given a function, the pass appends a call to an external bb_exec
function at the first available insertion point of each basic block. In addition, this project provides a default implementation for it. This default implementation prints a message if a basic block is executed more than 1000 times. This threshold can be changed by the PROFILER_THRESHOLD_ENV
environment variable.
A profiled binary only has external calls to bb_exec
. In order to provide an actual implementation, LD_PRELOAD
can be used. If no implementation is provided/linked, the binary can still be executed. The profiler injects a trampoline function which checks that bb_exec
is defined before calling it.
opt -load %shlibdir/libProfiler%shlibext -legacy-profiler
In this case, the pass is applied to every function processed by this clang call.
clang-12 -O2 -fexperimental-new-pass-manager -fpass-plugin=/llvm-tutor/build/lib/libProfiler.so
The pass entry point is lib/Profiler.cpp::runOnFunction.
Single-file program test is test/Profiler-test-1.c.
Source-code project test is here. The zip project is transformed by the Profiler pass. An example of the output can be found here
5: [PROFILER] Basic block '%150' from function 'tdefl_compress_normal' in module '/zip-profiled/src/zip.c' was executed more than 1000 times.
5: [PROFILER] Basic block '%32' from function 'tdefl_compress_normal' in module '/zip-profiled/src/zip.c' was executed more than 1000 times.
5: [PROFILER] Basic block '%45' from function 'tdefl_compress_normal' in module '/zip-profiled/src/zip.c' was executed more than 1000 times.
The zip project test-suite is successful after being profiled: 6 tests, 93 assertions, 0 failures
ProfileRuntime
is not meant to process multi-threaded code.- Improve histogram drawing.
- Histogram pass's output file should have extra columns to identify each basic block's size (function & module).
- Profiler pass is duplicating constants strings rather than re-using them.
- Is
bb_exec
GV correctly initialized tonullptr
if it is not linked? So far, it looks like yes. - Improve at which point of the optimisation pipeline Histogram and Profiler passes are registered in clang.