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);
> 

Reply via email to