3 ms·
> But that has nothing to do with overflow being undefined; That's not the whole story [0]. It looks like JF Bastien managed to convince everyone that 2's com
by xscott 4y ago
> But that has nothing to do with overflow being undefined;
That's not the whole story [0]. It looks like JF Bastien managed to convince everyone that 2's complement is the only signed representation that exists and is worth considering, and so pretending to be portable to anything else is pointless. But then he met "strong resistance" trying to finish the job:
The author had hoped to make this well-defined as wrapping (the operations produce the same value bits as for the corresponding unsigned type), but WG21 had strong resistance against this.
So at least one standards person tried to achieve sanity, but he was overwhelmed or outnumbered by the rest of the asylum.
For a stand alone application, -fwrapv makes this silliness go away. However, if I want to write a library where I don't get to control the options my end users select, we're going to end up with silliness like this:
struct integer { intptr_t val; };
integer operator +(integer lhs, integer rhs) {
return (integer) { intptr_t(uintptr_t(lhs.val) + uintptr_t(rhs.val)) };
}
There. Now I've got sane integers. Compliant, and I'll bet it optimizes just as well.
[0[] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r4.html https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p09...
- bonzini 4y ago> So at least one standards person tried to achieve sanity At the cost of real-world pessimization of generated code. It's basically impossible to optimize induction variables without undefined signed overflow, and it's possibly the most important optimization for C code, maybe after inlining and simple manipulations such as dead code elimination. On the other hand, defining right shift of negative numbers is now a no brainer. No compiler even thought of exploiting UB there, and C2X will codify that. > Compliant, and I'll bet it optimizes just as well. Try, you will be surprised.
- xscott 4y ago> It's basically impossible to optimize induction variables without undefined signed overflow Here's a piece of code you can compile with: gcc -O3 -Wall -Wextra mandel.c -DINTEGER=size_t -o mansize gcc -O3 -Wall -Wextra mandel.c -DINTEGER=int -o manint https://godbolt.org/z/Wx4aavvjj https://godbolt.org/z/Wx4aavvjj Both versions, the one with the signed integer UB you claim is so important, and the one using size_t with no UB worries at all run in about .28 seconds on my desktop. I can imagine you'll have some objection: This isn't a true Scotsman, or this isn't representative of real world code, or this example makes it too easy for the compiler to optimize, or that's not about induction variables, or something creative... That's fine, but the next example is on you. I look forward to seeing what you come up with. > it's possibly the most important optimization for C code, maybe after inlining and simple manipulations such as dead code elimination. Dead code elimination is one of the most important optimizations?!? Are you worried about binary size or CPU time?
- bonzini 4y ago> This isn't a true Scotsman, or this isn't representative of real world code It is, but induction variables optimization generally requires lots of memory accesses. I will try to come up with something. > Dead code elimination is one of the most important optimizations Yes, inlined code has a lot of constant conditions and code that similarly only follows one path only. Dead code elimination, constant propagation, eliminating stuff like &*x so that x can stay in a register, are all very important to achieve zero-cost abstraction. Mostly in C++, Rust and the like, but also in C.