4 ms·
> UB problems happen only when compilers detect it, understand it is an opportunity for optimization, because they are allowed to do anything, then do that opti
by MauranKilom 5y ago
> UB problems happen only when compilers detect it, understand it is an opportunity for optimization, because they are allowed to do anything, then do that optimization.
This is a deep misconception, and not at all how most undefined behavior is related to optimization.
Trivial example: Compilers assume that your variables aren't written to randomly from other threads. Without this assumption, virtually no optimization would be possible. Therefore, data races are UB - they violate a hard assumption of the compiler. But at no point did the compiler say "oh, you wrote to this variable without synchronization! Now I'll show you, hehehe!".
This is the same for e.g. removed overflow checks. Compilers can optimize many loops only if they assume signed integer overflow never happens. So, because compilers should be able to assume this, it is UB if it happens in your code. The same logic that deduces "this loop cannot wrap around" deduces "this if condition [an overflow check] cannot ever be true".
But it's easier for a programmer who got their UB-reliant checks optimized out to attribute malice to the compiler than to understand optimization fundamentals, and thus we get people complaining to high heaven and back.
- GoblinSlayer 5y ago>But at no point did the compiler say "oh, you wrote to this variable without synchronization! Now I'll show you, hehehe!". That's because the compiler doesn't detect the situation. If it knew, it could, say, remove all code leading to that point - it's legal and the resulting code would be faster. >Compilers can optimize many loops only if they assume signed integer overflow never happens. I don't think this happens. Most loops iterate over arrays, and at least in C tradition unsigned integers are used as array index with no signed integers in sight.
- dooglius 5y agoYou are strawmanning the parent, he did not claim that compilers will go "oh, you wrote to this variable without synchronization! Now I'll show you, hehehe!". Your description of the compiler's behavior matches his description; the compilers detect a case where the program might exhibit behavior defined ISO C spec (signed integer overflow), see it as a potential for optimization because they are allowed to do anything (certain passes can be made if overflow is assumed not to happen), then do that optimization.
- MauranKilom 5y agoYou can cast literally any optimization into this shape. For starters, virtually any optimization pass requires sane assumptions about (absence of) data races and/or out of bounds writes. The point you are arguing (or claiming OP argued) boils down to "compilers behave as I want when I turn all optimization passes off". No, the OP wrote specifically that "the compiler detects [UB]" and then does optimizations exploiting that. Not "detects potential UB". The former is a common misconception, the latter is basically a truism.
- dooglius 5y ago> You can cast literally any optimization into this shape Tell me how these use UB: integer constant folding, unused load removal, optimal use of GP registers to minimize stack spilling >sane assumptions "sane" here is doing a lot of work. Assuming overflow won't happen is not a sane assumption, assuming some other thread won't randomly write into your stack memory is.
- MauranKilom 5y ago> integer constant folding int a = 10; int var1; int b = 20; foo(&var1); int c = a + b; You'd like to constant fold c? Better assume no UB: void foo(int* x) { *(x-1) = 0; } > unused load removal Same idea as above. > Assuming overflow won't happen is not a sane assumption If the alternative is loops being much slower when you request optimizations, then maybe it is. Consult your compiler manuals if this default irks you.