Such an optimization happens in simple circumstances when the diverging function loop {}-s. However, the optimization should also be applied when eg. the diverging function recurses. Generally, every call to diverging function should just be a jump.
A diverging function can still unwind. I’m not entirely sure how exactly unwinding works on a technical level, but I’m certain you’ll need the stack for it, including the back-pointers from a call instruction.
I couldn’t figure out how to achieve this at all, do you mind sharing the code that did it for you? In particular, how would you achieve that the called function isn’t simply inlined in which case the jump could be part of the loop {} itself?
That won’t work due to unwinding, as explained above; however it could be an option for functions for which the compiler figures out that they never unwind. I’m not sure if this is something that rustc itself can reasonably implement, perhaps an optimization like this would have to be implemented in LLVM instead. Also it’s questionable how relevant this “optimization” is after all. As far as I can tell, we’re talking about a call instruction that will only be executed once in the entire runtime of the program; seems not really worth any optimization in terms of speed; and saving one back pointer worth of stack space, well…, it’s something bit it isn’t much.
I'm coming to this from the standpoint of making a kernel. There, diverging funtions are used for many tasks, and I found myself wanting to (cyclically) call such functions representing control flow of the kernel. Since unwinding isn't an option anyway in such environment, I thought it'd be neat to have these calls be simple jumps.
Hopefully one day we'll get opt-in guaranteed tail calls for Rust -- that's why the become keyword is reserved. But right now doing loops as recursion is usually a poor idea because it's not optimized in debug mode even when it'd work fine in release.
In a panic = "abort" environment, the IR generated correctly contains tail call.
However, the LLVM implementation rustc uses emits call nonetheless. On the other hand, feeding the IR to llc --tailcallopt produces jumps (but this is not used by rustc).