4 ms·
Here the author is constructing a theory based all on true statements, but the mental model he builds, which is philosophically valid, is IMHO not the best choi
by antirez 8y ago
Here the author is constructing a theory based all on true statements, but the mental model he builds, which is philosophically valid, is IMHO not the best choice in order to really address and simplify those concepts, for the scope of further reasoning upon that aspects of languages. My POV is that the interpretation of what a pointer is, should be more bound to the low level load/store instructions, and the address space of the process. In this declination a pointer is just a number, the problem is that certain programming statements in C/C++ that the programmer believes will result into a load/store operation, will be disregarded by the compiler, in name of a set of rules that violate what should be a normal behavior. So I think that a better mental model is to think at a program as a set of load/store operations (from the POV of memory), and how the compiler may decide to disregard such operations depending on the context. I think that reasoning like that also makes us pointing the finger in the right direction, which is the ANSI C committee.
- vardump 8y ago> Here the author is constructing a theory based all on true statements, but the mental model he builds, which is philosophically valid, is IMHO not the best choice in order to really address and simplify those concepts On the contrary, I feel those concepts are great for reasoning about code on a symbolic level. Which is what a compiler is all about. > In this declination a pointer is just a number, the problem is that certain programming statements in C/C++ that... Wouldn't this mean the compiler will need to generate a more memory loads and stores that could otherwise be proven redundant? It'll need to assume a store through a pointer 'a' at index unknown at compilation time can modify data at pointer 'b', even though it could otherwise deduce there's no aliasing.
- antirez 8y agoI meant to only change the reasoning the author is used in terms of optimizations being the ability to ignore loads/stores versus giving more semantical value to a pointer.
- vardump 8y agoYou need that semantic information for a pointer to reason about loads and stores to memory blocks. (This semantic information exists only during compiling process.) The compiler needs semantic data to answer questions like "can an access through pointer A access data visible through pointers B and C?" If it doesn't know that, it'll need to generate those redundant memory accesses. Before storing (or loading) through A, it'll need to store temporary values previously written to B and C. After a store through pointer A, it might need to load B and C values again for more computation, because a store to A might have modified them.
- antirez 8y agoYes, but giving each pointer metadata for the goal of saying, at compile time, I can ignore or not certain access patterns in this pointer, is conceptually different (but practically the same, it's just a POV) of saying that a pointer is not just a number. Both ways are ok to represent things, but I've the feeling that saying "a pointer is not just a number" in some way allows the ANSI-C culture of UBs to be culturally validated. Moreover, the definition given in the blog post, is also far from the actual nature of machines, where actually a load/store operation for this number will result in the same operation.
- dbaupp 8y agoThe model of "pointers are just a number" likely means that even "obvious" optimizations like int i = 0; *p = 10; return i; // becomes *p = 10; return 0; aren't valid, because p could "just be a number" pointing to i's stack slot.
- dingo_bat 8y agoCan you explain this more? Surely the compiler can reason about p being able to point to i's address.
- dbaupp 8y agop could be int *p = rand(); or that code could be in a function int f(int *p) which may be called from completely different compilation units (or even across a dynamic library boundary) meaning there's no way for the compiler to know what p is.
- antirez 8y agoI don't claim that the compiler should avoid any kind of optimizations because pointers are numbers, but that the formal model should be that the compiler can ignore certain loads/stores in certain paths, rather than overloading of semantical value the pointer itself. It's just a different POV that one could use to analyze what happens. Similarly, different statements should be used in order to specify how rigid we want the compiler to be with our loads/stores for a given pointer, so that certain optimizations that are obvious like the one above are the default, and others are performed only if the pointer is specified via keywords and other annotations to have a very special meaning.
- dbaupp 8y agoHow exactly does the model specify which loads/stores are okay to be ignored or reordered (etc.)? I feel like anything that gets close to the essence of the C/C++/Rust model (such as allowing the optimization in my example above), ends up with something pretty similar to the "allocation id" idea. As a specific example, consider the difference between these two versions of my example above: int f() { int i = 0; *(&i) = 10; return i; } and the original: int g(int *p) { int i = 0; *p = 10; return i; } If a call like g(rand()) ends up with p == &i, the unoptimized versions of that and of an f() call execute exactly the same sequence of memory accesses, and yet the optimization I mention above only applies to g. In essence, the source of the number "&i" seems to matter. > others are performed only if the pointer is specified via keywords and other annotations to have a very special meaning. Some of this already exists, such as 'restrict'.