(I posted this on GitHub as well, but I’ll reiterate it here just in case)
To explain briefly, Julia’s inference works as follows:
For a method m:
- Regular inference: First, inference is performed without constant information.
- Constant inference: Next, inference is performed with constant information for the same
m.
These steps are repeated recursively for calls within m.
If a method m contains a branch that becomes dead when its arguments are specific constant values, regular inference in step 1 cannot use that constant information, so it has to infer including that dead branch. This dead branch is identified as dead by constant inference in step 2, and the final generated code is optimized, but we already paid the compilation latency from step 1.
Now you might wonder why we perform regular inference. The reason is that regular inference can be used for any constant values and also even when there is no constant information, making it highly reusable and cache-beneficial.
Therefore, it is difficult to reduce the latency of constant inference for code that can only be optimized by constant inference. A solution, as implemented in this PR, is to refactor the code so that regular inference can recognize dead branches. By splitting methods into cases and using method dispatch to prevent the inference of dead cases, latency can be improved.