This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[HSA] Implementation of various omp_* function
- From: Martin LiÅka <mliska at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 27 Nov 2015 15:40:43 +0100
- Subject: [HSA] Implementation of various omp_* function
- Authentication-results: sourceware.org; auth=none
Hello.
Following pair of patches implements missing omp function.
Installed to the HSA branch.
Thanks,
Martin
>From 90cb91ca75ce29e560184fbd1ca03a7e58fc6685 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 26 Nov 2015 10:18:44 +0100
Subject: [PATCH 1/5] HSA: implement omp_get_level
libgomp/ChangeLog:
2015-11-26 Martin Liska <mliska@suse.cz>
* plugin/plugin-hsa.c (struct hsa_kernel_description):
Add field gridified_kernel_p.
(struct kernel_info): Likewise.
(GOMP_OFFLOAD_load_image): Fill-up the field.
(init_single_kernel): Dump value of the field.
(create_kernel_dispatch): Set-up omp_level for kernel
packet dispatch structure.
gcc/ChangeLog:
2015-11-26 Martin Liska <mliska@suse.cz>
* hsa-brig.c (hsa_output_kernels): Append gridified_kernel_p
to kernel_info structure.
* hsa-gen.c (gen_get_level): Generate call of the builtin.
(gen_hsa_insns_for_known_library_call): Call the aforementioned
function.
(generate_hsa):Output gridified_kernel_p from HSA summary.
* hsa.c (struct hsa_decl_kernel_map_element): Add
gridified_kernel_p field.
(hsa_add_kern_decl_mapping): Add argument for the field.
(hsa_get_decl_kernel_mapping_gridified): New function.
(hsa_summary_t::link_functions): Add new argument for
gridified_kernel_p.
(hsa_register_kernel): Mark gridified kernel within HSA summary.
* hsa.h (struct hsa_function_summary): Declare new field
in HSA summary.
* ipa-hsa.c (process_hsa_functions): Use modified signature of
link_functions.
include/ChangeLog:
2015-11-26 Martin Liska <mliska@suse.cz>
* gomp-constants.h (struct GOMP_hsa_kernel_dispatch): Declare
new field in kernel dispatch structure.
---
gcc/hsa-brig.c | 27 ++++++++++++++++++---------
gcc/hsa-gen.c | 39 ++++++++++++++++++++++++++++++++++++++-
gcc/hsa.c | 25 ++++++++++++++++++-------
gcc/hsa.h | 11 ++++++++---
gcc/ipa-hsa.c | 4 ++--
include/gomp-constants.h | 2 ++
libgomp/plugin/plugin-hsa.c | 7 +++++++
7 files changed, 93 insertions(+), 22 deletions(-)
diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index ca30598..9f65d50 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -1982,15 +1982,19 @@ hsa_output_kernels (tree *host_func_table, tree *kernels)
unsigned_type_node);
DECL_CHAIN (id_f2) = id_f1;
tree id_f3 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
- get_identifier ("kernel_dependencies_count"),
- unsigned_type_node);
+ get_identifier ("gridified_kernel_p"),
+ boolean_type_node);
DECL_CHAIN (id_f3) = id_f2;
tree id_f4 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ get_identifier ("kernel_dependencies_count"),
+ unsigned_type_node);
+ DECL_CHAIN (id_f4) = id_f3;
+ tree id_f5 = build_decl (BUILTINS_LOCATION, FIELD_DECL,
get_identifier ("kernel_dependencies"),
build_pointer_type (build_pointer_type
(char_type_node)));
- DECL_CHAIN (id_f4) = id_f3;
- finish_builtin_struct (kernel_info_type, "__hsa_kernel_info", id_f4,
+ DECL_CHAIN (id_f5) = id_f4;
+ finish_builtin_struct (kernel_info_type, "__hsa_kernel_info", id_f5,
NULL_TREE);
int_num_of_kernels = build_int_cstu (uint32_type_node, map_count);
@@ -2018,7 +2022,10 @@ hsa_output_kernels (tree *host_func_table, tree *kernels)
free (copy);
unsigned omp_size = hsa_get_decl_kernel_mapping_omp_size (i);
- tree omp_data_size = build_int_cstu (uint32_type_node, omp_size);
+ tree omp_data_size = build_int_cstu (unsigned_type_node, omp_size);
+ bool gridified_kernel_p = hsa_get_decl_kernel_mapping_gridified (i);
+ tree gridified_kernel_p_tree = build_int_cstu (boolean_type_node,
+ gridified_kernel_p);
unsigned count = 0;
kernel_dependencies_vector_type = build_array_type
@@ -2057,7 +2064,7 @@ hsa_output_kernels (tree *host_func_table, tree *kernels)
}
}
- tree dependencies_count = build_int_cstu (uint32_type_node, count);
+ tree dependencies_count = build_int_cstu (unsigned_type_node, count);
vec<constructor_elt, va_gc> *kernel_info_vec = NULL;
CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
@@ -2066,11 +2073,10 @@ hsa_output_kernels (tree *host_func_table, tree *kernels)
(kern_name)),
kern_name));
CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, omp_data_size);
+ CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE,
+ gridified_kernel_p_tree);
CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, dependencies_count);
- tree kernel_info_ctor = build_constructor (kernel_info_type,
- kernel_info_vec);
-
if (count > 0)
{
ASM_GENERATE_INTERNAL_LABEL (tmp_name, "__hsa_dependencies_list", i);
@@ -2098,6 +2104,9 @@ hsa_output_kernels (tree *host_func_table, tree *kernels)
else
CONSTRUCTOR_APPEND_ELT (kernel_info_vec, NULL_TREE, null_pointer_node);
+ tree kernel_info_ctor = build_constructor (kernel_info_type,
+ kernel_info_vec);
+
CONSTRUCTOR_APPEND_ELT (kernel_info_vector_vec, NULL_TREE,
kernel_info_ctor);
}
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index 0df1eb6..5993ed5 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -3594,6 +3594,38 @@ gen_get_team_num (gimple *stmt, hsa_bb *hbb)
hbb->append_insn (basic);
}
+/* Emit instructions that get levels-var ICV to lhs of gimple STMT.
+ Instructions are appended to basic block HBB. */
+
+static void
+gen_get_level (gimple *stmt, hsa_bb *hbb)
+{
+ if (gimple_call_lhs (stmt) == NULL_TREE)
+ return;
+
+ hbb->append_insn (new hsa_insn_comment ("omp_get_level"));
+
+ tree lhs = gimple_call_lhs (stmt);
+ hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
+
+ hsa_op_reg *shadow_reg_ptr = hsa_cfun->get_shadow_reg ();
+ if (shadow_reg_ptr == NULL)
+ {
+ HSA_SORRY_AT (gimple_location (stmt),
+ "support for HSA does not implement omp_get_level called "
+ "from a function not being inlined within a kernel");
+ return;
+ }
+
+ hsa_op_address *addr = new hsa_op_address
+ (shadow_reg_ptr, offsetof (GOMP_hsa_kernel_dispatch, omp_level));
+
+ hsa_insn_mem *mem = new hsa_insn_mem (BRIG_OPCODE_LD, BRIG_TYPE_U64, NULL,
+ addr);
+ hbb->append_insn (mem);
+ mem->set_output_in_type (dest, 0, hbb);
+}
+
/* Emit instructions that implement alloca builtin gimple STMT.
Instructions are appended to basic block HBB. */
@@ -3687,6 +3719,8 @@ gen_hsa_insns_for_known_library_call (gimple *stmt, hsa_bb *hbb)
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 (hsa_cfun->has_shadow_reg_p ())
@@ -5576,8 +5610,11 @@ generate_hsa (bool kernel)
if (hsa_cfun->m_kern_p)
{
+ hsa_function_summary *s = hsa_summaries->get
+ (cgraph_node::get (hsa_cfun->m_decl));
hsa_add_kern_decl_mapping (current_function_decl, hsa_cfun->m_name,
- hsa_cfun->m_maximum_omp_data_size);
+ hsa_cfun->m_maximum_omp_data_size,
+ s->m_gridified_kernel_p);
}
#ifdef ENABLE_CHECKING
diff --git a/gcc/hsa.c b/gcc/hsa.c
index 8ab5da7..7c4e404 100644
--- a/gcc/hsa.c
+++ b/gcc/hsa.c
@@ -52,6 +52,8 @@ struct GTY(()) hsa_decl_kernel_map_element
char * GTY((skip)) name;
/* Size of OMP data, if the kernel contains a kernel dispatch. */
unsigned omp_data_size;
+ /* True if the function is gridified kernel. */
+ bool gridified_kernel_p;
};
/* Mapping between decls and corresponding HSA kernels in this compilation
@@ -584,12 +586,14 @@ hsa_destroy_operand (hsa_op_base *op)
/* Create a mapping between the original function DECL and kernel name NAME. */
void
-hsa_add_kern_decl_mapping (tree decl, char *name, unsigned omp_data_size)
+hsa_add_kern_decl_mapping (tree decl, char *name, unsigned omp_data_size,
+ bool gridified_kernel_p)
{
hsa_decl_kernel_map_element dkm;
dkm.decl = decl;
dkm.name = name;
dkm.omp_data_size = omp_data_size;
+ dkm.gridified_kernel_p = gridified_kernel_p;
vec_safe_push (hsa_decl_kernel_mapping, dkm);
}
@@ -625,6 +629,14 @@ hsa_get_decl_kernel_mapping_omp_size (unsigned i)
return (*hsa_decl_kernel_mapping)[i].omp_data_size;
}
+/* Return if the function is gridified kernel in decl name mapping. */
+
+bool
+hsa_get_decl_kernel_mapping_gridified (unsigned i)
+{
+ return (*hsa_decl_kernel_mapping)[i].gridified_kernel_p;
+}
+
/* Free the mapping between original decls and kernel names. */
void
@@ -708,13 +720,9 @@ hsa_get_declaration_name (tree decl)
return NULL;
}
-/* Couple GPU and HOST as gpu-specific and host-specific implementation of the
- same function. KIND determines whether GPU is a host-invokable kernel or
- gpu-callable function. */
-
void
hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host,
- hsa_function_kind kind)
+ hsa_function_kind kind, bool gridified_kernel_p)
{
hsa_function_summary *gpu_summary = get (gpu);
hsa_function_summary *host_summary = get (host);
@@ -725,6 +733,9 @@ hsa_summary_t::link_functions (cgraph_node *gpu, cgraph_node *host,
gpu_summary->m_gpu_implementation_p = true;
host_summary->m_gpu_implementation_p = false;
+ gpu_summary->m_gridified_kernel_p = gridified_kernel_p;
+ host_summary->m_gridified_kernel_p = gridified_kernel_p;
+
gpu_summary->m_binded_function = host;
host_summary->m_binded_function = gpu;
@@ -761,7 +772,7 @@ hsa_register_kernel (cgraph_node *gpu, cgraph_node *host)
{
if (hsa_summaries == NULL)
hsa_summaries = new hsa_summary_t (symtab);
- hsa_summaries->link_functions (gpu, host, HSA_KERNEL);
+ hsa_summaries->link_functions (gpu, host, HSA_KERNEL, true);
}
/* Return true if expansion of the current HSA function has already failed. */
diff --git a/gcc/hsa.h b/gcc/hsa.h
index dc2202a..a59a725 100644
--- a/gcc/hsa.h
+++ b/gcc/hsa.h
@@ -1151,6 +1151,9 @@ struct hsa_function_summary
/* Identifies if the function is an HSA function or a host function. */
bool m_gpu_implementation_p;
+
+ /* True if the function is a gridified kernel. */
+ bool m_gridified_kernel_p;
};
inline
@@ -1168,10 +1171,11 @@ public:
/* Couple GPU and HOST as gpu-specific and host-specific implementation of
the same function. KIND determines whether GPU is a host-invokable kernel
- or gpu-callable function. */
+ or gpu-callable function and GRIDIFIED_KERNEL_P is set if the function was
+ gridified in OMP. */
void link_functions (cgraph_node *gpu, cgraph_node *host,
- hsa_function_kind kind);
+ hsa_function_kind kind, bool gridified_kernel_p);
};
/* in hsa.c */
@@ -1200,11 +1204,12 @@ BrigAlignment8_t hsa_alignment_encoding (unsigned n);
BrigAlignment8_t hsa_natural_alignment (BrigType16_t type);
void hsa_destroy_operand (hsa_op_base *op);
void hsa_destroy_insn (hsa_insn_basic *insn);
-void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned);
+void hsa_add_kern_decl_mapping (tree decl, char *name, unsigned, bool);
unsigned hsa_get_number_decl_kernel_mappings (void);
tree hsa_get_decl_kernel_mapping_decl (unsigned i);
char *hsa_get_decl_kernel_mapping_name (unsigned i);
unsigned hsa_get_decl_kernel_mapping_omp_size (unsigned i);
+bool hsa_get_decl_kernel_mapping_gridified (unsigned i);
void hsa_free_decl_kernel_mapping (void);
void hsa_add_kernel_dependency (tree caller, const char *called_function);
void hsa_sanitize_name (char *p);
diff --git a/gcc/ipa-hsa.c b/gcc/ipa-hsa.c
index d77fa6b..a497841 100644
--- a/gcc/ipa-hsa.c
+++ b/gcc/ipa-hsa.c
@@ -92,7 +92,7 @@ process_hsa_functions (void)
TREE_PUBLIC (clone->decl) = TREE_PUBLIC (node->decl);
clone->force_output = true;
- hsa_summaries->link_functions (clone, node, s->m_kind);
+ hsa_summaries->link_functions (clone, node, s->m_kind, false);
if (dump_file)
fprintf (dump_file, "Created a new HSA clone: %s, type: %s\n",
@@ -109,7 +109,7 @@ process_hsa_functions (void)
if (!cgraph_local_p (node))
clone->force_output = true;
- hsa_summaries->link_functions (clone, node, HSA_FUNCTION);
+ hsa_summaries->link_functions (clone, node, HSA_FUNCTION, false);
if (dump_file)
fprintf (dump_file, "Created a new HSA function clone: %s\n",
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index b710eb1..1dae474 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -294,6 +294,8 @@ struct GOMP_hsa_kernel_dispatch
uint32_t omp_num_threads;
/* Debug purpose argument. */
uint64_t debug;
+ /* Levels-var ICV. */
+ uint64_t omp_level;
/* Kernel dispatch structures created for children kernel dispatches. */
struct GOMP_hsa_kernel_dispatch **children_dispatches;
};
diff --git a/libgomp/plugin/plugin-hsa.c b/libgomp/plugin/plugin-hsa.c
index 39e2366..b132954 100644
--- a/libgomp/plugin/plugin-hsa.c
+++ b/libgomp/plugin/plugin-hsa.c
@@ -157,6 +157,7 @@ struct hsa_kernel_description
{
const char *name;
unsigned omp_data_size;
+ bool gridified_kernel_p;
unsigned kernel_dependencies_count;
const char **kernel_dependencies;
};
@@ -217,6 +218,8 @@ struct kernel_info
unsigned dependencies_count;
/* Maximum OMP data size necessary for kernel from kernel dispatches. */
unsigned max_omp_data_size;
+ /* True if the kernel is gridified. */
+ bool gridified_kernel_p;
};
/* Information about a particular brig module, its image and kernels. */
@@ -619,6 +622,7 @@ GOMP_OFFLOAD_load_image (int ord, unsigned version, void *target_data,
kernel->module = module;
kernel->name = d->name;
kernel->omp_data_size = d->omp_data_size;
+ kernel->gridified_kernel_p = d->gridified_kernel_p;
kernel->dependencies_count = d->kernel_dependencies_count;
kernel->dependencies = d->kernel_dependencies;
if (pthread_mutex_init (&kernel->init_mutex, NULL))
@@ -916,6 +920,7 @@ init_single_kernel (struct kernel_info *kernel, unsigned *max_omp_data_size)
HSA_DEBUG (" kernarg_segment_size: %u\n",
(unsigned) kernel->kernarg_segment_size);
HSA_DEBUG (" omp_data_size: %u\n", kernel->omp_data_size);
+ HSA_DEBUG (" gridified_kernel_p: %u\n", kernel->gridified_kernel_p);
if (kernel->omp_data_size > *max_omp_data_size)
*max_omp_data_size = kernel->omp_data_size;
@@ -1003,6 +1008,7 @@ create_kernel_dispatch (struct kernel_info *kernel, unsigned omp_data_size)
(kernel, omp_data_size);
shadow->omp_num_threads = 64;
shadow->debug = 0;
+ shadow->omp_level = kernel->gridified_kernel_p ? 1 : 0;
/* Create kernel dispatch data structures. We do not allow to have
a kernel dispatch with depth bigger than one. */
@@ -1014,6 +1020,7 @@ create_kernel_dispatch (struct kernel_info *kernel, unsigned omp_data_size)
(dependency, omp_data_size);
shadow->children_dispatches[i]->queue =
kernel->agent->kernel_dispatch_command_q;
+ shadow->children_dispatches[i]->omp_level = 1;
}
return shadow;
--
2.6.3
>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