On Mon, 30 Nov 2015, Gary Funck wrote: > > Background > ---------- > > An overview email, describing the UPC-related changes is here: > https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00005.html > > The GUPC branch is described here: > http://gcc.gnu.org/projects/gupc.html > > The UPC-related source code differences are summarized here: > http://gccupc.org/gupc-changes > > All languages (c, c++, fortran, go, lto, objc, obj-c++) have been > bootstrapped; no test suite regressions were introduced, > relative to the GCC trunk. > > If you are on the cc-list, your name was chosen either > because you are listed as a maintainer for the area that > applies to the patches described in this email, or you > were a frequent contributor of patches made to files listed > in this email. > > In the change log entries included in each patch, the directory > containing the affected files is listed, followed by the files. > When the patches are applied, the change log entries will be > distributed to the appropriate ChangeLog file. > > Overview > -------- > > UPC introduces a new qualifier, "shared", that indicates that the > qualified object is located in a global shared address space that is > accessible by all UPC threads. Additional qualifiers ("strict" and > "relaxed") further specify the semantics of accesses to > UPC shared objects. > > In UPC, a shared qualified array can further specify a "layout > qualifier" (blocking factor) that indicates how the shared data > is blocked and distributed. > > The following example illustrates the use of the UPC "shared" qualifier > combined with a layout qualifier. > > #define BLKSIZE 5 > #define N_PER_THREAD (4 * BLKSIZE) > shared [BLKSIZE] double A[N_PER_THREAD*THREADS]; > > Above the "[BLKSIZE]" construct is the UPC layout qualifier; this > specifies that the shared array, A, distributes its elements across > each thread in blocks of 5 elements. If the program is run with two > threads, then A is distributed as shown below: > > Thread 0 Thread 1 > -------- --------- > A[ 0.. 4] A[ 5.. 9] > A[10..14] A[15..19] > A[20..24] A[25..29] > A[30..34] A[35..39] > > Above, the elements shown for thread 0 are defined as having "affinity" > to thread 0. Similarly, those elements shown for thread 1 have > affinity to thread 1. In UPC, a pointer to a shared object can be > cast to a thread local pointer (a "C" pointer), when the designated > shared object has affinity to the referencing thread. > > A UPC "pointer-to-shared" (PTS) is a pointer that references a UPC > shared object. A UPC pointer-to-shared is a "fat" pointer with the > following logical fields: > (virt_addr, thread, phase) > > The virtual address (virt_addr) field is combined with the thread > number (thread) to derive the location of the referenced object > within the UPC shared address space. The phase field is used > keep track of the current block offset for PTS's that have > blocking factor that is greater than one. > > GUPC implements pointer-to-shared objects using a "struct" internal > representation. Until recently, GUPC also supported a "packed" > representation, which is more space efficient, but limits the range of > various fields in the UPC pointer-to-shared representation. We have > decided to support only the "struct" representation so that the > compiler uses a single ABI that supports the full range of addresses, > threads, and blocking factors. > > GCC's internal tree representation is extended to record the UPC > "shared", "strict", "relaxed" qualifiers, and the layout qualifier. > > --- gcc/tree-core.h (.../trunk) (revision 228959) > +++ gcc/tree-core.h (.../branches/gupc) (revision 229159) > @@ -470,7 +470,11 @@ enum cv_qualifier { > TYPE_QUAL_CONST = 0x1, > TYPE_QUAL_VOLATILE = 0x2, > TYPE_QUAL_RESTRICT = 0x4, > - TYPE_QUAL_ATOMIC = 0x8 > + TYPE_QUAL_ATOMIC = 0x8, > + /* UPC qualifiers */ > + TYPE_QUAL_SHARED = 0x10, > + TYPE_QUAL_RELAXED = 0x20, > + TYPE_QUAL_STRICT = 0x40 > }; > [...] > @@ -857,9 +875,14 @@ struct GTY(()) tree_base { > unsigned user_align : 1; > unsigned nameless_flag : 1; > unsigned atomic_flag : 1; > - unsigned spare0 : 3; > - > - unsigned spare1 : 8; > + unsigned shared_flag : 1; > + unsigned strict_flag : 1; > + unsigned relaxed_flag : 1; > + > + unsigned threads_factor_flag : 1; > + unsigned block_factor_0 : 1; > + unsigned block_factor_x : 1; > + unsigned spare1 : 5; > > A given type is a UPC shared type if its 'shared_flag' is set. > However, for array types, the shared_flag of the *element type* > must be checked. Thus, > > /* Return TRUE if TYPE is a shared type. For arrays, > the element type must be queried, because array types > are never qualified. */ > #define SHARED_TYPE_P(TYPE) \ > ((TYPE) && TYPE_P (TYPE) \ > && TYPE_SHARED ((TREE_CODE (TYPE) != ARRAY_TYPE \ > ? (TYPE) : strip_array_types (TYPE)))) > > By default, a type has a blocking factor of 1. If the blocking factor is 0 > (known as "indefinite") then 'block_factor_0' is set. If the blocking > factor is neither 0 nor 1, then 'block_factor_x' is set and the > actual blocking factor is found in a 'tree map' hash table called > 'block_factor_htab' which is managed in tree.c. > > This use of a garbage collected hash table which maps tree nodes to > a UPC blocking factor leads to a need to implement custom garbage > collection logic for all tree nodes. This custom garbage collection > logic is implemented in gt_ggc_mx(). PCH support is implemented > in gt_pch_nx(). This custom garbage collector is defined in tree-core.h > as follows: > > -struct GTY(()) tree_type_common { > +struct GTY((user)) tree_type_common { > struct tree_common common; > tree size; > tree size_unit; > [...] > tree pointer_to; > tree reference_to; > union tree_type_symtab { > - int GTY ((tag ("TYPE_SYMTAB_IS_ADDRESS"))) address; > - const char * GTY ((tag ("TYPE_SYMTAB_IS_POINTER"))) pointer; > - struct die_struct * GTY ((tag ("TYPE_SYMTAB_IS_DIE"))) die; > - } GTY ((desc ("debug_hooks->tree_type_symtab_field"))) symtab; > + int address; > + const char *pointer; > + struct die_struct *die; > + } symtab; > tree canonical; > tree next_variant; > > Above, 'tree_type_symtab' has to be explicitly traversed by > the garbage collection routine. > > 2015-11-30 Gary Funck <g...@intrepid.com> > > gcc/ > * expr.c (tree_expr_size): Move to tree.c and make it an > extern function. > * print-tree.c (print_node): Print UPC "shared" qualifier > and blocking factor (if present). Indicate THREADS scaling, > if present. > * tree-core.h (cv_qualifier): Add UPC type qualifiers: > TYPE_QUAL_SHARED, TYPE_QUAL_RELAXED, and TYPE_QUAL_STRICT. > (tree_index): Add UPC tree indexes: > TI_UPC_PTS_TYPE, TI_UPC_PTS_REP_TYPE, TI_UPC_CHAR_PTS_TYPE, > TI_UPC_PHASE_FIELD, TI_UPC_THREAD_FIELD, TI_UPC_VADDR_FIELD, > TI_UPC_NULL_PTS. > (tree_base): Add UPC-specific flags: > shared_flag, strict_flag, relaxed_flag, threads_factor_flag, > block_factor_0, block_factor_x. > (tree_type_common): Remove ggc tag type descriptions in > tree_type_symtab fields to accommodate UPC-related garbage collection > changes. > (gt_ggc_mx, gt_pch_nx, gt_pch_nx): New prototypes. > Add custom garbage collection and PCH support for tree_type_common. > * tree-dump.c (dequeue_and_dump): Add qualifier tags for > UPC language qualifier (shared, strict, relaxed). > * tree-pretty-print.c (dump_upc_type_quals): Print UPC language > qualifiers and blocking factor. > (dump_generic_node): Call dump_upc_type_quals() > if the type asserts the "shared" qualifier. > Print UPC qualifiers if applied to a tree node. > Print type name for the UPC pointer-to-shared representation type. > * tree-sra.c (find_param_candidates): > Exclude UPC pointer-to-shared types. > * tree.c: #include "debug.h". Needed for access to symtab > definition in the tree node garbage collection logic. > (tm_block_factor_hasher, block_factor_htab): New. > Define a garbage-collected mapping from tree node to > UPC blocking factor. > (init_ttree): Call block_factor_lookup_init(). > (copy_node_stat): Call SET_TYPE_BLOCK_FACTOR if > type has a UPC blocking factor. > (tree_expr_size): Move from expr.c and make it an > 'extern' function. > (stabilize_reference_1): Copy UPC qualifiers to result. > (build1_stat): Copy shared qualifier from type node. > (build1_stat, build2_stat): For unary and binary operations, > remove UPC "shared" qualifiers from the result type. > (build3_stat): For reference expressions, ensure that > the result node preserves the UPC qualifiers applied to the > first argument. > (set_type_quals): Add a 'tree' argument for the > UPC layout qualifier (blocking factor). Set the blocking factor > if the type asserts the "shared" qualifier. > (check_qualified_type): Add a 'tree' argument for the > UPC layout qualifier (blocking factor). Include the blocking factor > into the type check. > (check_aligned_type): Include the blocking factor > into the type check. > (get_qualified_type_1): Rename get_qualified_type() > to get_qualified_type_1() and add a blocking factor argument. > A #define of get_qualified_type is added to tree.h; > it will call get_qualified_type_1() with a null layout qualifier. > (build_qualified_type): Adjust calls to > get_qualified_type_1() and set_type_quals(). > (build_pointer_type): For UPC pointer-to-shared types > ensure that the resulting pointer type is compatible with the > UPC pointer-to-shared representation type. > (build_atomic_base): Adjust call to set_type_quals(). > (build_opaque_vector_type): > Adjust call to check_qualified_type(). > (tree_nop_conversion): Handle conversions involving > UPC pointer-to-shared types. > (gt_ggc_mx, gt_pch_nx, gt_pch_nx): Implement custom > garbage collection logic, necessitated by the use of a garbage > collected hash tree map used to look up UPC blocking factors. > Contributed by Meador Inge <mead...@codesourcery.com>. > (get_block_factor, build_unshared_type, > block_factor_lookup, block_factor_insert, > block_factor_lookup_init): New. > * tree.h (SHARED_TYPE_P, PTS_CVT_OP_P, TREE_QUALS, > TREE_SHARED, TREE_STRICT, TREE_RELAXED, > TYPE_SHARED, TYPE_STRICT, TYPE_RELAXED, TYPE_HAS_THREADS_FACTOR, > TREE_FUNC_QUALS, TYPE_HAS_BLOCK_FACTOR_0, TYPE_HAS_BLOCK_FACTOR_X, > TYPE_HAS_BLOCK_FACTOR, SET_TYPE_BLOCK_FACTOR): New. > (TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE, > TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC): > Add UPC type qualifiers (shared, relaxed, strict). > (block_factor_insert, block_factor_lookup, > build_unshared_type, block_factor_lookup_init, > get_block_factor): New. Declare prototypes. > (SSA_VAR_P): Exclude UPC shared types. > (upc_pts_type_node, upc_pts_rep_type_node, > upc_char_pts_type_node, upc_phase_field_node, > upc_thread_field_node, upc_vaddr_field_node, > upc_null_pts_node): New. Define UPC-related global tree nodes. > (check_qualified_type, get_qualified_type_1): > Adjust prototypes. > (get_qualified_type): Re-implement as a pre-processor macro > that invokes get_qualified_type_1() with a null blocking factor. > (tree_expr_size): New. Declare prototype for function > moved from expr.c into tree.c. > > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c (.../trunk) (revision 231059) > +++ gcc/expr.c (.../branches/gupc) (revision 231080) > @@ -137,7 +137,6 @@ static void emit_single_push_insn (machi > #endif > static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int); > static rtx const_vector_from_tree (tree); > -static tree tree_expr_size (const_tree); > static HOST_WIDE_INT int_expr_size (tree); > > > @@ -11566,18 +11565,6 @@ get_personality_function (tree decl) > return XEXP (DECL_RTL (personality), 0); > } > > -/* Returns a tree for the size of EXP in bytes. */ > - > -static tree > -tree_expr_size (const_tree exp) > -{ > - if (DECL_P (exp) > - && DECL_SIZE_UNIT (exp) != 0) > - return DECL_SIZE_UNIT (exp); > - else > - return size_in_bytes (TREE_TYPE (exp)); > -} > - > /* Return an rtx for the size in bytes of the value of EXP. */ > > rtx > Index: gcc/print-tree.c > =================================================================== > --- gcc/print-tree.c (.../trunk) (revision 231059) > +++ gcc/print-tree.c (.../branches/gupc) (revision 231080) > @@ -299,6 +299,8 @@ print_node (FILE *file, const char *pref > fputs (" readonly", file); > if (TYPE_P (node) && TYPE_ATOMIC (node)) > fputs (" atomic", file); > + if (TREE_SHARED (node)) > + fputs (" shared", file); > if (!TYPE_P (node) && TREE_CONSTANT (node)) > fputs (" constant", file); > else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node)) > @@ -607,6 +609,14 @@ print_node (FILE *file, const char *pref > > print_node (file, "size", TYPE_SIZE (node), indent + 4); > print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4); > + if (TYPE_SHARED (node)) > + { > + if (TYPE_HAS_THREADS_FACTOR(node)) > + fputs (" THREADS factor", file); > + if (TYPE_HAS_BLOCK_FACTOR (node)) > + print_node (file, "block factor", > + TYPE_BLOCK_FACTOR (node), indent + 4); > + } > indent_to (file, indent + 3); > > if (TYPE_USER_ALIGN (node)) > Index: gcc/tree-core.h > =================================================================== > --- gcc/tree-core.h (.../trunk) (revision 231059) > +++ gcc/tree-core.h (.../branches/gupc) (revision 231080) > @@ -501,7 +501,11 @@ enum cv_qualifier { > TYPE_QUAL_CONST = 0x1, > TYPE_QUAL_VOLATILE = 0x2, > TYPE_QUAL_RESTRICT = 0x4, > - TYPE_QUAL_ATOMIC = 0x8 > + TYPE_QUAL_ATOMIC = 0x8, > + /* UPC qualifiers */ > + TYPE_QUAL_SHARED = 0x10, > + TYPE_QUAL_RELAXED = 0x20, > + TYPE_QUAL_STRICT = 0x40 > }; > > /* Standard named or nameless data types of the C compiler. */ > @@ -578,6 +582,14 @@ enum tree_index { > TI_FILEPTR_TYPE, > TI_POINTER_SIZED_TYPE, > > + TI_UPC_PTS_TYPE, > + TI_UPC_PTS_REP_TYPE, > + TI_UPC_CHAR_PTS_TYPE, > + TI_UPC_PHASE_FIELD, > + TI_UPC_THREAD_FIELD, > + TI_UPC_VADDR_FIELD, > + TI_UPC_NULL_PTS, > + > TI_POINTER_BOUNDS_TYPE, > > TI_DFLOAT32_TYPE, > @@ -880,9 +892,14 @@ struct GTY(()) tree_base { > unsigned user_align : 1; > unsigned nameless_flag : 1; > unsigned atomic_flag : 1; > - unsigned spare0 : 3; > - > - unsigned spare1 : 8; > + unsigned shared_flag : 1; > + unsigned strict_flag : 1; > + unsigned relaxed_flag : 1; > + > + unsigned threads_factor_flag : 1; > + unsigned block_factor_0 : 1; > + unsigned block_factor_x : 1; > + unsigned spare1 : 5; > > /* This field is only used with TREE_TYPE nodes; the only reason it is > present in tree_base instead of tree_type is to save space. The size > @@ -1411,7 +1428,7 @@ struct GTY(()) tree_block { > struct die_struct *die; > }; > > -struct GTY(()) tree_type_common { > +struct GTY((user)) tree_type_common { > struct tree_common common; > tree size; > tree size_unit; > @@ -1441,10 +1458,10 @@ struct GTY(()) tree_type_common { > tree pointer_to; > tree reference_to; > union tree_type_symtab { > - int GTY ((tag ("TYPE_SYMTAB_IS_ADDRESS"))) address; > - const char * GTY ((tag ("TYPE_SYMTAB_IS_POINTER"))) pointer; > - struct die_struct * GTY ((tag ("TYPE_SYMTAB_IS_DIE"))) die; > - } GTY ((desc ("debug_hooks->tree_type_symtab_field"))) symtab; > + int address; > + const char *pointer; > + struct die_struct *die; > + } symtab;
Err, you don't have debug info for this? What is address? I do not like the explict GC of tree_type_common. > tree canonical; > tree next_variant; > tree main_variant; > @@ -1452,6 +1469,11 @@ struct GTY(()) tree_type_common { > tree name; > }; > > +/* Garbage collection and PCH support for tree_type_common. */ > +extern void gt_ggc_mx (tree_type_common *t); > +extern void gt_pch_nx (tree_type_common *t); > +extern void gt_pch_nx (tree_type_common *t, gt_pointer_operator, void *); > + > struct GTY(()) tree_type_with_lang_specific { > struct tree_type_common common; > /* Points to a structure whose details depend on the language in use. */ > Index: gcc/tree-dump.c > =================================================================== > --- gcc/tree-dump.c (.../trunk) (revision 231059) > +++ gcc/tree-dump.c (.../branches/gupc) (revision 231080) > @@ -387,10 +387,13 @@ dequeue_and_dump (dump_info_p di) > > if (quals != TYPE_UNQUALIFIED) > { > - fprintf (di->stream, "qual: %c%c%c ", > + fprintf (di->stream, "qual: %c%c%c%c%c%c ", > (quals & TYPE_QUAL_CONST) ? 'c' : ' ', > (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', > - (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); > + (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ', > + (quals & TYPE_QUAL_SHARED) ? 's' : ' ', > + (quals & TYPE_QUAL_STRICT) ? 't' : ' ', > + (quals & TYPE_QUAL_RELAXED) ? 'x' : ' '); > di->column += 14; > } > > Index: gcc/tree-pretty-print.c > =================================================================== > --- gcc/tree-pretty-print.c (.../trunk) (revision 231059) > +++ gcc/tree-pretty-print.c (.../branches/gupc) (revision 231080) > @@ -1105,6 +1105,25 @@ dump_block_node (pretty_printer *pp, tre > } > > > +static void > +dump_upc_type_quals (pretty_printer *buffer, tree type, int quals) Functions need comments. > +{ > + gcc_assert (type && TYPE_CHECK (type)); > + gcc_assert (quals & TYPE_QUAL_SHARED); > + if (quals & TYPE_QUAL_STRICT) > + pp_string (buffer, "strict "); > + if (quals & TYPE_QUAL_RELAXED) > + pp_string (buffer, "relaxed "); > + pp_string (buffer, "shared "); > + if (TYPE_HAS_BLOCK_FACTOR (type)) > + { > + tree block_factor = TYPE_BLOCK_FACTOR (type); > + pp_string (buffer, "["); > + pp_wide_integer (buffer, TREE_INT_CST_LOW (block_factor)); > + pp_string (buffer, "] "); > + } > +} > + > /* Dump the node NODE on the pretty_printer PP, SPC spaces of > indent. FLAGS specifies details to show in the dump (see TDF_* in > dumpfile.h). If IS_STMT is true, the object printed is considered > @@ -1204,6 +1223,8 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, "volatile "); > else if (quals & TYPE_QUAL_RESTRICT) > pp_string (pp, "restrict "); > + else if (quals & TYPE_QUAL_SHARED) > + dump_upc_type_quals (pp, node, quals); > > if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node))) > { > @@ -1346,6 +1367,14 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, " volatile"); > if (quals & TYPE_QUAL_RESTRICT) > pp_string (pp, " restrict"); > + if (quals & TYPE_QUAL_SHARED) > + { > + if (quals & TYPE_QUAL_STRICT) > + pp_string (pp, " strict"); > + if (quals & TYPE_QUAL_RELAXED) > + pp_string (pp, " relaxed"); > + pp_string (pp, " shared"); > + } > > if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node))) > { > @@ -1515,6 +1544,8 @@ dump_generic_node (pretty_printer *pp, t > pp_string (pp, "const "); > if (quals & TYPE_QUAL_VOLATILE) > pp_string (pp, "volatile "); > + if (quals & TYPE_QUAL_SHARED) > + dump_upc_type_quals (pp, node, quals); > > /* Print the name of the structure. */ > if (TREE_CODE (node) == RECORD_TYPE) > @@ -1522,7 +1553,12 @@ dump_generic_node (pretty_printer *pp, t > else if (TREE_CODE (node) == UNION_TYPE) > pp_string (pp, "union "); > > - if (TYPE_NAME (node)) > + if (upc_pts_rep_type_node && node == upc_pts_rep_type_node) > + /* Normally, builtin types will not be printed. > + We short-circuit that check for the UPC "struct PTS" > + representation type. */ > + pp_string (pp, "upc_shared_ptr_t"); > + else if (TYPE_NAME (node)) > dump_generic_node (pp, TYPE_NAME (node), spc, flags, false); > else if (!(flags & TDF_SLIM)) > /* FIXME: If we eliminate the 'else' above and attempt > Index: gcc/tree-sra.c > =================================================================== > --- gcc/tree-sra.c (.../trunk) (revision 231059) > +++ gcc/tree-sra.c (.../branches/gupc) (revision 231080) > @@ -3882,6 +3882,7 @@ find_param_candidates (void) > > if (TREE_CODE (type) == FUNCTION_TYPE > || TYPE_VOLATILE (type) > + || SHARED_TYPE_P (type) UPC_SHARED_TYPE_P () > || (TREE_CODE (type) == ARRAY_TYPE > && TYPE_NONALIASED_COMPONENT (type)) > || !is_gimple_reg (parm) > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c (.../trunk) (revision 231059) > +++ gcc/tree.c (.../branches/gupc) (revision 231080) > @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. > #include "langhooks-def.h" > #include "tree-diagnostic.h" > #include "except.h" > +#include "debug.h" > #include "builtins.h" > #include "print-tree.h" > #include "ipa-utils.h" > @@ -243,7 +244,23 @@ struct tree_vec_map_cache_hasher : ggc_c > static GTY ((cache)) > hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl; > > -static void set_type_quals (tree, int); > +struct tm_block_factor_hasher : ggc_cache_ptr_hash<tree_map> > +{ > + static hashval_t hash (tree_map *m) { return tree_map_hash (m); } > + static bool equal (tree_map *a, tree_map *b) { return tree_map_eq (a, b); } > + > + static int > + keep_cache_entry (tree_map *&e) > + { > + return ggc_marked_p (e->base.from); > + } > +}; > + > +/* Hash table for block factor lookups when the block factor > + is not 0 (the indefinite block factor) or 1 (the default). */ > +static GTY((cache)) hash_table<tm_block_factor_hasher> *block_factor_htab; > + > +static void set_type_quals (tree, int, tree); > static void print_type_hash_statistics (void); > static void print_debug_expr_statistics (void); > static void print_value_expr_statistics (void); > @@ -639,6 +656,9 @@ init_ttree (void) > type_hash_table > = hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE); > > + /* Initialize hash table used to manage blocking factors. */ > + block_factor_lookup_init (); > + > debug_expr_for_decl > = hash_table<tree_decl_map_cache_hasher>::create_ggc (512); > > @@ -1197,6 +1217,9 @@ copy_node_stat (tree node MEM_STAT_DECL) > TYPE_CACHED_VALUES_P (t) = 0; > TYPE_CACHED_VALUES (t) = NULL_TREE; > } > + > + if (TYPE_HAS_BLOCK_FACTOR (node)) > + SET_TYPE_BLOCK_FACTOR (t, TYPE_BLOCK_FACTOR (node)); > } > else if (code == TARGET_OPTION_NODE) > { > @@ -2932,6 +2955,18 @@ size_in_bytes (const_tree type) > return t; > } > > +/* Returns a tree for the size of EXP in bytes. */ > + > +tree > +tree_expr_size (const_tree exp) > +{ > + if (DECL_P (exp) > + && DECL_SIZE_UNIT (exp) != 0) > + return DECL_SIZE_UNIT (exp); > + else > + return size_in_bytes (TREE_TYPE (exp)); > +} > + > /* Return the size of TYPE (in bytes) as a wide integer > or return -1 if the size can vary or is larger than an integer. */ > > @@ -4155,6 +4190,9 @@ stabilize_reference_1 (tree e) > TREE_READONLY (result) = TREE_READONLY (e); > TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e); > TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e); > + TREE_SHARED (result) = TREE_SHARED (e); > + TREE_STRICT (result) = TREE_STRICT (e); > + TREE_RELAXED (result) = TREE_RELAXED (e); > > return result; > } > @@ -4238,6 +4276,9 @@ stabilize_reference (tree ref) > TREE_READONLY (result) = TREE_READONLY (ref); > TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref); > TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref); > + TREE_SHARED (result) = TREE_SHARED (ref); > + TREE_STRICT (result) = TREE_STRICT (ref); > + TREE_RELAXED (result) = TREE_RELAXED (ref); > > return result; > } > @@ -4381,6 +4422,7 @@ build1_stat (enum tree_code code, tree t > /* Whether a dereference is readonly has nothing to do with whether > its operand is readonly. */ > TREE_READONLY (t) = 0; > + TREE_SHARED (t) = SHARED_TYPE_P (type); This is frontend logic and should reside in FEs. > break; > > case ADDR_EXPR: > @@ -4396,6 +4438,12 @@ build1_stat (enum tree_code code, tree t > if (TREE_CODE_CLASS (code) == tcc_reference > && node && TREE_THIS_VOLATILE (node)) > TREE_THIS_VOLATILE (t) = 1; > + /* Drop the "shared" type qualifier for > + expressions involving shared objects. */ > + if (TREE_CODE_CLASS (code) == tcc_unary > + && node && !TYPE_P (node) > + && SHARED_TYPE_P (type)) > + TREE_TYPE (t) = build_unshared_type (type); Likewise. > break; > } > > @@ -4439,6 +4487,10 @@ build2_stat (enum tree_code code, tree t > && ptrofftype_p (TREE_TYPE (arg1))); > > t = make_node_stat (code PASS_MEM_STAT); > + > + /* Remove shared type qualifiers from the result type. */ > + if (SHARED_TYPE_P (tt)) > + tt = build_unshared_type (tt); Likewise. > TREE_TYPE (t) = tt; > > /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the > @@ -4516,6 +4568,14 @@ build3_stat (enum tree_code code, tree t > TREE_THIS_VOLATILE (t) > = (TREE_CODE_CLASS (code) == tcc_reference > && arg0 && TREE_THIS_VOLATILE (arg0)); > + TREE_SHARED (t) > + = (TREE_CODE_CLASS (code) == tcc_reference > + && arg0 && TREE_SHARED (arg0)); > + if (TREE_SHARED (t)) > + { > + TREE_STRICT (t) = TREE_STRICT (arg0); > + TREE_RELAXED (t) = TREE_RELAXED (arg0); > + } > Likewise. > return t; > } > @@ -6464,16 +6524,22 @@ handle_dll_attribute (tree * pnode, tree > #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */ > > /* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask > - of the various TYPE_QUAL values. */ > + of the various TYPE_QUAL values. Also, set the blocking factor, > + which is either null or a reference to an integral constant. */ > > static void > -set_type_quals (tree type, int type_quals) > +set_type_quals (tree type, int type_quals, tree block_factor) > { > TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0; > TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0; > TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0; > TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0; > TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals); > + TYPE_SHARED (type) = (type_quals & TYPE_QUAL_SHARED) != 0; > + TYPE_STRICT (type) = (type_quals & TYPE_QUAL_STRICT) != 0; > + TYPE_RELAXED (type) = (type_quals & TYPE_QUAL_RELAXED) != 0; > + if (TYPE_SHARED (type)) > + SET_TYPE_BLOCK_FACTOR (type, block_factor); > } > > /* Returns true iff unqualified CAND and BASE are equivalent. */ > @@ -6490,12 +6556,15 @@ check_base_type (const_tree cand, const_ > TYPE_ATTRIBUTES (base))); > } > > -/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */ > +/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS > + and BLOCK_FACTOR. */ > > bool > -check_qualified_type (const_tree cand, const_tree base, int type_quals) > +check_qualified_type (const_tree cand, const_tree base, > + int type_quals, tree block_factor) > { > return (TYPE_QUALS (cand) == type_quals > + && TYPE_BLOCK_FACTOR (cand) == block_factor > && check_base_type (cand, base)); > } > > @@ -6505,6 +6574,7 @@ static bool > check_aligned_type (const_tree cand, const_tree base, unsigned int align) > { > return (TYPE_QUALS (cand) == TYPE_QUALS (base) > + && TYPE_BLOCK_FACTOR (cand) == TYPE_BLOCK_FACTOR (base) > && TYPE_NAME (cand) == TYPE_NAME (base) > /* Apparently this is needed for Objective-C. */ > && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base) > @@ -6557,11 +6627,11 @@ find_atomic_core_type (tree type) > } > > /* Return a version of the TYPE, qualified as indicated by the > - TYPE_QUALS, if one exists. If no qualified version exists yet, > - return NULL_TREE. */ > + TYPE_QUALS, and BLOCK_FACTOR if one exists. > + If no qualified version exists yet, return NULL_TREE. */ > > tree > -get_qualified_type (tree type, int type_quals) > +get_qualified_type_1 (tree type, int type_quals, tree block_factor) > { > tree t; > > @@ -6572,28 +6642,28 @@ get_qualified_type (tree type, int type_ > like the one we need to have. If so, use that existing one. We must > preserve the TYPE_NAME, since there is code that depends on this. */ > for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) > - if (check_qualified_type (t, type, type_quals)) > + if (check_qualified_type (t, type, type_quals, block_factor)) > return t; > > return NULL_TREE; > } > > -/* Like get_qualified_type, but creates the type if it does not > +/* Like get_qualified_type_1, but creates the type if it does not > exist. This function never returns NULL_TREE. */ > > tree > -build_qualified_type (tree type, int type_quals) > +build_qualified_type_1 (tree type, int type_quals, tree block_factor) > { > tree t; > > /* See if we already have the appropriate qualified variant. */ > - t = get_qualified_type (type, type_quals); > + t = get_qualified_type_1 (type, type_quals, block_factor); > > /* If not, build it. */ > if (!t) > { > t = build_variant_type_copy (type); > - set_type_quals (t, type_quals); > + set_type_quals (t, type_quals, block_factor); > > if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC)) > { > @@ -7934,6 +8004,16 @@ build_pointer_type (tree to_type) > addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC > : TYPE_ADDR_SPACE (to_type); > machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); > + if (SHARED_TYPE_P (to_type)) > + { > + tree upc_pts_type; > + pointer_mode = TYPE_MODE (upc_pts_rep_type_node); > + upc_pts_type = build_pointer_type_for_mode (to_type, pointer_mode, > + false); > + TYPE_USER_ALIGN (upc_pts_type) = TYPE_USER_ALIGN > (upc_pts_rep_type_node); > + TYPE_ALIGN (upc_pts_type) = TYPE_ALIGN (upc_pts_rep_type_node); > + return upc_pts_type; > + } > return build_pointer_type_for_mode (to_type, pointer_mode, false); > } > > @@ -9991,7 +10071,7 @@ build_atomic_base (tree type, unsigned i > return t; > > t = build_variant_type_copy (type); > - set_type_quals (t, TYPE_QUAL_ATOMIC); > + set_type_quals (t, TYPE_QUAL_ATOMIC, NULL_TREE); > > if (align) > TYPE_ALIGN (t) = align; > @@ -10724,7 +10804,7 @@ build_opaque_vector_type (tree innertype > cand = TYPE_NEXT_VARIANT (t); > if (cand > && TYPE_VECTOR_OPAQUE (cand) > - && check_qualified_type (cand, t, TYPE_QUALS (t))) > + && check_qualified_type (cand, t, TYPE_QUALS (t), NULL_TREE)) > return cand; > /* Othewise build a variant type and make sure to queue it after > the non-opaque type. */ > @@ -12205,6 +12285,7 @@ static inline bool > tree_nop_conversion (const_tree exp) > { > tree outer_type, inner_type; > + int outer_is_pts_p, inner_is_pts_p; > > if (!CONVERT_EXPR_P (exp) > && TREE_CODE (exp) != NON_LVALUE_EXPR) > @@ -12218,6 +12299,22 @@ tree_nop_conversion (const_tree exp) > if (!inner_type) > return false; > > + outer_is_pts_p = (POINTER_TYPE_P (outer_type) > + && SHARED_TYPE_P (TREE_TYPE (outer_type))); > + inner_is_pts_p = (POINTER_TYPE_P (inner_type) > + && SHARED_TYPE_P (TREE_TYPE (inner_type))); > + > + /* Pointer-to-shared types have special > + equivalence rules that must be checked. */ > + if (outer_is_pts_p && inner_is_pts_p > + && lang_hooks.types_compatible_p) > + return lang_hooks.types_compatible_p (outer_type, inner_type); Sorry, but that can't fly with LTO. I wonder why you didn't use address-spaces for whatever UPC needs for pointers. > + > + /* Pointer-to-shared types are not interchangeable > + with integral types. */ > + if (outer_is_pts_p || inner_is_pts_p) > + return false; > + > return tree_nop_conversion_p (outer_type, inner_type); > } > > @@ -12731,6 +12828,121 @@ block_may_fallthru (const_tree block) > } > } > > +/* Garbage collection support for tree_type_common. */ > + > +extern void gt_ggc_mx (tree&); > +extern void gt_ggc_mx_die_struct (void *); > + > +void gt_ggc_mx (tree_type_common *tt) > +{ > + tree t = (tree) tt; > + tree block_factor = TYPE_BLOCK_FACTOR (t); > + > + gt_ggc_mx (tt->common.typed.type); > + gt_ggc_mx (tt->common.chain); > + gt_ggc_mx (tt->size); > + gt_ggc_mx (tt->size_unit); > + gt_ggc_mx (tt->attributes); > + gt_ggc_mx (tt->pointer_to); > + gt_ggc_mx (tt->reference_to); > + switch (debug_hooks->tree_type_symtab_field) > + { > + case TYPE_SYMTAB_IS_ADDRESS: > + break; > + case TYPE_SYMTAB_IS_POINTER: > + gt_ggc_m_S (tt->symtab.pointer); > + break; > + case TYPE_SYMTAB_IS_DIE: > + gt_ggc_mx_die_struct (tt->symtab.die); > + break; > + default: > + break; > + } > + gt_ggc_mx (tt->name); > + gt_ggc_mx (tt->next_variant); > + gt_ggc_mx (tt->main_variant); > + gt_ggc_mx (tt->context); > + gt_ggc_mx (tt->canonical); > + > + if (TYPE_HAS_BLOCK_FACTOR_X (t)) > + gt_ggc_mx (block_factor); > +} > + > +/* PCH support for tree_type_common. */ > + > +extern void gt_pch_nx (tree&); > +extern void gt_ggc_nx_die_struct (void *); > + > +void gt_pch_nx (tree_type_common *tt) > +{ > + tree t = (tree) tt; > + tree block_factor = TYPE_BLOCK_FACTOR (t); > + > + gt_pch_nx (tt->common.typed.type); > + gt_pch_nx (tt->common.chain); > + gt_pch_nx (tt->size); > + gt_pch_nx (tt->size_unit); > + gt_pch_nx (tt->attributes); > + gt_pch_nx (tt->pointer_to); > + gt_pch_nx (tt->reference_to); > + switch (debug_hooks->tree_type_symtab_field) > + { > + case TYPE_SYMTAB_IS_ADDRESS: > + break; > + case TYPE_SYMTAB_IS_POINTER: > + gt_pch_n_S (tt->symtab.pointer); > + break; > + case TYPE_SYMTAB_IS_DIE: > + gt_pch_nx_die_struct (tt->symtab.die); > + break; > + default: > + break; > + } > + gt_pch_nx (tt->name); > + gt_pch_nx (tt->next_variant); > + gt_pch_nx (tt->main_variant); > + gt_pch_nx (tt->context); > + gt_pch_nx (tt->canonical); > + > + if (TYPE_HAS_BLOCK_FACTOR_X (t)) > + gt_pch_nx (block_factor); > +} > + > +void gt_pch_nx (tree_type_common *tt, gt_pointer_operator op, void *cookie) > +{ > + tree t = (tree) tt; > + tree block_factor = TYPE_BLOCK_FACTOR (t); > + > + op (&(tt->common.typed.type), cookie); > + op (&(tt->common.chain), cookie); > + op (&(tt->size), cookie); > + op (&(tt->size_unit), cookie); > + op (&(tt->attributes), cookie); > + op (&(tt->pointer_to), cookie); > + op (&(tt->reference_to), cookie); > + switch (debug_hooks->tree_type_symtab_field) > + { > + case TYPE_SYMTAB_IS_ADDRESS: > + break; > + case TYPE_SYMTAB_IS_POINTER: > + op (&(tt->symtab.pointer), cookie); > + break; > + case TYPE_SYMTAB_IS_DIE: > + op (&(tt->symtab.die), cookie); > + break; > + default: > + break; > + } > + op (&(tt->name), cookie); > + op (&(tt->next_variant), cookie); > + op (&(tt->main_variant), cookie); > + op (&(tt->context), cookie); > + op (&(tt->canonical), cookie); > + > + if (TYPE_HAS_BLOCK_FACTOR_X (t)) > + op (&(block_factor), cookie); > +} > + > /* True if we are using EH to handle cleanups. */ > static bool using_eh_for_cleanups_flag = false; > > @@ -13901,6 +14113,103 @@ nonnull_arg_p (const_tree arg) > return false; > } > > +/* Return the blocking factor of the shared type, TYPE. > + If the blocking factor is NULL, then return the default blocking > + factor of 1. */ > + > +tree > +get_block_factor (const tree type) > +{ > + tree block_factor = size_one_node; > + const tree elt_type = strip_array_types (type); > + if (elt_type && (TREE_CODE (elt_type) != ERROR_MARK) > + && TYPE_HAS_BLOCK_FACTOR (elt_type)) > + block_factor = TYPE_BLOCK_FACTOR (elt_type); > + return block_factor; > +} > + > +/* Return a variant of TYPE, where the shared, strict, and relaxed > + qualifiers have been removed. */ > + > +tree > +build_unshared_type (tree type) Too generic names. I'd prefer if these routines were in a upc.c file rather than in tree.c. Likewise for the block hash I suppose. > +{ > + tree u_type = type; > + if (TREE_CODE (type) == ARRAY_TYPE) > + { > + const tree elem_type = TREE_TYPE(type); > + const tree u_elem_type = build_unshared_type (elem_type); > + if (u_elem_type != elem_type) > + { > + for (u_type = TYPE_MAIN_VARIANT (type); > + u_type && TREE_TYPE(u_type) != u_elem_type; > + u_type = TYPE_NEXT_VARIANT (u_type)) /* loop */; > + if (!u_type) > + { > + u_type = build_variant_type_copy (type); > + TREE_TYPE (u_type) = u_elem_type; > + } > + } > + } > + else > + { > + const int quals = TYPE_QUALS (type); > + const int u_quals = quals & ~(TYPE_QUAL_SHARED > + | TYPE_QUAL_RELAXED > + | TYPE_QUAL_STRICT); > + u_type = build_qualified_type (type, u_quals); > + } > + return u_type; > +} > + > +/* Lookup the block size of TYPE, and return it if we find one. */ > + > +tree > +block_factor_lookup (const_tree type) > +{ > + struct tree_map in; > + union > + { > + const_tree ct; > + tree t; > + } ct_to_t; > + ct_to_t.ct = type; > + /* Drop the const qualifier, avoid the warning. */ > + in.base.from = ct_to_t.t; > + in.hash = TYPE_HASH (in.base.from); > + struct tree_map **loc = block_factor_htab-> > + find_slot_with_hash (&in, in.hash, NO_INSERT); > + gcc_assert (loc != NULL); > + struct tree_map *h = *loc; > + if (h) > + return h->to; > + return NULL_TREE; > +} > + > +/* Insert a mapping TYPE->BLOCK_FACTOR in the block factor hashtable. */ > + > +void > +block_factor_insert (tree type, tree block_factor) > +{ > + > + gcc_assert (type && TYPE_P (type)); > + gcc_assert (block_factor && INTEGRAL_TYPE_P (TREE_TYPE (block_factor))); > + gcc_assert (!(integer_zerop (block_factor) || integer_onep > (block_factor))); > + tree_map *h = ggc_alloc<tree_map> (); > + h->base.from = type; > + h->hash = TYPE_HASH (type); > + h->to = block_factor; > + tree_map **loc = block_factor_htab-> > + find_slot_with_hash (h, h->hash, INSERT); > + *loc = h; > +} > + > +void > +block_factor_lookup_init (void) > +{ > + block_factor_htab = hash_table<tm_block_factor_hasher>::create_ggc (17); > +} > + > /* Given location LOC, strip away any packed range information > or ad-hoc information. */ > > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h (.../trunk) (revision 231059) > +++ gcc/tree.h (.../branches/gupc) (revision 231080) > @@ -636,6 +636,24 @@ extern void omp_clause_range_check_faile > #define FUNC_OR_METHOD_TYPE_P(NODE) \ > (TREE_CODE (NODE) == FUNCTION_TYPE || TREE_CODE (NODE) == METHOD_TYPE) > > +/* Return TRUE if TYPE is a shared type. For arrays, > + the element type must be queried, because array types > + are never qualified. */ > +#define SHARED_TYPE_P(TYPE) \ > + ((TYPE) && TYPE_P (TYPE) \ > + && TYPE_SHARED ((TREE_CODE (TYPE) != ARRAY_TYPE \ > + ? (TYPE) : strip_array_types (TYPE)))) > + > +/* Return TRUE if EXP is a conversion operation involving > + pointers-to-shared. If either of the types involved > + in the conversion is a pointer-to-shared type, return TRUE. */ > +#define PTS_CVT_OP_P(EXP) \ > + ((EXP) && ((POINTER_TYPE_P (TREE_TYPE (EXP)) \ > + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (EXP, 0)))) \ > + && (SHARED_TYPE_P (TREE_TYPE (TREE_TYPE (EXP))) \ > + || SHARED_TYPE_P (TREE_TYPE ( \ > + TREE_TYPE (TREE_OPERAND (EXP, 0))))))) > + > /* Define many boolean fields that all tree nodes have. */ > > /* In VAR_DECL, PARM_DECL and RESULT_DECL nodes, nonzero means address > @@ -812,6 +830,14 @@ extern void omp_clause_range_check_faile > #define DECL_UNSIGNED(NODE) \ > (DECL_COMMON_CHECK (NODE)->base.u.bits.unsigned_flag) > > +/* Convert tree flags to type qualifiers. */ > +#define TREE_QUALS(NODE) \ > + ((TREE_READONLY(NODE) * TYPE_QUAL_CONST) | \ > + (TREE_THIS_VOLATILE(NODE) * TYPE_QUAL_VOLATILE) | \ > + (TREE_SHARED(NODE) * TYPE_QUAL_SHARED) | \ > + (TREE_STRICT(NODE) * TYPE_QUAL_STRICT) | \ > + (TREE_RELAXED(NODE) * TYPE_QUAL_RELAXED)) > + > /* In integral and pointer types, means an unsigned type. */ > #define TYPE_UNSIGNED(NODE) (TYPE_CHECK (NODE)->base.u.bits.unsigned_flag) > > @@ -941,6 +967,11 @@ extern void omp_clause_range_check_faile > #define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \ > (IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag) > > +/* Shared, strict, and relaxed common tree flags */ > +#define TREE_SHARED(NODE) ((NODE)->base.u.bits.shared_flag) > +#define TREE_STRICT(NODE) ((NODE)->base.u.bits.strict_flag) > +#define TREE_RELAXED(NODE) ((NODE)->base.u.bits.relaxed_flag) > + > /* In an aggregate type, indicates that the scalar fields of the type are > stored in reverse order from the target order. This effectively > toggles BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN within the type. */ > @@ -1887,6 +1918,21 @@ extern machine_mode element_mode (const_ > the term. */ > #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type_common.restrict_flag) > > +/* If nonzero, this type is `shared'-qualified, in the UPC dialect */ > +#define TYPE_SHARED(NODE) (TYPE_CHECK (NODE)->base.u.bits.shared_flag) > + > +/* If nonzero, this type is `strict'-qualified, in the UPC dialect */ > +#define TYPE_STRICT(NODE) (TYPE_CHECK (NODE)->base.u.bits.strict_flag) > + > +/* If nonzero, this type is `relaxed'-qualified, in the UPC dialect */ > +#define TYPE_RELAXED(NODE) \ > + (TYPE_CHECK (NODE)->base.u.bits.relaxed_flag) > + > +/* Record that we are processing a UPC shared array declaration > + or type definition that refers to THREADS in its array dimension.*/ > +#define TYPE_HAS_THREADS_FACTOR(NODE) \ > + (TYPE_CHECK (NODE)->base.u.bits.threads_factor_flag) > + > /* If nonzero, type's name shouldn't be emitted into debug info. */ > #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.u.bits.nameless_flag) > > @@ -1911,13 +1957,24 @@ extern machine_mode element_mode (const_ > | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \ > | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \ > | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \ > + | (TYPE_SHARED (NODE) * TYPE_QUAL_SHARED) \ > + | (TYPE_STRICT (NODE) * TYPE_QUAL_STRICT) \ > + | (TYPE_RELAXED (NODE) * TYPE_QUAL_RELAXED) \ > | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE))))) > > +/* The set of qualifiers pertinent to a FUNCTION_DECL node. */ > +#define TREE_FUNC_QUALS(NODE) \ > + ((TREE_READONLY (NODE) * TYPE_QUAL_CONST) \ > + | (TREE_THIS_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)) > + > /* The same as TYPE_QUALS without the address space qualifications. */ > #define TYPE_QUALS_NO_ADDR_SPACE(NODE) \ > ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \ > | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \ > | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \ > + | (TYPE_SHARED (NODE) * TYPE_QUAL_SHARED) \ > + | (TYPE_STRICT (NODE) * TYPE_QUAL_STRICT) \ > + | (TYPE_RELAXED (NODE) * TYPE_QUAL_RELAXED) \ > | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))) > > /* The same as TYPE_QUALS without the address space and atomic > @@ -1925,8 +1982,72 @@ extern machine_mode element_mode (const_ > #define TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC(NODE) \ > ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \ > | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \ > + | (TYPE_SHARED (NODE) * TYPE_QUAL_SHARED) \ > + | (TYPE_STRICT (NODE) * TYPE_QUAL_STRICT) \ > + | (TYPE_RELAXED (NODE) * TYPE_QUAL_RELAXED) \ > | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))) > > +/* Non-zero if the blocking factor is 0. */ > +#define TYPE_HAS_BLOCK_FACTOR_0(NODE) \ > + TYPE_CHECK (NODE)->base.u.bits.block_factor_0 > + > +/* Non-zero if the blocking factor is greater than 1. > + In this case, the blocking factor value is stored in a hash table. */ > +#define TYPE_HAS_BLOCK_FACTOR_X(NODE) \ > + TYPE_CHECK (NODE)->base.u.bits.block_factor_x > + > +/* Non-zero if the blocking factor is not equal to 1 (the default). */ > +#define TYPE_HAS_BLOCK_FACTOR(NODE) \ > + (TYPE_SHARED(NODE) \ > + && (TYPE_HAS_BLOCK_FACTOR_0 (NODE) \ > + || TYPE_HAS_BLOCK_FACTOR_X (NODE))) > + > +/* Return the blocking factor of the type given by NODE.. > + The default block factor is one. The additional flag bits > + over-ride the default. */ > +#define TYPE_BLOCK_FACTOR(NODE) \ > + (TYPE_SHARED (NODE) \ > + ? (TYPE_HAS_BLOCK_FACTOR_0 (NODE) ? size_zero_node \ > + : TYPE_HAS_BLOCK_FACTOR_X (NODE) ? block_factor_lookup (NODE) \ > + : NULL_TREE) \ > + : NULL_TREE) > + > +/* Set the block factor in the type described by NODE. > + For a zero blocking factor set TYPE_BLOCK_FACTOR_0 (NODE). > + For a blocking factor greater than 1, insert the value > + into a hash table indexed by NODE, and then set the > + flag TYPE_BLOCK_FACTOR_X (NODE). */ > +#define SET_TYPE_BLOCK_FACTOR(NODE, VAL) \ > + do { \ > + if (TYPE_SHARED (NODE)) \ > + { \ > + TYPE_HAS_BLOCK_FACTOR_0 (NODE) = 0; \ > + TYPE_HAS_BLOCK_FACTOR_X (NODE) = 0; \ > + if (VAL) \ > + { \ > + gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (VAL))); \ > + if (!integer_onep (VAL)) \ > + { \ > + if (integer_zerop (VAL)) \ > + TYPE_HAS_BLOCK_FACTOR_0 (NODE) = 1; \ > + else \ > + { \ > + TYPE_HAS_BLOCK_FACTOR_X (NODE) = 1; \ > + block_factor_insert (NODE, VAL); \ > + } \ > + } \ > + } \ > + } \ > + else \ > + gcc_assert (!VAL); \ > + } while (0) > + Use a function please. No such unwiedlingly large macros. > +extern void block_factor_insert (tree, tree); > +extern tree block_factor_lookup (const_tree); > +extern tree build_unshared_type (tree); > +extern void block_factor_lookup_init (void); > +extern tree get_block_factor (const tree); > + > /* These flags are available for each language front end to use internally. > */ > #define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0) > #define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_1) > @@ -2176,7 +2297,7 @@ extern machine_mode element_mode (const_ > /* Nonzero if DECL represents an SSA name or a variable that can possibly > have an associated SSA name. */ > #define SSA_VAR_P(DECL) > \ > - (TREE_CODE (DECL) == VAR_DECL \ > + ((TREE_CODE (DECL) == VAR_DECL && !TREE_SHARED (DECL)) \ > || TREE_CODE (DECL) == PARM_DECL \ > || TREE_CODE (DECL) == RESULT_DECL \ > || TREE_CODE (DECL) == SSA_NAME) > @@ -3611,6 +3732,17 @@ tree_operand_check_code (const_tree __t, > #define boolean_false_node global_trees[TI_BOOLEAN_FALSE] > #define boolean_true_node global_trees[TI_BOOLEAN_TRUE] > > +/* The UPC type `void *'. */ > +#define upc_pts_type_node global_trees[TI_UPC_PTS_TYPE] > + > +/* UPC pointer to shared qualified object representation */ > +#define upc_pts_rep_type_node global_trees[TI_UPC_PTS_REP_TYPE] > +#define upc_char_pts_type_node global_trees[TI_UPC_CHAR_PTS_TYPE] > +#define upc_phase_field_node global_trees[TI_UPC_PHASE_FIELD] > +#define upc_thread_field_node global_trees[TI_UPC_THREAD_FIELD] > +#define upc_vaddr_field_node global_trees[TI_UPC_VADDR_FIELD] > +#define upc_null_pts_node global_trees[TI_UPC_NULL_PTS] > + Ugh. Please no further global tree nodes. Do you really need all of them in middle-end code? Richard. > /* The decimal floating point types. */ > #define dfloat32_type_node global_trees[TI_DFLOAT32_TYPE] > #define dfloat64_type_node global_trees[TI_DFLOAT64_TYPE] > @@ -4151,20 +4283,25 @@ extern tree handle_dll_attribute (tree * > extern bool check_base_type (const_tree cand, const_tree base); > > /* Check whether CAND is suitable to be returned from get_qualified_type > - (BASE, TYPE_QUALS). */ > + (BASE, TYPE_QUALS, BLOCK_FACTOR). */ > > -extern bool check_qualified_type (const_tree, const_tree, int); > +extern bool check_qualified_type (const_tree cand, const_tree base, > + int type_quals, tree block_factor); > > /* Return a version of the TYPE, qualified as indicated by the > - TYPE_QUALS, if one exists. If no qualified version exists yet, > - return NULL_TREE. */ > + TYPE_QUALS and BLOCK_FACTOR, if one exists. > + If no qualified version exists yet, return NULL_TREE. */ > > -extern tree get_qualified_type (tree, int); > +extern tree get_qualified_type_1 (tree type, int type_quals, tree > block_factor); > +#define get_qualified_type(TYPE, QUALS) \ > + get_qualified_type_1 (TYPE, QUALS, 0) > > /* Like get_qualified_type, but creates the type if it does not > exist. This function never returns NULL_TREE. */ > > -extern tree build_qualified_type (tree, int); > +extern tree build_qualified_type_1 (tree type, int type_quals, tree > block_factor); > +#define build_qualified_type(TYPE, QUALS) \ > + build_qualified_type_1 (TYPE, QUALS, 0) > > /* Create a variant of type T with alignment ALIGN. */ > > @@ -4195,6 +4332,7 @@ extern tree type_hash_canon (unsigned in > extern tree convert (tree, tree); > extern unsigned int expr_align (const_tree); > extern tree size_in_bytes (const_tree); > +extern tree tree_expr_size (const_tree); > extern HOST_WIDE_INT int_size_in_bytes (const_tree); > extern HOST_WIDE_INT max_int_size_in_bytes (const_tree); > extern tree bit_position (const_tree); >