Re: C++ and gather-detailed-mem-stats
On 2012-08-15 06:10 , Richard Guenther wrote: Maybe have a GNU C++ builtin type struct __Gcc_call_location_pack { const char *file; const char *function; unsigned line; }; and an attribute void foo (int bar) __attribute__((add_location_pack)); that directs GNU C++ to add a __Gcc_call_location_pack typed argument at each call site (properly constructed of course)? Or more explicitely: void foo (int bar, __Gcc_call_location_pack pack = __Gcc_create_location_pack ()); ? I'd be willing to pay the price that only GCC can build itself with mem-stat support. I really like this idea. Couldn't we make it even more transparent? If a function is marked with __attribute__((add_location_pack)) (or some other attribute name), the callers will always pass file, function and line as hidden arguments (in the same way that 'this' is passed as a hidden argument). The compiler will then always add 'file', 'function' and 'line' to the argument list, which can then be retrieved via builtins or special argument names (I think builtins may be safer). This would allow us to handle operators. I don't think it would be a big deal if this introduces ABI incompatibilities. Diego.
Re: C++ and gather-detailed-mem-stats
On Fri, Aug 24, 2012 at 10:01 AM, Diego Novillo wrote: > On 2012-08-15 06:10 , Richard Guenther wrote: > >> Maybe have a GNU C++ builtin type >> >> struct __Gcc_call_location_pack { >>const char *file; >>const char *function; >>unsigned line; >> }; >> >> and an attribute >> >> void foo (int bar) __attribute__((add_location_pack)); >> >> that directs GNU C++ to add a __Gcc_call_location_pack typed >> argument at each call site (properly constructed of course)? >> >> Or more explicitely: >> >> void foo (int bar, >>__Gcc_call_location_pack pack = __Gcc_create_location_pack ()); >> >> ? I'd be willing to pay the price that only GCC can build itself >> with mem-stat support. > > > I really like this idea. > > Couldn't we make it even more transparent? If a function is marked with > __attribute__((add_location_pack)) (or some other attribute name), the > callers will always pass file, function and line as hidden arguments (in the > same way that 'this' is passed as a hidden argument). If we go with this approach, then it must be made transparent (there is no point in adding such a facility in the compiler if its usage is a painpoint :-) > > The compiler will then always add 'file', 'function' and 'line' to the > argument list, which can then be retrieved via builtins or special argument > names (I think builtins may be safer). > > This would allow us to handle operators. I don't think it would be a big > deal if this introduces ABI incompatibilities. I think we still have ABI issue to resolve. So far, implicit arguments such as `this' as are still fully spelled out in function elaborations. E.g. a non-static member function of arity n is elaborated as a function of arity n+1. A binary operator is always elaborated as a binary function whether it is defined as a member or a free function. -- Gaby
Re: C++ and gather-detailed-mem-stats
> "Diego" == Diego Novillo writes: Diego> The compiler will then always add 'file', 'function' and 'line' to the Diego> argument list, which can then be retrieved via builtins or special Diego> argument names (I think builtins may be safer). Diego> This would allow us to handle operators. I don't think it would be a Diego> big deal if this introduces ABI incompatibilities. This will also require gdb changes, if you want to be able to call these functions from gdb. I guess it would need a DWARF extension as well. (I am not sure about other debuginfo formats.) Tom
Re: Auto-stuff in GCC
Hi Dimitrios, Dimitrios Apostolou skribis: > This process proved way more tedious than it ought to be, and even > after completing it there were some licensing issues because of GPL > incompatibilities since I borrowed code from gnulib. In general, Gnulib’s policy is to adjust module licenses to fit the needs of GNU projects. So if you need module X under license Z for inclusion in GCC, you can ask bug-gnu...@gnu.org and the module maintainer(s) if they would agree to change that. Ludo’.
Thoughts on Gengtype and Single Inheritance
To take full advantage of the conversion to C++, we will need to use single inheritance in some of our garbage collected structures. To that end, we need to make gengtype understand single inheritance. Here are my thoughts on how to make that happen. There are two major sections, one for non-polymorphic classes and one for polymorphic classes. Each section has a series of subsection pairs describing a new grammar and its implementation. NON-POLYMORPHIC CLASSES The classes we care about are polymorphic in the general sense, but not in the language sense, because they don't have virtual members or bases. That is, they use ad-hoc polymorphism via an enum discriminator to control casting. enum E { EA, EB, EC, ED, EE }; GRAMMAR The root class class must have a discriminator. class ATYPE GTY ((desc ("%h.type"))) { public: enum E type; other *pa; ... }; No derived class may have a discriminator. Every allocatable class must have a tag. class BTYPE : GTY ((tag ("EB"))) public ATYPE { public: other *pb; ... }; The root class may be allocatable, and so may have a tag. class ATYPE GTY ((desc ("%h.type"), tag ("EA"))) { public: enum E type; other *pa; ... }; Two derived classes may share a base, even indirectly, but be otherwise unrelated. class CTYPE : GTY ((tag ("EC"))) public BTYPE { ... }; class DTYPE : GTY ((tag ("ED"))) public BTYPE { ... }; class ETYPE : GTY ((tag ("EE"))) public ATYPE { ... }; Note the difference between C and D are siblings but D and E are siblings once removed (i.e. nephew and uncle). Private and protected fields are not supported, at least for those fields that gengtype cares about. IMPLEMENTATION We can probably hack into the existing generation for unions. However, there is a naming problem. The current gcc union approach creates a "top type" for every class hierarchy. A single-inheritance class hierarchy has no "top type" and so we cannot use it to name the marker. We can use the base type, (aka "bottom type"). That is, generate gt_ggc_mx_ATYPE full of a switch statement covering all known deriviations. Any gt_ggc_mx names for derived types would be simply aliased to the base. GRAMMAR Add support for protected and private data fields. class ATYPE GTY ((desc ("%h.type"))) { protected: enum E type; other *pa; ... }; However, gt_ggc_mx_ATYPE no longer has access to the fields. We can make the user declare gt_ggc_mx_ATYPE a friend of ATYPE and all derived classes. That extra declaration in every class is a mild burden, as it requires following the chain of bases to determine the root class name and then keying in the declaration. class ATYPE GTY ((desc ("%h.type"))) { friend void gt_ggc_mx_ATYPE(void*); protected: enum E type; other *pa; ... }; IMPLEMENTATION No new implementation is required. GRAMMAR Making gt_ggc_mx_ATYPE a friend of all derived classes is possible but far from ideal because the name is nonobvious and refers to implementation details that should be hidden. Instead, have the class itself declare, but not define, a function to mark its members. Gengtype will create the function. The gt_ggc_mx_ATYPE function need not be declared a friend as long as the tag itself is public. Otherwise, for the moment, we still need the friend declaration. class BTYPE GTY ((tag ("EB"))) : public ATYPE { friend void gt_ggc_mx_ATYPE(void*); public: void ggc_marker() const; private: other *pb; ... }; IMPLEMENTATION The mark function needs to be split into parts. One part contains the dispatcher; it retains the current name, void gt_ggc_mx_ATYPE(void*). The remaining parts are member functions that mark the members of an allocatable class. Gengtype fills out both functions. The marker function for a class will call the marker function for its base. GRAMMAR Support adding a second discriminator. This support is not for multiple inheritance, but for single inheritance when a second discriminator is used to further refine it. Look at struct tree_omp_clause. It contains a sub union. We can represent the hierarchy like: struct tree_omp_clause : tree_common { location_t locus; enum omp_clause_code code; }; struct tree_omp_default_clause : tree_omp_clause { enum omp_clause_default_kind default_kind; }; struct tree_omp_schedule_clause : tree_omp_clause { enum omp_clause_schedule_kind schedule_kind; }; struct tree_omp_reduction_clause : tree_omp_clause { enum tree_code reduction_code; }; We use TREE_CODE to understand that we have at least a tree_omp_clause and then we use tree_common.code to to distinguish these last three. Another possible case is tree_type_symtab inside tree_type_common. The syntax would be something like the following. enum F { F1, F2, F3, F4, F5 }; class CTYPE GTY ((desc ("%h.kind"), tag ("F1"))) : GTY ((tag ("EC"))) public BTYPE { public: enum F kind; something *pq; ... }; class FTYPE : GTY ((tag ("F2"))) public CTYPE { ... }; IMPLEMENTATION The dispatcher will have nested switch statements. GR
RFC - Introducing different VEC types
Now that we have a slightly cleaner implementation of vectors, I've been thinking of ways to fix some of the API warts: 1- Pointers vs references when handling vector elements. Elements are sometimes passed by value (vectors of pointers) and others they are passed by reference (vectors of objects). This forces us to have functions accepting 'T' and 'T *', which uglifies the interface when T is a pointer type. It forces the caller to use a explicit cast when passing a 0 value and we need to provide two overloads for the function. This is not hard to fix by making every function handle references. But it requires changes in the callers. I will be fixing this in the next few days. 2- All vectors are now pointers. This has the advantage that vectors occupy a single word when they are part of structure fields. However, it also means that most accessors need a couple of loads to reference the vector. Moreover, we use the convention that a NULL vector indicates an empty vector. This forces a test in every accessor and causes problems for member functions (which need to become static members). 3- The structure uses the trailing array idiom for storage. This makes it possible to implement embedded vectors, but it also means that an allocation or reallocation operation need to potentially reallocate the instance (returning a different VEC pointer) and they all need to have the allocation strategy passed as an argument to the call. Lawrence and I discussed ways of addressing these last 2 issues. We think we can provide three distinct VEC types to support different scenarios: - Embedded vectors of fixed size. These vectors are fields of a parent structure and are allocated by the parent using the trailing array idiom (e.g., tree_binfo::base_binfos). They are not allowed to grow and cannot be allocated (they have to be laid out on top of pre-allocated storage). We can support this with something very similar to the current structure: template struct VEC_embedded_fixed { unsigned num_; unsigned alloc_; T vec_[1]; }; This structure will not support a memory allocation strategy. It will implement most of the vector API, except functions that reallocate memory. Accessors to this type are quick. For instance, v.length() is { return v.num_; } - Embedded vectors of variable size. These vectors are fields of a parent structure, but they need to grow/shrink and support an allocation strategy. Additionally, they should occupy a single word in the structure when they are not allocated. Also, it would be convenient to make them regular instances (instead of pointers), so that accessor functions do not have to bother testing the value of the vector itself before accessing its fields: template struct GTY(()) VEC_embedded_variable { struct VEC_embedded_fixed *vec_; }; Instances of this type only need a word of storage until they are actually allocated. This will cause no growth in the structures where we use VECs. Accessors to this type are similar to the current implementation (slow). In this case v.length() is { return (v->vec_) ? v->vec_.num_ : 0 } - Standalone vectors. These vectors have a larger footprint, but accessors can be much quicker since they would not have to jump through many hoops: template struct VEC_fast { unsigned num_; unsigned alloc_; T *vec_; }; These are typically global or function-local variables. Access to these vectors is quick: v.length() is { return v.num_; } All three types will implement the current API. We will be able to simplify the user code in the following ways: - The type of vector need only be specified at the declaration site. In particular, the memory allocation strategy does not need to be specified in all the function calls that may reallocate the vector (it becomes a property of the type). - We can restrict the API for embedded vectors at compile time. Currently, there are runtime checks. We can make them compile time checks. - The standalone vectors are going to be quicker to access than the current VECs. This may provide some runtime improvements. Lawrence, I hope I didn't miss anything. Please correct me as you see fit. If this works for everyone, I will be implementing this in a sequence of patches following http://gcc.gnu.org/ml/gcc-patches/2012-08/msg01636.html. The names of the VECs will need to change (I don't like them, but I'm not good at names). Thanks. Diego.
gcc-4.6-20120824 is now available
Snapshot gcc-4.6-20120824 is now available on ftp://gcc.gnu.org/pub/gcc/snapshots/4.6-20120824/ and on various mirrors, see http://gcc.gnu.org/mirrors.html for details. This snapshot has been generated from the GCC 4.6 SVN branch with the following options: svn://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch revision 190657 You'll find: gcc-4.6-20120824.tar.bz2 Complete GCC MD5=50180ee1eb71dfb3fc7e1f129ad21820 SHA1=e155ef07101d9d080b10a96d365f4d29d5723fb9 Diffs from 4.6-20120817 are available in the diffs/ subdirectory. When a particular snapshot is ready for public consumption the LATEST-4.6 link is updated and a message is sent to the gcc list. Please do not use a snapshot before it has been announced that way.
Re: Question on calculating register pressure before ira pass
On Mon, Aug 20, 2012 at 5:00 PM, Bin.Cheng wrote: > Hi, > Currently I am working on improving hoist pass by calculating register > pressure and using the info to guide hoist process. It works well and > I will send a patch once I finish it. > > In this work I reused codes in loop-invariant and called > ira_set_pseudo_classes function to calculate register pressure. The > problem is that ira_set_pseudo_classes sets pseudo_classes_defined_p > to TRUE, which causes function find_costs_and_classes scans > instructions only once to find the best reg class to use for each > allocno. > > In my understanding, these part of codes is introduced for calculating > reg pressure in schedulor and loop-invariant. What I do not understand > is why we make IRA behave differently when register pressure is > calculated before IRA pass? > > In the work of hoist, I found bigger regression in code size causes by > the changed behavior of IRA. > > My questions are: > 1. could somebody give some explanation on this. > 2. Is it possible to calculate register pressure by reusing existing > code while do not change behavior of IRA? > I realized it is designed in this way to ensure register pressure are calculated and modeled in same way for loop-invariant/schedulor and ira. But hoist is an early rtl pass and patterns/pseudo are changed a lot from hoist to ira pass, it's better to not use classes for pseudo registers. The data I collected from CSiBE support this point. So how about I reset pseudo_classes_define_p after calculating register pressure in hoist pass? Any one give some comments? Thanks. -- Best Regards.