2014-05-06 18:08:46 +08:00
|
|
|
//===----- CGOpenMPRuntime.h - Interface to OpenMP Runtimes -----*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This provides a class for OpenMP runtime code generation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-08-14 00:25:19 +08:00
|
|
|
#ifndef LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
|
|
|
|
#define LLVM_CLANG_LIB_CODEGEN_CGOPENMPRUNTIME_H
|
2014-05-06 18:08:46 +08:00
|
|
|
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
#include "clang/AST/Type.h"
|
2014-12-15 15:07:06 +08:00
|
|
|
#include "clang/Basic/OpenMPKinds.h"
|
2015-01-14 19:29:14 +08:00
|
|
|
#include "clang/Basic/SourceLocation.h"
|
2014-05-06 18:08:46 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2014-11-11 12:05:39 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2014-09-22 18:01:53 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2014-11-11 12:05:39 +08:00
|
|
|
#include "llvm/IR/ValueHandle.h"
|
2014-05-06 18:08:46 +08:00
|
|
|
|
2014-10-10 20:19:54 +08:00
|
|
|
namespace llvm {
|
|
|
|
class ArrayType;
|
|
|
|
class Constant;
|
|
|
|
class Function;
|
|
|
|
class FunctionType;
|
2014-11-11 12:05:39 +08:00
|
|
|
class GlobalVariable;
|
2014-10-10 20:19:54 +08:00
|
|
|
class StructType;
|
|
|
|
class Type;
|
|
|
|
class Value;
|
|
|
|
} // namespace llvm
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2014-10-10 20:19:54 +08:00
|
|
|
namespace clang {
|
2014-11-20 12:34:54 +08:00
|
|
|
class Expr;
|
2014-10-10 20:19:54 +08:00
|
|
|
class OMPExecutableDirective;
|
|
|
|
class VarDecl;
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2014-10-10 20:19:54 +08:00
|
|
|
namespace CodeGen {
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2014-10-10 20:19:54 +08:00
|
|
|
class CodeGenFunction;
|
|
|
|
class CodeGenModule;
|
2014-05-06 18:08:46 +08:00
|
|
|
|
2015-04-10 12:50:10 +08:00
|
|
|
typedef llvm::function_ref<void(CodeGenFunction &)> RegionCodeGenTy;
|
|
|
|
|
2014-05-06 18:08:46 +08:00
|
|
|
class CGOpenMPRuntime {
|
2015-04-10 12:50:10 +08:00
|
|
|
private:
|
2014-05-06 18:08:46 +08:00
|
|
|
enum OpenMPRTLFunction {
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
|
|
|
|
/// kmpc_micro microtask, ...);
|
2014-05-06 18:08:46 +08:00
|
|
|
OMPRTL__kmpc_fork_call,
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc,
|
|
|
|
/// kmp_int32 global_tid, void *data, size_t size, void ***cache);
|
|
|
|
OMPRTL__kmpc_threadprivate_cached,
|
|
|
|
/// \brief Call to void __kmpc_threadprivate_register( ident_t *,
|
|
|
|
/// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
|
|
|
|
OMPRTL__kmpc_threadprivate_register,
|
2014-09-22 18:01:53 +08:00
|
|
|
// Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
|
|
|
|
OMPRTL__kmpc_global_thread_num,
|
2014-09-22 20:32:31 +08:00
|
|
|
// Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_critical_name *crit);
|
2014-09-22 18:01:53 +08:00
|
|
|
OMPRTL__kmpc_critical,
|
2014-09-22 20:32:31 +08:00
|
|
|
// Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_critical_name *crit);
|
2014-10-08 22:01:46 +08:00
|
|
|
OMPRTL__kmpc_end_critical,
|
2014-12-05 12:09:23 +08:00
|
|
|
// Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
|
|
|
|
// global_tid);
|
|
|
|
OMPRTL__kmpc_cancel_barrier,
|
2015-03-13 18:38:23 +08:00
|
|
|
// Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
|
2014-12-15 15:07:06 +08:00
|
|
|
OMPRTL__kmpc_for_static_fini,
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
// Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
|
|
|
|
// global_tid);
|
|
|
|
OMPRTL__kmpc_serialized_parallel,
|
|
|
|
// Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
|
|
|
|
// global_tid);
|
2014-10-13 16:23:51 +08:00
|
|
|
OMPRTL__kmpc_end_serialized_parallel,
|
|
|
|
// Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_int32 num_threads);
|
2014-11-20 12:34:54 +08:00
|
|
|
OMPRTL__kmpc_push_num_threads,
|
2015-02-24 20:55:09 +08:00
|
|
|
// Call to void __kmpc_flush(ident_t *loc);
|
2014-12-04 15:23:53 +08:00
|
|
|
OMPRTL__kmpc_flush,
|
|
|
|
// Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_master,
|
|
|
|
// Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_end_master,
|
2015-02-05 13:57:51 +08:00
|
|
|
// Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
|
|
|
|
// int end_part);
|
|
|
|
OMPRTL__kmpc_omp_taskyield,
|
2015-02-05 14:35:41 +08:00
|
|
|
// Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_single,
|
|
|
|
// Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_end_single,
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
// Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
|
|
|
|
// kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
|
|
|
// kmp_routine_entry_t *task_entry);
|
|
|
|
OMPRTL__kmpc_omp_task_alloc,
|
|
|
|
// Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
|
|
|
|
// new_task);
|
|
|
|
OMPRTL__kmpc_omp_task,
|
2015-03-23 14:18:07 +08:00
|
|
|
// Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
|
2015-04-30 11:47:32 +08:00
|
|
|
// size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
|
2015-03-23 14:18:07 +08:00
|
|
|
// kmp_int32 didit);
|
|
|
|
OMPRTL__kmpc_copyprivate,
|
[OPENMP] Codegen for 'reduction' clause in 'parallel' directive.
Emit a code for reduction clause. Next code should be emitted for reductions:
static kmp_critical_name lock = { 0 };
void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
...
*(Type<i> *)lhs[i] = RedOp<i>(*(Type<i> *)lhs[i], *(Type<i> *)rhs[i]);
...
}
... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n> - 1]};
switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) {
case 1:
...
<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
...
__kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
break;
case 2:
...
Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
...
break;
default:
;
}
Reduction variables are a kind of a private variables, they have private copies, but initial values are chosen in accordance with the reduction operation.
Differential Revision: http://reviews.llvm.org/D8915
llvm-svn: 234583
2015-04-10 18:43:45 +08:00
|
|
|
// Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
|
|
|
|
// (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
|
|
|
|
OMPRTL__kmpc_reduce,
|
|
|
|
// Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
|
|
|
|
// global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
|
|
|
|
// void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
|
|
|
|
// *lck);
|
|
|
|
OMPRTL__kmpc_reduce_nowait,
|
|
|
|
// Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_critical_name *lck);
|
|
|
|
OMPRTL__kmpc_end_reduce,
|
|
|
|
// Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// kmp_critical_name *lck);
|
|
|
|
OMPRTL__kmpc_end_reduce_nowait,
|
[OPENMP] Codegen for 'if' clause in 'task' directive.
If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D9143
llvm-svn: 235507
2015-04-22 21:57:31 +08:00
|
|
|
// Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
|
|
|
|
// kmp_task_t * new_task);
|
|
|
|
OMPRTL__kmpc_omp_task_begin_if0,
|
|
|
|
// Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
|
|
|
|
// kmp_task_t * new_task);
|
|
|
|
OMPRTL__kmpc_omp_task_complete_if0,
|
2015-04-22 19:15:40 +08:00
|
|
|
// Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_ordered,
|
|
|
|
// Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_end_ordered,
|
2015-04-27 13:22:09 +08:00
|
|
|
// Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
|
|
|
|
// global_tid);
|
|
|
|
OMPRTL__kmpc_omp_taskwait,
|
2015-06-18 20:14:09 +08:00
|
|
|
// Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_taskgroup,
|
|
|
|
// Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
|
|
|
|
OMPRTL__kmpc_end_taskgroup,
|
2015-06-18 21:40:03 +08:00
|
|
|
// Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
|
|
|
|
// int proc_bind);
|
|
|
|
OMPRTL__kmpc_push_proc_bind,
|
[OPENMP] Codegen for 'depend' clause (OpenMP 4.0).
If task directive has associated 'depend' clause then function kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called instead of __kmpc_omp_task().
If this directive has associated 'if' clause then also before a call of kmpc_omp_task_begin_if0() a function void __kmpc_omp_wait_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called.
Array sections are not supported yet.
llvm-svn: 240532
2015-06-24 19:01:36 +08:00
|
|
|
// Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
|
|
|
|
// gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
|
|
|
|
// *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
|
|
|
|
OMPRTL__kmpc_omp_task_with_deps,
|
|
|
|
// Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
|
|
|
|
// gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
|
|
|
|
// ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
|
|
|
|
OMPRTL__kmpc_omp_wait_deps,
|
2015-07-02 12:17:07 +08:00
|
|
|
// Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
|
|
|
|
// global_tid, kmp_int32 cncl_kind);
|
|
|
|
OMPRTL__kmpc_cancellationpoint,
|
2014-05-06 18:08:46 +08:00
|
|
|
};
|
|
|
|
|
2014-12-05 12:09:23 +08:00
|
|
|
/// \brief Values for bit flags used in the ident_t to describe the fields.
|
|
|
|
/// All enumeric elements are named and described in accordance with the code
|
|
|
|
/// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
|
|
|
|
enum OpenMPLocationFlags {
|
|
|
|
/// \brief Use trampoline for internal microtask.
|
|
|
|
OMP_IDENT_IMD = 0x01,
|
|
|
|
/// \brief Use c-style ident structure.
|
|
|
|
OMP_IDENT_KMPC = 0x02,
|
|
|
|
/// \brief Atomic reduction option for kmpc_reduce.
|
|
|
|
OMP_ATOMIC_REDUCE = 0x10,
|
|
|
|
/// \brief Explicit 'barrier' directive.
|
|
|
|
OMP_IDENT_BARRIER_EXPL = 0x20,
|
|
|
|
/// \brief Implicit barrier in code.
|
|
|
|
OMP_IDENT_BARRIER_IMPL = 0x40,
|
|
|
|
/// \brief Implicit barrier in 'for' directive.
|
|
|
|
OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
|
|
|
|
/// \brief Implicit barrier in 'sections' directive.
|
|
|
|
OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
|
|
|
|
/// \brief Implicit barrier in 'single' directive.
|
|
|
|
OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140
|
|
|
|
};
|
2014-05-06 18:08:46 +08:00
|
|
|
CodeGenModule &CGM;
|
|
|
|
/// \brief Default const ident_t object used for initialization of all other
|
|
|
|
/// ident_t objects.
|
|
|
|
llvm::Constant *DefaultOpenMPPSource;
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \brief Map of flags and corresponding default locations.
|
2014-05-07 14:18:01 +08:00
|
|
|
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDefaultLocMapTy;
|
|
|
|
OpenMPDefaultLocMapTy OpenMPDefaultLocMap;
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Value *getOrCreateDefaultLocation(OpenMPLocationFlags Flags);
|
2014-05-06 18:08:46 +08:00
|
|
|
/// \brief Describes ident structure that describes a source location.
|
|
|
|
/// All descriptions are taken from
|
|
|
|
/// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h
|
|
|
|
/// Original structure:
|
|
|
|
/// typedef struct ident {
|
|
|
|
/// kmp_int32 reserved_1; /**< might be used in Fortran;
|
|
|
|
/// see above */
|
|
|
|
/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
|
|
|
|
/// KMP_IDENT_KMPC identifies this union
|
|
|
|
/// member */
|
|
|
|
/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
|
|
|
|
/// see above */
|
|
|
|
///#if USE_ITT_BUILD
|
|
|
|
/// /* but currently used for storing
|
|
|
|
/// region-specific ITT */
|
|
|
|
/// /* contextual information. */
|
|
|
|
///#endif /* USE_ITT_BUILD */
|
|
|
|
/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
|
|
|
|
/// C++ */
|
|
|
|
/// char const *psource; /**< String describing the source location.
|
|
|
|
/// The string is composed of semi-colon separated
|
|
|
|
// fields which describe the source file,
|
|
|
|
/// the function and a pair of line numbers that
|
|
|
|
/// delimit the construct.
|
|
|
|
/// */
|
|
|
|
/// } ident_t;
|
|
|
|
enum IdentFieldIndex {
|
|
|
|
/// \brief might be used in Fortran
|
|
|
|
IdentField_Reserved_1,
|
|
|
|
/// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
|
|
|
|
IdentField_Flags,
|
|
|
|
/// \brief Not really used in Fortran any more
|
|
|
|
IdentField_Reserved_2,
|
|
|
|
/// \brief Source[4] in Fortran, do not use for C++
|
|
|
|
IdentField_Reserved_3,
|
|
|
|
/// \brief String describing the source location. The string is composed of
|
|
|
|
/// semi-colon separated fields which describe the source file, the function
|
|
|
|
/// and a pair of line numbers that delimit the construct.
|
|
|
|
IdentField_PSource
|
|
|
|
};
|
|
|
|
llvm::StructType *IdentTy;
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \brief Map for SourceLocation and OpenMP runtime library debug locations.
|
2014-05-30 13:48:40 +08:00
|
|
|
typedef llvm::DenseMap<unsigned, llvm::Value *> OpenMPDebugLocMapTy;
|
|
|
|
OpenMPDebugLocMapTy OpenMPDebugLocMap;
|
2014-05-06 18:08:46 +08:00
|
|
|
/// \brief The type for a microtask which gets passed to __kmpc_fork_call().
|
|
|
|
/// Original representation is:
|
|
|
|
/// typedef void (kmpc_micro)(kmp_int32 global_tid, kmp_int32 bound_tid,...);
|
|
|
|
llvm::FunctionType *Kmpc_MicroTy;
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \brief Stores debug location and ThreadID for the function.
|
|
|
|
struct DebugLocThreadIdTy {
|
|
|
|
llvm::Value *DebugLoc;
|
|
|
|
llvm::Value *ThreadID;
|
|
|
|
};
|
|
|
|
/// \brief Map of local debug location, ThreadId and functions.
|
|
|
|
typedef llvm::DenseMap<llvm::Function *, DebugLocThreadIdTy>
|
|
|
|
OpenMPLocThreadIDMapTy;
|
|
|
|
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap;
|
2014-09-22 18:01:53 +08:00
|
|
|
/// \brief Type kmp_critical_name, originally defined as typedef kmp_int32
|
|
|
|
/// kmp_critical_name[8];
|
|
|
|
llvm::ArrayType *KmpCriticalNameTy;
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief An ordered map of auto-generated variables to their unique names.
|
|
|
|
/// It stores variables with the following names: 1) ".gomp_critical_user_" +
|
|
|
|
/// <critical_section_name> + ".var" for "omp critical" directives; 2)
|
|
|
|
/// <mangled_name_for_global_var> + ".cache." for cache for threadprivate
|
|
|
|
/// variables.
|
|
|
|
llvm::StringMap<llvm::AssertingVH<llvm::Constant>, llvm::BumpPtrAllocator>
|
|
|
|
InternalVars;
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// \brief Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);
|
|
|
|
llvm::Type *KmpRoutineEntryPtrTy;
|
|
|
|
QualType KmpRoutineEntryPtrQTy;
|
2015-05-18 15:54:53 +08:00
|
|
|
/// \brief Type typedef struct kmp_task {
|
|
|
|
/// void * shareds; /**< pointer to block of pointers to
|
|
|
|
/// shared vars */
|
|
|
|
/// kmp_routine_entry_t routine; /**< pointer to routine to call for
|
|
|
|
/// executing task */
|
|
|
|
/// kmp_int32 part_id; /**< part id for the task */
|
|
|
|
/// kmp_routine_entry_t destructors; /* pointer to function to invoke
|
|
|
|
/// deconstructors of firstprivate C++ objects */
|
|
|
|
/// } kmp_task_t;
|
|
|
|
QualType KmpTaskTQTy;
|
[OPENMP] Codegen for 'depend' clause (OpenMP 4.0).
If task directive has associated 'depend' clause then function kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called instead of __kmpc_omp_task().
If this directive has associated 'if' clause then also before a call of kmpc_omp_task_begin_if0() a function void __kmpc_omp_wait_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called.
Array sections are not supported yet.
llvm-svn: 240532
2015-06-24 19:01:36 +08:00
|
|
|
/// \brief Type typedef struct kmp_depend_info {
|
|
|
|
/// kmp_intptr_t base_addr;
|
|
|
|
/// size_t len;
|
|
|
|
/// struct {
|
|
|
|
/// bool in:1;
|
|
|
|
/// bool out:1;
|
|
|
|
/// } flags;
|
|
|
|
/// } kmp_depend_info_t;
|
|
|
|
QualType KmpDependInfoTy;
|
|
|
|
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
|
|
|
|
/// \brief Build type kmp_routine_entry_t (if not built yet).
|
|
|
|
void emitKmpRoutineEntryT(QualType KmpInt32Ty);
|
2014-05-06 18:08:46 +08:00
|
|
|
|
|
|
|
/// \brief Emits object of ident_t type with info for source location.
|
|
|
|
/// \param Flags Flags for OpenMP location.
|
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
|
|
|
|
OpenMPLocationFlags Flags = OMP_IDENT_KMPC);
|
2014-05-06 18:08:46 +08:00
|
|
|
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
/// \brief Returns pointer to ident_t type.
|
2014-05-06 18:08:46 +08:00
|
|
|
llvm::Type *getIdentTyPointerTy();
|
|
|
|
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
/// \brief Returns pointer to kmpc_micro type.
|
2014-05-06 18:08:46 +08:00
|
|
|
llvm::Type *getKmpc_MicroPointerTy();
|
|
|
|
|
|
|
|
/// \brief Returns specified OpenMP runtime function.
|
|
|
|
/// \param Function OpenMP runtime function.
|
|
|
|
/// \return Specified function.
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Constant *createRuntimeFunction(OpenMPRTLFunction Function);
|
2014-09-22 18:01:53 +08:00
|
|
|
|
2015-03-13 18:38:23 +08:00
|
|
|
/// \brief Returns __kmpc_for_static_init_* runtime function for the specified
|
|
|
|
/// size \a IVSize and sign \a IVSigned.
|
|
|
|
llvm::Constant *createForStaticInitFunction(unsigned IVSize, bool IVSigned);
|
|
|
|
|
2015-03-12 21:37:50 +08:00
|
|
|
/// \brief Returns __kmpc_dispatch_init_* runtime function for the specified
|
|
|
|
/// size \a IVSize and sign \a IVSigned.
|
|
|
|
llvm::Constant *createDispatchInitFunction(unsigned IVSize, bool IVSigned);
|
|
|
|
|
|
|
|
/// \brief Returns __kmpc_dispatch_next_* runtime function for the specified
|
|
|
|
/// size \a IVSize and sign \a IVSigned.
|
|
|
|
llvm::Constant *createDispatchNextFunction(unsigned IVSize, bool IVSigned);
|
|
|
|
|
2015-04-22 19:15:40 +08:00
|
|
|
/// \brief Returns __kmpc_dispatch_fini_* runtime function for the specified
|
|
|
|
/// size \a IVSize and sign \a IVSigned.
|
|
|
|
llvm::Constant *createDispatchFiniFunction(unsigned IVSize, bool IVSigned);
|
|
|
|
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief If the specified mangled name is not in the module, create and
|
|
|
|
/// return threadprivate cache object. This object is a pointer's worth of
|
|
|
|
/// storage that's reserved for use by the OpenMP runtime.
|
2014-11-11 15:58:06 +08:00
|
|
|
/// \param VD Threadprivate variable.
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \return Cache variable for the specified threadprivate.
|
|
|
|
llvm::Constant *getOrCreateThreadPrivateCache(const VarDecl *VD);
|
|
|
|
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
/// \brief Emits address of the word in a memory where current thread id is
|
|
|
|
/// stored.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual llvm::Value *emitThreadIDAddress(CodeGenFunction &CGF,
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
SourceLocation Loc);
|
|
|
|
|
2014-10-08 22:01:46 +08:00
|
|
|
/// \brief Gets thread id value for the current thread.
|
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Value *getThreadID(CodeGenFunction &CGF, SourceLocation Loc);
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief Gets (if variable with the given name already exist) or creates
|
|
|
|
/// internal global variable with the specified Name. The created variable has
|
|
|
|
/// linkage CommonLinkage by default and is initialized by null value.
|
|
|
|
/// \param Ty Type of the global variable. If it is exist already the type
|
|
|
|
/// must be the same.
|
|
|
|
/// \param Name Name of the variable.
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Constant *getOrCreateInternalVariable(llvm::Type *Ty,
|
2014-11-11 12:05:39 +08:00
|
|
|
const llvm::Twine &Name);
|
|
|
|
|
|
|
|
/// \brief Set of threadprivate variables with the generated initializer.
|
|
|
|
llvm::DenseSet<const VarDecl *> ThreadPrivateWithDefinition;
|
|
|
|
|
|
|
|
/// \brief Emits initialization code for the threadprivate variables.
|
|
|
|
/// \param VDAddr Address of the global variable \a VD.
|
|
|
|
/// \param Ctor Pointer to a global init function for \a VD.
|
|
|
|
/// \param CopyCtor Pointer to a global copy function for \a VD.
|
|
|
|
/// \param Dtor Pointer to a global destructor function for \a VD.
|
|
|
|
/// \param Loc Location of threadprivate declaration.
|
2015-02-25 16:32:46 +08:00
|
|
|
void emitThreadPrivateVarInit(CodeGenFunction &CGF, llvm::Value *VDAddr,
|
|
|
|
llvm::Value *Ctor, llvm::Value *CopyCtor,
|
|
|
|
llvm::Value *Dtor, SourceLocation Loc);
|
2014-11-11 12:05:39 +08:00
|
|
|
|
2014-12-01 19:32:38 +08:00
|
|
|
/// \brief Returns corresponding lock object for the specified critical region
|
|
|
|
/// name. If the lock object does not exist it is created, otherwise the
|
|
|
|
/// reference to the existing copy is returned.
|
|
|
|
/// \param CriticalName Name of the critical region.
|
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Value *getCriticalRegionLock(StringRef CriticalName);
|
2014-12-01 19:32:38 +08:00
|
|
|
|
2014-10-08 22:01:46 +08:00
|
|
|
public:
|
|
|
|
explicit CGOpenMPRuntime(CodeGenModule &CGM);
|
|
|
|
virtual ~CGOpenMPRuntime() {}
|
2015-03-18 12:13:55 +08:00
|
|
|
virtual void clear();
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2015-04-10 12:50:10 +08:00
|
|
|
/// \brief Emits outlined function for the specified OpenMP parallel directive
|
|
|
|
/// \a D. This outlined function has type void(*)(kmp_int32 *ThreadID,
|
|
|
|
/// kmp_int32 BoundID, struct context_vars*).
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \param D OpenMP directive.
|
|
|
|
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
|
2015-04-10 12:50:10 +08:00
|
|
|
/// \param CodeGen Code generation sequence for the \a D directive.
|
|
|
|
virtual llvm::Value *
|
|
|
|
emitParallelOutlinedFunction(const OMPExecutableDirective &D,
|
|
|
|
const VarDecl *ThreadIDVar,
|
|
|
|
const RegionCodeGenTy &CodeGen);
|
2014-10-10 20:19:54 +08:00
|
|
|
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// \brief Emits outlined function for the OpenMP task directive \a D. This
|
|
|
|
/// outlined function has type void(*)(kmp_int32 ThreadID, kmp_int32
|
|
|
|
/// PartID, struct context_vars*).
|
|
|
|
/// \param D OpenMP directive.
|
|
|
|
/// \param ThreadIDVar Variable for thread id in the current OpenMP region.
|
2015-04-10 12:50:10 +08:00
|
|
|
/// \param CodeGen Code generation sequence for the \a D directive.
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
///
|
|
|
|
virtual llvm::Value *emitTaskOutlinedFunction(const OMPExecutableDirective &D,
|
|
|
|
const VarDecl *ThreadIDVar,
|
2015-04-10 12:50:10 +08:00
|
|
|
const RegionCodeGenTy &CodeGen);
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
|
2014-10-08 22:01:46 +08:00
|
|
|
/// \brief Cleans up references to the objects in finished function.
|
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
void functionFinished(CodeGenFunction &CGF);
|
2014-10-08 22:01:46 +08:00
|
|
|
|
[OPENMP] Codegen for 'if' clause in 'task' directive.
If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D9143
llvm-svn: 235507
2015-04-22 21:57:31 +08:00
|
|
|
/// \brief Emits code for parallel or serial call of the \a OutlinedFn with
|
|
|
|
/// variables captured in a record which address is stored in \a
|
|
|
|
/// CapturedStruct.
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \param OutlinedFn Outlined function to be run in parallel threads. Type of
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// this function is void(*)(kmp_int32 *, kmp_int32, struct context_vars*).
|
2014-10-08 22:01:46 +08:00
|
|
|
/// \param CapturedStruct A pointer to the record with the references to
|
|
|
|
/// variables used in \a OutlinedFn function.
|
[OPENMP] Codegen for 'if' clause in 'task' directive.
If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D9143
llvm-svn: 235507
2015-04-22 21:57:31 +08:00
|
|
|
/// \param IfCond Condition in the associated 'if' clause, if it was
|
|
|
|
/// specified, nullptr otherwise.
|
2014-10-08 22:01:46 +08:00
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
|
|
|
|
llvm::Value *OutlinedFn,
|
[OPENMP] Codegen for 'if' clause in 'task' directive.
If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D9143
llvm-svn: 235507
2015-04-22 21:57:31 +08:00
|
|
|
llvm::Value *CapturedStruct,
|
|
|
|
const Expr *IfCond);
|
[OPENMP] Codegen for 'if' clause in 'parallel' directive.
Adds codegen for 'if' clause. Currently only for 'if' clause used with the 'parallel' directive.
If condition evaluates to true, the code executes parallel version of the code by calling __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/), where loc - debug location, 1 - number of additional parameters after "microtask" argument, microtask - is outlined finction for the code associated with the 'parallel' directive, captured_struct - list of variables captured in this outlined function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
global_thread_id.addr = alloca i32
store i32 global_thread_id, global_thread_id.addr
zero.addr = alloca i32
store i32 0, zero.addr
kmpc_serialized_parallel(loc, global_thread_id);
microtask(global_thread_id.addr, zero.addr, captured_struct/*context*/);
kmpc_end_serialized_parallel(loc, global_thread_id);
Where loc - debug location, global_thread_id - global thread id, returned by __kmpc_global_thread_num() call or passed as a first parameter in microtask() call, global_thread_id.addr - address of the variable, where stored global_thread_id value, zero.addr - implicit bound thread id (should be set to 0 for serial call), microtask() and captured_struct are the same as in parallel call.
Also this patch checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D4716
llvm-svn: 219597
2014-10-13 14:02:40 +08:00
|
|
|
|
2014-12-01 19:32:38 +08:00
|
|
|
/// \brief Emits a critical region.
|
2014-10-10 20:19:54 +08:00
|
|
|
/// \param CriticalName Name of the critical region.
|
2014-12-01 19:32:38 +08:00
|
|
|
/// \param CriticalOpGen Generator for the statement associated with the given
|
|
|
|
/// critical region.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName,
|
2015-04-10 12:50:10 +08:00
|
|
|
const RegionCodeGenTy &CriticalOpGen,
|
2015-02-25 16:32:46 +08:00
|
|
|
SourceLocation Loc);
|
2014-10-08 22:01:46 +08:00
|
|
|
|
2014-12-04 15:23:53 +08:00
|
|
|
/// \brief Emits a master region.
|
|
|
|
/// \param MasterOpGen Generator for the statement associated with the given
|
|
|
|
/// master region.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitMasterRegion(CodeGenFunction &CGF,
|
2015-04-10 12:50:10 +08:00
|
|
|
const RegionCodeGenTy &MasterOpGen,
|
2015-02-25 16:32:46 +08:00
|
|
|
SourceLocation Loc);
|
2014-12-04 15:23:53 +08:00
|
|
|
|
2015-02-05 13:57:51 +08:00
|
|
|
/// \brief Emits code for a taskyield directive.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
|
2015-02-05 13:57:51 +08:00
|
|
|
|
2015-06-18 20:14:09 +08:00
|
|
|
/// \brief Emit a taskgroup region.
|
|
|
|
/// \param TaskgroupOpGen Generator for the statement associated with the
|
|
|
|
/// given taskgroup region.
|
|
|
|
virtual void emitTaskgroupRegion(CodeGenFunction &CGF,
|
|
|
|
const RegionCodeGenTy &TaskgroupOpGen,
|
|
|
|
SourceLocation Loc);
|
|
|
|
|
2015-02-05 14:35:41 +08:00
|
|
|
/// \brief Emits a single region.
|
|
|
|
/// \param SingleOpGen Generator for the statement associated with the given
|
|
|
|
/// single region.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitSingleRegion(CodeGenFunction &CGF,
|
2015-04-10 12:50:10 +08:00
|
|
|
const RegionCodeGenTy &SingleOpGen,
|
2015-03-23 14:18:07 +08:00
|
|
|
SourceLocation Loc,
|
|
|
|
ArrayRef<const Expr *> CopyprivateVars,
|
2015-04-14 13:11:24 +08:00
|
|
|
ArrayRef<const Expr *> DestExprs,
|
2015-03-23 14:18:07 +08:00
|
|
|
ArrayRef<const Expr *> SrcExprs,
|
|
|
|
ArrayRef<const Expr *> AssignmentOps);
|
2015-02-05 14:35:41 +08:00
|
|
|
|
2015-04-22 19:15:40 +08:00
|
|
|
/// \brief Emit an ordered region.
|
|
|
|
/// \param OrderedOpGen Generator for the statement associated with the given
|
2015-06-18 20:14:09 +08:00
|
|
|
/// ordered region.
|
2015-04-22 19:15:40 +08:00
|
|
|
virtual void emitOrderedRegion(CodeGenFunction &CGF,
|
|
|
|
const RegionCodeGenTy &OrderedOpGen,
|
|
|
|
SourceLocation Loc);
|
|
|
|
|
2015-03-30 12:30:22 +08:00
|
|
|
/// \brief Emit an implicit/explicit barrier for OpenMP threads.
|
|
|
|
/// \param Kind Directive for which this implicit barrier call must be
|
|
|
|
/// generated. Must be OMPD_barrier for explicit barrier generation.
|
2014-10-08 22:01:46 +08:00
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
|
2015-03-30 12:30:22 +08:00
|
|
|
OpenMPDirectiveKind Kind);
|
2014-10-13 16:23:51 +08:00
|
|
|
|
2014-12-15 15:07:06 +08:00
|
|
|
/// \brief Check if the specified \a ScheduleKind is static non-chunked.
|
|
|
|
/// This kind of worksharing directive is emitted without outer loop.
|
|
|
|
/// \param ScheduleKind Schedule kind specified in the 'schedule' clause.
|
|
|
|
/// \param Chunked True if chunk is specified in the clause.
|
|
|
|
///
|
|
|
|
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
|
|
|
|
bool Chunked) const;
|
|
|
|
|
2015-01-22 16:49:35 +08:00
|
|
|
/// \brief Check if the specified \a ScheduleKind is dynamic.
|
|
|
|
/// This kind of worksharing directive is emitted without outer loop.
|
|
|
|
/// \param ScheduleKind Schedule Kind specified in the 'schedule' clause.
|
|
|
|
///
|
|
|
|
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const;
|
|
|
|
|
2014-12-15 15:07:06 +08:00
|
|
|
/// \brief Call the appropriate runtime routine to initialize it before start
|
|
|
|
/// of loop.
|
|
|
|
///
|
|
|
|
/// Depending on the loop schedule, it is nesessary to call some runtime
|
|
|
|
/// routine before start of the OpenMP loop to get the loop upper / lower
|
|
|
|
/// bounds \a LB and \a UB and stride \a ST.
|
|
|
|
///
|
|
|
|
/// \param CGF Reference to current CodeGenFunction.
|
|
|
|
/// \param Loc Clang source location.
|
2014-12-17 22:47:06 +08:00
|
|
|
/// \param SchedKind Schedule kind, specified by the 'schedule' clause.
|
2014-12-15 15:07:06 +08:00
|
|
|
/// \param IVSize Size of the iteration variable in bits.
|
|
|
|
/// \param IVSigned Sign of the interation variable.
|
2015-05-20 21:12:48 +08:00
|
|
|
/// \param Ordered true if loop is ordered, false otherwise.
|
2014-12-15 15:07:06 +08:00
|
|
|
/// \param IL Address of the output variable in which the flag of the
|
|
|
|
/// last iteration is returned.
|
|
|
|
/// \param LB Address of the output variable in which the lower iteration
|
|
|
|
/// number is returned.
|
|
|
|
/// \param UB Address of the output variable in which the upper iteration
|
|
|
|
/// number is returned.
|
|
|
|
/// \param ST Address of the output variable in which the stride value is
|
|
|
|
/// returned nesessary to generated the static_chunked scheduled loop.
|
|
|
|
/// \param Chunk Value of the chunk for the static_chunked scheduled loop.
|
|
|
|
/// For the default (nullptr) value, the chunk 1 will be used.
|
|
|
|
///
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
|
|
|
|
OpenMPScheduleClauseKind SchedKind, unsigned IVSize,
|
2015-05-20 21:12:48 +08:00
|
|
|
bool IVSigned, bool Ordered, llvm::Value *IL,
|
|
|
|
llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
|
2015-02-25 16:32:46 +08:00
|
|
|
llvm::Value *Chunk = nullptr);
|
2014-12-15 15:07:06 +08:00
|
|
|
|
2015-04-22 19:15:40 +08:00
|
|
|
/// \brief Call the appropriate runtime routine to notify that we finished
|
|
|
|
/// iteration of the ordered loop with the dynamic scheduling.
|
|
|
|
///
|
|
|
|
/// \param CGF Reference to current CodeGenFunction.
|
|
|
|
/// \param Loc Clang source location.
|
|
|
|
/// \param IVSize Size of the iteration variable in bits.
|
|
|
|
/// \param IVSigned Sign of the interation variable.
|
|
|
|
///
|
2015-05-20 21:12:48 +08:00
|
|
|
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF,
|
|
|
|
SourceLocation Loc, unsigned IVSize,
|
|
|
|
bool IVSigned);
|
2015-04-22 19:15:40 +08:00
|
|
|
|
2014-12-15 15:07:06 +08:00
|
|
|
/// \brief Call the appropriate runtime routine to notify that we finished
|
|
|
|
/// all the work with current loop.
|
|
|
|
///
|
|
|
|
/// \param CGF Reference to current CodeGenFunction.
|
|
|
|
/// \param Loc Clang source location.
|
|
|
|
///
|
2015-04-22 19:15:40 +08:00
|
|
|
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc);
|
2014-12-15 15:07:06 +08:00
|
|
|
|
2015-03-12 21:37:50 +08:00
|
|
|
/// Call __kmpc_dispatch_next(
|
|
|
|
/// ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
|
|
|
|
/// kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
|
|
|
|
/// kmp_int[32|64] *p_stride);
|
|
|
|
/// \param IVSize Size of the iteration variable in bits.
|
|
|
|
/// \param IVSigned Sign of the interation variable.
|
|
|
|
/// \param IL Address of the output variable in which the flag of the
|
|
|
|
/// last iteration is returned.
|
|
|
|
/// \param LB Address of the output variable in which the lower iteration
|
|
|
|
/// number is returned.
|
|
|
|
/// \param UB Address of the output variable in which the upper iteration
|
|
|
|
/// number is returned.
|
|
|
|
/// \param ST Address of the output variable in which the stride value is
|
|
|
|
/// returned.
|
|
|
|
virtual llvm::Value *emitForNext(CodeGenFunction &CGF, SourceLocation Loc,
|
|
|
|
unsigned IVSize, bool IVSigned,
|
|
|
|
llvm::Value *IL, llvm::Value *LB,
|
|
|
|
llvm::Value *UB, llvm::Value *ST);
|
|
|
|
|
2014-10-13 16:23:51 +08:00
|
|
|
/// \brief Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32
|
|
|
|
/// global_tid, kmp_int32 num_threads) to generate code for 'num_threads'
|
|
|
|
/// clause.
|
|
|
|
/// \param NumThreads An integer value of threads.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitNumThreadsClause(CodeGenFunction &CGF,
|
|
|
|
llvm::Value *NumThreads,
|
|
|
|
SourceLocation Loc);
|
2014-11-11 12:05:39 +08:00
|
|
|
|
2015-06-18 21:40:03 +08:00
|
|
|
/// \brief Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32
|
|
|
|
/// global_tid, int proc_bind) to generate code for 'proc_bind' clause.
|
|
|
|
virtual void emitProcBindClause(CodeGenFunction &CGF,
|
|
|
|
OpenMPProcBindClauseKind ProcBind,
|
|
|
|
SourceLocation Loc);
|
|
|
|
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \brief Returns address of the threadprivate variable for the current
|
|
|
|
/// thread.
|
2014-11-11 15:58:06 +08:00
|
|
|
/// \param VD Threadprivate variable.
|
2014-11-11 12:05:39 +08:00
|
|
|
/// \param VDAddr Address of the global variable \a VD.
|
|
|
|
/// \param Loc Location of the reference to threadprivate var.
|
|
|
|
/// \return Address of the threadprivate variable for the current thread.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual llvm::Value *getAddrOfThreadPrivate(CodeGenFunction &CGF,
|
|
|
|
const VarDecl *VD,
|
|
|
|
llvm::Value *VDAddr,
|
|
|
|
SourceLocation Loc);
|
2014-11-11 12:05:39 +08:00
|
|
|
|
|
|
|
/// \brief Emit a code for initialization of threadprivate variable. It emits
|
|
|
|
/// a call to runtime library which adds initial value to the newly created
|
|
|
|
/// threadprivate variable (if it is not constant) and registers destructor
|
|
|
|
/// for the variable (if any).
|
|
|
|
/// \param VD Threadprivate variable.
|
|
|
|
/// \param VDAddr Address of the global variable \a VD.
|
|
|
|
/// \param Loc Location of threadprivate declaration.
|
|
|
|
/// \param PerformInit true if initialization expression is not constant.
|
|
|
|
virtual llvm::Function *
|
2015-02-25 16:32:46 +08:00
|
|
|
emitThreadPrivateVarDefinition(const VarDecl *VD, llvm::Value *VDAddr,
|
|
|
|
SourceLocation Loc, bool PerformInit,
|
|
|
|
CodeGenFunction *CGF = nullptr);
|
2014-11-20 12:34:54 +08:00
|
|
|
|
|
|
|
/// \brief Emit flush of the variables specified in 'omp flush' directive.
|
|
|
|
/// \param Vars List of variables to flush.
|
2015-02-25 16:32:46 +08:00
|
|
|
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *> Vars,
|
|
|
|
SourceLocation Loc);
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
|
|
|
|
/// \brief Emit task region for the task directive. The task region is
|
2015-04-29 02:19:18 +08:00
|
|
|
/// emitted in several steps:
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// 1. Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32
|
|
|
|
/// gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
|
|
|
|
/// kmp_routine_entry_t *task_entry). Here task_entry is a pointer to the
|
|
|
|
/// function:
|
|
|
|
/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
|
|
|
|
/// TaskFunction(gtid, tt->part_id, tt->shareds);
|
|
|
|
/// return 0;
|
|
|
|
/// }
|
|
|
|
/// 2. Copy a list of shared variables to field shareds of the resulting
|
|
|
|
/// structure kmp_task_t returned by the previous call (if any).
|
|
|
|
/// 3. Copy a pointer to destructions function to field destructions of the
|
|
|
|
/// resulting structure kmp_task_t.
|
|
|
|
/// 4. Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid,
|
|
|
|
/// kmp_task_t *new_task), where new_task is a resulting structure from
|
|
|
|
/// previous items.
|
2015-04-30 14:51:57 +08:00
|
|
|
/// \param D Current task directive.
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// \param Tied true if the task is tied (the task is tied to the thread that
|
|
|
|
/// can suspend its task region), false - untied (the task is not tied to any
|
|
|
|
/// thread).
|
|
|
|
/// \param Final Contains either constant bool value, or llvm::Value * of i1
|
|
|
|
/// type for final clause. If the value is true, the task forces all of its
|
|
|
|
/// child tasks to become final and included tasks.
|
|
|
|
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
|
|
|
|
/// /*part_id*/, captured_struct */*__context*/);
|
|
|
|
/// \param SharedsTy A type which contains references the shared variables.
|
[OPENMP] Codegen for 'depend' clause (OpenMP 4.0).
If task directive has associated 'depend' clause then function kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called instead of __kmpc_omp_task().
If this directive has associated 'if' clause then also before a call of kmpc_omp_task_begin_if0() a function void __kmpc_omp_wait_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called.
Array sections are not supported yet.
llvm-svn: 240532
2015-06-24 19:01:36 +08:00
|
|
|
/// \param Shareds Context with the list of shared variables from the \p
|
[OPENMP] Initial codegen for 'omp task' directive.
The task region is emmitted in several steps:
Emit a call to kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry).
Here task_entry is a pointer to the function:
kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
TaskFunction(gtid, tt->part_id, tt->shareds);
return 0;
}
Copy a list of shared variables to field shareds of the resulting structure kmp_task_t returned by the previous call (if any).
Copy a pointer to destructions function to field destructions of the resulting structure kmp_task_t.
Emit a call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task), where new_task is a resulting structure from previous items.
Differential Revision: http://reviews.llvm.org/D7560
llvm-svn: 231762
2015-03-10 15:28:44 +08:00
|
|
|
/// TaskFunction.
|
[OPENMP] Codegen for 'if' clause in 'task' directive.
If condition evaluates to true, the code executes task by calling @__kmpc_omp_task() runtime function.
If condition evaluates to false, the code executes serial version of the code by executing the following code:
call void @__kmpc_omp_task_begin_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
proxy_task_entry(<gtid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
call void @__kmpc_omp_task_complete_if0(<loc>, <threadid>, <task_t_ptr, returned by @__kmpc_omp_task_alloc()>);
Also it checks if the condition is constant and if it is constant it evaluates its value and then generates either parallel version of the code (if the condition evaluates to true), or the serial version of the code (if the condition evaluates to false).
Differential Revision: http://reviews.llvm.org/D9143
llvm-svn: 235507
2015-04-22 21:57:31 +08:00
|
|
|
/// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
|
|
|
|
/// otherwise.
|
2015-04-30 14:51:57 +08:00
|
|
|
/// \param PrivateVars List of references to private variables for the task
|
|
|
|
/// directive.
|
|
|
|
/// \param PrivateCopies List of private copies for each private variable in
|
[OPENMP] Codegen for 'firstprivate' clause in 'task' directive.
For tasks codegen for private/firstprivate variables are different rather than for other directives.
1. Build an internal structure of privates for each private variable:
struct .kmp_privates_t. {
Ty1 var1;
...
Tyn varn;
};
2. Add a new field to kmp_task_t type with list of privates.
struct kmp_task_t {
void * shareds;
kmp_routine_entry_t routine;
kmp_int32 part_id;
kmp_routine_entry_t destructors;
.kmp_privates_t. privates;
};
3. Create a function with destructors calls for all privates after end of task region.
kmp_int32 .omp_task_destructor.(kmp_int32 gtid, kmp_task_t *tt) {
~Destructor(&tt->privates.var1);
...
~Destructor(&tt->privates.varn);
return 0;
}
4. Perform initialization of all firstprivate fields (by simple copying for POD data, copy constructor calls for classes) + provide address of a destructor function after kmpc_omp_task_alloc() and before kmpc_omp_task() calls.
kmp_task_t *new_task = __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, kmp_routine_entry_t *task_entry);
CopyConstructor(new_task->privates.var1, *new_task->shareds.var1_ref);
new_task->shareds.var1_ref = &new_task->privates.var1;
...
CopyConstructor(new_task->privates.varn, *new_task->shareds.varn_ref);
new_task->shareds.varn_ref = &new_task->privates.varn;
new_task->destructors = .omp_task_destructor.;
kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *new_task)
Differential Revision: http://reviews.llvm.org/D9370
llvm-svn: 236479
2015-05-05 12:05:12 +08:00
|
|
|
/// \p PrivateVars.
|
|
|
|
/// \param FirstprivateVars List of references to private variables for the
|
|
|
|
/// task directive.
|
|
|
|
/// \param FirstprivateCopies List of private copies for each private variable
|
|
|
|
/// in \p FirstprivateVars.
|
|
|
|
/// \param FirstprivateInits List of references to auto generated variables
|
|
|
|
/// used for initialization of a single array element. Used if firstprivate
|
|
|
|
/// variable is of array type.
|
[OPENMP] Codegen for 'depend' clause (OpenMP 4.0).
If task directive has associated 'depend' clause then function kmp_int32 __kmpc_omp_task_with_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called instead of __kmpc_omp_task().
If this directive has associated 'if' clause then also before a call of kmpc_omp_task_begin_if0() a function void __kmpc_omp_wait_deps ( ident_t *loc_ref, kmp_int32 gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) must be called.
Array sections are not supported yet.
llvm-svn: 240532
2015-06-24 19:01:36 +08:00
|
|
|
/// \param Dependences List of dependences for the 'task' construct, including
|
|
|
|
/// original expression and dependency type.
|
|
|
|
virtual void emitTaskCall(
|
|
|
|
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
|
|
|
|
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
|
|
|
|
llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds,
|
|
|
|
const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
|
|
|
|
ArrayRef<const Expr *> PrivateCopies,
|
|
|
|
ArrayRef<const Expr *> FirstprivateVars,
|
|
|
|
ArrayRef<const Expr *> FirstprivateCopies,
|
|
|
|
ArrayRef<const Expr *> FirstprivateInits,
|
|
|
|
ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences);
|
[OPENMP] Codegen for 'reduction' clause in 'parallel' directive.
Emit a code for reduction clause. Next code should be emitted for reductions:
static kmp_critical_name lock = { 0 };
void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
...
*(Type<i> *)lhs[i] = RedOp<i>(*(Type<i> *)lhs[i], *(Type<i> *)rhs[i]);
...
}
... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n> - 1]};
switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) {
case 1:
...
<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
...
__kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
break;
case 2:
...
Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
...
break;
default:
;
}
Reduction variables are a kind of a private variables, they have private copies, but initial values are chosen in accordance with the reduction operation.
Differential Revision: http://reviews.llvm.org/D8915
llvm-svn: 234583
2015-04-10 18:43:45 +08:00
|
|
|
|
2015-04-10 12:50:10 +08:00
|
|
|
/// \brief Emit code for the directive that does not require outlining.
|
|
|
|
///
|
|
|
|
/// \param CodeGen Code generation sequence for the \a D directive.
|
|
|
|
virtual void emitInlinedDirective(CodeGenFunction &CGF,
|
|
|
|
const RegionCodeGenTy &CodeGen);
|
[OPENMP] Codegen for 'reduction' clause in 'parallel' directive.
Emit a code for reduction clause. Next code should be emitted for reductions:
static kmp_critical_name lock = { 0 };
void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
...
*(Type<i> *)lhs[i] = RedOp<i>(*(Type<i> *)lhs[i], *(Type<i> *)rhs[i]);
...
}
... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n> - 1]};
switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) {
case 1:
...
<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
...
__kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
break;
case 2:
...
Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
...
break;
default:
;
}
Reduction variables are a kind of a private variables, they have private copies, but initial values are chosen in accordance with the reduction operation.
Differential Revision: http://reviews.llvm.org/D8915
llvm-svn: 234583
2015-04-10 18:43:45 +08:00
|
|
|
/// \brief Emit a code for reduction clause. Next code should be emitted for
|
|
|
|
/// reduction:
|
|
|
|
/// \code
|
|
|
|
///
|
|
|
|
/// static kmp_critical_name lock = { 0 };
|
|
|
|
///
|
|
|
|
/// void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
|
|
|
|
/// ...
|
|
|
|
/// *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
|
|
|
|
/// ...
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// ...
|
|
|
|
/// void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
|
|
|
|
/// switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
|
|
|
|
/// RedList, reduce_func, &<lock>)) {
|
|
|
|
/// case 1:
|
|
|
|
/// ...
|
|
|
|
/// <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
|
|
|
|
/// ...
|
|
|
|
/// __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
|
|
|
|
/// break;
|
|
|
|
/// case 2:
|
|
|
|
/// ...
|
|
|
|
/// Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
|
|
|
|
/// ...
|
|
|
|
/// break;
|
|
|
|
/// default:;
|
|
|
|
/// }
|
|
|
|
/// \endcode
|
|
|
|
///
|
|
|
|
/// \param LHSExprs List of LHS in \a ReductionOps reduction operations.
|
|
|
|
/// \param RHSExprs List of RHS in \a ReductionOps reduction operations.
|
|
|
|
/// \param ReductionOps List of reduction operations in form 'LHS binop RHS'
|
|
|
|
/// or 'operator binop(LHS, RHS)'.
|
|
|
|
/// \param WithNowait true if parent directive has also nowait clause, false
|
|
|
|
/// otherwise.
|
|
|
|
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
|
|
|
|
ArrayRef<const Expr *> LHSExprs,
|
|
|
|
ArrayRef<const Expr *> RHSExprs,
|
|
|
|
ArrayRef<const Expr *> ReductionOps,
|
2015-06-17 14:21:39 +08:00
|
|
|
bool WithNowait, bool SimpleReduction);
|
2015-04-27 13:22:09 +08:00
|
|
|
|
|
|
|
/// \brief Emit code for 'taskwait' directive.
|
|
|
|
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
|
2015-07-02 12:17:07 +08:00
|
|
|
|
|
|
|
/// \brief Emit code for 'cancellation point' construct.
|
|
|
|
/// \param CancelRegion Region kind for which the cancellation point must be
|
|
|
|
/// emitted.
|
|
|
|
///
|
|
|
|
virtual void emitCancellationPointCall(CodeGenFunction &CGF,
|
|
|
|
SourceLocation Loc,
|
|
|
|
OpenMPDirectiveKind CancelRegion);
|
2014-05-06 18:08:46 +08:00
|
|
|
};
|
2015-02-26 18:27:34 +08:00
|
|
|
|
2014-06-18 15:08:49 +08:00
|
|
|
} // namespace CodeGen
|
|
|
|
} // namespace clang
|
2014-05-06 18:08:46 +08:00
|
|
|
|
|
|
|
#endif
|