I'm continuing my work on my C# compiler for my Compilers Class. At the moment I'm nearly finished with the chapters on Compiler Optimizations in my textbook.
For the most part, my textbook didn't have Just-In-Time compilation in mind when it was written and I'm curious about the kinds of static, pre-jit optimizations the C# compiler performs versus what it does during the JIT process?
When I talk to people about compiling against the CLR, I typically hear things like, "Most of the optimizations are done by the JIT".
Are things like loop unrolling, constant folding/propagation, instruction interweaving done pre-Jit by C#'s compiler or handled by the jitter? If they aren't handled by the jitter, then what kind of optimizations does the jitter do that are unique to a just-in-time compiler?
Optimizing compilers are a mainstay of modern software: allowing a programmer to write code in a language that makes sense to them, while transforming it into a form that makes sense for the underlying hardware to run efficiently.
Optimization is a program transformation technique, which tries to improve the code by making it consume less resources (i.e. CPU, Memory) and deliver high speed. In optimization, high-level general programming constructs are replaced by very efficient low-level programming codes.
The compiler can do the following: create a separate version of the loop for each possible value of the variable operation . The transformation is called loop unswitching, because there is a different version of the loop for each value of the condition.
I can imagine there being a number of optimizations that are unique to JIT; specifically, any optimization that depends on the environment/context that the application runs in. (Note, all the following are hypothetical, I do not know for sure, which or if any of these are actually performed)
Most boring: the JIT can optimize depending on 32-bit/64-bit underlying OS, or even potentially depending on the exact processor architecture.
Not applicable: More interesting: the JIT could optimize out anything that only runs in Debug mode (certain conditional code for example) when the application is not run inside a debug context.
Most interesting: the JIT could optimize out conditional branches in a class that depend only on a readonly
field, because at least theoretically that value will never change during the execution of the class.
Basically I'd imagine that deferring optimizations until JIT would generally be the way to go, because at JIT time there is the most information available about the context the code is actually running in, making more meaningful optimizations possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With