Re: basic VRP min/max range overflow question
Paul Schlie wrote: [Justification snipped] > Therefore regardless of the result of an "undefined" result/operation at > it's enclosing sequence point, the remaining program must continue to abide > by the specified semantics of the language. Tell that to Mister my_array[sizeof(my_array) / sizeof(*my_array)] = 0; I believe this is theoretically impossible in general. -- Tristan Wibberley Opinions expressed are my own and certainly *not* those of my employer, etc.
Re: 4.2 Project: "@file" support
Mark Mitchell wrote: > However, there's demonstrable interest in this feature for GNU/Linux as > well, from the lists, and for Java on all operating systems. > Please don't use '@filename' on Linux, use a normal switch with an argument. The problems of '-' being used for switches is bad enough without another valid filename character being overloaded. At least the '-' problem is well understood and people can avoid using filenames beginning with '-'. -- Tristan Wibberley Opinions expressed are my own and do not necessarily coincide with those of my employer, etc.
Re: 4.2 Project: "@file" support
Mark Mitchell wrote: > Tristan Wibberley wrote: > >> Mark Mitchell wrote: >> >> >> >>> However, there's demonstrable interest in this feature for GNU/Linux as >>> well, from the lists, and for Java on all operating systems. >>> >> >> >> Please don't use '@filename' on Linux, use a normal switch with an >> argument. The problems of '-' being used for switches is bad enough >> without another valid filename character being overloaded. At least the >> '-' problem is well understood and people can avoid using filenames >> beginning with '-'. > > > Again, I'm amenable to changes to the technical details. > > The first step is agreeing that (a) the feature is beneficial, and (b) > the mechanism for implementing it, such as whether it should be done in > crt0 or in libiberty. I think everyone's agreed on (a), but I don't > think DJ and I are yet seeing eye-to-eye on (b). Once we get past that, > we can work out these details. I certainly agree with (a). For (b), I think a gcc compiler that is intended to produce normal Windows binaries should have the same commandline interface as Microsoft's compiler (I mean *all* of the commandline interface) - for build scripts and development environments that expect to see Micrsoft's tools. If it also provides a gcc commandline interface, it should look exectly like the *NIX gcc, and long commandlines could be supported by *NIX style shells that use CreateProcess wrappers such as exec to use IPC to pass the cmdline (where libcrt handles it). So if you use normal Windows tools to build, you can use the MS style cmdline, and if you use ported GNU tools, you can use the GNU style commandline (and both shell, make, etc. and compiler contain specific support for long commandline via IPC). More work, its true, but its also much nicer (IMHO). My justification is that Windows programmers expect to use /F /OO:bar and @argsfile commandline arguments from cmd, and Linux developers working on Windows expect to use -f --oo=bar and --args=argsfile commandline arguments from bash. So that is what they respectively ought to be given. In the case of the GNU interface, it looks like the shell and compiler are capable of long commandlines... use Microsoft counterparts for either and you lose the facility and can fall back to --args= or @. When GNU utilities are ported, libcrt and exec can understand the long commandline method, when new programs are written they can use an LGPL libWinGNU.dll that contains such functions as LongCreateProcess (or link to a dll that contains its own CreateProcess or something). -- Tristan Wibberley Opinions expressed are my own and do not necessarily coincide with those of my employer, etc.
Re: funny problem with g++
Morten Welinder wrote: >>>This is a joke, you are kidding, right ? >> >>No, we're not kidding. RTFM: Section, 5.12 Arrays of Length Zero > > > He is kind of right, though. Outside struct (or perhaps union), > zero-sized arrays > make little sense and could be rejected. Or else I am missing something too. If you've got an array that is a cache of items and you have a constant defined that specifies how many cache entries to use, then you can tune the cache size to any number except zero. That doesn't make any sense, but being able to define a zero length array *does* make sense. The alternative is to hide the array in an extra layer of templates, and to specialise it for zero to not use a real array in its implementation, and that's so nasty. IMHO, this is a good extension, at least until boost::array gets standardised. -- Tristan Wibberley
Re: why are we not using const?
Manuel López-Ibáñez wrote: On 27/06/06, Daniel Berlin <[EMAIL PROTECTED]> wrote: Manuel López-Ibáñez wrote: > Apart from its main > purpose, I believed that the use of 'const' helps the compiler to > optimise the code. It generally doesn't, unless you apply const to the underlying type, and not just the pointer. IE you say you have a pointer to a constant piece of memory, not a constant pointer to a piece of memory. But... tree is a pointer to "union tree_node" , isn't it? perhaps it is that "const tree" is not the same as " const union tree_node * " ? (btw, thanks for taking the time to clarify my doubts...) typedef union tree_node *tree; void f(const tree a); is equivalent to void f(union tree_node * const a); ie, it says the pointer is const so there's little point in using it. typedef union tree_node const *const_tree; void f(const_tree a); *would* be meaningful, however. -- Tristan Wibberley
Re: gcc visibility used by moz
Jason Merrill wrote: It seems that you have a different mental model of type visibility. The way I was thinking about it, if a type has hidden visibility, we can't refer to it from outside its object. Thus, it doesn't make sense for members or objects with that type to have greater visibility because even if people can call the accessor they can't do anything with the return value. > However, I'm not attached to this in defiance of practical concerns. What is your model of type visibility? This isn't "type" visibility. Shared objects don't export "types" they export "symbols". The types are defined in headers and are thus known to exist - no visibility attributes will or should change that. If the programmer had intended that the type should appear to not exist. it wouldn't be defined in a header #include-able by client code. The compiler should assume that the type exists and can be used if it is defined and shouldn't change attributes on other parts of the program. In the examples above, client code that knows (via headers) that the classes exist should be able to get pointers to instances via exported functions, access any visible or virtual members, and pass the pointers back into visible functions of the shared object - or even dereference the pointers to pass by reference. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Daniel Jacobowitz wrote: On Wed, Jul 12, 2006 at 02:04:37AM +0100, Tristan Wibberley wrote: If the programmer had intended that the type should appear to not exist. it wouldn't be defined in a header #include-able by client code. The GCC doesn't know if the header is includable by client code; I assume that's the use Jason intended for marking classes hidden ("it belongs to this shared object and no one else can see it"). No, that's why we need programmer provided attributes. The programmer says: "the client code needs to know about the existence of this type so it can get pointers and references to instances and pass them back in later and maybe be able to call virtual member functions and access non-static members" by putting it in a header which they document should be included by client code - thus client code includes it and knows about the type. But the programmer says: "it is documented that the member functions and static members of this type should not need to be accessed outside of the shared object that I will define by use of the linker later on - nor should its constructors/destructors need to be called from outside that shared object, except maybe *this* one and *that* one. Thus the symbols used to lookup those things do not need to be exported from the shared object." In the examples above, client code that knows (via headers) that the classes exist should be able to get pointers to instances via exported functions, access any visible or virtual members, and pass the pointers back into visible functions of the shared object - or even dereference the pointers to pass by reference. So... what does it restrict, then? Is it just defaulting methods to hidden, as a strange form of access control? As above, I thought it wasn't there originally to "restrict" anything, but to remove stuff from symbol tables that the programmer knows don't need to be there, but the compiler has no way of working out - the purpose for which most annotations in C++ are there. If all code that refers to a type's name (and possibly one or more members) and that will be compiled to a different shared object file (or executable) does not need the symbols for some parts of that classes definition to be exported, then the symbols do not need to be exported from the shared object in which their instances appear. This provides a large space saving, and startup time improvement. That does not require that all symbols whose C++ prototypes say they return a pointer or reference to a "hidden" type are also hidden. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Daniel Jacobowitz wrote: On Wed, Jul 12, 2006 at 02:04:37AM +0100, Tristan Wibberley wrote: If the programmer had intended that the type should appear to not exist. it wouldn't be defined in a header #include-able by client code. The GCC doesn't know if the header is includable by client code; I assume that's the use Jason intended for marking classes hidden ("it belongs to this shared object and no one else can see it"). No, that's why we need programmer provided attributes. The programmer says: "the client code needs to know about the existence of this type so it can get pointers and references to instances and pass them back in later and maybe be able to call virtual member functions and access non-static members" by putting it in a header which they document should be included by client code - thus client code includes it and knows about the type. But the programmer says: "it is documented that the member functions and static members of this type should not need to be accessed outside of the shared object that I will define by use of the linker later on - nor should its constructors/destructors need to be called from outside that shared object, except maybe *this* one and *that* one. Thus the symbols used to lookup those things do not need to be exported from the shared object." In the examples above, client code that knows (via headers) that the classes exist should be able to get pointers to instances via exported functions, access any visible or virtual members, and pass the pointers back into visible functions of the shared object - or even dereference the pointers to pass by reference. So... what does it restrict, then? Is it just defaulting methods to hidden, as a strange form of access control? As above, I thought it wasn't there originally to "restrict" anything, but to remove stuff from symbol tables that the programmer knows don't need to be there, but the compiler has no way of working out - the purpose for which most annotations in C++ are there. If all code that refers to a type's name (and possibly one or more members) and that will be compiled to a different shared object file (or executable) does not need the symbols for some parts of that class's definition to be exported, then the symbols do not need to be exported from the shared object in which their instances appear. This provides a large space saving, and startup time improvement. That does not require that all symbols whose C++ prototypes say they return a pointer or reference to a "hidden" type are also hidden. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Mike Stump wrote: On Jul 12, 2006, at 11:49 AM, Tristan Wibberley wrote: "the client code needs to know about the existence of this type so it can get pointers and references to instances and pass them back in later and maybe be able to call virtual member functions and access non-static members" by putting it in a header which they document should be included by client code - thus client code includes it and knows about the type. And what do you expect the type equality operator return for two types called S? I don't expect two types called S - I don't recall suggesting that multiple types with the same name should be able to exist. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Gabriel Dos Reis wrote: Tristan Wibberley <[EMAIL PROTECTED]> writes: | The programmer says: | | "the client code needs to know about the existence of this type so it | can get pointers and references to instances and pass them back in | later and maybe be able to call virtual member functions and access | non-static members" by putting it in a header which they document | should be included by client code - thus client code includes it and | knows about the type. But the programmer says: It strikes as you are assuming C and C++ have a notion of module. They don't. They have the notion of "translation unit." C++ adds the notion of "One Definition Rule" to make sure Bad Things don't happen. You have to operate within that framework if you're going to touch the C++ type system in any way. No but the linker does, and that's the program for which the attributes are intended. C++ doesn't even have a concept of "visibility", so C++ isn't really the matter here. The visibility attributes should simply map to the symbols used to export the thing that the visiblity attribute is applied to so the linker can pick them up as the programmer expects. I am suggesting that visibility attributes should *not* touch the C++ type system in any way. Since C++ doesn't have a notion of module a class that the C++ type system regards as hidden must be hidden from everything (in which case, you could just comment out the class definition instead) or nothing. I suggest that should be nothing, and that the linker should apply the visibility attributes to *its* notion of module. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Daniel Jacobowitz wrote: On Wed, Jul 12, 2006 at 07:49:21PM +0100, Tristan Wibberley wrote: No, that's why we need programmer provided attributes. The programmer says: "the client code needs to know about the existence of this type so it can get pointers and references to instances and pass them back in later and maybe be able to call virtual member functions and access non-static members" by putting it in a header which they document should be included by client code - thus client code includes it and knows about the type. But the programmer says: "it is documented that the member functions and static members of this type should not need to be accessed outside of the shared object that I will define by use of the linker later on - nor should its constructors/destructors need to be called from outside that shared object, except maybe *this* one and *that* one. Thus the symbols used to lookup those things do not need to be exported from the shared object." I just don't get it. Why should it matter whether a member function is virtual or not in order to be able to call it from outside this shared object? Either you can access the public members of the class, or you can't. Being able to access some of them and get link errors on others is a very strange default interpretation. Because virtual functions don't require anything to be exported from a shared object other than a function to get a pointer to an instance. From C++'s point of view, the hidden attributes should have no effect. From the linker's point of view, they document what the code that links to a shared object will not be using, and so what symbols do not need to be exported. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Gabriel Dos Reis wrote: Joe Buck <[EMAIL PROTECTED]> writes: | On Thu, Jul 13, 2006 at 01:36:46AM +0200, Gabriel Dos Reis wrote: | > So, -concretely- what happens to a class S (e.g. associated type info object | > address, address of member functions, etc.) with external linkage, | > defined in multiple translation units, with say hidden visibility? | | Well, there are the C++ rules, and then there are the ELF rules. At the | object code level we have only symbol definitions (corresponding to | the addresses of member functions, virtual tables, and typeinfo). If | the relevant symbols are hidden, then it's as if they aren't there, so | we can violate the one-definition rule. Thanks. So both notions are not as orthogonal as they may appear. Now, this being a conscious decision for ODR violation, it would probably need to be documented because then we may have typeinfo1 != typeinfo2 and yet !typeinfo1.before(typeinfo2) && !typeinfo2.before(typeinfo1) There are probably other inconsistencies to audit. | We can have two distinct | classes named S, and no one can tell. Each bit of code will see one | definition of S. But I think it is important that there are three places where visibility is a factor (as a concept of "being able to see things" rather than the attribute). 1) If a class definition is not present in a given translation unit, but a class declaration is, then the translation unit may normally pass around a pointer to an instance of that class and also a reference to an instance of that class, but may not do anything else with it. 2) Until now, the visibility attribute was used for optimising symbols exported from a .so for when things will only be used within that .so (but used across its constituent .o files). Saving unnecessary runtime costs and non-volatile storage costs. This is really valuable and I'd like to see it remain available. The last is the interesting case, which it seems 2) has broken while this was being worked on. 3) For file scope functions and file scope variables, the static keyword is overloaded to indicate that their definition should be created for this translation unit such that it is a unique function or variable even if other functions or variables use the same name in both translation units. I can see that something could be desirable to define classes just for the internal behaviour of a translation unit without having to consider name conflict, but the unnamed namespace should do that shouldn't it? Which also satisfies the ODR since each unnamed namespace in separate translation units is a different one. It kind of makes sense to hide functions that take arguments or return pointers to types in the translation unit unnamed namespace (but that is so easy for the programmer to cause just by putting the prototype into the unnamed namespace that its not worth doing anything fancy other than warning since they may be trying to do some clever multi-language interoperability thing. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
Re: gcc visibility used by moz
Gabriel Dos Reis wrote: Tristan Wibberley <[EMAIL PROTECTED]> writes: [...] | I am suggesting that visibility attributes should *not* touch the C++ | type system in any way. But then, at the same time you're talking of polymorphic types (e.g. vtables). vtables happen to just work with types whose associated symbols are not exported from a shared object - as long as you are not trying to construct an instance from outside the shared object. So you can call a function that *is* exported and get a pointer to a type that you know (from an included header) has some virtual functions that you can lookup with an offset relative to the pointer to the instance (an offset calculated at compile time). Thus not requiring any change in the C++ type system - nor any propagation to infer new access controls on members. | Since C++ doesn't have a notion of module a | class that the C++ type system regards as hidden must be hidden from | everything (in which case, you could just comment out the class | definition instead) or nothing. That brings us back to Mike's question. We are not making progress. | I suggest that should be nothing, and | that the linker should apply the visibility attributes to *its* notion | of module. Please elaborate. I've sent another email in reply elsewhere with a list of the three visibility concepts that I've seen (which are all mostly orthogonal). Which hopefully will make sure I'm talking about the same things as you are. -- Tristan Wibberley These opinions are my own, and do not reflect those of my employer.
poor optimisation case
Hi I've found a case which looks like it should be possible to optimise but gcc (very recent trunk) isn't doing which could give improvements in many cases - certainly in a case I've come across: #ifdef NEW unsigned int fn(unsigned int n, unsigned int dmax) throw() { for (unsigned int d = 0; d < dmax; ++d) { n += d?d:1; } return n; } #else unsigned int fn(unsigned int n, unsigned int dmax) throw() { unsigned int add = 1; for (unsigned int d = 0; d < dmax; add = ++d) { n += add; } return n; } #endif When compiled with -O3 -DOLD I get: .p2align 4,,15 .globl _Z2fnjj .type _Z2fnjj, @function _Z2fnjj: .LFB2: testl %esi, %esi je .L2 movl$1, %edx xorl%eax, %eax .p2align 4,,10 .p2align 3 .L3: addl$1, %eax addl%edx, %edi cmpl%esi, %eax movl%eax, %edx jne .L3 .L2: movl%edi, %eax ret .LFE2: .size _Z2fnjj, .-_Z2fnjj but with -DNEW I get: .p2align 4,,15 .globl _Z2fnjj .type _Z2fnjj, @function _Z2fnjj: .LFB2: testl %esi, %esi je .L2 movl$1, %edx xorl%eax, %eax movl$1, %ecx jmp .L7 .p2align 4,,10 .p2align 3 .L5: testl %eax, %eax movl%ecx, %edx cmovne %eax, %edx .L7: addl$1, %eax addl%edx, %edi cmpl%esi, %eax jne .L5 .L2: movl%edi, %eax ret .LFE2: .size _Z2fnjj, .-_Z2fnjj The performance difference is about 50% with -DNEW taking 1.5 times as long as -DOLD (that was with dmax == 10). The loop unfortunately can't always be written as in -DOLD as the implementation of an iterator adapter might use ?: to special case the first element of a sequence and when used in a generic algorithm which just has the simple loop of -DNEW it ought to be optimised like -DOLD if inlining occurs. -- Tristan Wibberley Any opinion expressed is mine (or else I'm playing devils advocate for the sake of a good argument). My employer had nothing to do with this communication.
Re: poor optimisation case
On Sun, 2007-08-05 at 16:58 -0400, Tim Prince wrote: > [EMAIL PROTECTED] wrote: [snip] > > The loop unfortunately can't always be written as in -DOLD as the > > implementation of an iterator adapter might use ?: to special case the > > first element of a sequence and when used in a generic algorithm which > > just has the simple loop of -DNEW it ought to be optimised like -DOLD if > > inlining occurs. > > > I don't see why you special case the first iteration of a loop with ? > inside the loop. Simply write the first iteration separately, and begin > the loop with the next iteration. It should be a lot clearer both to us > and to the compiler what is your intention. > Doesn't this belong on gcc-help? Better peeling optimization needs more > justification than this. As above. When using C++ as it's supposed to be used this isn't possible. If I've got a sequence of values and I want to sum them there is a generic sum algorithm that I'm supposed to use (and which I *should* use to avoid unmaintainable spaghetti code which soon turns up when every thing has to be hand coded to be fast - I've read "numerical recipes in C" and nearly killed myself by the end of it). If I've got a 100 element sequence and want (on one thread) to compare what would happen in my generic algorithm (such as std::sum) if the first element is doubled but (on a second thread) with the sequence as it is, I'm not supposed to be required to write two versions of a large piece of code - I'm supposed to be able to just write an iterator that returns a different value for the first element. In the case of returning a different value for the first element, I'd use something in operator* that after inlining would end up as equivalent to d?d:1 and the compiler should optimise that if it can and if it would reduce runtime by a massive 33% and text size by quite a bit. Both of those are true in this case. Basically, writing two versions of the loop is not an option in real life because developing on spaghetti C code is costly while elegant C++ code is cheap. For example, my real (big) case is that I've got an iterator that moves around an image or video thusly (or 4,5,6 dimensional equivalent): it = it[1] + 6; // move 6 rows along the 2nd dimension When I move in all dimensions at once I quite sensibly have a loop from dimension zero to the top dimension adding (amount-to-move*stride-of-dimension) to the pointer that the iterator is implemented with for each one. The strides of the dimensions are previously recorded in an array that the iterator holds a reference to - except the first (because when you have a one dimensional image - a signal - nothing needs to be stored) which is always 1. So everything gets reduced down correctly by g++, except that this special case is not moved out of the loop. So this is not a programming problem that I need help with (I know how to micro-optimise with C-style ugly-stuff). I'm just reporting a significant missed optimisation opportunity that will help C++ developers even if not C or fortran developers. The only reason I didn't reflect the C++ simple-vs-spaghetti code issue in my example is because I wanted to keep it simple to target one of the problems very specifically. -- Tristan Wibberley Any opinion expressed is mine (or else I'm playing devils advocate for the sake of a good argument). My employer had nothing to do with this communication.
Re: poor optimisation case
On Mon, 2007-08-06 at 07:38 -0700, Ian Lance Taylor wrote: > Tristan Wibberley <[EMAIL PROTECTED]> writes: > > > I've found a case which looks like it should be possible to optimise but > > gcc (very recent trunk) isn't doing which could give improvements in > > many cases - certainly in a case I've come across: > > Looks reasonable to me. Please open a missed-optimization report, > with your test case, at http://gcc.gnu.org/bugzilla/. For more > information see http://gcc.gnu.org/bugs.html. Thanks. Oh no, not another username and password to remember... :( Would it be a breach of your bugzilla terms and conditions if I write my username and password down and keep it next to my computer? Any chance of moving to launchpad.net? -- Tristan Wibberley Any opinion expressed is mine (or else I'm playing devils advocate for the sake of a good argument). My employer had nothing to do with this communication.