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



_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to