Well they should have an always_returns attribute and they cannot simply remove calls to functions based on that not being present. They already handle this correctly in terms of unwinding. For example, pure_may_unwind(); pure_may_unwind(); will be optimized to 1 call, but not 0.
Conversation
I don't think it'd even be that hard to add support for always_returns. There's just no one particularly interested in arguing for a new function attribute and implementing it in order to *constrain* existing optimizations to make them correct, rather than making code faster.
2
One observation from having had many conversations like this with you: your fatalism about things like this often seems exaggerated, and makes it hard to get anything productive out of these exchanges.
1
My perspective on it is based on bugs.llvm.org/show_bug.cgi?i breaking Rust, LLVM falsely justifying it based on C semantics (even though even the C11 semantics don't permit it) and then throwing some scraps at other languages that aren't acceptable to use: reviews.llvm.org/D38336.
1
2
The way the C standard ends up working is they can just take the shortcut of making everything undefined, even changing things to be *retroactively* undefined, and then other languages without that option using the same compilers are just completely screwed.
1
So for example, type-based alias analysis is important for other languages, but in those other languages it actually has to be a sound model / implementation or it can't be used. Similarly, the pointer provenance stuff is important to them, but it actually has to be sound too.
1
So, I find the whole thing frustrating, based on my perspective where these rules are internal to the compiler, and don't actually make the language less safe to use, unless they are broken. Sadly, they are okay with stuff simply being broken or partially fleshed out for perf.
2
It's so stupid that they expect non-C / non-C++ languages to mark every maybe non-terminating loop or potentially recursive call as having a side effect. It would completely destroy optimization just to work around them not making a sound model and falsely justifying it via C.
2
Non-termination *is a side effect*. A function which does not terminate is not pure in any reasonable sense of the word.
1
No language needs to cater to optimization of functions which don't obviously terminate. Writing such functions is a bug - either a behavioral bug (if it turns out really not to terminate) or an analyzability bug (correctness is non-obvious).
1
Turning non-termination into memory corruption and other awfulness isn't something that safe languages can accept. It doesn't matter that it's already a bug. It has to remain safe, and has an impact on language semantics. The sideeffect attribute has a huge performance cost.
There are different kinds of side effects. What LLVM should be doing is not making incorrect optimizations, and properly modelling termination as a side effect as they do for unwinding. When I'm saying pure in this thread I mean the LLVM definition of it, not a high-level one.
1
They model unwinding and termination separately from other side effects. There's also the concept of functions that can depend on external state, those that can depend on it and change it, and separately from that unwinding and termination effects.
1
Show replies
That's not the consequence of what I said. Rather, unless the safe language has a proof of termination, it marks the function non-pure.
1
If this produces notably worse optimization, it's the fault of the person who wrote the code that doesn't obviously terminate, not the compiler's fault.
1
Show replies

