[LLVMdev] Does nounwind have semantics?

Nick Lewycky nicholas at mxc.ca
Sun Jul 21 21:07:56 PDT 2013


Andrew Trick wrote:
> Does 'nounwind' have semantics that inform optimization passes? It seems to in some cases, but not consistently. For example...
>
> int32_t foo(int32_t* ptr) {
>    int i = 0;
>    int result;
>    do {
>      bar(ptr);
>      result = *ptr;
>      bar(ptr);
>    } while (i++<  *ptr);
>    return result;
> }
>
> Say we have a front end that declares bar as...
>
> declare void @bar(i32*) readonly;
>
> So 'bar' is 'readonly' and 'may-unwind'.
>
> When LICM tries to hoist the load it interprets the 'may-unwind' as "MayThrow" in LICM-language and bails. However, when it tries to sink the call itself it sees the 'readonly', assumes no side effects and sinks it below the loads. Hmm...
>
> There doesn't appear to be a way to declare a function that is guaranteed not to write to memory in a way that affects the caller, but may have another well-defined side effect like aborting the program. This is interesting, because that is the way runtime checks for safe languages would like to be defined. I'm perfectly happy telling front ends to generate control flow for well-defined traps, since I like lots of basic blocks in my IR. But I'm still curious how others deal with this.

Yes, we went through a phase where people would try to use 
"nounwind+readonly == no side-effects" to optimize. All such 
optimizations are wrong. Unless otherwise proven, a function may 
inf-loop, terminate the program, or longjmp.

I tried to add 'halting' to help solve part of this a long time ago, but 
it never went in. The problem is that determining whether you have loops 
requires a FunctionPass (LoopInfo to find loops and SCEV to determine an 
upper bound) and applying function attributes is an SCC operation 
(indeed, an SCC is itself a loop), so it's all blocked behind fixing the 
PassManager to allow CGSGGPasses to depend on FunctionPasses.
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20100705/103670.html

I'm now in a similar situation where I want 'nounwind' to mean "only 
exits by terminating the program or a return instruction" but 
unfortunately functions which longjmp are considered nounwind. I would 
like to change llvm to make longjmp'ing a form of unwinding (an 
exceptional exit to the function), but if I were to apply that rule 
today then we'd start putting dwarf eh tables on all our C code, oops.

Nick



More information about the llvm-dev mailing list