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 <[email protected]>
>
> 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 <[email protected]>.
> (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);
>