diff mbox

[HSA] Implementation of various omp_* function

Message ID 56586B6B.3030203@suse.cz
State New
Headers show

Commit Message

Martin Liška Nov. 27, 2015, 2:40 p.m. UTC
Hello.

Following pair of patches implements missing omp function.

Installed to the HSA branch.
Thanks,
Martin
diff mbox

Patch

From d44e7fa95b57574fade387a8094e1b733221f8b5 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 26 Nov 2015 10:59:52 +0100
Subject: [PATCH 2/5] HSA: implement various omp_* functions.

gcc/ChangeLog:

2015-11-26  Martin Liska  <mliska@suse.cz>

	* hsa-gen.c (hsa_init_simple_builtins): New function.
	(hsa_deinit_data_for_cfun): Release memory of
	omp_simple_builtins.
	(gen_get_num_teams): Change comment message.
	(gen_get_team_num): Likewise.
	(gen_get_max_threads): Dtto.
	(omp_simple_builtin::generate): New method.
	(gen_hsa_insns_for_known_library_call): Handle new set
	of OMP functions.
	* hsa.h (class simple_omp_builtin): New class.
---
 gcc/hsa-gen.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 gcc/hsa.h     |  32 +++++++++-
 2 files changed, 197 insertions(+), 26 deletions(-)

diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 5993ed5..ed47b35 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -306,6 +306,76 @@  hsa_function_representation::create_hsa_temporary (BrigType16_t type)
   return s;
 }
 
