sergio masci wrote: > *** YOU *** are saying "'knows' the intent of the line". *** I *** > am saying"'knows' the intent of several seperate lines as one unit" Ok. But so far you didn't explain how this is different for language elements that are implemented in the compiler versus language elements that are implemented in a library. The compiler can only "know" a priori what a single language element is doing (for both the built-in elements and the ones that are implemented in a standard library); the rest it has to figure out based on the program -- independently of where exactly the language elements are implemented. > I am saying something like: > > j = x * 2 + y * 2; > > temp = arr[j]; > > j = (x + y) * 2; > > arr[j] = temp; > > should also be reduced to nothing *** AND *** the compiler should warn > the user that this piece of code has no effect and so may be in > error. This is not possible if you understand only the intent of > single lines but can be fudged by the compiler by keeping track of > what is evaluated and where the result is placed. So although the > compiler might be able to reduce it to zero it doesn't understand > that this might be an error. How is this dependent on where the involved operators are defined -- as long as the compilers "knows" what they are supposed to do? > Things get much more difficult if we re-write the above as: > > int func_get(int arr[], int x, int y) > { > int j; > > j = x * 2 + y * 2; > > return arr[j]; > } > > void func_set(int arr[], int x, int y, int val) > { > k = (x + y) * 2; > > arr[k] = val; > } > > temp = func_get(arr, x, y); > > func_set(arr, x, y, temp); > > Ok the compiler *** MIGHT *** still be able to hack this if it is very > smart and all the source is available for the functions. BUT change > the type of the array from a straight forward int to a struct and > things get incredibly complicated (I mean they are really complicated > now with int but they will get MUCH worse with a struct :) I don't doubt that it's incredibly complicated, but I don't see how the exact implementation of the various operators affects this optimization. This optimization is based on the compiler "knowing" that (x * 2 + y * 2) == ((x + y) * 2), no matter how exactly they are calculated. If this identity can be derived from what's defined in the standard about the involved operators, then this optimization can be made, no matter where the operators are implemented. If it's not defined in the standard (for example, for typical floating point variables, this identity is generally not given), such an optimization can't be made -- no matter where the operators are implemented. > Here having built-in type like STRING, LIST etc reduces the > complication because the lanuage and compiler control the way they > are used. It's like the difference between a menu interface and a > command line interface. With the menu interface you guide the users > interactions and there can be no unexpected commands issued that will > break things (kind of). I still don't see this. You repeat that there is a difference, but don't really say where the difference is. The analogy with the menu doesn't seem to be very helpful; if I have a list defined with the operations insert, delete, replace, find, the "menu" is the same whether they are implemented in the compiler or in a standard library. It seems you forget that the library I'm talking about has an interface that's as strictly and precisely defined as the language itself, by the same language standard. Can you give an example where a programmer could give an "unexpected command" in the case the list is implemented in a standard library, versus the programmer not being able to give that "unexpected command" in the case it is implemented in the compiler? (Keep in mind that in both cases it is defined in the language standard what the programmer can do with the list -- and it's the exact same definition.) > But the same argument could be made for floating point. Many people > require different precission (wheather greater or less than that > provided by C) yet they either use what is available in a way that > suits them of they use a specialised library *** AS WELL *** as the > supported floating point. > > Often people will fit the solution to the tools available. I didn't understand the point you're making here (WRT the discussion about built-in versus standard library). Yes, I think it's helpful for both strings and floating-point when a user can use custom libraries instead of the implementations built into the compiler. And I also think that this only makes real sense if the syntax is the same in both cases. And IMO this means that there can't be any syntax advantage for the implementations that are built into the compiler. > in the above, how would I tell the compiler the relationship between > string_alloc, string_assign, string_substr and string_release such that > the compiler is able to: > > (1) ... indicate an error if tmp_str is not initialised with string_alloc > before string_assign is used on it (simply assigning a value to tmp_str is > not what I mean, I mean actually using string_alloc to initialise it). > > (2) ... indicate an error if tmp_str goes out of scope before it is > cleaned up with string_release > > (3) ... optimise the combined use of string_assign and string_substr > > (4) ... recognise that tmp_str is undefined after the use of > string_release > > This is why you need to be able to add special attributes to the > functions, to be able to tell the compiler about all this stuff. If I understand you correctly, this wouldn't be defined as attribute of the function, but it would be defined in the language standard, /before/ any implementation of a compiler or a standard library. Every library function I'm talking about is assumed to be defined in the same language standard where you define how your built-in list works. > in each of these cases C ensures that the actual paraemeters val_1, > val_2 and val_3 are floats before passing them to func_A. FWIW, I'm not a friend of this. I prefer explicit casts, and if I had a way to switch off all implicit casts in C or C++, I'd probably do it. (At least I'd start doing it to see how it works out.) But this is not related to our discussion about built-in vs library. > [...] All of this is the calling protocol. > > So yes the the compiler "understands" a standard library function in > as much as it "understands" its parameter requirements. This is not what I mean. This is what the compiler "knows" about any function, standard or user-defined. It "knows" more (or could "know" more) about standard library functions -- as much as there is defined in the language standard. > The C++ compiler still doesn't understand the relationships between > functions. The programmer does and he arranges all the objects to get > sensible optimised results. Whether it actual does or doesn't doesn't really matter here. What matters is whether this is /possible/ -- and whether there's a difference between implemented in the compiler or in a standard library. One of your first points was the replacement of a delete followed by an insert with a replace, for a list. This is possible because the compiler "knows" what delete, insert and replace do to a list, and how the list is supposed to work. It needs a definition for this. If this definition is given in the language standard, I still fail to see how it matters whether the list is implemented in a standard library or in the compiler itself. >>> An intrinsic function is one that the compiler understands >>> intimately. Not just what parameters it takes and what result it >>> returns. >> >> Next step is to define what "understands intimately" means. Does a >> specification (like in a language standard) qualify? > > No. I guess we don't really need to define what intrinsic functions are (and consequently what "understands intimately" means for you), as it's not what seems to be important in the question what exactly is the difference in optimizing sequences of commands, depending on whether they are implemented in the compiler or in a standard library (always given that both implementations follow the same language standard). >> Not sure whether the standard can tell you what kind of optimizations >> actual compilers implement. Much of this is probably a trade secret. >> Then I'm not convinced a casual look at this is enough to find out >> what /could/ be implemented. They don't talk about optimizations in >> the standard; they just say what has to be the result. >> >> Going back to one of your original arguments, the one that prompted >> my question about what the difference is between list operations >> that are implemented by the compiler and list operations that are >> implemented in a standard library: the substitution of a delete from >> a list followed by an insert into a list at the same location by a >> replace. >> >> If you want to implement such an optimization in your compiler, >> what's the difference between having these functions as part of the >> compiler, or having them defined as standard library functions in >> the standard that the compiler is based upon? In both cases, the >> compiler "knows" that this substitution is possible and the exact >> implementation of the three functions is not necessary to be known >> for this optimization to be possible. > > Yes I understand what you mean here. But in the case of functions > this relies on the compiler actually recognising the function names > and executing some internal code to perform checks, issue warning (or > errors) and perform optimisations. Yes. > That internal compiler code needs to be activated somehow and it needs > to perform a very specific task (not something that would be there > anyway - somthing that is written specially for that one perpose). Yes. Just as with your insert+delete==replace example. The compiler can do this, independently of where these functions are implemented. Pretty much every C++ compiler does this, for example, for custom implementations of the operator new. This is a special operator, and no matter whether I use a built-in version or a standard library version that came with the compiler or my own custom version, there are a number of special checks that are related to this operator that are executed by the compiler, based on what the language standard says about operator new. This internal code is activated by the use of an operator new; this is a reserved word, just like all other tokens/identifiers in the language standard. > If you really wanted to you could say that the function names are > undefined to the compiler but then you need some way of telling the > compiler which functions are special (what their names are) and what > is special about them (under special circustances you can replace > func_A + func_B with func_C). No, I don't want to. The function names are defined in the language standard, just as the language elements are defined in the (same) language standard. For example, the C++ std::list::insert. In C++, this /is/ a special function, and it always has this name. There's nothing that prevents a C++ compiler from implementing some optimization that is based on what the standard says this function is doing. There's also nothing that would prevent a compiler writer from providing an implementation of this function that is built into the compiler itself. But it still couldn't do anything with this function that's contrary to the standard. (If there's something lacking in the standard to make its definitions more useful, it should be added to the standard -- not to a single implementation.) > This is why you would need to be able to add special attributes to a > function, so that you can tell the compiler that these are special > functions that need to be handled in a special way (execute the > special internal code for them). (sorry about all the specials :-) No. I'm talking /exclusively/ about /standard/ libraries, which contain implementations for functions that have their behavior defined in the language standard. Like the C++ std::list member functions, for example. Their names are known to the compiler implementers; no special attributes are needed to identify these functions. > Other than having special attributes you really would need to make > these functions intrinsic (known and understood by the compiler) so > that it can execute its special internal code when it sees them in > the users source code. No. If their interface is defined accordingly, the compiler can assume that insert followed by delete can be replaced by replace in a given situation. The functions must be defined in a way in the language standard that the compiler can assume this -- but this must be the case no matter whether the list is implemented in the compiler or in a standard library. This optimization can then be performed, independently of whether the functions are implemented by the compiler or in a standard library. (The compiler's optimization stage that deals with this type of high-level optimization doesn't even have to "know" this.) Gerhard -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist