-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[OpenMP][WIP] Use ATTACH maps for array-sections/subscripts on pointers. #153683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[OpenMP][WIP] Use ATTACH maps for array-sections/subscripts on pointers. #153683
Conversation
For the following: ```c int *p; \#pragma omp target map(p[0]) // (A) (void)p; \#pragma omp target map(p) // (B) (void)p; \#pragma omp target map(p, p[0]) // (C) (void)p; \#pragma omp target map(p[0], p) // (D) (void)p; ``` For (A), the pointer `p` is predetermined `firstprivate`, so it should be (and is) captured by-copy. However, for (B), (C), and (D), since `p` is already listed in a `map` clause, it's not predetermined `firstprivate`, and hence, should be captured by-reference, like any other mapped variable. To ensure the correct handling of (C) and (D), the following changes were made: 1. In SemaOpenMP, we now ensure that `p` is marked to be captured by-reference in these cases. 2. We no longer ignore `map(p)` during codegen of `target` constructs, even if there's another map like `map(p[0])` that would have been mapped using a PTR_AND_OBJ map. 3. For cases like (D), we now handle `map(p)` before `map(p[0])`, so the former gets the TARGET_PARAM flag and sets the kernel argument.
… before their derefs.
The output of the compile-and-run tests is incorrect. These will be used for reference in future commits that resolve the issues. Also updated the existing clang LIT test, target_map_both_pointer_pointee_codegen.cpp, with more regions and more narrowed-down update_cc_test_checks filters.
…mapped-ptrs-by-ref
…ion-using-attach-maptype
…ion-using-attach-maptype
This patch introduces libomptarget support for the ATTACH map-type, which can be used to implement OpenMP conditional compliant pointer attachment, based on whether the pointer/pointee is newly mapped on a given construct. For example, for the following: ```c int *p; #pragma omp target enter data map(p[1:10]) ``` The following maps can be emitted by clang: ``` (A) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM &p, &p[1], sizeof(p), ATTACH ``` Without this map-type, the two possible maps emitted by clang: ``` (B) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM (C) &p, &p[1], 10 * sizeof(p[1]), TO | FROM | PTR_AND_OBJ ```` (B) does not perform any pointer attachment, while (C) also maps the pointer p, which are both incorrect. In terms of implementation, maps with the ATTACH map-type are handled after all other maps have been processed, as it requires knowledge of which new allocations happened as part of the construct. As per OpenMP 5.0, an attachment should happen only when either the pointer or the pointee was newly mapped while handling the construct. Maps with ATTACH map-type-bit do not increase/decrease the ref-count. With OpenMP 6.1, `attach(always/never)` can be used to force/prevent attachment. For `attach(always)`, the compiler will insert the ALWAYS map-type, which would let libomptarget bypass the check about one of the pointer/pointee being new. With `attach(never)`, the ATTACH map will not be emitted at all. The size argument of the ATTACH map-type can specify values greater than `sizeof(void*)` which can be used to support pointer attachment on Fortran descriptors. Note that this also requires shadow-pointer tracking to also support them. That has not been implemented in this patch. This was worked upon in coordination with Ravi Narayanaswamy, who has since retired. Happy retirement, Ravi!
This patch introduces libomptarget support for the ATTACH map-type, which can be used to implement OpenMP conditional compliant pointer attachment, based on whether the pointer/pointee is newly mapped on a given construct. For example, for the following: ```c int *p; #pragma omp target enter data map(p[1:10]) ``` The following maps can be emitted by clang: ``` (A) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM &p, &p[1], sizeof(p), ATTACH ``` Without this map-type, the two possible maps emitted by clang: ``` (B) &p[0], &p[1], 10 * sizeof(p[1]), TO | FROM (C) &p, &p[1], 10 * sizeof(p[1]), TO | FROM | PTR_AND_OBJ ```` (B) does not perform any pointer attachment, while (C) also maps the pointer p, which are both incorrect. In terms of implementation, maps with the ATTACH map-type are handled after all other maps have been processed, as it requires knowledge of which new allocations happened as part of the construct. As per OpenMP 5.0, an attachment should happen only when either the pointer or the pointee was newly mapped while handling the construct. Maps with ATTACH map-type-bit do not increase/decrease the ref-count. With OpenMP 6.1, `attach(always/never)` can be used to force/prevent attachment. For `attach(always)`, the compiler will insert the ALWAYS map-type, which would let libomptarget bypass the check about one of the pointer/pointee being new. With `attach(never)`, the ATTACH map will not be emitted at all. The size argument of the ATTACH map-type can specify values greater than `sizeof(void*)` which can be used to support pointer attachment on Fortran descriptors. Note that this also requires shadow-pointer tracking to also support them. That has not been implemented in this patch. This was worked upon in coordination with Ravi Narayanaswamy, who has since retired. Happy retirement, Ravi!
…ay-section-using-attach-maptype
…erateInfoForCaptureFromClauseInfo. This will be useful for future changes where we use the information outside this function.
…s by attach-ptrs.
target-data, fix matching of use-device-ptr/addr.
…uce-attach-support
…ay-section-using-attach-maptype
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions inc,c,cpp,h -- clang/include/clang/AST/OpenMPClause.h clang/include/clang/Basic/OpenMPKinds.h clang/lib/Basic/OpenMPKinds.cpp clang/lib/CodeGen/CGOpenMPRuntime.cpp clang/lib/Sema/SemaOpenMP.cpp clang/test/OpenMP/bug60602.cpp clang/test/OpenMP/copy-gaps-1.cpp clang/test/OpenMP/copy-gaps-6.cpp clang/test/OpenMP/reduction_implicit_map.cpp clang/test/OpenMP/target_data_codegen.cpp clang/test/OpenMP/target_data_map_codegen_hold.cpp clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp clang/test/OpenMP/target_data_use_device_addr_codegen.cpp clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp clang/test/OpenMP/target_map_codegen_18.inc clang/test/OpenMP/target_map_codegen_19.cpp clang/test/OpenMP/target_map_codegen_20.cpp clang/test/OpenMP/target_map_codegen_21.cpp clang/test/OpenMP/target_map_codegen_22.cpp clang/test/OpenMP/target_map_codegen_23.cpp clang/test/OpenMP/target_map_codegen_26.cpp clang/test/OpenMP/target_map_codegen_27.cpp clang/test/OpenMP/target_map_codegen_33.cpp clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp clang/test/OpenMP/target_map_ptr_and_star_global.cpp clang/test/OpenMP/target_map_ptr_and_star_local.cpp clang/test/OpenMP/target_map_structptr_and_member_global.cpp clang/test/OpenMP/target_map_structptr_and_member_local.cpp clang/test/OpenMP/target_task_affinity_codegen.cpp llvm/include/llvm/Frontend/OpenMP/OMPConstants.h llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp offload/include/OpenMP/Mapping.h offload/include/device.h offload/include/omptarget.h offload/libomptarget/device.cpp offload/libomptarget/interface.cpp offload/libomptarget/omptarget.cpp offload/plugins-nextgen/amdgpu/src/rtl.cpp offload/plugins-nextgen/common/include/PluginInterface.h offload/plugins-nextgen/common/src/PluginInterface.cpp offload/plugins-nextgen/cuda/src/rtl.cpp offload/plugins-nextgen/host/src/rtl.cpp offload/test/mapping/map_ptr_and_star_global.c offload/test/mapping/map_ptr_and_star_local.c offload/test/mapping/map_ptr_and_subscript_global.c offload/test/mapping/map_ptr_and_subscript_local.c offload/test/mapping/map_structptr_and_member_global.c offload/test/mapping/map_structptr_and_member_local.c View the diff from clang-format here.diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index c1a92970c..7f6cc22d0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8993,8 +8993,9 @@ private:
IE->dump();
}
}
- // For use_device_addr, we match an existing map clause if its attach-ptr
- // is same as the attach-ptr of the use_device_addr clause. e.g.
+ // For use_device_addr, we match an existing map clause if its
+ // attach-ptr is same as the attach-ptr of the use_device_addr clause.
+ // e.g.
// map(p) use_device_addr(p) // match
// map(p[1]) use_device_addr(p[0]) // match
// map(ps->a) use_device_addr(ps->b) // match
@@ -9762,7 +9763,8 @@ public:
->isPointerType()) || /*&&
// Check if both component lists share the same attach pointer
// This allows struct member access through pointers when they
- // belong to the same struct, including nested cases like ps->qs->x
+ // belong to the same struct, including nested cases like
+ ps->qs->x
!(AttachPtr1 &&
AttachPtr2 &&
AttachPtr1 == AttachPtr2)) ||*/
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently failing. Please ignore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is currently failing. The IR hasn't been updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look at the comments in this example to see the maps we are emitting. It's a smaller/easier to read test.
// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976711171] | ||
// CHECK: @.offload_sizes.3 = private unnamed_addr constant [6 x i64] [i64 8, i64 8, i64 0, i64 0, i64 0, i64 4] | ||
// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [6 x i64] [i64 35, i64 16, i64 16, i64 844424930131971, i64 844424930131971, i64 844424930132483] | ||
// &spp[0], &spp[0], 0, IMPLICIT | PARAM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows how we handle mapping of struct-members that have the same attach-ptr. They are allocated as a contiguous chunk.
// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976711171] | ||
// CHECK: @.offload_sizes.3 = private unnamed_addr constant [6 x i64] [i64 8, i64 8, i64 0, i64 0, i64 0, i64 4] | ||
// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [6 x i64] [i64 35, i64 16, i64 16, i64 844424930131971, i64 844424930131971, i64 844424930132483] | ||
// &spp[0], &spp[0], 0, IMPLICIT | PARAM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implicit map is because spp is a pointer referenced within the target construct, and neither spp, nor an expression that has spp as its attach-ptr is mapped on the construct.
…on-using-attach-maptype
This is the initial clang change to support using
ATTACH
map-type for pointer-attachment.This includes changes from the following:
target
by reference. #145454For example, for the following:
The following maps are now emitted by clang:
Previously, the two possible maps emitted by clang were:
(B) does not perform any pointer attachment, while (C) also maps the
pointer p, both of which are incorrect.
With this change, we are using ATTACH-style maps, like
(A)
, for cases where the expression has a base-pointer. For example:We also group mapping of clauses with the same base decl in the order of the increasing complexity of their base-pointers, e.g. for something like:
We first map
spp
, thenspp[0]
then spp[0][0] and spp[0][0].a.This allows us to also group "struct" allocation based on their attach pointers.
Cases that need handling:
p
is a base-pointer in a map from a member function within the same class, p is not beingprivatized
, instead, we still try to create an implicit map ofthis[0:1]
, and accessp
through that, which is incorrect.use_device_addr
clause does not work properly, because we don't have a proper component-list set-up for it, just one component, so we cannot find the proper attach-ptr. Foruse_device_addr
, we should match existing maps whose attach-ptr matches the attach-ptr of theuse_device_addr
operand.use_device_ptr
handling has some issues too. Need debugging.Some tests still haven't been updated. These include: