I have a question about how clang handles exit() calls. It seems that two instructions (when -emit-llvm is used) are generated : CallInst followed by UnreachableInst. While this makes perfect sense from semantics/optimization/correctness perspective, I am curious to know whether it is possible to treat exit() like any other library call (ie, generate a BranchInst instead of UnreachableInst) via a compile time switch/option ? Any pointers to the relevant code (for handling exit()) within clang will also be very helpful.
I am asking because some of the analysis I am writing in the backend would be easier if I did not have to deal with exit() as a special case (mainly to do with structured control flow).
It's generally better to send questions about LLVM IR to the llvmdev list. In this case, I'm not really sure. It sounds like you should handle general LLVM IR. Trying to special case things is a recipe for fragile code.
Thanks for the reply. Right now, I disabled the doesNotReturn() check in the code for emitting calls in clang (CGCall) and also disabled running simplifycfg/prune-eh passes that introduce UnreachableInst after exit().
The main issue is that the particular transform pass that I am using in our backend does not yet support multiple loop exits and common case where this issue arises is when there are exit() calls inside the loop. With the above change, -loopsimplify is able to transform all loops (that i have tested) that have exit() calls within them to have single loop exits.
But, as you said, this kind of change is fragile and also gives up on some scalar optimization opportunities. I guess the right solution in the long term would be to add support for multiple loop exits in the custom transform pass.