[LLVMdev] Does nounwind have semantics?
Andrew Trick
atrick at apple.com
Mon Jul 22 00:32:48 PDT 2013
On Jul 21, 2013, at 11:55 PM, Duncan Sands <baldrick at free.fr> wrote:
> Hi Andrew,
>
> On 22/07/13 02:56, 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...
>
> is your worry here about the following case?
> - the load will trap if executed
> - bar throws an exception
> Thus with the original code the trap will not occur, because an exception will
> be thrown first, while if you move the first bar call below the load then the
> tap will occur.
Essentially, yes. My takeaway from looking into it is:
- nounwind means no dwarf EH. Absence of nounwind means absence of dwarf EH. It would be unwise for optimization passes to reason about the semantics beyond that. I was momentarily mislead by the LICM code that handles MayThrow specially.
- Things that throw exceptions or trap in defined ways are not readonly.
- Runtime checks for overflow, div-by-zero, bounds checks, etc. should be implemented at the IR level as branches to noreturn calls because it can be done that way and I haven’t seen concrete evidence that it’s too expensive. Don’t try to do something fancy with intrinsics and attributes unless absolutely required.
- Optimizing readonly calls in C is a tangentially related issue, as Nick explained. My answer to that problem is that C compilers are effectively forced to assume that calls terminate, so developers should not expect otherwise. If C developers don’t want the compiler to optimize their infinite loop or infinite recursion, they need to throw in a volatile dereference.
-Andy
>>
>> 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.
>
> I'm pretty sure that exiting the program is considered to write memory, so bar
> can't do that itself.
>
> Ciao, Duncan.
>
> 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.
>>
>> -Andy
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130722/25ea056f/attachment.html>
More information about the llvm-dev
mailing list