> The question here is: can the compiler hoist the final division operation above assignment to x?
A division calculation not a visible effect. Therefore the question doesn't even m ake sense: it's asking: can we see something that is not a visible effect (division) before or after a visible effect (modification of a volatile object).
What if x is a register to toggle divide-by-zero exceptions? Normally this is none of the compilers business, but the whole point of volatile is a mechanism to express stuff like that, so it needs minimal semantics, e.g. no time traveling (compiler barrier), to be fit for purpose.
Hmmmmm. It's late, but FWIW I think this comment from Martin from last year might be relevant: https://news.ycombinator.com/item?id=40838721 And I'm guessing the note that was added is fn#150 in C23. Volatile accesses aren't general memory barriers, but I think Martin's point is the potential for UB behavior means the compiler has to preserve the sequence order of the potentially UB operation relative to the volatile access.
Both the C and C++ standardization have decided that even when there is undefined behavior the program is partially defined. But nobody is confounded by this.
We don't need to suppose this, as this is what is already required in C. You are right that when I/O is performed it is up to the host system what happens, and it is also possible that on UB the whole system crashes if it is poor. But this is outside the jurisdiction of the C language.
What it is important though is that where C spec can be complemented by other specification that add reasonable requirements about the host system, e.g. that it does not crash then a program misbehaves or that I/O is performed according to certain rules, certain safety properties can then be ensured. This would not be possible without UB being restricted in this way. As compilers are now being fixed, this is not churn but a real world improvement people have asked for.
But a division that traps because you divide by zero would prevent previous observable behavior from happening when hoisted above it. So it is not about the division itself but about the indirect effect on other behavior that can be observed.
Compilers already understand this: For example, they would not hoist a potentially trapping operation such as a division above a function call. The issue is that they did not apply this rule also to volatile accesses, but LLVM now does because this was fixed.
I thought this would be about adding a switch by which to undo every silent code removal operation because the compiler concluded a section includes undefined behavior in some obscure case, like overflow. And doing so silently. So when you recompile on a new compiler, on embedded, your code now fails. Can't do that Dave.
How did we ever get here??
As a user that's so outrageous it must be a deliberate conspiracy against C. I'm sure it isn't but it certainly helps it's demise, as the feeling the tool is in the hands of imbeciles that mistake the trees for he forest. C now requires you to be an expert on undefined behavior, and the psychology regarding the matter, while previously C would be forgiving.
So I thought the article would be about --forgive --generous, or --embedded while there should have been --petty in the first place.
I wish they added some simple form of generics so that one could, for example, create types like "list of files", "list of processes" without duplicating the code.
Also, something for RAII, so that one could automatically deallocate allocated memory.
14 comments
[ 0.17 ms ] story [ 54.3 ms ] threadA division calculation not a visible effect. Therefore the question doesn't even m ake sense: it's asking: can we see something that is not a visible effect (division) before or after a visible effect (modification of a volatile object).
What it is important though is that where C spec can be complemented by other specification that add reasonable requirements about the host system, e.g. that it does not crash then a program misbehaves or that I/O is performed according to certain rules, certain safety properties can then be ensured. This would not be possible without UB being restricted in this way. As compilers are now being fixed, this is not churn but a real world improvement people have asked for.
Compilers already understand this: For example, they would not hoist a potentially trapping operation such as a division above a function call. The issue is that they did not apply this rule also to volatile accesses, but LLVM now does because this was fixed.
How did we ever get here??
As a user that's so outrageous it must be a deliberate conspiracy against C. I'm sure it isn't but it certainly helps it's demise, as the feeling the tool is in the hands of imbeciles that mistake the trees for he forest. C now requires you to be an expert on undefined behavior, and the psychology regarding the matter, while previously C would be forgiving.
So I thought the article would be about --forgive --generous, or --embedded while there should have been --petty in the first place.
Also, something for RAII, so that one could automatically deallocate allocated memory.