>>106197289
>>106197355
Compiler retard here
It's induction variable simplification after tail call elimination.
The compiler converts the self-call into something like this during tail-call elimination:
bool isEven(unsigned int a)
{
bool res = true;
while(true)
{
if(a == 0)
{
return res;
}
a = a - 1;
res = !res;
}
}
Or, lowered:
bool isEven(unsigned int a)
{
bool res = true;
_start:
if(a == 0)
{
return res;
}
a = a - 1;
res = res ^ true;
goto _start;
}
Since the only definition of a within the loop are of the form "a = a - 1" it can be treated as an induction variable, and so the compiler can determine the number of loop iterations are equivalent to the value of a. from that you can derive the value of res in terms of a as a closed form and after that the loop can easily be eliminated.
Heavy hitter for this in LLVM is rewriteLoopExitValues:
https://llvm.org/doxygen/LoopUtils_8cpp_source.html#l01549 it's called by the induction variable elimination pass. The variable is represented with a SCEV (SCalar EVolution) model, defined here:
https://llvm.org/doxygen/ScalarEvolution_8cpp_source.html. Compiler's able to pretty quickly calculate the final value using this. Won't pretend to understand the code but you can read it if you want. We end up with:
bool isEven(unsigned int a) {
return (a & 1) == 0;
}
which compiles as shown