5 ms·
You didn't understand the example. Certainly this may be true, but I've re-read it again with your prompting and still think I understand it. Your proposal de
by nkurz 11y ago
You didn't understand the example.
Certainly this may be true, but I've re-read it again with your prompting and still think I understand it.
Your proposal destroys load-load forwarding, as the article demonstrates.
I'm fine a compiler that optimizes out the write to a value on the stack on the assumption that this can't be the same address as a passed pointer, whether that parameter is an int or float. I'm fine with a compiler that creates assembly that simply returns 0 here, with or without 'restrict'.
That you and the author think this example represents a conflict with John's "friendly C" proposal makes me more certain that you don't mean the same thing by "friendly C" as I do, or as I think John does. Really, I think we're asking for something quite different, and much simpler to achieve.
- pcwalton 11y agoAre you proposing that compilers emit actual load instructions for every memory access you write in your code? That is, preventing the compiler from optimizing out memory loads? I can't read your comment any other way, but I may have missed something. In any case, if you require that a compiler emit an actual load instruction for every memory access then you've destroyed SROA, which is one of the most important optimizations, especially in C++. Without SROA C++ can easily be 4x-5x slower.
- nkurz 11y agoAre you proposing that compilers emit actual load instructions for every memory access you write in your code? No, if the compiler can reason that that there is no aliasing between pointers, there is no need to emit a load. Reordering operations so a value remains in registers is desirable, even if an out-of-bounds write would otherwise have had the side-effect of changing the value. The problem (in this context) is limited to optimizations that reason that the value of the read is "undefined" (as opposed to "implementation defined"), and that the compiler no longer has any obligation to be faithful to the source code for any actions that follow. For example (conceptual rather than exact) if I set all the bits in a region to 1's, and then somehow manage to write an unaligned load from within this region, I do not want the compiler to reason that this value is undefined and that all consequent code can be ignored. I'm fine with a compile time error, and I'm fine with generating assembly that attempts the load and uses the result. Getting SIGBUS for the load on some processors is perfectly acceptable. I'd probably even be OK with skipping the load and using a constant, although I'd hope this would at least be accompanied by a warning message. What I don't want is for the compiler to silently omit the load and all the rest of the code within that function on the theory that once undefined behavior has been encountered it no longer has any obligations, not even the obligation to inform the programmer that it has perversely optimized the function to nothingness. (And while most of the lack of clarity is probably my own fault, I do now realize that I was being thrown off by an unfortunate typo in the original post: presumably he meant for the second argument to be a 'float *' rather than a 'float'. Please ignore my comment about 'stack variables' higher in the thread.)
- pcwalton 11y ago> No, if the compiler can reason that that there is no aliasing between pointers, there is no need to emit a load. Without strict aliasing? Then you destroyed a bunch of optimizations that lower for loops to memset. 4x performance loss if AVX would have been used in memset. See: http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-... ("Violating Type Rules") > What I don't want is for the compiler to silently omit the load and all the rest of the code within that function on the theory that once undefined behavior has been encountered it no longer has any obligations, not even the obligation to inform the programmer that it has perversely optimized the function to nothingness. No, you need that optimization too. After aggressive inlining, especially of templated code like the STL in C++, it's often the case that large swathes of code are never dynamically reached, and people want that dead code to be removed. However, the only—or at least the easiest—way the compiler can tell that this is the case is by observing that, for example, a null pointer would have to be dereferenced to get to that dead code. Therefore the compiler is doing you a favor by eliminating that obviously dead code. Again, all of these optimizations do not stem from compiler authors being language lawyers for the fun of it. They stem from their customers filing bugs on real-world missed optimizations.
- nkurz 11y agoWithout strict aliasing? Generally, I think strict aliasing is a fine thing. It would have been nicer to have "restrict" be the default and "alias" being an optional specifier, but likely there was no way to do this without breaking too much existing code. Warnings are often nice, but I don't recall having any issues with compilers optimizing based on assumptions of lack of aliasing. especially of templated code like the STL in C++ I'm an opinionated C programmer, but have no opinion of how C++ should handle things. I'm only considering the impact on C. If the STL requires an unfriendly C++ compiler, I'm OK with that, but this doesn't affect my thinking about C compilers. However, the only—or at least the easiest—way the compiler can tell that this is the case is by observing that, for example, a null pointer would have to be dereferenced to get to that dead code. Or, for example, that a signed integer addition would have to overflow. Or a full-width shift. Or a variety of other things that have a might make sense in both the programmers mental model and on the processor on which the compiled program will be run. Therefore the compiler is doing you a favor by eliminating that obviously dead code. Do you really believe that the compiler is doing you a favor by silently removing a check for signed integer overflow that you explicitly included? If so, we have found (at least one of) the point(s) of our disagreement! If on the other hand you feel that removing security related error checking is an unfortunate negative consequence of a necessary optimization, perhaps we can find a way to mitigate the consequences?