Re: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread Paolo Bonzini



That is what I missed. Thanks.

This patch should work.


Sure, but it makes the mess even worse.  You should instead:

- in config/t-svr4, change the two CFLAGS assignments to use +=
- in config/i386/t-sol2, change the CRTSTUFF_T_CFLAGS assignment to "+= 
-O2" and remove the TARGET_LIBGCC2_CFLAGS assignment

- in config.gcc, change

  tmake_file="t-sol2 i386/t-sol2 t-svr4"

to

  tmake_file="${tmake_file} t-sol2 i386/t-sol2 t-svr4"

and move it at the end of the case stanza, i.e. before

  ;;
  i[34567]86-*-sysv5*)   # Intel x86 on System V Release 5


Paolo


Re: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread H.J. Lu
On Wed, Aug 08, 2007 at 10:06:03AM +0200, Paolo Bonzini wrote:
> 
> >That is what I missed. Thanks.
> >
> >This patch should work.
> 
> Sure, but it makes the mess even worse.  You should instead:
> 
> - in config/t-svr4, change the two CFLAGS assignments to use +=

There is

CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC

How do you use +=?

> - in config/i386/t-sol2, change the CRTSTUFF_T_CFLAGS assignment to "+= 
> -O2" and remove the TARGET_LIBGCC2_CFLAGS assignment
> - in config.gcc, change
> 
>   tmake_file="t-sol2 i386/t-sol2 t-svr4"
> 
> to
> 
>   tmake_file="${tmake_file} t-sol2 i386/t-sol2 t-svr4"
> 
> and move it at the end of the case stanza, i.e. before
> 
>   ;;
>   i[34567]86-*-sysv5*)   # Intel x86 on System V Release 5
> 

There are so many changes and I can't test any of them. I will leave
them to someone who can test. I will be happy to back out:

-   tmake_file="$tmake_file i386/t-sol2-10"
+   tmake_file="$tmake_file i386/t-crtstuff i386/t-sol2-10"

in the mean time.

H.J.


Re: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread Paolo Bonzini



CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC

How do you use +=?


Sorry, I was looking at an old checkout.

Could you simply test patching config/i386/t-crtstuff like this:

-CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer -fno-asynchronous-unwind-tables
+CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer 
-fno-asynchronous-unwind-tables


(It would be great if you, H.J., tested on Linux, and Art tested on 
Solaris 10).


Thanks,

Paolo


[tuples] gimplification of other FEs and platforms

2007-08-08 Thread Diego Novillo
I've updated http://gcc.gnu.org/wiki/tuples to show the items we still
have to go through.  To avoid stepping on each other's toes, please
claim the items you are working (or plan to work on) in the list.

I've arranged the items in the plan to reflect the critical path that
should take us to bootstrap C on our desktops.  If you notice anything
missing please add it to the list.

I've marked the major milestones in bold.

Thanks.


RE: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread Arthur Haas

> -Original Message-
> [ ... snip ... ]
> 
> > CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
> > 
> > How do you use +=?
> 
> Sorry, I was looking at an old checkout.
> 
> Could you simply test patching config/i386/t-crtstuff like this:
> 
> -CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer 
> -fno-asynchronous-unwind-tables
> +CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer 
> -fno-asynchronous-unwind-tables
> 
> (It would be great if you, H.J., tested on Linux, and Art tested on 
> Solaris 10).
> 
> Thanks,
> 
> Paolo

Hi.

Making the change above results in a successful build. Quite a
difference what a '+' can make.

Art Haas


Re: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread H.J. Lu
On Wed, Aug 08, 2007 at 09:45:00AM -0500, Arthur Haas wrote:
> 
> > -Original Message-
> > [ ... snip ... ]
> > 
> > > CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
> > > 
> > > How do you use +=?
> > 
> > Sorry, I was looking at an old checkout.
> > 
> > Could you simply test patching config/i386/t-crtstuff like this:
> > 
> > -CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer 
> > -fno-asynchronous-unwind-tables
> > +CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer 
> > -fno-asynchronous-unwind-tables
> > 
> > (It would be great if you, H.J., tested on Linux, and Art tested on 
> > Solaris 10).
> > 
> > Thanks,
> > 
> > Paolo
> 
> Hi.
> 
> Making the change above results in a successful build. Quite a
> difference what a '+' can make.
> 

This patch works fine on Linux/x86 and Linux/x86-64.


H.J.
---
2007-08-08  Paolo Bonzini <[EMAIL PROTECTED]>

* config/i386/t-crtstuff (CRTSTUFF_T_CFLAGS): Use +=.

--- gcc/config/i386/t-crtstuff.sol2 2007-08-06 17:05:40.0 -0700
+++ gcc/config/i386/t-crtstuff  2007-08-08 06:56:17.0 -0700
@@ -4,4 +4,4 @@
 # section.  -fno-asynchronous-unwind-tables is off by default for i386
 # and is on by default for x86-64.  We turn it off for both i386 and
 # x86-64.
-CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer -fno-asynchronous-unwind-tables
+CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer -fno-asynchronous-unwind-tables


Re: Bootstrap failed on i386-pc-solaris2.10

2007-08-08 Thread Paolo Bonzini



Making the change above results in a successful build. Quite a
difference what a '+' can make.



This patch works fine on Linux/x86 and Linux/x86-64.


Thanks!

Paolo


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Michael Matz
Hi,

On Tue, 7 Aug 2007, Ollie Wild wrote:

> In response to a suggestion from Mark Mitchell, I've been attempting to 
> migrate pointers to members to the GCC middle end.  The goal of this is 
> twofold: (a) to enable conversion of pointer to member dereferences to 
> direct function calls and member accesses when analysis determines this 
> is unambiguous and (b) to obsolete the need for the expand_constant 
> language hook.
> 
> Under my current approach, I've added the following new nodes to 
> gcc/tree.def:
> 
>   DEFTREECODE (PTRMEM_TYPE, "ptrmem_type", tcc_type, 0)
>   DEFTREECODE (PTRMEM_CST, "ptrmem_cst", tcc_constant, 0)
>   DEFTREECODE (PTRMEM_PLUS_EXPR, "ptrmem_plus_expr", tcc_binary, 2)
>   DEFTREECODE (PTRMEM_REF, "ptrmem_ref", tcc_reference, 2)
> 
> I then modify the C++ front end to instantiate the new nodes, expand
> them inside expand_expr_real_1 and output_constant, and perform
> folding in the various fold-const functions.

So those tree expressions would live throughout the middle-end and only 
then become lowered to RTL directly?  I'm not sure that's worthwhile.  
E.g. I'm not sure why there's a need to really get rid of the 
expand_constant langhook.  It's only important that it isn't called too 
late, i.e. ideally during gimplification.  It seems it only makes use of 
type information which should be available at that time, so if it 
currently is called too late (interfering with LTO in the future) it 
should be possible to move it earlier.

I have a conceptual problem with moving pointer to members into the 
middle-end: my mental model of what the middle-end should be concerned 
about is complete expressions/constants/types, like adding two numbers, 
accessing an integer two words away from that address (i.e. you see I 
already sort of decompose structures in my mental model).  Pointers to 
members is a very different beast: they can't be accessed without a real 
object, yet they can be stored into objects themself (sort of an 
incomplete memory reference).  If anything they simply resemble offsets 
(perhaps variable ones), so you might perhaps model them as such.  
Conversions between them sometimes requires adjustments to 'this', 
resulting in real operations (the delta field of the struct, how pointer 
to member values are currently modelled).  IMHO it would be wrong if we 
wouldn't make those adjustments explicit in the middle end.

So, why do you think you need the PTRMEM_TYPE in the middle end?  And why 
the PTRMEM_CST (i.e. why couldn't it be lowered to some explicit constant 
during gimplificaton)?  Same for PTRMEM_PLUS_EXPR, why is (PTR_)PLUS_EXPR 
not enough, if the semantic is only to add the integer argument to the 
pointer argument (is that even an operation which can be done to pointers 
to members?)?  Also PTRMEM_REF seems to equivalent to a normal 
COMPONENT_REF, just that the second operand is a funny "offset" 
specification instead of a simple field decl.

> However, pointers to virtual functions are turning out to be 
> problematic.  As far I can tell, the middle end has no concept of 
> virtual functions and virtual function tables: they appear to be 
> implemented solely in the C++ front end.  This suggests that a migration 
> of the virtual function machinery is a necessary precondition to pointer 
> to member migration.

Ugh, I wouldn't like that either.  I have the feeling that it would drag 
too much specifics of C++ into the middle end.  After all e.g. the virtual 
tables have to follow a certain layout according to the C++ ABI, which 
needn't be the right one for other languages.  I think you need only one 
feature, namely given a definite class type and an offset into the 
vtable, what definite FUNCTION_DECL that corresponds too.  I can't think 
of many places where you'd like to have this information, as the most 
interesting user of it would be the inliner.  There aren't that many 
transformations which make a former indefinite class type definite, and 
most of them can be done when the C++ frontend is still around to ask.

If you were to implement something like virtual functions into the middle 
end, it should be expressed in a fairly low level way IMHO.  E.g. a 
virtual table simply being a vector of pointers to function decls (which 
we can express already just fine).  That way they could also be written 
out for LTO and read back in, and the question what function decl is 
connected to what slot can also be answered trivially.  Then definite 
class type merely has the characteristic that they can point to such a 
function table, whereas indefinite class types (i.e. those whose runtime 
type can be any derived one) can not.  E.g. I wouldn't try to model the 
inheritance relationship.

But even with that I don't really see the need for new tree nodes.  
Pointer to members are a fancy offset, so why not model them as such?  
It's obviously possible I'm missing something, in that case, please 
educate me where the problems are ... :-)


Ciao,
Michael.

Re: ICE on valid code, cse related

2007-08-08 Thread Pranav Bhandarkar
Hi,

