Hi,

the HSA/BRIG back-end does not have any support for CONST_DECSs so far.
This patch adds it, emitting readonly segment symbols with initializers
for them.  One complication is that addresses pertaining to HSA readonly
segment cannot be converted to flat addresses.  So when we need an
address of a CONST_DECL, we take an address of a normal private symbol
instead.

Will commit to the HSA branch now and queue for trunk.

Martin

2016-08-08  Martin Jambor  <mjam...@suse.cz>

        * hsa-gen.c (get_symbol_for_decl): Accept CONST_DECLs, put them to
        readonly segment.
        (gen_hsa_addr): Also process CONST_DECLs.
        (gen_hsa_addr_insns): Process CONST_DECLs by creating private
        copies.

        * hsa-brig.c (emit_immediate_operand): Declare.
        (emit_directive_variable): Also emit initializers of CONST_DECLs.
---
 gcc/hsa-brig.c | 10 +++++++++-
 gcc/hsa-gen.c  | 53 +++++++++++++++++++++++++++++++++++++++++++++--------
 gcc/hsa.h      |  3 ++-
 3 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index 6128c4b..237069e 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -570,6 +570,7 @@ enqueue_op (hsa_op_base *op)
   return ret;
 }
 
+static void emit_immediate_operand (hsa_op_immed *imm);
 
 /* Emit directive describing a symbol if it has not been emitted already.
    Return the offset of the directive.  */
@@ -608,7 +609,14 @@ emit_directive_variable (struct hsa_symbol *symbol)
     }
 
   dirvar.name = lendian32 (name_offset);
-  dirvar.init = 0;
+
+  if (symbol->m_decl && TREE_CODE (symbol->m_decl) == CONST_DECL)
+    {
+      hsa_op_immed *tmp = new hsa_op_immed (DECL_INITIAL (symbol->m_decl));
+      dirvar.init = lendian32 (enqueue_op (tmp));
+    }
+  else
+    dirvar.init = 0;
   dirvar.type = lendian16 (symbol->m_type);
   dirvar.segment = symbol->m_segment;
   dirvar.align = symbol->m_align;
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index a9f4a8f..baa20b9 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -820,7 +820,8 @@ get_symbol_for_decl (tree decl)
 
   gcc_assert (TREE_CODE (decl) == PARM_DECL
              || TREE_CODE (decl) == RESULT_DECL
-             || TREE_CODE (decl) == VAR_DECL);
+             || TREE_CODE (decl) == VAR_DECL
+             || TREE_CODE (decl) == CONST_DECL);
 
   dummy.m_decl = decl;
 
@@ -862,11 +863,14 @@ get_symbol_for_decl (tree decl)
   else
     {
       hsa_symbol *sym;
-      gcc_assert (TREE_CODE (decl) == VAR_DECL);
+      /* PARM_DECLs and RESULT_DECL should be already in m_local_symbols.  */
+      gcc_assert (TREE_CODE (decl) == VAR_DECL
+                 || TREE_CODE (decl) == CONST_DECL);
       BrigAlignment8_t align = hsa_object_alignment (decl);
 
       if (is_in_global_vars)
        {
+         gcc_checking_assert (TREE_CODE (decl) != CONST_DECL);
          sym = new hsa_symbol (BRIG_TYPE_NONE, BRIG_SEGMENT_GLOBAL,
                                BRIG_LINKAGE_PROGRAM, true,
                                BRIG_ALLOCATION_PROGRAM, align);
@@ -888,11 +892,15 @@ get_symbol_for_decl (tree decl)
          if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
            align = MAX ((BrigAlignment8_t) BRIG_ALIGNMENT_8, align);
 
-         /* PARM_DECL and RESULT_DECL should be already in m_local_symbols.  */
-         gcc_assert (TREE_CODE (decl) == VAR_DECL);
-
+         BrigAllocation allocation = BRIG_ALLOCATION_AUTOMATIC;
          BrigSegment8_t segment;
-         if (lookup_attribute ("hsa_group_segment", DECL_ATTRIBUTES (decl)))
+         if (TREE_CODE (decl) == CONST_DECL)
+           {
+             segment = BRIG_SEGMENT_READONLY;
+             allocation = BRIG_ALLOCATION_AGENT;
+           }
+         else if (lookup_attribute ("hsa_group_segment",
+                                    DECL_ATTRIBUTES (decl)))
            segment = BRIG_SEGMENT_GROUP;
          else if (TREE_STATIC (decl)
                   || lookup_attribute ("hsa_global_segment",
@@ -901,8 +909,8 @@ get_symbol_for_decl (tree decl)
          else
            segment = BRIG_SEGMENT_PRIVATE;
 
-         sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION);
-         sym->m_align = align;
+         sym = new hsa_symbol (BRIG_TYPE_NONE, segment, BRIG_LINKAGE_FUNCTION,
+                               false, allocation, align);
          sym->fillup_for_decl (decl);
          hsa_cfun->m_private_variables.safe_push (sym);
        }
@@ -1944,6 +1952,7 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT 
*output_bitsize = NULL,
     case PARM_DECL:
     case VAR_DECL:
     case RESULT_DECL:
+    case CONST_DECL:
       gcc_assert (!symbol);
       symbol = get_symbol_for_decl (ref);
       addrtype = hsa_get_segment_addr_type (symbol->m_segment);
@@ -2161,6 +2170,34 @@ gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb 
*hbb)
     val = TREE_OPERAND (val, 0);
   addr = gen_hsa_addr (val, hbb);
 
+  if (TREE_CODE (val) == CONST_DECL
+      && is_gimple_reg_type (TREE_TYPE (val)))
+    {
+      gcc_assert (addr->m_symbol
+                 && addr->m_symbol->m_segment == BRIG_SEGMENT_READONLY);
+      /* CONST_DECLs are in readonly segment which however does not have
+        addresses convertible to flat segments.  So copy it to a private one
+        and take address of that.  */
+      BrigType16_t csttype
+       = mem_type_for_type (hsa_type_for_scalar_tree_type (TREE_TYPE (val),
+                                                           false));
+      hsa_op_reg *r = new hsa_op_reg (csttype);
+      hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_LD, csttype, r,
+                                         new hsa_op_address (addr->m_symbol)));
+      hsa_symbol *copysym = hsa_cfun->create_hsa_temporary (csttype);
+      hbb->append_insn (new hsa_insn_mem (BRIG_OPCODE_ST, csttype, r,
+                                         new hsa_op_address (copysym)));
+      addr->m_symbol = copysym;
+    }
+  else if (addr->m_symbol && addr->m_symbol->m_segment == 
BRIG_SEGMENT_READONLY)
+    {
+      HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
+                    "not implement taking addresses of complex "
+                    "CONST_DECLs such as %E", val);
+      return;
+    }
+
+
   convert_addr_to_flat_segment (addr, dest, hbb);
 }
 
diff --git a/gcc/hsa.h b/gcc/hsa.h
index 588c85a..c00ffd5 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -71,7 +71,8 @@ struct hsa_symbol
   void fillup_for_decl (tree decl);
 
   /* Pointer to the original tree, which is PARM_DECL for input parameters and
-     RESULT_DECL for the output parameters.  */
+     RESULT_DECL for the output parameters.  Also can be CONST_DECL for Fortran
+     constants which need to be put into readonly segment.  */
   tree m_decl;
 
   /* Name of the symbol, that will be written into output and dumps.  Can be
-- 
2.9.2

Reply via email to