Conversation

Compilers are extremely bad at proving termination and the issue with the sideeffect intrinsic is it acts as a universal side effect and is not handled by optimizations. It is treated as potentially doing global memory writes, etc. and completely breaks all other optimizations.
1
So for example, you can have a simple loop over an array based on the length, and the compiler may not be able to tell that terminates since it can't tell that the length of the array isn't changed (even though a human trivially can). If you insert the intrinsic it destroys perf.
2
It depends on the simplicity of a condition and how it's written. You could write a binary search so that the compiler can see that it always terminates, but it wouldn't be the normal way to write it, etc. Many loops are not going to be verifiable as trivially terminating.
1
Mutually recursive function calls are another case that's very difficult. In order to avoid treating every single function call as needing to have that universal side effect inserted (destroying tons of optimization), the compiler would have to analyze the call graph.
1
Even if the recursion isn't via guaranteed tail calls stack overflow is well-defined and safe in these languages. It CANNOT be replaced with arbitrary memory corruption. They're saying that even remotely safe languages should have significantly worse compile-time and performance.
2
C compilers should be guaranteeing that stack overflow is safe and guaranteed to trap too. They shouldn't be optimizing out infinite recursion as they will happily do. It should either infinite loop or crash to be correct, not fall through to other code in an indeterminate state.
1
Guaranteed-to-trap isn't really safe unless you just count process termination is safe. In the presence of optimizations, there's no good way to assess what changes to state have or haven't taken place yet at the point of trap, so you can't really continue execution.
1
Their wrong implementation of the optimization can lead to arbitrary memory corruption. It breaks the safety semantics in safe languages very blatantly. It lets control flow fall through somewhere that's supposed to be impossible per the language's control flow and type system.
1
So for example, Rust has a concept of a function that doesn't return. After you call one, it isn't going to force you to write any more code afterwards since it knows the control flow can't get there. It's often explicitly needed to write code that can pass type checking.
1
Show replies
Yeah, but even if Clang had -fstack-clash-protection (it doesn't yet), it will happily optimize based on the *assumption* that infinite recursion doesn't happen, so it will remove the possibility of a stack overflow guaranteed to safely terminate the process, and allow worse.
2
Show replies