@code_lowered
is not useful for understanding performance.
@code_warntype
is best.
Basically the different steps:
Parsing:
Source code -> Abstract Syntax Tree (like what one manipulates with macros), blocks like loops and conditionals are branches in the tree.
You can see it by quoting the source code.
quote
if x>1
x=x-1
end
end
Lowering:
Abstract Syntract Tree -> Lowered Intermediate Representatation (IR), which i think is best describnes as an abstract syntax list,
Basically nothing has been done to it, no optimization etc.
Just the tree form has become a list where nothing has subexpressesions, instread each temporary is on its own line. Loops and ifs becomes various kinds of jumps (like labels and conditional gotos)
A few things change to lowered representation like the end
in xs[end-1]
becomes lastindex(xs)
This lowering can be done fully ahead of time, it doesn't need the JIT.
it is just a transform of the syntax
You can access it via @code_lowered f(x)
for some function f
taking argument x
.
or if you have a Method
then you can do Base.uncompressed_ast(method)
.
Specialization
The type information is made use of, and the optimizer runs.
Things get inlined, conditions that are always true or false are removed (e.g. checks on types).
The lowered IR gets turned into Typed IR.
@code_typed f(x)
gets you this.
@code_typed optimize=false f(x)
gets you this without the optimization step being run.
@code_warntype f(x)
gets you this with extra helpful performance annotations highlighting type instabilities
This is one of the most useful layers to look at.
Probably second only to the source-code itself.
Code-generation (LLVM)
This is where we Typed IR becomes LLVM.
And LLVM internally goes through like a bunch of intermediate representations.
LLVM does a ton of optimization of its own.
e.g. various maths intrinstics constant propagate as this stage.
Access this via @code_llvm f(x)
This is the next most useful stage after Typed.
(Tying with Native Machine code, depending if you read LLVM IR better or worse than Assembly).
Code-generation (Assembly)
The LLVM becomes Assembly,
human readable machine code basically.
Access this via @code_native f(x)
After that there is only assumbling, to machine code.
Though I suspect that the assembly is normally bypassed as one goes straght from LLVM to machine-code since they are 1-1.
See also: https://stackoverflow.com/a/43456211/179081