[PATCH] [OPENMP] Do not emit references to original variables in 'private' clause.
Bataev, Alexey
a.bataev at hotmail.com
Mon May 18 20:49:35 PDT 2015
John, we need all this stuff because of asynchronous nature of tasks.
In other OpenMP directives we can directly allocate private copies and
use them instead of the original variables in the outlined OpenMP function:
void outlined(...) {
%g = alloca i32
store i32 0, %g
}
But for tasks we cannot allocate private copies on stack in the outlined
function. It happens because there are actually 2 kind of tasks - tied
tasks and untied tasks. Untied tasks may have many entry/exit points and
because of that we cant simply allocate private copies in the outlined
function.
Also we can't allocate memory for these privates in a calling function
because tasks are asynchronous and the parent function may be terminated
earlier than the task itself.
Instead we're adding private copies at the end of kmp_task_t structure
and the memory for them is allocated by the runtime. Also we're
generating a function with the destructors calls for each private field
(if it is required) and provide a pointer to this function to runtime:
1. struct kmp_task_t_with_privates {
struct kmp_task_t {
void *shareds; /**< pointer to block of pointers to shared vars */
kmp_routine_entry_t routine; /**< pointer to outlined
function for tasks */
kmp_int32 part_id; /**< part id for the untied
task (defines current entry point) */
kmp_routine_entry_t destructors; /* pointer to function to
invoke deconstructors of private C++ objects */
} task_data;
struct .kmp_private. { // private copies of all private/firstprivate
variables
int a;
S s;
} privates;
};
2. Our outlined function for task has the next profile
void oulined(int ThreadID, int PartId, void *shareds) {
...
}
This function with this profile is automatically generated from
CapturedStmt construct.
3. Then we have to create a task using
void *new_task = __kmpc_task_allocate(<loc>, i32 ThreadId, flags, size_t
sizeof(kmp_task_t_with_privates), size_t sizeof(shareds),
kmp_routine_entry_t outlined);
libcall and it returns a pointer to created kmp_task_t_with_privates
structure.
4. We have to initialize our private copies:
(kmp_task_t_with_privates*)new_task->privates.a = original_a; // if 'a'
is a firstprivate;
DefaultConstructor_for_S_class
(&(kmp_task_t_with_privates*)new_task->privates.s); // if 's' is a
private and because of that it must be initialized with the default
constructor.
5. We have to generate a function for destructors calls:
void destructors(kmp_task_t_with_privates *task) {
~Destructor_for_S_class(&task->privates.s);
}
...
(kmp_task_t_with_privates*)new_task->task_data.destructors =
(kmp_routine_entry_t)&destructors;
6. You're saying that capture field is not initialized. It is not so.
We're using it to provide a reference to private copy to outlined task
function:
(shareds_type*)((kmp_task_t_with_privates*)new_task->task_data.shareds)->ref_a
= &(kmp_task_t_with_privates*)new_task->privates.a;
(shareds_type*)((kmp_task_t_with_privates*)new_task->task_data.shareds)->ref_s
= &(kmp_task_t_with_privates*)new_task->privates.s;
So we have to initialize these references manually rather than
automatically as for other constructs.
Shareds is the structure of captures generated by the CapturedStmt
construct.
7. We're creating a task by calling
__kmpc_omp_task(<loc>, i32 ThreadId, new_task);
This is how tasks are implemented in libiomp5 runtime library.
19.05.2015 1:56, John McCall пишет:
> Can you expand a bit on what the task directive needs the capture field for if it's never initialized? This feels like a very significant change, and I'd be a lot happier if the field could be dropped entirely.
>
> At the very least, CapturedStmt need to document this.
>
>
> ================
> Comment at: lib/CodeGen/CGStmt.cpp:2120
> @@ +2119,3 @@
> + // Do not emit initialization for OpenMP private variables.
> + if (CurField->hasCapturedVLAType() || *I) {
> + LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
> ----------------
> The more officially-approved way to do this would be to use "continue". Not a big deal, though.
>
> http://reviews.llvm.org/D9550
>
> EMAIL PREFERENCES
> http://reviews.llvm.org/settings/panel/emailpreferences/
>
>
>
>
--
Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team
More information about the cfe-commits
mailing list