>   Pranav, although there is indeed a bug in the mid-end here, from your point
> of view the simple and effective workaround should be to implement a movdi
> pattern (and movsf and movdf if you don't have them yet: it's an absolute
> requirement to implement movMM for any modes you expect your machine to
> handle) in the backend.  This won't fix the underlying bug, but it'll stop it
> from affecting you, and you'll get better codegen all round into the bargain
> if you expand movdi early.

It worked!!! I implemented the movsf pattern ( and also movdf so that
the absence of a movdf also doesnt wont affect me in the future). Due
to the movsf pattern, the return value is now restored with

(insn 17 16 18 testcase-min.i:8 (set (reg:SF 139)
(mem/c/i:SF (reg/f:SI 129 virtual-stack-vars) [2 S4 A32])) -1
(expr_list:REG_LIBCALL_ID (const_int 1 [0x1])
(insn_list:REG_RETVAL 14 (expr_list:REG_EQUAL (float:SF (reg:SI 138))
(nil)

i.e. there is no subreg in the destination.
Later in cse when the above REG_EQUAL (float:SF (reg:SI 138)  note is
converted into  REG_EQUAL (const_double:SF 0 [0x0] 0.0 [0x0.0p+0] , It
doesnt replace
(subreg:SI (reg:SF 139) 0) in the insn
 (set (reg:SI 141)
   (xor:SI (subreg:SI (reg:SF 139) 0)
   (reg:SI 140))) 65 {xorsi3} (expr_list:REG_EQUAL
(const_double:SF 0 [0x0] -0.0 [-0x0.0p+0])
   (nil)))

and the compiler doesnt crash :)

Thanks Dave and Ian for your help!!

cheers!
Pranav


x86_64 ABI

2007-08-08 Thread Maurizio Vitale

with reference to the following:

  struct data {
data (long v) : m_data (v) {}
data (const data&) {}
long  m_data;
  };

  data foo (data v) {
return v;
  }

my reading of the x86_64 ABI (v .98, sept 2006) on page 17 is that
data should have class MEMORY when passed as argument to function foo.
This because it has a non-trivial copy constructor 
(it is not implicitely declared).

But GCC 4.1.1 and a more recent version from svn give (for foo):

  .globl _Z3foo4data
  .type   _Z3foo4data, @function
  _Z3foo4data:
  .LFB8:
  movq%rdi, %rax
  ret
  .LFE8:

[so v is passed in a register]

The gimple dump (from the svn version) is:

  data::data(long int) (this, v)
  {
this->m_data = v;
  }


  data::data(const data&) (this, D.2481)
  {

  }


  data foo(data) (v)
  {
struct data & D.2509;

D.2509 = ;
__comp_ctor  (D.2509, v);
return ;
  }

which seems to confirm v in a register.

So the question is whether my reading of the ABI is wrong (and why).
Thanks a lot and best regards,

   Maurizio





Fixed function compilation order

2007-08-08 Thread Cupertino Miranda

Hello everyone,

I am currently trying to enable GCC to perform compilation without  
having to respect any compilation order, i.e. execute some pass to  
any function at any time (it is not only pass reordering).


As what I have seen from (trunk version of) GCC, it doesn't seem an  
easy task to be achieved and it might traduce in many complications  
later in development.
In that sense I would like to have some opinions and suggestions from  
you all:


 - Imagining I am able to change the function context by updating  
cfun, etc. Will passes (all_passes) execute without
missing/wrong data, i.e. is all shared data between passes accessed/ 
updated thought pointers such as cfun, etc. ?


 - What should I initialise/finalise to be able to perform the  
function context change ?


I would like to have your opinion and tips on how to approach it and  
which problems I might expect to have later.


Thanks in advance,
Cupertino Miranda



Re: Fixed function compilation order

2007-08-08 Thread Daniel Berlin
On 8/8/07, Cupertino Miranda <[EMAIL PROTECTED]> wrote:
> Hello everyone,
>
> I am currently trying to enable GCC to perform compilation without
> having to respect any compilation order, i.e. execute some pass to
> any function at any time (it is not only pass reordering).

>
> As what I have seen from (trunk version of) GCC, it doesn't seem an
> easy task to be achieved and it might traduce in many complications
> later in development.
> In that sense I would like to have some opinions and suggestions from
> you all:


For tree level optimization, this is really not difficult.
For RTL, this is probably going to be really hard.
>
>   - Imagining I am able to change the function context by updating
> cfun, etc. Will passes (all_passes) execute without
> missing/wrong data, i.e. is all shared data between passes accessed/
> updated thought pointers such as cfun, etc. ?

What do you mean "missing/wrong" data.
>   - What should I initialise/finalise to be able to perform the
> function context change ?

See any IPA pass
>
> I would like to have your opinion and tips on how to approach it and
> which problems I might expect to have later.
>
> Thanks in advance,
> Cupertino Miranda
>
>


Re: x86_64 ABI

2007-08-08 Thread Michael Matz
Hi,

On Wed, 8 Aug 2007, Maurizio Vitale wrote:

> with reference to the following:
> 
>   struct data {
> data (long v) : m_data (v) {}
> data (const data&) {}
> long  m_data;
>   };
> 
>   data foo (data v) {
> return v;
>   }
> 
> my reading of the x86_64 ABI (v .98, sept 2006) on page 17 is that
> data should have class MEMORY when passed as argument to function foo.
> This because it has a non-trivial copy constructor 
> (it is not implicitely declared).

That is correct.

> But GCC 4.1.1 and a more recent version from svn give (for foo):
> 
>   .globl _Z3foo4data
>   .type   _Z3foo4data, @function
>   _Z3foo4data:
>   .LFB8:
>   movq%rdi, %rax
>   ret
>   .LFE8:

That is also correct.

> [so v is passed in a register]

But this conclusion isn't.  In short: that's the address of the return 
slot.

Longr version:

Your confusion stems from the fact, that your 
copy-ctor is empty (so it's code can't be seen in the asm dump), and that 
also your return type of 'foo' is data, which also needs to be returned by 
memory.  Returning in memory is done by the caller allocating the place 
for the return value on its stack, and giving the address of that 
to-be-written-to place as implicit first argument to the function.  That 
address is then also returned in %rax.

So what's placed in %rdi here is not 'v' itself, but some place on it's 
callers stack, which is also to be returned in %rax.  As you have an empty 
copy-ctor you also don't see any other interesting access to 'v' itself, 
so the asm is confusing because nothing hints at the fact that %rdi really 
only holds the address of the return slot.  Look at some arbitrary caller 
of your foo function.  For clarity I've also removed the empty body of of 
cctor, so that calls to external functions remain:

data foo (data v) { return v; }
void callfoo()
{
  data d(32);
  foo (d);
}

callfoo now looks like so:

Z7callfoov:
pushq   %rbx
subq$48, %rsp
leaq16(%rsp), %rbx
leaq32(%rsp), %rsi
movq$32, 32(%rsp)
movq%rbx, %rdi
call_ZN4dataC1ERKS_
movq%rsp, %rdi
movq%rbx, %rsi
call_Z3foo4data
addq$48, %rsp
popq%rbx
ret

You can see three objects overall allocated on the stack 
(%rsp,%rsp+16,%rsp+32).  In particular the one at %rsp is used for the 
return slot for the call of 'foo'.  foo itself is given the address of 
that return slot, and it's input argument 'd', placed in memory at %rsp+16 
(initialised by the cctor from the object at %rsp+32).  So it's passed and 
return in memory, as defined by the ABI.

The passing by memory can be seen easier by actually accessing something 
in the object, like here:

long access (data v) { return v.m_data; }

That's assembled into 

_Z6access4data:
movq(%rdi), %rax
ret

I.e. accessing the m_data member of 'v', which is given only as its 
address in %rdi, i.e. passed by memory.  All as intended.


Ciao,
Michael.


Zdenek Dvorak appointed loop infrastructure maintainer

2007-08-08 Thread David Edelsohn
I am pleased to announce that the GCC Steering Committee has
promoted Zdenek Dvorak to full maintainership of all of the GCC
loop infrastructure.

Please join me in congratulating Zdenek on his new role.
Zdenek, please update your listing in the MAINTAINERS file.

Happy hacking!
David



Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Ian Lance Taylor
Michael Matz <[EMAIL PROTECTED]> writes:

> If you were to implement something like virtual functions into the middle 
> end, it should be expressed in a fairly low level way IMHO.  E.g. a 
> virtual table simply being a vector of pointers to function decls (which 
> we can express already just fine).  That way they could also be written 
> out for LTO and read back in, and the question what function decl is 
> connected to what slot can also be answered trivially.  Then definite 
> class type merely has the characteristic that they can point to such a 
> function table, whereas indefinite class types (i.e. those whose runtime 
> type can be any derived one) can not.  E.g. I wouldn't try to model the 
> inheritance relationship.

There is some advantage to knowing class heirarchy relationships in
LTO.  Some C++ programs implement different virtual subclasses in
different files.  LTO can put those together.  When the compiler can
then determine that a variable definitely has a particular subclass,
it can devirtualize the virtual calls, turning an indirect function
call into a direct function calls, also exposing inlining
opportunities.

I don't know how important an optimization this is, but it seems like
a real one, and one which is only available if the LTO middle-end
knows something about class relationships.

Ian


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Daniel Berlin
On 08 Aug 2007 17:36:43 -0700, Ian Lance Taylor <[EMAIL PROTECTED]> wrote:
> Michael Matz <[EMAIL PROTECTED]> writes:
>
> > If you were to implement something like virtual functions into the middle
> > end, it should be expressed in a fairly low level way IMHO.  E.g. a
> > virtual table simply being a vector of pointers to function decls (which
> > we can express already just fine).  That way they could also be written
> > out for LTO and read back in, and the question what function decl is
> > connected to what slot can also be answered trivially.  Then definite
> > class type merely has the characteristic that they can point to such a
> > function table, whereas indefinite class types (i.e. those whose runtime
> > type can be any derived one) can not.  E.g. I wouldn't try to model the
> > inheritance relationship.
>
> There is some advantage to knowing class heirarchy relationships in
> LTO.  Some C++ programs implement different virtual subclasses in
> different files.  LTO can put those together.  When the compiler can
> then determine that a variable definitely has a particular subclass,
> it can devirtualize the virtual calls, turning an indirect function
> call into a direct function calls, also exposing inlining
> opportunities.
>
> I don't know how important an optimization this is, but it seems like
> a real one, and one which is only available if the LTO middle-end
> knows something about class relationships.

I believe we do want to have this info in the middle end, but i don't
necessarily believe what Ollie's current approach is the best one.

It looks like all the code is still C++ specific, and it's semantics
are only defined by how they get generated in cp/*

I'd rather see us go the route of deciding what the semantics *should
be*, which of these tree codes are *actually necessary*, then make
cp/* gimplify it to what we've got.  The semantics should also be
completely documented independently of the C++ FE (even if we were
decide to give the middle end codes the exact same semantics as C++)

For example, I see no reason for PTRMEM_PLUS_EXPR.

To put it concretely, i think the proposal has gone backwards, and
worked from "we have an implementation of something in the C++ FE,
let's move it to the middle end" instead of "we have a design for
something we want to do in the middle end, let's make the C++
FE/gimplifier do it".

It's not at all clear to me from the current proposal where/when/how
these tree codes occur in the normal GIMPLE datastream, how I would
handle them in points-to analysis, etc.

Note that to directly adress your point, the middle end *already does*
have a notion of class relationships.  The BINFO_* (base class
information) is already common to the middle-end.  This is how the
ipa-cha stuff that was submitted a while ago knows how to find base
classes.

Besides type-based devirt, you will also get a lot out of points-to
based devirt, because it can do without the whole program, whereas
type-based devirt cannot.

--Dan


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Michael Matz

Hi,

On Thu, 8 Aug 2007, Ian Lance Taylor wrote:

those whose runtime type can be any derived one) can not.  E.g. I 
wouldn't try to model the inheritance relationship.


There is some advantage to knowing class heirarchy relationships in LTO. 
Some C++ programs implement different virtual subclasses in different 
files.  LTO can put those together.  When the compiler can then 
determine that a variable definitely has a particular subclass, it can 
devirtualize the virtual calls, turning an indirect function call into a 
direct function calls, also exposing inlining opportunities.


Yes, devirtualization.  But I wonder if you really need class hierarchies 
for this (actually I'm fairly sure you don't).  In effect you only need to 
determine where this virtual call, when you know the definite runtime type 
of the object pointer, points to, i.e. to which function decl.  For that 
you don't need the class hierarchy (i.e. the edges in the inheritance 
graph, or in fact any information about what base classes might or might 
exist or about other classes), but simply a list of all slot-number -> 
function-decls mappings for that type, i.e. the vtable (but let's call it 
different to not confuse it with the C++-ABI thingy which actually is 
written to the .o file).  As the middle end should have all thunks already 
also 'this' pointer adjusting virtual calls should be taken care of (i.e. 
the slot->function mapping should already have the thunks referenced).


Then you just need a way to get from a definite type to that 
slot->function mapping.  As the LTO frontend needs to emit something 
similar anyway somewhere (as it needs to express all C++ types in some 
lowered form appropriate for the LTO reader), it will be available 
somehow, presumably hanging off the RECORD_TYPE.  If you have the definite 
runtime type of the pointer, you also have that RECORD_TYPE, hence the 
slot->function mapping, the slot number from the virtual call itself, and 
ergo the finally called function_decl.  No need for hierarchies.


There were also other patches already floating around which (tried to) 
implement devirtualization (via profile feedback testing at runtime if a 
pointer was of certain type), which didn't need real inheritance 
hierarchies in the middle-end, so it can be done.


We also need to make sure to not munge together too many of these not 
entirely trivial topics.  We have pointer to members (IMHO just fancy 
offsets) and virtual function calls (for devirtualization) up to now. 
They only relate via pointer to virtual member functions, which still are 
only fancy offsets (referring to a slot number, not a byte offset).  So 
IMHO the C++ frontend should lower all these constructs as much as 
possible and try to express them in basic types and expressions, instead 
of pulling the whole hair into the middle end.  If something is right now 
not possible in the middle-end, then we should try to carefully add the 
necessary information (and only that) to enable whatever we want.  For 
devirtualization I think I pointed out one possibility.  I'm not sure what 
else we want.  Surely I've seen nothing which would make me think "hell, 
yes, let's pull pointer to members into the middle end, and as we are at 
it, let's add virtual functions right away too" ;-)



Ciao,
Michael.

PS: From time to time I'm forced to dive into either of these areas of 
cp/*.[ch] and it has some very complex code.  Most of it really front-end 
related I know, but intertwined with the code generation and layouting 
code.  I'm fairly certain that this all should stay in cp/ .


bootstrap failure on hppa-unknown-linux-gnu

2007-08-08 Thread John David Anglin
In stage2,

../../gcc/gcc/tree.c:7694: error: passing argument 1 of 'fixed_zerop' discards 
qualifiers from pointer target type

Dave
-- 
J. David Anglin  [EMAIL PROTECTED]
National Research Council of Canada  (613) 990-0752 (FAX: 952-6602)


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Ollie Wild
On 8/8/07, Michael Matz <[EMAIL PROTECTED]> wrote:
> So those tree expressions would live throughout the middle-end and only
> then become lowered to RTL directly?  I'm not sure that's worthwhile.
> E.g. I'm not sure why there's a need to really get rid of the
> expand_constant langhook.  It's only important that it isn't called too
> late, i.e. ideally during gimplification.  It seems it only makes use of
> type information which should be available at that time, so if it
> currently is called too late (interfering with LTO in the future) it
> should be possible to move it earlier.

You're correct.  It is possible to remove the expand_constant language
hook without supporting pointers to members in the middle end.  In
fact, I submitted such a patch back in March
(http://gcc.gnu.org/ml/gcc-patches/2007-03/msg01819.html).  The
various follow-up emails illustrate some of the reasons why migrating
pointers to members to the middle end is a good thing (at least for
C++).

It would have been more accurate for me to describe the language hooks
removal as a jumping off point.  Strictly speaking, the middle end
migration is only necessary for language hook removal if the C++
maintainers won't approve my patch.  :)

That said, I think there is real value in moving pointers to members
to the middle end.  Keep reading.

> I have a conceptual problem with moving pointer to members into the
> middle-end: my mental model of what the middle-end should be concerned
> about is complete expressions/constants/types, like adding two numbers,
> accessing an integer two words away from that address (i.e. you see I
> already sort of decompose structures in my mental model).  Pointers to
> members is a very different beast: they can't be accessed without a real
> object, yet they can be stored into objects themself (sort of an
> incomplete memory reference).  If anything they simply resemble offsets
> (perhaps variable ones), so you might perhaps model them as such.
> Conversions between them sometimes requires adjustments to 'this',
> resulting in real operations (the delta field of the struct, how pointer
> to member values are currently modelled).  IMHO it would be wrong if we
> wouldn't make those adjustments explicit in the middle end.

I think the primary purpose of the middle end is to provide a
representation which captures the semantics of a program at a
sufficiently high level to enable efficient optimization.  COMPLEX_CST
and COMPLEX_TYPE are a good example.  In theory, the middle end has
enough information to optimize complex arithmetic based solely on the
constituent operations on real and imaginary components, but it's
easier to deal with the complex number as an atomic unit.

Similarly, consider the following code fragment:

  struct S { virtual void f(); };
  typedef void (S::*P)(void);
  const P p = &S::f, NULL;
 void g(S s) {
   (s.*p)();
 }

GCC should be able to optimize g() to call s.S::f() directly.  In
theory, it can optimize out the null pointer to member check, the
virtual bit check, and the vtable lookup, but that's a lot of work.
Right now, GCC can't do it.

> So, why do you think you need the PTRMEM_TYPE in the middle end?  And why
> the PTRMEM_CST (i.e. why couldn't it be lowered to some explicit constant
> during gimplificaton)?  Same for PTRMEM_PLUS_EXPR, why is (PTR_)PLUS_EXPR
> not enough, if the semantic is only to add the integer argument to the
> pointer argument (is that even an operation which can be done to pointers
> to members?)?  Also PTRMEM_REF seems to equivalent to a normal
> COMPONENT_REF, just that the second operand is a funny "offset"
> specification instead of a simple field decl.

The implementation is certainly negotiable.  That's part of why I sent
out this email.

For pointers to data members, PTRMEM_CST doesn't give much information
that isn't already provided by integers of OFFSET_TYPE (It does
explicitly indicate NULL pointers to members, which offsets do not.
In fact, GCC currently handles NULL pointer to member casts
incorrectly, as it fails to preserve NULLs).  However, for pointers to
member functions, it bypasses the need to decode an
architecture-dependent virtual bit, and replaces the virtual function
offset with FUNCTION_DECL, which means we don't need to decode vtable
lookups in order to inline function calls.

PTRMEM_PLUS_EXPR is supposed to represent casts (CAST_EXPR didn't seem
appropriate, but I could be convinced otherwise).  It expands to a
conditional which propagates NULL or increments the offset.  I don't
think PTR_PLUS_EXPR checks for NULL, and it's designed to increment
pointers.  A pointer to data member expands to an offset, and a
pointer to member function expands to a fairly complex structure.  In
fact, for some architectures, the offset field is shifted, so
PTRMEM_PLUS_EXPR (p, 1), would actually have to add 2 to the offset.

Take a look at the expand_ptrmemfunc_cst() and build_ptrmemfunc1()
calls inside cplus_expand_constant().  Now reverse that to

Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Mark Mitchell
Ollie Wild wrote:
> On 8/8/07, Michael Matz <[EMAIL PROTECTED]> wrote:

Ollie, thanks for patiently trying out different approaches.

> I think the primary purpose of the middle end is to provide a
> representation which captures the semantics of a program at a
> sufficiently high level to enable efficient optimization.  COMPLEX_CST
> and COMPLEX_TYPE are a good example.  In theory, the middle end has
> enough information to optimize complex arithmetic based solely on the
> constituent operations on real and imaginary components, but it's
> easier to deal with the complex number as an atomic unit.

I agree.

When I discussed this with Ollie, my feeling was that, yes, it's
possible to express all this stuff in terms of GIMPLE (in fact, we
already do, aside from PTRMEM_CST itself!), but we're essentially
obfuscating information and then trying to get it back.  Creating
RECORD_TYPE instances to represent pointers-to-member-functions and then
hoping that the middle end will scalarize the struct, fold all the tests
for virtual-ness, dereference the virtual table entry, etc. seems like a
lot of work to do de-virtualization.  But, the information is in fact
there, so I guess we could go that way.

Michael and Danny have expressed opinions; does anyone else have one?

Thanks,

-- 
Mark Mitchell
CodeSourcery
[EMAIL PROTECTED]
(650) 331-3385 x713


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Daniel Berlin
On 8/8/07, Mark Mitchell <[EMAIL PROTECTED]> wrote:
> Ollie Wild wrote:
> > On 8/8/07, Michael Matz <[EMAIL PROTECTED]> wrote:
>
> Ollie, thanks for patiently trying out different approaches.
>
> > I think the primary purpose of the middle end is to provide a
> > representation which captures the semantics of a program at a
> > sufficiently high level to enable efficient optimization.  COMPLEX_CST
> > and COMPLEX_TYPE are a good example.  In theory, the middle end has
> > enough information to optimize complex arithmetic based solely on the
> > constituent operations on real and imaginary components, but it's
> > easier to deal with the complex number as an atomic unit.
>
> I agree.
>
> When I discussed this with Ollie, my feeling was that, yes, it's
> possible to express all this stuff in terms of GIMPLE (in fact, we
> already do, aside from PTRMEM_CST itself!), but we're essentially
> obfuscating information and then trying to get it back.

This is true of all the lowering we perform (loops->gotos, for example)

>  Creating
> RECORD_TYPE instances to represent pointers-to-member-functions and then
> hoping that the middle end will scalarize the struct, fold all the tests
> for virtual-ness, dereference the virtual table entry, etc. seems like a
> lot of work to do de-virtualization.
>  But, the information is in fact
> there, so I guess we could go that way.
>
We have no need for scalarization to occur to perform points-to *or*
type based devirtualization.  Dereferencing is just a call, it is
always there anyway.
Folding is something we have to be doing anyway.
I just don't see this as as much work as you do.  Both the type-based
that was posted before, and the points-to based one, are just not that
large in terms of code.

I also haven't necessarily said what Ollie has proposed is a bad idea.
 I have simply said the way he has come up with what he proposed is
not the way we should go about this.  It may turn out he has come up
with exactly the representation we want (though I doubt this, for
various reasons).The specification given also doesn't even explain
where/how these operations can occur in GIMPLE, and what they do other
than "a C++ something something".

Also given that someone already wrote a type-based devirtualizer that
worked fine, and i don't see how a points-to one is much work, I'd
like to see more justification for things like PTRMEM_PLUS_EXPR than
"hey, the C++ FE generates this internally".

So i have no real objection to either the type or the CST, I just want
to see semantics that are actually described in terms of our language
independent intermediate language, not in terms "what the C++ FE
does".

Example:
"* A pointer-to-member constant.
TREE_PTRMEM_CST_MEMBER is the _DECL for the member.
TREE_PTRMEM_CST_OFFSET takes on different interpretations depending on
the type of the member.  If the member is NULL, it is ignored.  If the
member is a FIELD_DECL it refers to the field offset.  Otherwise, it refers
to the offset of the this pointer passed to methods.  */"

No justification was given why there is a member and an offset, what
is allowed to be the _DECL for the member, why member is allowed to be
null, why member would sometimes be a FIELD_DECL, sometimes NULL, and
apparently sometimes neither NULL nor a FIELD_DECL, how to find the
this pointer offset refers to (only sometimes, apparently!), etc.

As I said, i'm really not necessarily opposed to seeing pointer to
members in the middle end, i'd just rather not see us underspecify it
and just take what the C++ FE currently does as "the word of the
lord".

> Michael and Danny have expressed opinions; does anyone else have one?
>
> Thanks,
>
> --
> Mark Mitchell
> CodeSourcery
> [EMAIL PROTECTED]
> (650) 331-3385 x713
>


Re: [RFC] Migrate pointers to members to the middle end

2007-08-08 Thread Ollie Wild
On 8/8/07, Daniel Berlin <[EMAIL PROTECTED]> wrote:
> I also haven't necessarily said what Ollie has proposed is a bad idea.
>  I have simply said the way he has come up with what he proposed is
> not the way we should go about this.  It may turn out he has come up
> with exactly the representation we want (though I doubt this, for
> various reasons).The specification given also doesn't even explain
> where/how these operations can occur in GIMPLE, and what they do other
> than "a C++ something something".
>
> Also given that someone already wrote a type-based devirtualizer that
> worked fine, and i don't see how a points-to one is much work, I'd
> like to see more justification for things like PTRMEM_PLUS_EXPR than
> "hey, the C++ FE generates this internally".

OK.  It sounds like I need to go into a lot more detail.  The new
nodes I've proposed aren't actually motivated by the C++ front end,
but rather by a consideration of the semantics dictated by the C++
standard.  Naturally, this gives rise to some similarity, but for
instance, there is no PTRMEM_PLUS_EXPR in the C++ front end, and my
definition of PTRMEM_CST disagrees with the current node of the same
name.

Let's walk through them:


PTRMEM_TYPE

Contains the types of the member (TREE_TYPE) and class
(TYPE_PTRMEM_BASETYPE) of this pointer to member.  This is hopefully
self-explanatory.  In the language of the C++ standard, it is the type
of a "pointer to member of class TYPE_PTRMEM_BASETYPE of type
TREE_TYPE."  This is the type of PTRMEM_CST's, PTRMEM_PLUS_EXPR's, and
various variable types (VAR_DECL, FIELD_DECL, PARM_DECL, etc.).


PTRMEM_CST

The C++ front end already has a PTRMEM_CST node.  However, the
existing node only contains a class (PTRMEM_CST_CLASS) and member
(PTRMEM_CST_MEMBER), and is unable to represent an arbitrary pointer
to member value.  This is especially evident when dealing with
multiple inheritance.  Consider the following example:

  struct B { int f (); };
  struct L : B {};
  struct R : B {};;
  struct D : L, R {};

  int (B::*pb)() = &B::f;
  int (L::*pl)() = pb;
  int (R::*pr)() = pb;
  int (D::*pd[2])() = { pl, pr };

In this case, pd[0] and pd[1] both have the same type and point to the
same member of the same class (B::f), but they point to different base
class instances of B.  To represent this, we need an offset.  Now, one
might argue that rather than a numeric offset, we should point to the
_DECL of the base class subobject, but that breaks down because the
following is also legal:

  struct B {};
  struct D : B { int f (); };

  int (D::*pd)() = &D::f;
  int (B::*pb)() = static_cast(pd);

In this case, pb points to D::f in the derived class.  Since there is
no subobject to point to, we see that a numeric offset representation
is required.

This leads to the definition of PTRMEM_CST which I have adopted.
Since the class type is already provided in its type, we store the
member (TREE_PTRMEM_CST_MEMBER) and numeric offset
(TREE_PTRMEM_CST_OFFSET).  The member is one of NULL (for NULL
pointers to members), a FIELD_DECL (for non-NULL pointers to data
members), or a FUNCTION_DECL (for non-NULL pointers to member
functions).  I've chosen the offset value according to convenience.
For NULL pointers to members, it's irrelevant.  For pointers to data
members, it's the offset of the member relative to the current class
(as determined by any type conversions).  For pointers to member
functions, it's the offset to the this pointer which must be passed to
the function.

PTRMEM_PLUS_EXPR

>From the discussion above, it's clear that type conversions on
pointers to members require adjustments to the offsets (to fields or
this pointers).  We could handle this via CONVERT_EXPRs, but that has
two shortcomings: (1) it requires the middle end to compute offsets to
base class subobjects, and (2) as the first code example above
illustrates, multiple CONVERT_EXPRs cannot be folded together.  To
work around these issues, I've implemented the PTRMEM_PLUS_EXPR.  It's
a binary expression which takes two arguments, a PTRMEM_TYPE object,
and an integral offset expression.  These can be nicely constant
folded, either with other PTRMEM_PLUS_EXPRs or with PTRMEM_CSTs.

There's also an added benefit when dealing with NULL pointers to
members.  Consider the following code:

  struct B { int a; };
  struct L : B {};
  struct R : B {};;
  struct D : L, R {};

  int B::*pb = NULL;
  int L::*pl = pb;
  int R::*pr = pb;
  int D::*pd[2] = { pl, pr };

The C++ standard states that pd[0] == pd[1] since all NULL pointers to
members of the same type compare equal.  However, the current GCC
implementation gets this wrong because the C++ front end implements
pointer to data member via simple addition.  In practice, it needs to
check for NULL first.  However, folding stacked conversions then
requires optimizing code like:

  if (d != NULL_MARKER) d += offset1;
  if (d != NULL_MARKER) d += offset2;
  if (d != NULL_MARKER) d += offset3;

to

  if (d!= NULL_MA