summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGStmtOpenMP.cpp
Commit message (Collapse)AuthorAgeFilesLines
...
* [OPENMP 4.0] Fixed codegen for 'cancellation point' construct.Alexey Bataev2015-07-031-21/+24
| | | | | | | | | | Generate the next code for 'cancellation point': if (__kmpc_cancellationpoint()) { __kmpc_cancel_barrier(); <exit construct>; } llvm-svn: 241336
* Switch users of the 'for (StmtRange range = stmt->children(); range; ↵Benjamin Kramer2015-07-021-2/+3
| | | | | | | | | ++range)‘ pattern to range for loops. The pattern was born out of the lack of range-based for loops in C++98 and is somewhat obscure. No functionality change intended. llvm-svn: 241300
* [OPENMP 4.0] Initial support for 'omp cancel' construct.Alexey Bataev2015-07-021-0/+4
| | | | | | Implemented parsing/sema analysis + (de)serialization. llvm-svn: 241253
* [OPENMP 4.0] Codegen for 'cancellation point' directive.Alexey Bataev2015-07-021-35/+41
| | | | | | | | | | The next code is generated for this construct: ``` if (__kmpc_cancellationpoint(ident_t *loc, kmp_int32 global_tid, kmp_int32 cncl_kind) != 0) <exit from outer innermost construct>; ``` llvm-svn: 241239
* [OPENMP] Introduced type trait "__builtin_omp_required_simd_align" for ↵Alexey Bataev2015-07-021-2/+4
| | | | | | | | | default simd alignment. Adds type trait "__builtin_omp_required_simd_align" after discussions here http://reviews.llvm.org/D9894 Differential Revision: http://reviews.llvm.org/D10597 llvm-svn: 241237
* [OPENMP 4.0] Initial support for 'omp cancellation point' construct.Alexey Bataev2015-07-011-0/+7
| | | | | | Add parsing and sema analysis for 'omp cancellation point' directive. llvm-svn: 241145
* [OPENMP] Codegen for 'depend' clause (OpenMP 4.0).Alexey Bataev2015-06-241-1/+10
| | | | | | | | 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
* [OPENMP] Initial support for 'depend' clause (4.0).Alexey Bataev2015-06-231-0/+1
| | | | | | Parsing and sema analysis (without support for array sections in arguments) for 'depend' clause (used in 'task' directive, OpenMP 4.0). llvm-svn: 240409
* [OPENMP] Codegen for 'proc_bind' clause (4.0).Alexey Bataev2015-06-181-0/+6
| | | | | | | Adds emission of the code for 'proc_bind(master|close|spread)' clause: call void @__kmpc_push_proc_bind(<loc>, i32 thread_id, i32 4|3|2) llvm-svn: 240018
* [OPENMP] Support for '#pragma omp taskgroup' directive.Alexey Bataev2015-06-181-0/+10
| | | | | | | | | | | | | Added parsing, sema analysis and codegen for '#pragma omp taskgroup' directive (OpenMP 4.0). The code for directive is generated the following way: #pragma omp taskgroup <body> void __kmpc_taskgroup(<loc>, thread_id); <body> void __kmpc_end_taskgroup(<loc>, thread_id); llvm-svn: 240011
* [OPENMP] Add support for 'omp parallel for' directive.Alexey Bataev2015-06-181-10/+32
| | | | | | Codegen for this directive is a combined codegen for 'omp parallel' region with 'omp for simd' region inside. Clauses are supported. llvm-svn: 240006
* [OPENMP] Add support for 'omp for simd' directive.Alexey Bataev2015-06-181-33/+55
| | | | | | Added codegen for combined 'omp for simd' directives, that is a combination of 'omp for' directive followed by 'omp simd' directive. Includes support for all clauses. llvm-svn: 239990
* [OPENMP] Code reformatting for omp simd codegen, NFC.Alexey Bataev2015-06-171-103/+103
| | | | llvm-svn: 239889
* [OPENMP] Supported reduction clause in omp simd construct.Alexey Bataev2015-06-171-1/+5
| | | | | | | | | | | | | | | | The following code is generated for reduction clause within 'omp simd' loop construct: #pragma omp simd reduction(op:var) for (...) <body> alloca priv_var priv_var = <initial reduction value>; <loop_start>: <body> // references to original 'var' are replaced by 'priv_var' <loop_end>: var op= priv_var; llvm-svn: 239881
* [OPENMP] Support lastprivate clause in omp simd directive.Alexey Bataev2015-06-161-17/+31
| | | | | | Added codegen for lastprivate clauses within simd loop-based directives. llvm-svn: 239813
* [OPENMP] Remove last iteration separation for loop-based constructs.Alexey Bataev2015-06-161-14/+6
| | | | | | Previously the last iteration for simd loop-based OpenMP constructs were generated as a separate code. This feature is not required and codegen is simplified. llvm-svn: 239810
* [OPENMP] Fox for http://llvm.org/PR23663: OpenMP crashAlexey Bataev2015-06-111-24/+26
| | | | | | Destroy RuntimeCleanupScope before generation of termination instruction in parallel loop precondition. llvm-svn: 239524
* [OPENMP] Prepare codegen for privates in tasks for non-capturing of privates ↵Alexey Bataev2015-05-221-33/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | in CapturedStmt. Reworked codegen for privates in tasks: call @kmpc_omp_task_alloc(); ... call @kmpc_omp_task(task_proxy); void map_privates(.privates_rec. *privs, type1 ** priv1_ref, ..., typen **privn_ref) { *priv1_ref = &privs->private1; ... *privn_ref = &privs->privaten; ret void } i32 task_entry(i32 ThreadId, i32 PartId, void* privs, void (void*, ...) map_privates, shareds* captures) { type1 **priv1; ... typen **privn; call map_privates(privs, priv1, ..., privn); <Task body with priv1, .., privn instead of the captured variables>. ret i32 } i32 task_proxy(i32 ThreadId, kmp_task_t_with_privates *tt) { call task_entry(ThreadId, tt->task_data.PartId, &tt->privates, map_privates, tt->task_data.shareds); } llvm-svn: 238010
* [OPENMP] Fixed codegen for parameters privatization.Alexey Bataev2015-05-211-9/+0
| | | | | | For parameters we shall take a derived type of parameters, not the original one. llvm-svn: 237882
* [OPENMP] Fixed codegen for lastprivate LCV in worksharing constructs.Alexey Bataev2015-05-211-3/+35
| | | | | | If loop control variable in a worksharing construct is marked as lastprivate, we should copy last calculated value of private counter back to original variable. llvm-svn: 237879
* [OPENMP] Fix codegen for ordered loop directives.Alexey Bataev2015-05-201-26/+28
| | | | | | loops with ordered clause must be generated the same way as dynamic loops, but with static scheduleing. llvm-svn: 237788
* [OPENMP] Fixed codegen for copying/initialization of array variables/parameters.Alexey Bataev2015-05-191-8/+19
| | | | | | This modification generates proper copyin/initialization sequences for array variables/parameters. Before they were considered as pointers, not arrays. llvm-svn: 237691
* [OPENMP] Fixed codegen for firstprivate variables, also marked as lastprivate.Alexey Bataev2015-05-131-11/+13
| | | | | | In some rare cases shared copies of lastprivate/firstprivate variables were not updated after the loop directive. llvm-svn: 237243
* [OPENMP] Fixed support for 'schedule' clause with non-constant chunk size.Alexey Bataev2015-05-121-11/+39
| | | | | | 'schedule' clause for combined directives requires additional processing. Special helper variable is generated, that is captured in the outlined parallel region for 'parallel for' region. This captured variable is used to store chunk expression from the 'schedule' clause in this 'parallel for' region. llvm-svn: 237100
* [OPENMP] Fixed atomic construct with non-integer expressions.Alexey Bataev2015-05-081-4/+5
| | | | | | Do not emit 'atomicrmw' instruction for simple atomic constructs with non-integer expressions. llvm-svn: 236828
* [OPENMP] Code cleanup for capturing of variables in OpenMP regions.Alexey Bataev2015-05-081-1/+21
| | | | llvm-svn: 236821
* [OPENMP] Generate !llvm.mem.loop_parallel_access metadata for loops with ↵Alexey Bataev2015-05-071-0/+5
| | | | | | | | | | dynamic/guided scheduling. Inner bodies of OpenMP worksharing loop-based constructs with dynamic or guided scheduling are allowed to be marked with !llvm.mem.parallel_loop_access metadata for better optimization. Worksharing constructs with static scheduling cannot be marked this way (according to OpenMP standard "A data dependence between the same logical iterations in two such loops is guaranteed"). Constructs with auto and runtime scheduling are also not marked because automatically chosen scheduling may be static also. Differential Revision: http://reviews.llvm.org/D9518 llvm-svn: 236693
* [OPENMP] Codegen for 'firstprivate' clause in 'task' directive.Alexey Bataev2015-05-051-4/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Make helper functions static. NFC.Benjamin Kramer2015-05-011-4/+5
| | | | llvm-svn: 236315
* [OPENMP] Codegen for 'private' clause in 'task' directive.Alexey Bataev2015-04-301-2/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 default initialization of all private fields (no initialization for POD data, default 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); DefaultConstructor(new_task->privates.var1); new_task->shareds.var1_ref = &new_task->privates.var1; ... DefaultConstructor(new_task->privates.varn); 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/D9322 llvm-svn: 236207
* [OPENMP] Fix crash on loop control vars explicitly marked as private.Alexey Bataev2015-04-281-4/+1
| | | | | | It is allowed to mark loop control vars as private in 'private' or 'lastprivate' clause, so no need to assert here. llvm-svn: 235985
* [OPENMP] Simplified iteration over clauses, NFC.Alexey Bataev2015-04-271-66/+21
| | | | llvm-svn: 235838
* [OPENMP] Codegen for 'taskwait' directive.Alexey Bataev2015-04-271-2/+2
| | | | | | | | Emit the following code for 'taskwait' directive within tied task: call i32 @__kmpc_omp_taskwait(<loc>, i32 <thread_id>); Differential Revision: http://reviews.llvm.org/D9245 llvm-svn: 235836
* [OPENMP] Codegen for 'reduction' clause in 'sections' directive.Alexey Bataev2015-04-271-6/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>]) { *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); ... *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], *(Type<n>-1*)rhs[<n>-1]); } ... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) { case 1: <LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0]); ... <LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1]); __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); break; case 2: Atomic(<LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0])); ... Atomic(<LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1])); 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. If sections directive has only single section, then original shared variables are used instead with barrier at the end of the directive. Differential Revision: http://reviews.llvm.org/D9242 llvm-svn: 235835
* [OPENMP] Codegen for 'lastprivate' clause in 'sections' directive.Alexey Bataev2015-04-271-5/+31
| | | | | | | | | | | | | | | | | | | | | | | | | #pragma omp sections lastprivate(<var>) <BODY>; This construct is translated into something like: <last_iter> = alloca i32 <init for lastprivates>; <last_iter> = 0 ; No initializer for simple variables or a default constructor is called for objects. ; For arrays perform element by element initialization by the call of the default constructor. ... OMP_FOR_START(...,<last_iter>, ..); sets <last_iter> to 1 if this is the last iteration. <BODY> ... OMP_FOR_END if (<last_iter> != 0) { <final copy for lastprivate>; Update original variable with the lastprivate value. } call __kmpc_cancel_barrier() ; an implicit barrier to avoid possible data race. If there is only one section, there is no special code generation, original shared variables are used + barrier is emitted at the end of the directive. Differential Revision: http://reviews.llvm.org/D9240 llvm-svn: 235834
* [OPENMP] Codegen for 'private' clause in 'sections' directive.Alexey Bataev2015-04-271-0/+2
| | | | | | | | | | | | | | | | | | If there are 2 or more sections in a 'section' directive the following code is generated: <default init for privates> @__kmpc_for_static_init_4(); <BODY for sections directive> @__kmpc_for_static_fini() If there is only one section, the following code is generated: if (@__kmpc_single()) { <default init for privates> @__kmpc_end_single(); } Differential Revision: http://reviews.llvm.org/D9239 llvm-svn: 235833
* [OPENMP] Codegen for 'private' clause in 'single' directive.Alexey Bataev2015-04-271-0/+1
| | | | | | | | | | | | Emit the following code for 'single' directive with 'private' clause: if (@__kmpc_single()) { <default init for privates> @__kmpc_end_single(); } Differential Revision: http://reviews.llvm.org/D9238 llvm-svn: 235832
* [OPENMP] Codegen for 'firstprivate' clause in 'single' directive.Alexey Bataev2015-04-241-5/+13
| | | | | | | | | | | | | Emit the following code for 'single' directive with 'firtstprivate' clause: if (@__kmpc_single()) { <init for firstprivates> @__kmpc_end_single(); } @__kmpc_cancel_barrier(); // To avoid data race in firstprivate init Differential Revision: http://reviews.llvm.org/D9223 llvm-svn: 235694
* [OPENMP] Do not emit implicit barrier for single directive with ↵Alexey Bataev2015-04-241-2/+3
| | | | | | | | | 'copyprivate' clause(s). Runtime function for 'copyprivate' directive generates implicit barriers, so no need to emit it. Differential Revision: http://reviews.llvm.org/D9215 llvm-svn: 235692
* [OPENMP] Codegen for 'firstprivate' clause in 'sections' directive.Alexey Bataev2015-04-241-1/+25
| | | | | | | | | | | | | | | | | | | | If there are 2 or more sections in a 'section' directive the following code is generated: <init for firstprivates> @__kmpc_cancel_barrier();// To avoid data race in firstprivate init @__kmpc_for_static_init_4(); <BODY for sections directive> @__kmpc_for_static_fini() If there is only one section, the following code is generated: if (@__kmpc_single()) { <init for firstprivates> @__kmpc_end_single(); } @__kmpc_cancel_barrier(); // To avoid data race in firstprivate init Differential Revision: http://reviews.llvm.org/D9214 llvm-svn: 235691
* InstrProf: Stop using RegionCounter outside of CodeGenPGO (NFC)Justin Bogner2015-04-231-10/+7
| | | | | | | | | The RegionCounter type does a lot of legwork, but most of it is only meaningful within the implementation of CodeGenPGO. The uses elsewhere in CodeGen generally just want to increment or read counters, so do that directly. llvm-svn: 235664
* [OPENMP] Codegen for 'atomic capture'.Alexey Bataev2015-04-231-42/+164
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Adds codegen for 'atomic capture' constructs with the following forms of expressions/statements: v = x binop= expr; v = x++; v = ++x; v = x--; v = --x; v = x = x binop expr; v = x = expr binop x; {v = x; x = binop= expr;} {v = x; x++;} {v = x; ++x;} {v = x; x--;} {v = x; --x;} {x = x binop expr; v = x;} {x binop= expr; v = x;} {x++; v = x;} {++x; v = x;} {x--; v = x;} {--x; v = x;} {x = x binop expr; v = x;} {x = expr binop x; v = x;} {v = x; x = expr;} If x and expr are integer and binop is associative or x is a LHS in a RHS of the assignment expression, and atomics are allowed for type of x on the target platform atomicrmw instruction is emitted. Otherwise compare-and-swap sequence is emitted. Update of 'v' is not required to be be atomic with respect to the read or write of the 'x'. bb: ... atomic load <x> cont: <expected> = phi [ <x>, label %bb ], [ <new_failed>, %cont ] <desired> = <expected> binop <expr> <res> = cmpxchg atomic &<x>, desired, expected <new_failed> = <res>.field1; br <res>field2, label %exit, label %cont exit: atomic store <old/new x>, <v> ... Differential Revision: http://reviews.llvm.org/D9049 llvm-svn: 235573
* [OPENMP] Codegen for 'if' clause in 'task' directive.Alexey Bataev2015-04-221-74/+19
| | | | | | | | | | | | | 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
* [OPENMP] Codegen for 'reduction' clause in 'for' directive.Alexey Bataev2015-04-221-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>]) { *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); ... *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], *(Type<n>-1*)rhs[<n>-1]); } ... void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>)) { case 1: <LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0]); ... <LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1]); __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); break; case 2: Atomic(<LHSExprs>[0] = ReductionOperation0(*<LHSExprs>[0], *<RHSExprs>[0])); ... Atomic(<LHSExprs>[<n>-1] = ReductionOperation<n>-1(*<LHSExprs>[<n>-1], *<RHSExprs>[<n>-1])); 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/D9139 llvm-svn: 235506
* [OPENMP] Codegen for 'private' clause in 'for' directive.Alexey Bataev2015-04-221-11/+16
| | | | | | | This patch generates helper variables which used as a private copies of the corresponding original variables inside an OpenMP 'for' directive. These generated variables are initialized by default (with the default constructor, if any). In OpenMP region references to original variables are replaced by the references to these private helper variables. Differential Revision: http://reviews.llvm.org/D9106 llvm-svn: 235503
* [OPENMP] Fix use of unsigned counters in loops with zero trip count.Alexey Bataev2015-04-221-51/+90
| | | | | | | | Patch fixes bugs in codegen for loops with unsigned counters and zero trip count. Previously preconditions for all loops were built using logic (Upper - Lower) > 0. But if the loop is a loop with zero trip count, then Upper - Lower is < 0 only for signed integer, for unsigned we're running into an underflow situation. In this patch we're using original Lower<Upper condition to check that loop body can be executed at least once. Also this allows to skip code generation for loops, if it is known that preconditions for the loop are always false. Differential Revision: http://reviews.llvm.org/D9103 llvm-svn: 235500
* [OPENMP] Codegen for 'ordered' directive.Alexey Bataev2015-04-221-19/+40
| | | | | | | | | | | | | | | | | | | Add codegen for 'ordered' directive: __kmpc_ordered(ident_t *, gtid); <associated statement>; __kmpc_end_ordered(ident_t *, gtid); Also for 'for' directives with the dynamic scheduling and an 'ordered' clause added a call to '__kmpc_dispatch_fini_(4|8)[u]()' function after increment expression for loop control variable: while(__kmpc_dispatch_next(&LB, &UB)) { idx = LB; while (idx <= UB) { BODY; ++idx; __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only. } // inner loop } Differential Revision: http://reviews.llvm.org/D9070 llvm-svn: 235496
* Make helper function static. NFC.Benjamin Kramer2015-04-181-3/+3
| | | | llvm-svn: 235253
* [OPENMP] Codegen for 'copyin' clause in 'parallel' directive.Alexey Bataev2015-04-161-2/+62
| | | | | | | | | | | | | | | Emits the following code for the clause at the beginning of the outlined function for implicit threads: if (<not a master thread>) { ... <thread local copy of var> = <master thread local copy of var>; ... } <sync point>; Checking for a non-master thread is performed by comparing of the address of the thread local variable with the address of the master's variable. Master thread always uses original variables, so you always know the address of the variable in the master thread. Differential Revision: http://reviews.llvm.org/D9026 llvm-svn: 235075
* [OPENMP] Codegen for 'lastprivate' clause in 'for' directive.Alexey Bataev2015-04-161-4/+106
| | | | | | | | | | | | | | | | | | | | | | | | | | | #pragma omp for lastprivate(<var>) for (i = a; i < b; ++b) <BODY>; This construct is translated into something like: <last_iter> = alloca i32 <lastprivate_var> = alloca <type> <last_iter> = 0 ; No initializer for simple variables or a default constructor is called for objects. ; For arrays perform element by element initialization by the call of the default constructor. ... OMP_FOR_START(...,<last_iter>, ..); sets <last_iter> to 1 if this is the last iteration. <BODY> ... OMP_FOR_END if (<last_iter> != 0) { <var> = <lastprivate_var> ; Update original variable with the lastprivate value. } call __kmpc_cancel_barrier() ; an implicit barrier to avoid possible data race. Differential Revision: http://reviews.llvm.org/D8658 llvm-svn: 235074
OpenPOWER on IntegriCloud