3 ms·
Why do you assume we want either Pascal ("wrapping semantics") or random-"optimizations". Those are not the choices. It's actually very easy for the compiler to
by vyodaiken 8y ago
Why do you assume we want either Pascal ("wrapping semantics") or random-"optimizations". Those are not the choices. It's actually very easy for the compiler to detect that it is a check to avoid overflow, it's the text of the program. You don't need to compile with wrapping semantics: the compiler generates code that actually does overflow the counter. All you need to do is to stop using invalid reasoning of the type: We assume that overflow cannot happen, yet generate code in which it does happen.
- BeeOnRope 8y ago> Why do you assume we want either Pascal ("wrapping semantics") or random-"optimizations". I don't think I assumed that. I think there are a variety of ways of dealing with the overflow issue, which fall at a variety of points within the multi-dimensional design space that includes considerations like (a) comprehensibility by the average programmer and principle of least surprise (b) performance (c) fast failure (d) portability across hardware. I don't know if C and C++ made the right decision with leaving this UB, nor am I convinced of the compiler writers method of handling the UB, but they are at least consistent in usually favoring performance and portability above other concerns. That it, is it is not obviously wrong to me or, nor dominated with another obviously better behavior. > It's actually very easy for the compiler to detect that it is a check to avoid overflow, it's the text of the program. I guess you are suggesting some type of idiom recognition, which will preserve these checks, but still allow full optimization in other cases where overflow is not expected or the intent of the programmer was different? I don't think that will ever happen. The best you can hope for is that the involved compilers simply decide to define signed overflow as wrapping, i.e., make the -fwrapv behavior the default. Personally I think that's a reasonable choice.
- vyodaiken 8y agoI can't imagine it is ever the intent of the programmer that if(i+1 < i)x be there simply as decoration to be removed by the compiler. If the compiler can deduce that the test will evaluate as false (or true), it is perfectly reasonable to optimize by deleting the line (or the check, in case of true). But this should be sound deduction. For example, if the target processor traps on overflow, the compiler can deduct that the conditional is always false. But what GCC/Clang do now is (a) generate machine code on x86 and ARM that does wrap, and (b) transform code on the axiom that ints will not wrap!That is, they take "false" for a theorem.
- BeeOnRope 8y ago> I can't imagine it is ever the intent of the programmer that if(i+1 < i)x be there simply as decoration to be removed by the compiler. I agree. > But this should be sound deduction. For example, if the target processor traps on overflow, the compiler can deduct that the conditional is always false. But what GCC/Clang do now is (a) generate machine code on x86 and ARM that does wrap, and (b) transform code on the axiom that ints will not wrap!That is, they take "false" for a theorem. I understand the desire, but you are talking about a different language, maybe assembly. C and C++ compilers just aren't in the habit of purposely compiling ill-formed code differently depending on the target processor. First and foremost they apply the rules of the language, and the rules are oriented towards portable-yet-fast code, and then as a last step they generate assembly or machine code. I _really_ don't think you want the compiler changing the rules of the game depending on the target architecture. In fact, the trend is almost entirely away from this in all modern languages: towards a single consistent execution regardless of the architecture. So the "deductions" you talk about are necessarily going to be against the abstract machine defined in the language, not against the final target. It worth noting too that there is even an increasing trend towards separating the higher-level compilation and optimization and the final generation of a binary from the IR, for example in the Apple App Store I think you now submit IR which can be specialized by the store itself for each target device, including some not created yet. So at least in the initial stages of compilation, you may not even know the target, or it may not even exist at the current time!
- vyodaiken 8y agoEven the C standard still pays lip service to the notion of C as high level assembler. The notion that C should be an abstract high level language insulated from the machine is foreign both to the language design and usage. C is not designed to be memory safe, for example. The intent of implementation dependent and undefined in the C specification was to make explicit that the compiler was not entrusted with safeguarding the programmer against non-portable use. The bizarre theory that this can be interpreted as a license to sabotage the programmer in the case of non-portable use makes C unusable for its intended purposes - even if it make it possible to wring performance from terribly written benchmarks.