[Clang][OpenMP] Capture mapped pointers on target by reference. by abhinavgaba · Pull Request #145454 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-offload
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: Abhinav Gaba (abhinavgaba)

Changes

For the following:

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.

Patch is 34.47 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/145454.diff

5 Files Affected:

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 8ccc37ef98a74..39571105e26b2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7270,8 +7270,14 @@ class MappableExprsHandler { // of arguments, hence MEMBER_OF(4) // // map(p, p[:100])

@@ -7289,14 +7295,26 @@ class MappableExprsHandler { // components. bool IsExpressionFirstInfo = true; bool FirstPointerInComplexData = false;

@@ -7672,7 +7690,7 @@ class MappableExprsHandler { getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, !IsExpressionFirstInfo || RequiresReference || FirstPointerInComplexData || IsMemberReference,

@@ -8811,8 +8829,19 @@ class MappableExprsHandler { ++EI; } }

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 00f4658180807..02e4e7b910d2e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2146,6 +2146,7 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // | ptr | n.a. | - | x | - | - | bycopy| // | ptr | n.a. | x | - | - | - | null | // | ptr | n.a. | - | - | - | x | byref |

@@ -2198,8 +2203,19 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,

       assert(EI != EE && "Invalid map expression!");

@@ -2213,8 +2229,10 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, isa(EI->getAssociatedExpression()) || isa(Last->getAssociatedExpression())) { IsVariableAssociatedWithSection = true;

@@ -2223,8 +2241,23 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,

 if (IsVariableUsedInMapClause) {
   // If variable is identified in a map clause it is always captured by

diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp index 87fa7fe462daa..9a8f234da718c 100644 --- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp +++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp @@ -1,174 +1,178 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --include-generated-funcs --replace-value-regex "_omp_offloading[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ // RUN: %clang_cc1 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s

// expected-no-diagnostics #ifndef HEADER #define HEADER

+// CHECK: @.[[KERNEL00:_omp_offloading.*foov_l[0-9]+]].region_id = weak constant i8 0 +// CHECK: [[SIZE00:@.+]] = private unnamed_addr constant [2 x i64] [i64 {{8|4}}, i64 8] +// CHECK: [[MYTYPE00:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 19] + +// CHECK: @.[[KERNEL01:_omp_offloading.*foov_l[0-9]+]].region_id = weak constant i8 0 +// CHECK: [[SIZE01:@.+]] = private unnamed_addr constant [2 x i64] [i64 {{8|4}}, i64 4] +// CHECK: [[MYTYPE01:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 19] + +// CHECK: @.[[KERNEL02:_omp_offloading.*foov_l[0-9]+]].region_id = weak constant i8 0 +// CHECK: [[SIZE02:@.+]] = private unnamed_addr constant [2 x i64] [i64 {{8|4}}, i64 4] +// CHECK: [[MYTYPE02:@.+]] = private unnamed_addr constant [2 x i64] [i64 35, i64 19] + +// CHECK: [[SIZE03:@.+]] = private unnamed_addr constant [1 x i64] [i64 4] +// CHECK: [[MYTYPE03:@.+]] = private unnamed_addr constant [1 x i64] [i64 51] + extern void *malloc (int __size) throw () attribute ((malloc));

+// CHECK-LABEL: define{{.}}@_Z3foov{{.}}( void foo() { int *ptr = (int *) malloc(3 * sizeof(int));

+// Region 00 +// &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM +// &ptr, &ptr[0], 2 * sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ +// +// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.[[KERNEL00]].region_id, ptr [[ARGS:%.+]]) +// CHECK-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2 +// CHECK-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]] +// CHECK-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3 +// CHECK-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]] +// CHECK-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] +// CHECK-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// +// CHECK-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 +// CHECK-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CHECK-DAG: store ptr [[VAR0:%ptr]], ptr [[BP0]] +// CHECK-DAG: store ptr [[VAR0]], ptr [[P0]] +// +// CHECK-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CHECK-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CHECK-DAG: store ptr [[VAR0:%ptr]], ptr [[BP1]] +// CHECK-DAG: store ptr [[RVAR00:%.+]], ptr [[P1]] +// +// CHECK-DAG: [[RVAR00]] = getelementptr inbounds {{.}}[[RVAR0:%.+]], i{{.+}} 0 +// CHECK-DAG: [[RVAR0]] = load ptr, ptr [[VAR0]] +// +// CHECK-DAG: call void @[[KERNEL00]](ptr [[VAR0]]) #pragma omp target map(ptr, ptr[0:2]) { ptr[1] = 6; } + +// Region 01 +// &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM +// &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ +// +// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.[[KERNEL01]].region_id, ptr [[ARGS:%.+]]) +// CHECK-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2 +// CHECK-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]] +// CHECK-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3 +// CHECK-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]] +// CHECK-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] +// CHECK-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] +// +// CHECK-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 +// CHECK-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 +// CHECK-DAG: store ptr [[VAR0:%ptr]], ptr [[BP0]] +// CHECK-DAG: store ptr [[VAR0]], ptr [[P0]] +// +// CHECK-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 +// CHECK-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 +// CHECK-DAG: store ptr [[VAR0:%ptr]], ptr [[BP1]] +// CHECK-DAG: store ptr [[RVAR02:%.+]], ptr [[P1]] +// +// CHECK-DAG: [[RVAR02]] = getelementptr inbounds {{.}}[[RVAR0:%.+]], i{{.+}} 2 +// CHECK-DAG: [[RVAR0]] = load ptr, ptr [[VAR0]] +// +// CHECK-DAG: call void @[[KERNEL01]](ptr [[VAR0]]) #pragma omp target map(ptr, ptr[2]) { ptr[2] = 8; }