3 ms·
On the contrary: if clang assumed that signed integers could overflow by default, then that would be a bug. Why? Because it would result in missed optimizations
by pcwalton 8y ago
On the contrary: if clang assumed that signed integers could overflow by default, then that would be a bug. Why? Because it would result in missed optimizations, and optimizations are the reason why we use an optimizing compiler.
Here's an example of what can happen if the compiler doesn't perform these optimizations: https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759de5a7 https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759...
The loop codegen when the optimization is not performed is pretty atrocious. That is the bug, and solving that bug is the reason why compilers assume signed overflow cannot happen.
If you want to blame something, blame the C language. Compiler developers are just doing their jobs.
- nkurz 8y agoHere's an example of what can happen if the compiler doesn't perform these optimizations: That's a great article, although I don't think it shows the advantage of assuming that undefined behavior will never occur. Rather than assuming "no undefined behavior", wouldn't it be legal (and preferable) for a compiler to just let the overflow (or lack of overflow) occur, and make the same optimization? For me the entire point of contention is the difference between "undefined" and "implementation defined". Maybe I'm wrong about the details here, but I think this is a case where a compiler could be just as fast without the nasal daemons.
- BeeOnRope 8y agoIt is doing exactly what you say - the code as generated simply lets the "overflow" occur, which is what makes it fast. In particular, if the index variable overflows the size of `int` it will just keep increasing. Effectively, the compiler has replaced int with long under the covers, since the cases where the behavior between int and long differ are exactly the cases where the int has overflowed. So it's not always the case that the compiler assumes "overflow won't happen" and then _removes code_ - it just compiles code in a way that is ideal for the non overflow case and then what happens in the overflow case just falls out of the generated assembly (usually it does something bad like OOB access, but the same would generally be true of a wrapping overflow also). You can't make this "implementation defined though", because the behavior is from a C-source point of view, it is effectively: "In the case an int overflows, we silently add 32 more bits and keep incrementing". Obviously you can't support that behavior in general, and even in specific cases it leads to nonsense like ints have non-representable values, etc.
- ajross 8y agoGCC gets those loops optimized correctly without hitting the broken code in the linked article. I don't see that that's particularly responsive. Software is a concrete thing, it has concrete behavior, and problems can be solved there instead of pontificating about what paper standards say.
- twtw 8y ago> If you want to blame something, blame the C language. Compiler developers are just doing their jobs. Compiler developers are doing a fantastic job, and I absolutely do blame the C language and standard. For the cases referenced in the article, it seems to me that the preferred solutions would be making int 64-bits and leaning on the restrict keyword rather than the semi-disaster that is strict aliasing (https://blog.regehr.org/archives/1307 https://blog.regehr.org/archives/1307).