3 ms·
That's not a good take. Compilers love UB because it signals unreachable code, and unreachable code can be removed and/or its surroundings can be simplified. If
by fay59 5y ago
That's not a good take. Compilers love UB because it signals unreachable code, and unreachable code can be removed and/or its surroundings can be simplified. If UB was instead defined to trap, most optimizations that are made possible by UB would still be possible, but without the footgun part.
Specifically with this example, if the rust community cared, it could implement pattern detection for this operation and reduce it to a constant-time operation too; the reality is just that nobody cares and this optimization was probably only added to make Clang look better on a specific benchmark.
The other problem with UB is how capricious the specification is. There is no contemporary reason for why signed integer arithmetic is UB and unsigned integer arithmetic isn't. It's just a wrinkle from the past that somehow, some people prefer to praise than to fix.
- mike_hock 5y ago> If UB was instead defined to trap, most optimizations that are made possible by UB would still be possible, but without the footgun part. ... on hardware where the native instruction happens to trap. Otherwise it needs to generate a conditional branch and explicit trap instruction, which is as unoptimal as any other imposed behavior.
- fay59 5y agoNo, you’ve missed the point. It’s still much better to have a trap than “any other imposed behaviour” because the compiler can reason that this condition is impossible on the happy path and remove code accordingly. Removing code is both among the most sensitive and the most effective optimizations that compilers do, and they use UB as another signal for “unreachable”. The current model of “assume things never happen and don’t plan anything in particular if it does happen” does no one a service.
- mike_hock 5y agoIf you impose that the unhappy path must trap, the compiler has to guarantee that. Conversely, if the compiler can reason that the condition is impossible, it can remove code regardless of what behavior is imposed for the condition that it knows can't happen.
- UncleMeat 5y ago> If UB was instead defined to trap, most optimizations that are made possible by UB would still be possible, but without the footgun part. That's not true. Suddenly, almost every single signed integer operation on a machine with different hardware integer widths than the language implementation requires branching to check for overflow.
- fay59 5y agoYou could also take a measured approach and, like rust, just define signed overflow to wrap. UB and its current interpretation is not worth whatever small sliver of performance the current implementation of LLVM appears to give you.
- UncleMeat 5y agoI don't agree that this is measured. It has a few big problems. 1. Basically no developer actually wants it to wrap. This is almost certainly a logical bug that just pushes the problem a few statements further into the program. 2. Defining it to wrap means that you need software checks for architectures that don't support hardware wrapping on the same width as the integer type. This means that all programs get slower when targeting these architectures. This isn't a "sliver of performance". It is a software branch at almost every integer operation. This approach is not especially well loved in the C/C++ communities.