TIL: Inspecting LLVM inlining decisions with LLVM logging
I was curious about how LLVM makes decisions on whether to inline a function or not, and wanted to
get a high level overview of its strategy. Thankfully, it seems like there is some relevant
logging in InlineCost.cpp
that we can take advantage of!
All we have to do is compile Clang in debug mode, then invoke clang with the arguments
-mllvm -debug
. All this does is pass the -debug
flag to the llvm
backend, which enables
logging statements for us.
For example, if we wanted to analyze why the function foo
may or may not be inlined below:
#include <stdio.h>
#include <stdlib.h>
int foo(int a) {
if (a < 10) return 5;
for (int i = 0; i < a; i++) {
printf("%u ", i);
}
puts("");
puts("");
puts("");
puts("");
return 0;
}
int main(int argc, char** argv) {
if (argc < 2) {
puts("Please enter an integer.");
}
// You'll want error handling in a real application here,
// but for simplicity we're omitting it.
int i = strtol(argv[1], 0, 10);
return foo(i);
}
We would invoke clang main.c -mllvm -debug -O2
and look at the outputted logs. Here are the
interesting log lines after redirecting the logs to a file:
Initial cost: -35
NumConstantArgs: 0
NumConstantOffsetPtrArgs: 0
NumAllocaArgs: 0
NumConstantPtrCmps: 0
NumConstantPtrDiffs: 0
NumInstructionsSimplified: 4
NumInstructions: 14
SROACostSavings: 0
SROACostSavingsLost: 0
LoadEliminationCost: 0
ContainsNoDuplicateCall: 0
Cost: 170
Threshold: 225
Inlining (cost=170, threshold=225), Call: %call2 = call i32 @foo(i32 noundef %conv), !range !9
Note that the -debug
argument won't work if clang
is not compiled in debug mode.