Re: basic VRP min/max range overflow question

2005-06-18 Thread Tristan Wibberley
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

2005-08-25 Thread Tristan Wibberley
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

2005-08-26 Thread Tristan Wibberley
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++

2005-12-07 Thread Tristan Wibberley
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?

2006-06-27 Thread Tristan Wibberley

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

2006-07-11 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2006-07-12 Thread Tristan Wibberley

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

2007-08-05 Thread Tristan Wibberley
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

2007-08-05 Thread Tristan Wibberley
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

2007-08-06 Thread Tristan Wibberley
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.