+/* Hash map of simple OMP builtins.  */
+static hash_map <nofree_string_hash, omp_simple_builtin> *omp_simple_builtins
+  = NULL;
+
+/* Warning messages for OMP builtins.  */
+
+#define HSA_WARN_LOCK_ROUTINE "support for HSA does not implement OMP lock " \
+  "routine"
+#define HSA_WARN_TIMING_ROUTINE "support for HSA does not implement OMP " \
+  "timing routine"
+#define HSA_WARN_MEMORY_ROUTINE "support for HSA does not implement OMP " \
+  "device memory routine"
+
+/* Initialize hash map with simple OMP builtins.  */
+
+static void
+hsa_init_simple_builtins ()
+{
+  if (omp_simple_builtins != NULL)
+    return;
+
+  omp_simple_builtins = new hash_map <nofree_string_hash, omp_simple_builtin>
+    ();
+
+  omp_simple_builtin omp_builtins[] =
+    {
+      omp_simple_builtin
+	("omp_get_initial_device", NULL, false,
+	 new hsa_op_immed (GOMP_DEVICE_HOST, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin ("omp_is_initial_device", NULL, false,
+			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin ("omp_get_dynamic", NULL, false,
+			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin ("omp_set_dynamic", NULL, false, NULL),
+      omp_simple_builtin ("omp_init_lock", HSA_WARN_LOCK_ROUTINE, true),
+      omp_simple_builtin ("omp_init_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
+			  true),
+      omp_simple_builtin ("omp_init_nest_lock_with_hint", HSA_WARN_LOCK_ROUTINE,
+			  true),
+      omp_simple_builtin ("omp_destroy_lock", HSA_WARN_LOCK_ROUTINE, true),
+      omp_simple_builtin ("omp_set_lock", HSA_WARN_LOCK_ROUTINE, true),
+      omp_simple_builtin ("omp_unset_lock", HSA_WARN_LOCK_ROUTINE, true),
+      omp_simple_builtin ("omp_test_lock", HSA_WARN_LOCK_ROUTINE, true),
+      omp_simple_builtin ("omp_get_wtime", HSA_WARN_TIMING_ROUTINE, true),
+      omp_simple_builtin ("omp_get_wtick", HSA_WARN_TIMING_ROUTINE, true),
+      omp_simple_builtin ("omp_target_alloc", HSA_WARN_MEMORY_ROUTINE, false,
+			  new hsa_op_immed (0, (BrigType16_t) BRIG_TYPE_U64)),
+      omp_simple_builtin ("omp_target_free", HSA_WARN_MEMORY_ROUTINE, false),
+      omp_simple_builtin
+	("omp_target_is_present", HSA_WARN_MEMORY_ROUTINE,
+	 false, new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin ("omp_target_memcpy", HSA_WARN_MEMORY_ROUTINE, false,
+			  new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin
+	("omp_target_memcpy_rect", HSA_WARN_MEMORY_ROUTINE,
+	 false, new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin
+	("omp_target_associate_ptr", HSA_WARN_MEMORY_ROUTINE, false,
+	 new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S64)),
+      omp_simple_builtin
+	("omp_target_disassociate_ptr", HSA_WARN_MEMORY_ROUTINE,
+	 false, new hsa_op_immed (-1, (BrigType16_t) BRIG_TYPE_S64))
+    };
+
+  unsigned count = sizeof (omp_builtins) / sizeof (omp_simple_builtin);
+
+  for (unsigned i = 0; i < count; i++)
+    omp_simple_builtins->put (omp_builtins[i].m_name, omp_builtins[i]);
+}
+
 /* Allocate HSA structures that we need only while generating with this.  */
 
 static void
@@ -382,6 +452,12 @@  hsa_deinit_data_for_cfun (void)
 
   hsa_instructions.release ();
 
+  if (omp_simple_builtins != NULL)
+    {
+      delete omp_simple_builtins;
+      omp_simple_builtins = NULL;
+    }
+
   delete hsa_allocp_operand_address;
   delete hsa_allocp_operand_immed;
   delete hsa_allocp_operand_reg;
@@ -908,7 +984,7 @@  hsa_op_immed::hsa_op_immed (tree tree_val, bool min32int)
 /* Constructor of class representing HSA immediate values.  INTEGER_VALUE is the
    integer representation of the immediate value.  TYPE is BRIG type.  */
 
-hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigKind16_t type)
+hsa_op_immed::hsa_op_immed (HOST_WIDE_INT integer_value, BrigType16_t type)
   : hsa_op_with_type (BRIG_KIND_OPERAND_CONSTANT_BYTES, type),
   m_tree_value (NULL), m_brig_repr (NULL)
 {
@@ -3559,8 +3635,7 @@  gen_get_num_teams (gimple *stmt, hsa_bb *hbb)
   if (gimple_call_lhs (stmt) == NULL_TREE)
     return;
 
-  hbb->append_insn
-    (new hsa_insn_comment ("__builtin_omp_get_num_teams"));
+  hbb->append_insn (new hsa_insn_comment ("omp_get_num_teams"));
 
   tree lhs = gimple_call_lhs (stmt);
   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
@@ -3581,8 +3656,7 @@  gen_get_team_num (gimple *stmt, hsa_bb *hbb)
   if (gimple_call_lhs (stmt) == NULL_TREE)
     return;
 
-  hbb->append_insn
-    (new hsa_insn_comment ("__builtin_omp_get_team_num"));
+  hbb->append_insn (new hsa_insn_comment ("omp_get_team_num"));
 
   tree lhs = gimple_call_lhs (stmt);
   hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
@@ -3626,6 +3700,23 @@  gen_get_level (gimple *stmt, hsa_bb *hbb)
   mem->set_output_in_type (dest, 0, hbb);
 }
 
+/* Emit instruction that implement omp_get_max_threads of gimple STMT.  */
+
+static void
+gen_get_max_threads (gimple *stmt, hsa_bb *hbb)
+{
+  tree lhs = gimple_call_lhs (stmt);
+  if (!lhs)
+    return;
+
+  hbb->append_insn (new hsa_insn_comment ("omp_get_max_threads"));
+
+  hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
+  hsa_op_with_type *num_theads_reg = gen_num_threads_for_dispatch (hbb)
+    ->get_in_type (dest->m_type, hbb);
+  hsa_build_append_simple_mov (dest, num_theads_reg, hbb);
+}
+
 /* Emit instructions that implement alloca builtin gimple STMT.
    Instructions are appended to basic block HBB.  */
 
@@ -3690,6 +3781,35 @@  set_debug_value (hsa_bb *hbb, hsa_op_with_type *value)
   hbb->append_insn (mem);
 }
 
+void
+omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
+{
+  if (m_sorry)
+    {
+      if (m_warning_message)
+	HSA_SORRY_AT (gimple_location (stmt), m_warning_message)
+      else
+	HSA_SORRY_ATV (gimple_location (stmt),
+		       "Support for HSA does not implement calls to %s\n",
+		       m_name)
+    }
+  else if (m_warning_message != NULL)
+    warning_at (gimple_location (stmt), OPT_Whsa, m_warning_message);
+
+  if (m_return_value != NULL)
+    {
+      tree lhs = gimple_call_lhs (stmt);
+      if (!lhs)
+	return;
+
+      hbb->append_insn (new hsa_insn_comment (m_name));
+
+      hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
+      hsa_build_append_simple_mov
+	(dest, m_return_value->get_in_type (dest->m_type, hbb), hbb);
+    }
+}
+
 /* If STMT is a call of a known library function, generate code to perform
    it and return true.  */
 
@@ -3698,30 +3818,51 @@  gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
 {
   const char *name = hsa_get_declaration_name (gimple_call_fndecl (stmt));
 
-  if (strcmp (name, "omp_is_initial_device") == 0)
+  /* Handle omp_* routines.  */
+  if (strstr (name, "omp_") == name)
     {
-      tree lhs = gimple_call_lhs (stmt);
-      if (!lhs)
-	return true;
+      hsa_init_simple_builtins ();
+      omp_simple_builtin *builtin = omp_simple_builtins->get (name);
+      if (builtin)
+	{
+	  builtin->generate (stmt, hbb);
+	  return true;
+	}
 
-      hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
-      hsa_op_immed *imm = new hsa_op_immed (build_zero_cst (TREE_TYPE (lhs)));
+      bool handled = true;
 
-      hsa_build_append_simple_mov (dest, imm, hbb);
+      if (strcmp (name, "omp_set_num_threads") == 0)
+	gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
+      else if (strcmp (name, "omp_get_thread_num") == 0)
+	{
+	  hbb->append_insn (new hsa_insn_comment (name));
+	  query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
+	}
+      else if (strcmp (name, "omp_get_num_threads") == 0)
+	{
+	  hbb->append_insn (new hsa_insn_comment (name));
+	  query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
+	}
+      else if (strcmp (name, "omp_get_num_teams") == 0)
+	gen_get_num_teams (stmt, hbb);
+      else if (strcmp (name, "omp_get_team_num") == 0)
+	gen_get_team_num (stmt, hbb);
+      else if (strcmp (name, "omp_get_level") == 0)
+	gen_get_level (stmt, hbb);
+      else if (strcmp (name, "omp_get_active_level") == 0)
+	gen_get_level (stmt, hbb);
+      else if (strcmp (name, "omp_in_parallel") == 0)
+	gen_get_level (stmt, hbb);
+      else if (strcmp (name, "omp_get_max_threads") == 0)
+	gen_get_max_threads (stmt, hbb);
+      else
+	handled = false;
+
+      if (handled)
+	return true;
     }
-  else if (strcmp (name, "omp_set_num_threads") == 0)
-    gen_set_num_threads (gimple_call_arg (stmt, 0), hbb);
-  else if (strcmp (name, "omp_get_thread_num") == 0)
-    query_hsa_grid (stmt, BRIG_OPCODE_WORKITEMABSID, 0, hbb);
-  else if (strcmp (name, "omp_get_num_threads") == 0)
-    query_hsa_grid (stmt, BRIG_OPCODE_GRIDSIZE, 0, hbb);
-  else if (strcmp (name, "omp_get_num_teams") == 0)
-    gen_get_num_teams (stmt, hbb);
-  else if (strcmp (name, "omp_get_team_num") == 0)
-    gen_get_team_num (stmt, hbb);
-  else if (strcmp (name, "omp_get_level") == 0)
-    gen_get_level (stmt, hbb);
-  else if (strcmp (name, "hsa_set_debug_value") == 0)
+
+  if (strcmp (name, "__hsa_set_debug_value") == 0)
     {
       if (hsa_cfun->has_shadow_reg_p ())
 	{
diff --git a/gcc/hsa.h b/gcc/hsa.h
index a59a725..e4bea99 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -163,7 +163,7 @@  class hsa_op_immed : public hsa_op_with_type
 {
 public:
   hsa_op_immed (tree tree_val, bool min32int = true);
-  hsa_op_immed (HOST_WIDE_INT int_value, BrigKind16_t type);
+  hsa_op_immed (HOST_WIDE_INT int_value, BrigType16_t type);
   void *operator new (size_t);
   ~hsa_op_immed ();
   void set_type (BrigKind16_t t);
@@ -1178,6 +1178,36 @@  public:
 		       hsa_function_kind kind, bool gridified_kernel_p);
 };
 
+/* OMP simple builtin describes behavior that should be done for
+   the routine.  */
+class omp_simple_builtin
+{
+public:
+  omp_simple_builtin (const char *name, const char *warning_message,
+	       bool sorry, hsa_op_immed *return_value = NULL):
+    m_name (name), m_warning_message (warning_message), m_sorry (sorry),
+    m_return_value (return_value)
+  {}
+
+  /* Generate HSAIL instructions for the builtin or produce warning message.  */
+  void generate (gimple *stmt, hsa_bb *hbb);
+
+  /* Name of function.  */
+  const char *m_name;
+
+  /* Warning message.  */
+  const char *m_warning_message;
+
+  /* Flag if we should sorry after the warning message is printed.  */
+  bool m_sorry;
+
+  /* Return value of the function.  */
+  hsa_op_immed *m_return_value;
+
+  /* Emission function.  */
+  void (*m_emit_func) (gimple *stmt, hsa_bb *);
+};
+
 /* in hsa.c */
 extern struct hsa_function_representation *hsa_cfun;
 extern hash_map <tree, vec <const char *> *> *hsa_decl_kernel_dependencies;
-- 
2.6.3