[clang] [llvm] [OpenMP][WIP] Use ATTACH maps for array-sections/subscripts on pointers. (PR #153683)

Abhinav Gaba via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 14 16:04:45 PDT 2025


https://github.com/abhinavgaba updated https://github.com/llvm/llvm-project/pull/153683

>From d867ab3a20b1999cb5b00554fdb21cbe6766a1d5 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 22 Jun 2025 18:36:16 -0700
Subject: [PATCH 01/66] [Clang][OpenMP] Capture mapped pointers on `target` by
 reference.

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.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |  37 ++-
 clang/lib/Sema/SemaOpenMP.cpp                 |  51 ++-
 ...arget_map_both_pointer_pointee_codegen.cpp | 290 +++++++++---------
 .../mapping/map_ptr_and_subscript_global.c    |  65 ++++
 4 files changed, 287 insertions(+), 156 deletions(-)
 create mode 100644 offload/test/mapping/map_ptr_and_subscript_global.c

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])
+    // For "pragma omp target":
+    // &p, &p, sizeof(p), TARGET_PARAM | TO | FROM
+    // &p, &p[0], 100*sizeof(float), PTR_AND_OBJ | TO | FROM (*)
+    // Otherwise:
     // ===> map(p[:100])
     // &p, &p[0], 100*sizeof(float), TARGET_PARAM | PTR_AND_OBJ | TO | FROM
+    // (*) We need to use PTR_AND_OBJ here to ensure that the mapped copies of
+    // p and p[0] get attached.
 
     // Track if the map information being generated is the first for a capture.
     bool IsCaptureFirstInfo = IsFirstComponentList;
@@ -7289,14 +7295,26 @@ class MappableExprsHandler {
     // components.
     bool IsExpressionFirstInfo = true;
     bool FirstPointerInComplexData = false;
+    bool SkipStandalonePtrMapping = false;
     Address BP = Address::invalid();
     const Expr *AssocExpr = I->getAssociatedExpression();
     const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-    if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
+    // For map(p, p[0]) on a "target" construct, we need to map "p" by itself
+    // as it has to be passed by-reference as the kernel argument.
+    // For other constructs, we can skip mapping "p" because the PTR_AND_OBJ
+    // mapping for map(p[0]) will take care of mapping p as well.
+    SkipStandalonePtrMapping =
+        AreBothBasePtrAndPteeMapped &&
+        (!isa<const OMPExecutableDirective *>(CurDir) ||
+         !isOpenMPTargetExecutionDirective(
+             cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind()));
+
+    if (SkipStandalonePtrMapping && std::next(I) == CE)
       return;
+
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
@@ -7672,7 +7690,7 @@ class MappableExprsHandler {
               getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
                              !IsExpressionFirstInfo || RequiresReference ||
                                  FirstPointerInComplexData || IsMemberReference,
-                             AreBothBasePtrAndPteeMapped ||
+                             SkipStandalonePtrMapping ||
                                  (IsCaptureFirstInfo && !RequiresReference),
                              IsNonContiguous);
 
@@ -8811,8 +8829,19 @@ class MappableExprsHandler {
         ++EI;
       }
     }
-    llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
-                                             const MapData &RHS) {
+    llvm::stable_sort(DeclComponentLists, [VD](const MapData &LHS,
+                                               const MapData &RHS) {
+      // For cases like map(p, p[0], p[0][0]), the shortest map, like map(p)
+      // in this case, should be handled first, to ensure that it gets the
+      // TARGET_PARAM flag.
+      OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+          std::get<0>(LHS);
+      OMPClauseMappableExprCommon::MappableExprComponentListRef ComponentsR =
+          std::get<0>(RHS);
+      if (VD && VD->getType()->isAnyPointerType() && Components.size() == 1 &&
+          ComponentsR.size() > 1)
+        return true;
+
       ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
       OpenMPMapClauseKind MapType = std::get<1>(RHS);
       bool HasPresent =
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 |
+    // | ptr  |      n.a.     |  -  |   -   |       -       |   x, x[] | bycopy|
     // | ptr  |      n.a.     |  -  |   -   |       -       |    x[]   | bycopy|
     // | ptr  |      n.a.     |  -  |   -   |       x       |          | bycopy|
     // | ptr  |      n.a.     |  -  |   -   |       x       |     x    | bycopy|
@@ -2171,18 +2172,22 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
     //  - For pointers mapped by value that have either an implicit map or an
     //    array section, the runtime library may pass the NULL value to the
     //    device instead of the value passed to it by the compiler.
+    //  - If both a pointer an a dereference of it are mapped, then the pointer
+    //    should be passed by reference.
 
     if (Ty->isReferenceType())
       Ty = Ty->castAs<ReferenceType>()->getPointeeType();
 
-    // Locate map clauses and see if the variable being captured is referred to
-    // in any of those clauses. Here we only care about variables, not fields,
-    // because fields are part of aggregates.
+    // Locate map clauses and see if the variable being captured is mapped by
+    // itself, or referred to, in any of those clauses. Here we only care about
+    // variables, not fields, because fields are part of aggregates.
     bool IsVariableAssociatedWithSection = false;
+    bool IsVariableItselfMapped = false;
 
     DSAStack->checkMappableExprComponentListsForDeclAtLevel(
         D, Level,
         [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
+         &IsVariableItselfMapped,
          D](OMPClauseMappableExprCommon::MappableExprComponentListRef
                 MapExprComponents,
             OpenMPClauseKind WhereFoundClauseKind) {
@@ -2198,8 +2203,19 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
 
           assert(EI != EE && "Invalid map expression!");
 
-          if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
-            IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
+          if (isa<DeclRefExpr>(EI->getAssociatedExpression()) &&
+              EI->getAssociatedDeclaration() == D) {
+            IsVariableUsedInMapClause = true;
+
+            // If the component list has only one element, it's for mapping the
+            // variable itself, like map(p). This takes precedence in
+            // determining how it's captured, so we don't need to look further
+            // for any other maps that use the variable (like map(p[0]) etc.)
+            if (MapExprComponents.size() == 1) {
+              IsVariableItselfMapped = true;
+              return true;
+            }
+          }
 
           ++EI;
           if (EI == EE)
@@ -2213,8 +2229,10 @@ bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
               isa<MemberExpr>(EI->getAssociatedExpression()) ||
               isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
             IsVariableAssociatedWithSection = true;
-            // There is nothing more we need to know about this variable.
-            return true;
+            // We've found a case like map(p[0]) or map(p->a) or map(*p),
+            // so we are done with this particular map, but we need to keep
+            // looking in case we find a map(p).
+            return false;
           }
 
           // Keep looking for more map info.
@@ -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
-      // reference except if it is a pointer that is dereferenced somehow.
-      IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
+      // reference except if it is a pointer that is dereferenced somehow, but
+      // not itself mapped.
+      //
+      // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
+      // in a construct::
+      // If a list item in a has_device_addr clause or in a map clause on the
+      // target construct has a base pointer, and the base pointer is a scalar
+      // variable *that is not a list item in a map clause on the construct*,
+      // the base pointer is firstprivate.
+      //
+      // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
+      // Referenced in a Construct:
+      // If an array section is a list item in a map clause on the target
+      // construct and the array section is derived from a variable for which
+      // the type is pointer then that variable is firstprivate.
+      IsByRef = IsVariableItselfMapped ||
+                !(Ty->isPointerType() && IsVariableAssociatedWithSection);
     } else {
       // By default, all the data that has a scalar type is mapped by copy
       // (except for reduction variables).
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;
   }
-  #pragma omp target data map(ptr, ptr[2])
+
+// Region 02
+//   &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 @.[[KERNEL02]].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 @[[KERNEL02]](ptr [[VAR0]])
+  #pragma omp target map(ptr[2], ptr)
   {
     ptr[2] = 9;
   }
+
+// Region 03
+//   &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+//   FIXME: PARAM seems to be redundant here.
+//
+// CHECK-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 1, ptr [[BPGEP:.+]], ptr [[PGEP:.+]], ptr [[SIZE03]], ptr [[MYTYPE03]], ptr null, ptr null)
+// 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 [[RVAR02:%.+]], ptr [[P0]]
+//
+// CHECK-DAG: [[RVAR02]] = getelementptr inbounds {{.*}}[[RVAR0:%.+]], i{{.+}} 2
+// CHECK-DAG: [[RVAR0]] = load ptr, ptr [[VAR0]]
+  #pragma omp target data map(ptr, ptr[2])
+  {
+    ptr[2] = 10;
+  }
 }
-#endif
-// CHECK-LABEL: define {{[^@]+}}@_Z3foov
-// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+
+// CHECK-LABEL: define internal void
+// CHECK-SAME: @[[KERNEL00]](ptr {{[^,]*}}[[PTR:%[^,]+]])
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS9:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS10:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS11:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[CALL:%.*]] = call noalias noundef ptr @_Z6malloci(i32 noundef signext 12) #[[ATTR3:[0-9]+]]
-// CHECK-NEXT:    store ptr [[CALL]], ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP4]], align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP7]], align 4
-// CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP8]], align 4
-// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP5]], ptr [[TMP9]], align 8
-// CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP10]], align 8
-// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes, ptr [[TMP11]], align 8
-// CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP12]], align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP13]], align 8
-// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP14]], align 8
-// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP15]], align 8
-// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP16]], align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP17]], align 4
-// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP18]], align 4
-// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP19]], align 4
-// CHECK-NEXT:    [[TMP20:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15.region_id, ptr [[KERNEL_ARGS]])
-// CHECK-NEXT:    [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0
-// CHECK-NEXT:    br i1 [[TMP21]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
-// CHECK:       omp_offload.failed:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15(ptr [[TMP0]]) #[[ATTR3]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT]]
-// CHECK:       omp_offload.cont:
-// CHECK-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP23]], i64 2
-// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP24]], align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP25]], align 8
-// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP26]], align 8
-// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP29]], align 4
-// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP30]], align 4
-// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP27]], ptr [[TMP31]], align 8
-// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP28]], ptr [[TMP32]], align 8
-// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes.1, ptr [[TMP33]], align 8
-// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP34]], align 8
-// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP35]], align 8
-// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP36]], align 8
-// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP37]], align 8
-// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP38]], align 8
-// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP39]], align 4
-// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP40]], align 4
-// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP41]], align 4
-// CHECK-NEXT:    [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19.region_id, ptr [[KERNEL_ARGS5]])
-// CHECK-NEXT:    [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0
-// CHECK-NEXT:    br i1 [[TMP43]], label [[OMP_OFFLOAD_FAILED6:%.*]], label [[OMP_OFFLOAD_CONT7:%.*]]
-// CHECK:       omp_offload.failed6:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19(ptr [[TMP22]]) #[[ATTR3]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT7]]
-// CHECK:       omp_offload.cont7:
-// CHECK-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds i32, ptr [[TMP44]], i64 2
-// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP45]], align 8
-// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP46]], align 8
-// CHECK-NEXT:    [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS11]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP47]], align 8
-// CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP48]], ptr [[TMP49]], ptr @.offload_sizes.3, ptr @.offload_maptypes.4, ptr null, ptr null)
-// CHECK-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX12:%.*]] = getelementptr inbounds i32, ptr [[TMP50]], i64 2
-// CHECK-NEXT:    store i32 9, ptr [[ARRAYIDX12]], align 4
-// CHECK-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP51]], ptr [[TMP52]], ptr @.offload_sizes.3, ptr @.offload_maptypes.4, ptr null, ptr null)
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr
+// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]]
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i{{.*}} 1
+// CHECK-NEXT:    store i32 6, ptr [[ARRAYIDX]]
 // CHECK-NEXT:    ret void
-//
-//
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2:[0-9]+]] {
+
+// CHECK-LABEL: define internal void
+// CHECK-SAME: @[[KERNEL01]](ptr {{[^,]*}}[[PTR:%[^,]+]])
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
-// CHECK-NEXT:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr
+// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]]
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i{{.*}} 2
+// CHECK-NEXT:    store i32 8, ptr [[ARRAYIDX]]
 // CHECK-NEXT:    ret void
-//
-//
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2]] {
+
+// CHECK-LABEL: define internal void
+// CHECK-SAME: @[[KERNEL02]](ptr {{[^,]*}}[[PTR:%[^,]+]])
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK-NEXT:    store i32 8, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr
+// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]]
+// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i{{.*}} 2
+// CHECK-NEXT:    store i32 9, ptr [[ARRAYIDX]]
 // CHECK-NEXT:    ret void
-//
+#endif
diff --git a/offload/test/mapping/map_ptr_and_subscript_global.c b/offload/test/mapping/map_ptr_and_subscript_global.c
new file mode 100644
index 0000000000000..1861064bc95df
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_subscript_global.c
@@ -0,0 +1,65 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+int *p;
+
+void f1() {
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to:p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *p0_mappedptr =
+      (int *)omp_get_mapped_ptr(&p[0], omp_get_default_device());
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("p0_mappedptr %s null\n", p0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: p0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(p[0]) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[0]);
+    // CHECK: 111 0 1
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : p[0], p) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[0]);
+    // CHECK: 111 1 1
+    p++;
+  }
+
+#pragma omp target map(to : p, p[0]) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[-1]);
+    // CHECK: 222 1 1
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[-2]);
+    // CHECK: 333 1 1
+  }
+
+#pragma omp target exit data map(delete:p[0 : 5], p)
+}
+
+int main() { f1(); }

>From 97b2dfff5b85e6e011eb241615fb4babd9bfb7ab Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 23 Jun 2025 21:19:21 -0700
Subject: [PATCH 02/66] Add another test, minor clang-format fix.

---
 .../mapping/map_ptr_and_subscript_global.c    |  7 +-
 .../mapping/map_ptr_and_subscript_local.c     | 66 +++++++++++++++++++
 2 files changed, 70 insertions(+), 3 deletions(-)
 create mode 100644 offload/test/mapping/map_ptr_and_subscript_local.c

diff --git a/offload/test/mapping/map_ptr_and_subscript_global.c b/offload/test/mapping/map_ptr_and_subscript_global.c
index 1861064bc95df..880a1e405b383 100644
--- a/offload/test/mapping/map_ptr_and_subscript_global.c
+++ b/offload/test/mapping/map_ptr_and_subscript_global.c
@@ -14,7 +14,7 @@ void f1() {
   p[3] = 444;
 
 #pragma omp target enter data map(to : p)
-#pragma omp target enter data map(to:p[0 : 5])
+#pragma omp target enter data map(to : p[0 : 5])
 
   int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
   int *p0_mappedptr =
@@ -53,13 +53,14 @@ void f1() {
     p++;
   }
 
-#pragma omp target map(present, alloc : p) firstprivate(p_mappedptr, p0_mappedptr)
+#pragma omp target map(present, alloc : p)                                     \
+    firstprivate(p_mappedptr, p0_mappedptr)
   {
     printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[-2]);
     // CHECK: 333 1 1
   }
 
-#pragma omp target exit data map(delete:p[0 : 5], p)
+#pragma omp target exit data map(delete : p[0 : 5], p)
 }
 
 int main() { f1(); }
diff --git a/offload/test/mapping/map_ptr_and_subscript_local.c b/offload/test/mapping/map_ptr_and_subscript_local.c
new file mode 100644
index 0000000000000..24c5d0c7c5532
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_subscript_local.c
@@ -0,0 +1,66 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+
+void f1() {
+  int *p;
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to : p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *p0_mappedptr =
+      (int *)omp_get_mapped_ptr(&p[0], omp_get_default_device());
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("p0_mappedptr %s null\n", p0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: p0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(p[0]) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[0]);
+    // CHECK: 111 0 1
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : p[0], p) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[0]);
+    // CHECK: 111 1 1
+    p++;
+  }
+
+#pragma omp target map(to : p, p[0]) firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[-1]);
+    // CHECK: 222 1 1
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p)                                     \
+    firstprivate(p_mappedptr, p0_mappedptr)
+  {
+    printf("%d %d %d\n", p[0], p_mappedptr == &p, p0_mappedptr == &p[-2]);
+    // CHECK: 333 1 1
+  }
+
+#pragma omp target exit data map(delete : p[0 : 5], p)
+}
+
+int main() { f1(); }

>From a31ea2a50e0e3206a98bf1c3580343f609db4d63 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 24 Jun 2025 11:21:01 -0700
Subject: [PATCH 03/66] Update the comparator for sort, plus minor additions to
 offload tests.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp               | 6 +++---
 offload/test/mapping/map_ptr_and_subscript_global.c | 7 +++++++
 offload/test/mapping/map_ptr_and_subscript_local.c  | 7 +++++++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 39571105e26b2..f126feb214b6a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8838,9 +8838,9 @@ class MappableExprsHandler {
           std::get<0>(LHS);
       OMPClauseMappableExprCommon::MappableExprComponentListRef ComponentsR =
           std::get<0>(RHS);
-      if (VD && VD->getType()->isAnyPointerType() && Components.size() == 1 &&
-          ComponentsR.size() > 1)
-        return true;
+      if (VD && VD->getType()->isAnyPointerType() &&
+          Components.size() != ComponentsR.size())
+        return Components.size() < ComponentsR.size();
 
       ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
       OpenMPMapClauseKind MapType = std::get<1>(RHS);
diff --git a/offload/test/mapping/map_ptr_and_subscript_global.c b/offload/test/mapping/map_ptr_and_subscript_global.c
index 880a1e405b383..fdbd050be4cc7 100644
--- a/offload/test/mapping/map_ptr_and_subscript_global.c
+++ b/offload/test/mapping/map_ptr_and_subscript_global.c
@@ -60,6 +60,13 @@ void f1() {
     // CHECK: 333 1 1
   }
 
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
 
diff --git a/offload/test/mapping/map_ptr_and_subscript_local.c b/offload/test/mapping/map_ptr_and_subscript_local.c
index 24c5d0c7c5532..30ef0ce706be9 100644
--- a/offload/test/mapping/map_ptr_and_subscript_local.c
+++ b/offload/test/mapping/map_ptr_and_subscript_local.c
@@ -60,6 +60,13 @@ void f1() {
     // CHECK: 333 1 1
   }
 
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
 

>From cc90643865a53ef341c486bc76f6091a508d9705 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 11 Jun 2025 12:17:00 -0700
Subject: [PATCH 04/66] [WIP] Use ATTACH maps for array-sections/subscripts on
 pointers.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 203 ++++--
 clang/test/OpenMP/bug60602.cpp                | 372 ++++++-----
 clang/test/OpenMP/reduction_implicit_map.cpp  | 613 ++++++++++--------
 ...ta_map_pointer_array_subscript_codegen.cpp |  30 +-
 .../target_data_use_device_addr_codegen.cpp   | 113 ++--
 .../target_data_use_device_ptr_codegen.cpp    |  76 ++-
 .../target_data_use_device_ptr_if_codegen.cpp |  31 +-
 clang/test/OpenMP/target_map_codegen_18.inc   | 106 ++-
 clang/test/OpenMP/target_map_codegen_19.cpp   |  15 +-
 clang/test/OpenMP/target_map_codegen_20.cpp   |  27 +-
 clang/test/OpenMP/target_map_codegen_21.cpp   |  54 +-
 clang/test/OpenMP/target_map_codegen_22.cpp   |  18 +-
 clang/test/OpenMP/target_map_codegen_26.cpp   |  60 +-
 clang/test/OpenMP/target_map_codegen_27.cpp   |  31 +-
 .../OpenMP/target_task_affinity_codegen.cpp   | 586 +++++++++--------
 .../llvm/Frontend/OpenMP/OMPConstants.h       |   3 +
 16 files changed, 1436 insertions(+), 902 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index f126feb214b6a..69d14f03b6af3 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7091,8 +7091,7 @@ class MappableExprsHandler {
       const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false,
       const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
-          OverlappedElements = {},
-      bool AreBothBasePtrAndPteeMapped = false) const {
+          OverlappedElements = {}) const {
     // The following summarizes what has to be generated for each map and the
     // types below. The generated information is expressed in this order:
     // base pointer, section pointer, size, flags
@@ -7270,14 +7269,9 @@ class MappableExprsHandler {
     //     of arguments, hence MEMBER_OF(4)
     //
     // map(p, p[:100])
-    // For "pragma omp target":
-    // &p, &p, sizeof(p), TARGET_PARAM | TO | FROM
-    // &p, &p[0], 100*sizeof(float), PTR_AND_OBJ | TO | FROM (*)
-    // Otherwise:
-    // ===> map(p[:100])
-    // &p, &p[0], 100*sizeof(float), TARGET_PARAM | PTR_AND_OBJ | TO | FROM
-    // (*) We need to use PTR_AND_OBJ here to ensure that the mapped copies of
-    // p and p[0] get attached.
+    // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
+    // &p[0], &p[0], 100*sizeof(float), TO | FROM
+    // &p, &p[0], sizeof(float*), ATTACH
 
     // Track if the map information being generated is the first for a capture.
     bool IsCaptureFirstInfo = IsFirstComponentList;
@@ -7302,19 +7296,12 @@ class MappableExprsHandler {
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-    // For map(p, p[0]) on a "target" construct, we need to map "p" by itself
-    // as it has to be passed by-reference as the kernel argument.
-    // For other constructs, we can skip mapping "p" because the PTR_AND_OBJ
-    // mapping for map(p[0]) will take care of mapping p as well.
-    SkipStandalonePtrMapping =
-        AreBothBasePtrAndPteeMapped &&
-        (!isa<const OMPExecutableDirective *>(CurDir) ||
-         !isOpenMPTargetExecutionDirective(
-             cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind()));
-
-    if (SkipStandalonePtrMapping && std::next(I) == CE)
-      return;
+    // ATTACH entries are generated based solely on array section presence
 
+    // Track info for ATTACH entry generation
+    bool ShouldGenerateAttachEntry = false;
+    Address AttachBaseAddr = Address::invalid();
+    Address AttachFirstElemAddr = Address::invalid();
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
@@ -7357,9 +7344,8 @@ class MappableExprsHandler {
         // can be associated with the combined storage if shared memory mode is
         // active or the base declaration is not global variable.
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
-        if (!AreBothBasePtrAndPteeMapped &&
-            (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
-             !VD || VD->hasLocalStorage()))
+        if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
+            !VD || VD->hasLocalStorage())
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
         else
           FirstPointerInComplexData = true;
@@ -7469,6 +7455,8 @@ class MappableExprsHandler {
       // types.
       const auto *OASE =
           dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
+      const auto *ASE =
+          dyn_cast<ArraySubscriptExpr>(I->getAssociatedExpression());
       const auto *OAShE =
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
       const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
@@ -7643,6 +7631,40 @@ class MappableExprsHandler {
           break;
         }
         llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
+        // Check if this is an array section or subscript on a standalone pointer (not struct member)
+        bool IsArraySectionOnPointer = false;
+        
+        // Lambda to handle BP loading for global pointers
+        auto LoadGlobalPointerIfNeeded = [&]() {
+          if (FirstPointerInComplexData) {
+            QualType Ty = Components.rbegin()
+                              ->getAssociatedDeclaration()
+                              ->getType()
+                              .getNonReferenceType();
+            BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+            FirstPointerInComplexData = false;
+          }
+        };
+        
+        // Check if we should use ATTACH-style mapping for this expression
+        IsArraySectionOnPointer = shouldUseAttachStyleMapping(I->getAssociatedExpression(), EncounteredME != nullptr);
+        
+        if (IsArraySectionOnPointer) {
+          // For global pointers, load the pointer value so BP points to &p[0] instead of &p
+          LoadGlobalPointerIfNeeded();
+          // Set flags for ATTACH entry generation (only for the first array section/subscript we encounter)
+          if (!ShouldGenerateAttachEntry) {
+            ShouldGenerateAttachEntry = true;
+            if (OASE) {
+              AttachBaseAddr = CGF.EmitLValue(OASE->getBase()).getAddress();
+              AttachFirstElemAddr = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+            } else if (ASE) {
+              AttachBaseAddr = CGF.EmitLValue(ASE->getBase()).getAddress();
+              AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
+            }
+          }
+        }
+        
         // Skip adding an entry in the CurInfo of this combined entry if the
         // whole struct is currently being mapped. The struct needs to be added
         // in the first position before any data internal to the struct is being
@@ -7686,12 +7708,13 @@ class MappableExprsHandler {
           // same expression except for the first one. We also need to signal
           // this map is the first one that relates with the current capture
           // (there is a set of entries for each capture).
+          // Don't use PTR_AND_OBJ when we have array sections/subscripts on pointers
+          bool AddPtrFlag = (!IsExpressionFirstInfo || RequiresReference ||
+                             FirstPointerInComplexData || IsMemberReference) &&
+                            !IsArraySectionOnPointer;
           OpenMPOffloadMappingFlags Flags =
               getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
-                             !IsExpressionFirstInfo || RequiresReference ||
-                                 FirstPointerInComplexData || IsMemberReference,
-                             SkipStandalonePtrMapping ||
-                                 (IsCaptureFirstInfo && !RequiresReference),
+                             AddPtrFlag, IsCaptureFirstInfo && !RequiresReference,
                              IsNonContiguous);
 
           if (!IsExpressionFirstInfo || IsMemberReference) {
@@ -7784,6 +7807,34 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
+    // Generate ATTACH entry for array sections and subscripts on standalone
+    // pointers Info was already collected during the main component loop
+
+    if (ShouldGenerateAttachEntry && AttachBaseAddr.isValid() &&
+        AttachFirstElemAddr.isValid()) {
+      // Generate ATTACH entry: &pointer, &pointer[idx], sizeof(pointer), ATTACH
+      // Since this is for standalone pointers only, we use CombinedInfo
+      CombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
+      CombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
+      CombinedInfo.DevicePtrDecls.push_back(nullptr);
+      CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+      CombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
+      // Size is the size of the pointer itself - use pointer size, not BaseDecl
+      // size
+      llvm::Value *PointerSize = CGF.Builder.CreateIntCast(
+          llvm::ConstantInt::get(
+              CGF.CGM.SizeTy,
+              CGF.getContext().getTypeSize(
+                  CGF.getContext().getPointerType(CGF.getContext().VoidTy)) /
+                  8),
+          CGF.Int64Ty, /*isSigned=*/true);
+      CombinedInfo.Sizes.push_back(PointerSize);
+      // ATTACH flag
+      CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
+      CombinedInfo.Mappers.push_back(nullptr);
+      CombinedInfo.NonContigInfo.Dims.push_back(1);
+    }
+
     if (!IsNonContiguous)
       return;
 
@@ -8057,6 +8108,47 @@ class MappableExprsHandler {
     }
   }
 
+  /// Helper to check if we should use ATTACH-style mapping for single-level
+  /// pointers This is used for both ATTACH generation and use_device_ptr
+  /// consistency
+  static bool shouldUseAttachStyleMapping(const Expr *E,
+                                          bool IsInStructContext) {
+    if (IsInStructContext)
+    const Expr *BaseExpr = nullptr;
+    if (const auto *OASE = dyn_cast<ArraySectionExpr>(E)) {
+      if (!ArraySectionExpr::getBaseOriginalType(OASE->getBase())
+               .getCanonicalType()
+               ->isAnyPointerType())
+        return false;
+      BaseExpr = OASE->getBase();
+    } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+      if (!ArraySectionExpr::getBaseOriginalType(ASE->getBase())
+               .getCanonicalType()
+               ->isAnyPointerType())
+        return false;
+      BaseExpr = ASE->getBase();
+    } else {
+      return false;
+    }
+
+    // Only handle simple variable references to single-level pointers
+    // Skip complex expressions like (*q)[3:10] and multi-level pointers like
+    // q[1][3:5]
+    if (const auto *DRE =
+            dyn_cast<DeclRefExpr>(BaseExpr->IgnoreParenImpCasts())) {
+      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+        // Check that the original declaration is a single-level pointer, not
+        // pointer-to-pointer
+        QualType DeclType =
+            VD->getType().getNonReferenceType().getCanonicalType();
+        bool result = DeclType->isPointerType() &&
+               !DeclType->getPointeeType()->isPointerType();
+        return result;
+      }
+    }
+    return false;
+  }
+
   /// Generate all the base pointers, section pointers, sizes, map types, and
   /// mappers for the extracted mappable expressions (all included in \a
   /// CombinedInfo). Also, for each item that relates with a device pointer, a
@@ -8211,7 +8303,24 @@ class MappableExprsHandler {
           }
         };
 
-    auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF, const ValueDecl *VD,
+    // Helper to check if a component list uses ATTACH-style mapping for
+    // single-level pointers
+    auto ComponentListUsesAttachStyleMapping =
+        [](const auto &Components) -> bool {
+      if (Components.empty())
+        return false;
+
+      // Check if any component uses ATTACH-style mapping
+      for (const auto &Component : Components) {
+        const Expr *E = Component.getAssociatedExpression();
+        if (E && shouldUseAttachStyleMapping(E, false)) {
+          return true;
+        }
+      }
+      return false;
+    };
+
+    auto &&IsMapInfoExist = [&Info, &ComponentListUsesAttachStyleMapping](CodeGenFunction &CGF, const ValueDecl *VD,
                                     const Expr *IE, bool IsDevAddr) -> bool {
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
@@ -8246,7 +8355,12 @@ class MappableExprsHandler {
                   !VD->getType().getNonReferenceType()->isPointerType() ||
                   PrevCI == CI->Components.rend() ||
                   isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
-                  VarD->hasLocalStorage()) {
+                  VarD->hasLocalStorage() ||
+                  // For global pointers with ATTACH-style mapping, also allow
+                  // ReturnDevicePointer to ensure consistent behavior between
+                  // global and local pointers
+                  (VarD && !VarD->hasLocalStorage() &&
+                   ComponentListUsesAttachStyleMapping(CI->Components))) {
                 CI->ForDeviceAddr = IsDevAddr;
                 CI->ReturnDevicePointer = true;
                 Found = true;
@@ -8315,21 +8429,6 @@ class MappableExprsHandler {
       MapCombinedInfoTy StructBaseCurInfo;
       const Decl *D = Data.first;
       const ValueDecl *VD = cast_or_null<ValueDecl>(D);
-      bool HasMapBasePtr = false;
-      bool HasMapArraySec = false;
-      if (VD && VD->getType()->isAnyPointerType()) {
-        for (const auto &M : Data.second) {
-          HasMapBasePtr = any_of(M, [](const MapInfo &L) {
-            return isa_and_present<DeclRefExpr>(L.VarRef);
-          });
-          HasMapArraySec = any_of(M, [](const MapInfo &L) {
-            return isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
-                L.VarRef);
-          });
-          if (HasMapBasePtr && HasMapArraySec)
-            break;
-        }
-      }
       for (const auto &M : Data.second) {
         for (const MapInfo &L : M) {
           assert(!L.Components.empty() &&
@@ -8346,8 +8445,7 @@ class MappableExprsHandler {
               CurInfo, StructBaseCurInfo, PartialStruct,
               /*IsFirstComponentList=*/false, L.IsImplicit,
               /*GenerateAllInfoForClauses*/ true, L.Mapper, L.ForDeviceAddr, VD,
-              L.VarRef, /*OverlappedElements*/ {},
-              HasMapBasePtr && HasMapArraySec);
+              L.VarRef, /*OverlappedElements*/ {});
 
           // If this entry relates to a device pointer, set the relevant
           // declaration and add the 'return pointer' flag.
@@ -8805,8 +8903,6 @@ class MappableExprsHandler {
     assert(isa<const OMPExecutableDirective *>(CurDir) &&
            "Expect a executable directive");
     const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
-    bool HasMapBasePtr = false;
-    bool HasMapArraySec = false;
     for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
       const auto *EI = C->getVarRefs().begin();
       for (const auto L : C->decl_component_lists(VD)) {
@@ -8818,11 +8914,6 @@ class MappableExprsHandler {
         assert(VDecl == VD && "We got information for the wrong declaration??");
         assert(!Components.empty() &&
                "Not expecting declaration with no component lists.");
-        if (VD && E && VD->getType()->isAnyPointerType() && isa<DeclRefExpr>(E))
-          HasMapBasePtr = true;
-        if (VD && E && VD->getType()->isAnyPointerType() &&
-            (isa<ArraySectionExpr>(E) || isa<ArraySubscriptExpr>(E)))
-          HasMapArraySec = true;
         DeclComponentLists.emplace_back(Components, C->getMapType(),
                                         C->getMapTypeModifiers(),
                                         C->isImplicit(), Mapper, E);
@@ -9016,7 +9107,7 @@ class MappableExprsHandler {
             StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
             IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
             /*ForDeviceAddr=*/false, VD, VarRef,
-            /*OverlappedElements*/ {}, HasMapBasePtr && HasMapArraySec);
+            /*OverlappedElements*/ {});
       IsFirstComponentList = false;
     }
   }
diff --git a/clang/test/OpenMP/bug60602.cpp b/clang/test/OpenMP/bug60602.cpp
index 0789ef958e523..88af942cedb60 100644
--- a/clang/test/OpenMP/bug60602.cpp
+++ b/clang/test/OpenMP/bug60602.cpp
@@ -1,4 +1,4 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 2
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --version 2
 // Test host codegen.
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
 // expected-no-diagnostics
@@ -16,6 +16,12 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
   }
   return a[N-1];
 }
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [5 x i64] [i64 4, i64 0, i64 8, i64 0, i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [5 x i64] [i64 800, i64 35, i64 16384, i64 35, i64 16384]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [5 x i64] [i64 4, i64 0, i64 8, i64 0, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 800, i64 35, i64 16384, i64 35, i64 16384]
+//.
 // CHECK-LABEL: define dso_local noundef signext i32 @_Z18kernel_within_loopPiS_ii
 // CHECK-SAME: (ptr noundef [[A:%.*]], ptr noundef [[B:%.*]], i32 noundef signext [[N:%.*]], i32 noundef signext [[NUM_ITERS:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  entry:
@@ -25,20 +31,20 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
 // CHECK-NEXT:    [[NUM_ITERS_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[N_CASTED:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [3 x i64], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [5 x i64], align 8
 // CHECK-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK-NEXT:    [[N_CASTED3:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS8:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS9:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS10:%.*]] = alloca [3 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_SIZES11:%.*]] = alloca [3 x i64], align 8
+// CHECK-NEXT:    [[N_CASTED5:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS12:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS13:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS14:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_SIZES15:%.*]] = alloca [5 x i64], align 8
 // CHECK-NEXT:    [[TMP:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[DOTCAPTURE_EXPR_:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTCAPTURE_EXPR_12:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[KERNEL_ARGS14:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK-NEXT:    [[DOTCAPTURE_EXPR_16:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[KERNEL_ARGS18:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 8
 // CHECK-NEXT:    store ptr [[B]], ptr [[B_ADDR]], align 8
 // CHECK-NEXT:    store i32 [[N]], ptr [[N_ADDR]], align 4
@@ -62,171 +68,203 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
 // CHECK-NEXT:    [[TMP8:%.*]] = load i32, ptr [[N_ADDR]], align 4
 // CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP8]] to i64
 // CHECK-NEXT:    [[TMP9:%.*]] = mul nuw i64 [[CONV]], 4
-// CHECK-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP10]], i64 0
 // CHECK-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP11]], i64 0
-// CHECK-NEXT:    [[TMP12:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV2:%.*]] = sext i32 [[TMP12]] to i64
-// CHECK-NEXT:    [[TMP13:%.*]] = mul nuw i64 [[CONV2]], 4
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes, i64 24, i1 false)
-// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP14]], align 8
-// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP15]], align 8
-// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP16]], align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP17]], align 8
-// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP18]], align 8
-// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP9]], ptr [[TMP19]], align 8
-// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP20]], align 8
-// CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP10]], ptr [[TMP21]], align 8
-// CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP22]], align 8
-// CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 2
-// CHECK-NEXT:    store i64 [[TMP13]], ptr [[TMP23]], align 8
-// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP24]], align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP28]], align 4
-// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP29]], align 4
-// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP25]], ptr [[TMP30]], align 8
-// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP26]], ptr [[TMP31]], align 8
-// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP27]], ptr [[TMP32]], align 8
-// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP33]], align 8
-// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP34]], align 8
-// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP35]], align 8
-// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP36]], align 8
-// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP37]], align 8
-// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP38]], align 4
-// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP39]], align 4
-// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP40]], align 4
-// CHECK-NEXT:    [[TMP41:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2:[0-9]+]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9.region_id, ptr [[KERNEL_ARGS]])
-// CHECK-NEXT:    [[TMP42:%.*]] = icmp ne i32 [[TMP41]], 0
-// CHECK-NEXT:    br i1 [[TMP42]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP12]], i64 0
+// CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV3:%.*]] = sext i32 [[TMP13]] to i64
+// CHECK-NEXT:    [[TMP14:%.*]] = mul nuw i64 [[CONV3]], 4
+// CHECK-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP15]], i64 0
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes, i64 40, i1 false)
+// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP16]], align 8
+// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP17]], align 8
+// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP18]], align 8
+// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP19]], align 8
+// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP20]], align 8
+// CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP9]], ptr [[TMP21]], align 8
+// CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP22]], align 8
+// CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP23]], align 8
+// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP24]], align 8
+// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP25]], align 8
+// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP11]], ptr [[TMP26]], align 8
+// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[ARRAYIDX2]], ptr [[TMP27]], align 8
+// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
+// CHECK-NEXT:    store i64 [[TMP14]], ptr [[TMP28]], align 8
+// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK-NEXT:    store ptr null, ptr [[TMP29]], align 8
+// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP30]], align 8
+// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP31]], align 8
+// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK-NEXT:    store ptr null, ptr [[TMP32]], align 8
+// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP36]], align 4
+// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK-NEXT:    store i32 5, ptr [[TMP37]], align 4
+// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP33]], ptr [[TMP38]], align 8
+// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP34]], ptr [[TMP39]], align 8
+// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[TMP35]], ptr [[TMP40]], align 8
+// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP41]], align 8
+// CHECK-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP42]], align 8
+// CHECK-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP43]], align 8
+// CHECK-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP44]], align 8
+// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP45]], align 8
+// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP46]], align 4
+// CHECK-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP47]], align 4
+// CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP48]], align 4
+// CHECK-NEXT:    [[TMP49:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2:[0-9]+]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9.region_id, ptr [[KERNEL_ARGS]])
+// CHECK-NEXT:    [[TMP50:%.*]] = icmp ne i32 [[TMP49]], 0
+// CHECK-NEXT:    br i1 [[TMP50]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK:       omp_offload.failed:
 // CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9(i64 [[TMP3]], ptr [[TMP4]], ptr [[TMP5]]) #[[ATTR2:[0-9]+]]
 // CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK:       omp_offload.cont:
-// CHECK-NEXT:    [[TMP43:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP43]], ptr [[N_CASTED3]], align 4
-// CHECK-NEXT:    [[TMP44:%.*]] = load i64, ptr [[N_CASTED3]], align 8
-// CHECK-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP48]], i64 0
-// CHECK-NEXT:    [[TMP49:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV5:%.*]] = sext i32 [[TMP49]] to i64
-// CHECK-NEXT:    [[TMP50:%.*]] = mul nuw i64 [[CONV5]], 4
-// CHECK-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP52]], i64 0
-// CHECK-NEXT:    [[TMP53:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV7:%.*]] = sext i32 [[TMP53]] to i64
-// CHECK-NEXT:    [[TMP54:%.*]] = mul nuw i64 [[CONV7]], 4
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES11]], ptr align 8 @.offload_sizes.1, i64 24, i1 false)
-// CHECK-NEXT:    [[TMP55:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP44]], ptr [[TMP55]], align 8
-// CHECK-NEXT:    [[TMP56:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP44]], ptr [[TMP56]], align 8
-// CHECK-NEXT:    [[TMP57:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP57]], align 8
-// CHECK-NEXT:    [[TMP58:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[TMP47]], ptr [[TMP58]], align 8
-// CHECK-NEXT:    [[TMP59:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP59]], align 8
-// CHECK-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP50]], ptr [[TMP60]], align 8
-// CHECK-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP61]], align 8
-// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP51]], ptr [[TMP62]], align 8
-// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP63]], align 8
-// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 2
-// CHECK-NEXT:    store i64 [[TMP54]], ptr [[TMP64]], align 8
-// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP65]], align 8
-// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP69:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP69]], ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK-NEXT:    [[TMP70:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP70]], -2
+// CHECK-NEXT:    [[TMP51:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP51]], ptr [[N_CASTED5]], align 4
+// CHECK-NEXT:    [[TMP52:%.*]] = load i64, ptr [[N_CASTED5]], align 8
+// CHECK-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP56]], i64 0
+// CHECK-NEXT:    [[TMP57:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV7:%.*]] = sext i32 [[TMP57]] to i64
+// CHECK-NEXT:    [[TMP58:%.*]] = mul nuw i64 [[CONV7]], 4
+// CHECK-NEXT:    [[TMP59:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP59]], i64 0
+// CHECK-NEXT:    [[TMP60:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP61:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP61]], i64 0
+// CHECK-NEXT:    [[TMP62:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV10:%.*]] = sext i32 [[TMP62]] to i64
+// CHECK-NEXT:    [[TMP63:%.*]] = mul nuw i64 [[CONV10]], 4
+// CHECK-NEXT:    [[TMP64:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP64]], i64 0
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES15]], ptr align 8 @.offload_sizes.1, i64 40, i1 false)
+// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP52]], ptr [[TMP65]], align 8
+// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP52]], ptr [[TMP66]], align 8
+// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP67]], align 8
+// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP55]], ptr [[TMP68]], align 8
+// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP69]], align 8
+// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP58]], ptr [[TMP70]], align 8
+// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP71]], align 8
+// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP72]], align 8
+// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP73]], align 8
+// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP74]], align 8
+// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP60]], ptr [[TMP75]], align 8
+// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[ARRAYIDX9]], ptr [[TMP76]], align 8
+// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 3
+// CHECK-NEXT:    store i64 [[TMP63]], ptr [[TMP77]], align 8
+// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 3
+// CHECK-NEXT:    store ptr null, ptr [[TMP78]], align 8
+// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP79]], align 8
+// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[ARRAYIDX11]], ptr [[TMP80]], align 8
+// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 4
+// CHECK-NEXT:    store ptr null, ptr [[TMP81]], align 8
+// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP85:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP85]], ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK-NEXT:    [[TMP86:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP86]], -2
 // CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[SUB]], 3
-// CHECK-NEXT:    [[SUB13:%.*]] = sub i32 [[DIV]], 1
-// CHECK-NEXT:    store i32 [[SUB13]], ptr [[DOTCAPTURE_EXPR_12]], align 4
-// CHECK-NEXT:    [[TMP71:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_12]], align 4
-// CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP71]], 1
-// CHECK-NEXT:    [[TMP72:%.*]] = zext i32 [[ADD]] to i64
-// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP73]], align 4
-// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP74]], align 4
-// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP66]], ptr [[TMP75]], align 8
-// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP67]], ptr [[TMP76]], align 8
-// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP68]], ptr [[TMP77]], align 8
-// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP78]], align 8
-// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP79]], align 8
-// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP80]], align 8
-// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
-// CHECK-NEXT:    store i64 [[TMP72]], ptr [[TMP81]], align 8
-// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP82]], align 8
-// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP83]], align 4
-// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP84]], align 4
-// CHECK-NEXT:    [[TMP85:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP85]], align 4
-// CHECK-NEXT:    [[TMP86:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13.region_id, ptr [[KERNEL_ARGS14]])
-// CHECK-NEXT:    [[TMP87:%.*]] = icmp ne i32 [[TMP86]], 0
-// CHECK-NEXT:    br i1 [[TMP87]], label [[OMP_OFFLOAD_FAILED15:%.*]], label [[OMP_OFFLOAD_CONT16:%.*]]
-// CHECK:       omp_offload.failed15:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13(i64 [[TMP44]], ptr [[TMP45]], ptr [[TMP46]]) #[[ATTR2]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT16]]
-// CHECK:       omp_offload.cont16:
+// CHECK-NEXT:    [[SUB17:%.*]] = sub i32 [[DIV]], 1
+// CHECK-NEXT:    store i32 [[SUB17]], ptr [[DOTCAPTURE_EXPR_16]], align 4
+// CHECK-NEXT:    [[TMP87:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_16]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP87]], 1
+// CHECK-NEXT:    [[TMP88:%.*]] = zext i32 [[ADD]] to i64
+// CHECK-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP89]], align 4
+// CHECK-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1
+// CHECK-NEXT:    store i32 5, ptr [[TMP90]], align 4
+// CHECK-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP82]], ptr [[TMP91]], align 8
+// CHECK-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP83]], ptr [[TMP92]], align 8
+// CHECK-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[TMP84]], ptr [[TMP93]], align 8
+// CHECK-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP94]], align 8
+// CHECK-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP95]], align 8
+// CHECK-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP96]], align 8
+// CHECK-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 8
+// CHECK-NEXT:    store i64 [[TMP88]], ptr [[TMP97]], align 8
+// CHECK-NEXT:    [[TMP98:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP98]], align 8
+// CHECK-NEXT:    [[TMP99:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP99]], align 4
+// CHECK-NEXT:    [[TMP100:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP100]], align 4
+// CHECK-NEXT:    [[TMP101:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP101]], align 4
+// CHECK-NEXT:    [[TMP102:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13.region_id, ptr [[KERNEL_ARGS18]])
+// CHECK-NEXT:    [[TMP103:%.*]] = icmp ne i32 [[TMP102]], 0
+// CHECK-NEXT:    br i1 [[TMP103]], label [[OMP_OFFLOAD_FAILED19:%.*]], label [[OMP_OFFLOAD_CONT20:%.*]]
+// CHECK:       omp_offload.failed19:
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13(i64 [[TMP52]], ptr [[TMP53]], ptr [[TMP54]]) #[[ATTR2]]
+// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT20]]
+// CHECK:       omp_offload.cont20:
 // CHECK-NEXT:    br label [[FOR_INC:%.*]]
 // CHECK:       for.inc:
-// CHECK-NEXT:    [[TMP88:%.*]] = load i32, ptr [[I]], align 4
-// CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP88]], 1
+// CHECK-NEXT:    [[TMP104:%.*]] = load i32, ptr [[I]], align 4
+// CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP104]], 1
 // CHECK-NEXT:    store i32 [[INC]], ptr [[I]], align 4
-// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]]
+// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]]
 // CHECK:       for.end:
-// CHECK-NEXT:    [[TMP89:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP90:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[SUB17:%.*]] = sub nsw i32 [[TMP90]], 1
-// CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[SUB17]] to i64
-// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds i32, ptr [[TMP89]], i64 [[IDXPROM]]
-// CHECK-NEXT:    [[TMP91:%.*]] = load i32, ptr [[ARRAYIDX18]], align 4
-// CHECK-NEXT:    ret i32 [[TMP91]]
+// CHECK-NEXT:    [[TMP105:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP106:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[SUB21:%.*]] = sub nsw i32 [[TMP106]], 1
+// CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[SUB21]] to i64
+// CHECK-NEXT:    [[ARRAYIDX22:%.*]] = getelementptr inbounds i32, ptr [[TMP105]], i64 [[IDXPROM]]
+// CHECK-NEXT:    [[TMP107:%.*]] = load i32, ptr [[ARRAYIDX22]], align 4
+// CHECK-NEXT:    ret i32 [[TMP107]]
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9
diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp
index a7db3da7d1f86..4c2c1a267c6bf 100644
--- a/clang/test/OpenMP/reduction_implicit_map.cpp
+++ b/clang/test/OpenMP/reduction_implicit_map.cpp
@@ -1,4 +1,4 @@
-// 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 _
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*"
 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-cuda-mode -x c++ \
 // RUN:  -triple powerpc64le-unknown-unknown -DCUDA \
 // RUN:  -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o \
@@ -97,6 +97,21 @@ int main()
 #endif
   return 0;
 }
+//.
+// CHECK1: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK1: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 547]
+// CHECK1: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 8000]
+// CHECK1: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 547]
+//.
+// CHECK2: @.offload_sizes = private unnamed_addr constant [5 x i64] [i64 4, i64 4, i64 4, i64 0, i64 4]
+// CHECK2: @.offload_maptypes = private unnamed_addr constant [5 x i64] [i64 800, i64 547, i64 16384, i64 33, i64 16384]
+// CHECK2: @.offload_sizes.1 = private unnamed_addr constant [5 x i64] [i64 4, i64 12, i64 4, i64 0, i64 4]
+// CHECK2: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 800, i64 547, i64 16384, i64 33, i64 16384]
+// CHECK2: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK2: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 800, i64 547]
+// CHECK2: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 4, i64 4]
+// CHECK2: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 800, i64 547]
+//.
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3fooi_l32
 // CHECK-SAME: (ptr noalias noundef [[DYN_PTR:%.*]], ptr noundef [[E:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  entry:
@@ -410,7 +425,7 @@ int main()
 // CHECK1-NEXT:  entry:
 // CHECK1-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
 // CHECK1-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8
-// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8
+// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !nonnull [[META7:![0-9]+]], !align [[META8:![0-9]+]]
 // CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3barv_l50.omp_outlined, ptr [[TMP0]])
 // CHECK1-NEXT:    ret void
 //
@@ -427,7 +442,7 @@ int main()
 // CHECK1-NEXT:    store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
 // CHECK1-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8
-// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8
+// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !nonnull [[META7]], !align [[META8]]
 // CHECK1-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [5 x %class.S2], ptr [[TMP0]], i64 0, i64 0
 // CHECK1-NEXT:    call void @_ZN2S2C1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[O1]])
 // CHECK1-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
@@ -447,7 +462,7 @@ int main()
 // CHECK1-NEXT:    [[TMP7:%.*]] = load i32, ptr [[I]], align 4
 // CHECK1-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP7]], 1
 // CHECK1-NEXT:    store i32 [[INC]], ptr [[I]], align 4
-// CHECK1-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP5:![0-9]+]]
+// CHECK1-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP9:![0-9]+]]
 // CHECK1:       for.end:
 // CHECK1-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[O1]], ptr [[TMP8]], align 8
@@ -498,7 +513,7 @@ int main()
 // CHECK1-NEXT:  entry:
 // CHECK1-NEXT:    [[B_ADDR:%.*]] = alloca ptr, align 8
 // CHECK1-NEXT:    store ptr [[B]], ptr [[B_ADDR]], align 8
-// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !nonnull [[META7]], !align [[META13:![0-9]+]]
 // CHECK1-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 1, ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3barv_l55.omp_outlined, ptr [[TMP0]])
 // CHECK1-NEXT:    ret void
 //
@@ -524,7 +539,7 @@ int main()
 // CHECK1-NEXT:    store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
 // CHECK1-NEXT:    store ptr [[B]], ptr [[B_ADDR]], align 8
-// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK1-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[B_ADDR]], align 8, !nonnull [[META7]], !align [[META13]]
 // CHECK1-NEXT:    store i64 0, ptr [[DOTOMP_LB]], align 8
 // CHECK1-NEXT:    store i64 9, ptr [[DOTOMP_UB]], align 8
 // CHECK1-NEXT:    store i64 1, ptr [[DOTOMP_STRIDE]], align 8
@@ -811,34 +826,34 @@ int main()
 // CHECK2-NEXT:    [[SIZE_ADDR:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    [[OUTPUT_ADDR:%.*]] = alloca ptr, align 4
 // CHECK2-NEXT:    [[SIZE_CASTED:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [3 x i64], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [5 x i64], align 4
 // CHECK2-NEXT:    [[TMP:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    [[DOTCAPTURE_EXPR_:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_2:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_4:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK2-NEXT:    [[SIZE_CASTED4:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [3 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES10:%.*]] = alloca [3 x i64], align 4
-// CHECK2-NEXT:    [[_TMP11:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_12:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_13:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS18:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED6:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS12:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS13:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES14:%.*]] = alloca [5 x i64], align 4
+// CHECK2-NEXT:    [[_TMP15:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_16:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_17:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS22:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK2-NEXT:    [[A:%.*]] = alloca [10 x i32], align 4
-// CHECK2-NEXT:    [[SIZE_CASTED21:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS23:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS24:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS25:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS26:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
-// CHECK2-NEXT:    [[SIZE_CASTED29:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS34:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED25:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS28:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED33:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS35:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS36:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS37:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS38:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK2-NEXT:    store ptr [[INPUT]], ptr [[INPUT_ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 4
@@ -850,262 +865,294 @@ int main()
 // CHECK2-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0
-// CHECK2-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
 // CHECK2-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP7]], i32 0
-// CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP9:%.*]] = mul nuw i32 [[TMP8]], 4
-// CHECK2-NEXT:    [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
-// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes, i32 24, i1 false)
-// CHECK2-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP11]], align 4
-// CHECK2-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP12]], align 4
-// CHECK2-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP13]], align 4
-// CHECK2-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[TMP4]], ptr [[TMP14]], align 4
-// CHECK2-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP15]], align 4
-// CHECK2-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP16]], align 4
-// CHECK2-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP6]], ptr [[TMP17]], align 4
-// CHECK2-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP18]], align 4
-// CHECK2-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 2
-// CHECK2-NEXT:    store i64 [[TMP10]], ptr [[TMP19]], align 4
-// CHECK2-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr null, ptr [[TMP20]], align 4
-// CHECK2-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP24:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP24]], ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK2-NEXT:    [[TMP25:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK2-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP25]], 0
+// CHECK2-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP8]], i32 0
+// CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP10:%.*]] = mul nuw i32 [[TMP9]], 4
+// CHECK2-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP11]], i32 0
+// CHECK2-NEXT:    [[TMP12:%.*]] = sext i32 [[TMP10]] to i64
+// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes, i32 40, i1 false)
+// CHECK2-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP13]], align 4
+// CHECK2-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP14]], align 4
+// CHECK2-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP15]], align 4
+// CHECK2-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[TMP4]], ptr [[TMP16]], align 4
+// CHECK2-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP17]], align 4
+// CHECK2-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP18]], align 4
+// CHECK2-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP19]], align 4
+// CHECK2-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP20]], align 4
+// CHECK2-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr null, ptr [[TMP21]], align 4
+// CHECK2-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP7]], ptr [[TMP22]], align 4
+// CHECK2-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[ARRAYIDX2]], ptr [[TMP23]], align 4
+// CHECK2-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
+// CHECK2-NEXT:    store i64 [[TMP12]], ptr [[TMP24]], align 4
+// CHECK2-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr null, ptr [[TMP25]], align 4
+// CHECK2-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP26]], align 4
+// CHECK2-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[ARRAYIDX3]], ptr [[TMP27]], align 4
+// CHECK2-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr null, ptr [[TMP28]], align 4
+// CHECK2-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP32:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP32]], ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK2-NEXT:    [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK2-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP33]], 0
 // CHECK2-NEXT:    [[DIV:%.*]] = sdiv i32 [[SUB]], 1
-// CHECK2-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[DIV]], 1
-// CHECK2-NEXT:    store i32 [[SUB3]], ptr [[DOTCAPTURE_EXPR_2]], align 4
-// CHECK2-NEXT:    [[TMP26:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4
-// CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP26]], 1
-// CHECK2-NEXT:    [[TMP27:%.*]] = zext i32 [[ADD]] to i64
-// CHECK2-NEXT:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP28]], align 4
-// CHECK2-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 3, ptr [[TMP29]], align 4
-// CHECK2-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP21]], ptr [[TMP30]], align 4
-// CHECK2-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP22]], ptr [[TMP31]], align 4
-// CHECK2-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[TMP23]], ptr [[TMP32]], align 4
-// CHECK2-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes, ptr [[TMP33]], align 4
-// CHECK2-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP34]], align 4
-// CHECK2-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP35]], align 4
-// CHECK2-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 [[TMP27]], ptr [[TMP36]], align 8
-// CHECK2-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP37]], align 8
-// CHECK2-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP38]], align 4
-// CHECK2-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP39]], align 4
-// CHECK2-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP40]], align 4
-// CHECK2-NEXT:    [[TMP41:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4:[0-9]+]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69.region_id, ptr [[KERNEL_ARGS]])
-// CHECK2-NEXT:    [[TMP42:%.*]] = icmp ne i32 [[TMP41]], 0
-// CHECK2-NEXT:    br i1 [[TMP42]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK2-NEXT:    [[SUB5:%.*]] = sub nsw i32 [[DIV]], 1
+// CHECK2-NEXT:    store i32 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 4
+// CHECK2-NEXT:    [[TMP34:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_4]], align 4
+// CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP34]], 1
+// CHECK2-NEXT:    [[TMP35:%.*]] = zext i32 [[ADD]] to i64
+// CHECK2-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP36]], align 4
+// CHECK2-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 5, ptr [[TMP37]], align 4
+// CHECK2-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP29]], ptr [[TMP38]], align 4
+// CHECK2-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP30]], ptr [[TMP39]], align 4
+// CHECK2-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[TMP31]], ptr [[TMP40]], align 4
+// CHECK2-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes, ptr [[TMP41]], align 4
+// CHECK2-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP42]], align 4
+// CHECK2-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP43]], align 4
+// CHECK2-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 [[TMP35]], ptr [[TMP44]], align 8
+// CHECK2-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP45]], align 8
+// CHECK2-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
+// CHECK2-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP47]], align 4
+// CHECK2-NEXT:    [[TMP48:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP48]], align 4
+// CHECK2-NEXT:    [[TMP49:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4:[0-9]+]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69.region_id, ptr [[KERNEL_ARGS]])
+// CHECK2-NEXT:    [[TMP50:%.*]] = icmp ne i32 [[TMP49]], 0
+// CHECK2-NEXT:    br i1 [[TMP50]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK2:       omp_offload.failed:
 // CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69(i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]]) #[[ATTR2:[0-9]+]]
 // CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK2:       omp_offload.cont:
-// CHECK2-NEXT:    [[TMP43:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP43]], ptr [[SIZE_CASTED4]], align 4
-// CHECK2-NEXT:    [[TMP44:%.*]] = load i32, ptr [[SIZE_CASTED4]], align 4
-// CHECK2-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP48]], i32 0
-// CHECK2-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP50]], i32 0
 // CHECK2-NEXT:    [[TMP51:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP52:%.*]] = mul nuw i32 [[TMP51]], 4
-// CHECK2-NEXT:    [[TMP53:%.*]] = sext i32 [[TMP52]] to i64
-// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES10]], ptr align 4 @.offload_sizes.1, i32 24, i1 false)
-// CHECK2-NEXT:    [[TMP54:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP44]], ptr [[TMP54]], align 4
-// CHECK2-NEXT:    [[TMP55:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP44]], ptr [[TMP55]], align 4
-// CHECK2-NEXT:    [[TMP56:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP56]], align 4
-// CHECK2-NEXT:    [[TMP57:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[TMP47]], ptr [[TMP57]], align 4
-// CHECK2-NEXT:    [[TMP58:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP58]], align 4
-// CHECK2-NEXT:    [[TMP59:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP59]], align 4
-// CHECK2-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP49]], ptr [[TMP60]], align 4
-// CHECK2-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP61]], align 4
-// CHECK2-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES10]], i32 0, i32 2
-// CHECK2-NEXT:    store i64 [[TMP53]], ptr [[TMP62]], align 4
-// CHECK2-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr null, ptr [[TMP63]], align 4
-// CHECK2-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES10]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP67:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP67]], ptr [[DOTCAPTURE_EXPR_12]], align 4
-// CHECK2-NEXT:    [[TMP68:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_12]], align 4
-// CHECK2-NEXT:    [[SUB14:%.*]] = sub nsw i32 [[TMP68]], 0
-// CHECK2-NEXT:    [[DIV15:%.*]] = sdiv i32 [[SUB14]], 1
-// CHECK2-NEXT:    [[SUB16:%.*]] = sub nsw i32 [[DIV15]], 1
-// CHECK2-NEXT:    store i32 [[SUB16]], ptr [[DOTCAPTURE_EXPR_13]], align 4
-// CHECK2-NEXT:    [[TMP69:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_13]], align 4
-// CHECK2-NEXT:    [[ADD17:%.*]] = add nsw i32 [[TMP69]], 1
-// CHECK2-NEXT:    [[TMP70:%.*]] = zext i32 [[ADD17]] to i64
-// CHECK2-NEXT:    [[TMP71:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP71]], align 4
-// CHECK2-NEXT:    [[TMP72:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 3, ptr [[TMP72]], align 4
-// CHECK2-NEXT:    [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP64]], ptr [[TMP73]], align 4
-// CHECK2-NEXT:    [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP65]], ptr [[TMP74]], align 4
-// CHECK2-NEXT:    [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[TMP66]], ptr [[TMP75]], align 4
-// CHECK2-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP76]], align 4
-// CHECK2-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP77]], align 4
-// CHECK2-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP78]], align 4
-// CHECK2-NEXT:    [[TMP79:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 [[TMP70]], ptr [[TMP79]], align 8
-// CHECK2-NEXT:    [[TMP80:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP80]], align 8
-// CHECK2-NEXT:    [[TMP81:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP81]], align 4
-// CHECK2-NEXT:    [[TMP82:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP82]], align 4
-// CHECK2-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP83]], align 4
-// CHECK2-NEXT:    [[TMP84:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73.region_id, ptr [[KERNEL_ARGS18]])
-// CHECK2-NEXT:    [[TMP85:%.*]] = icmp ne i32 [[TMP84]], 0
-// CHECK2-NEXT:    br i1 [[TMP85]], label [[OMP_OFFLOAD_FAILED19:%.*]], label [[OMP_OFFLOAD_CONT20:%.*]]
-// CHECK2:       omp_offload.failed19:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73(i32 [[TMP44]], ptr [[TMP45]], ptr [[TMP46]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT20]]
-// CHECK2:       omp_offload.cont20:
-// CHECK2-NEXT:    [[TMP86:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP86]], ptr [[SIZE_CASTED21]], align 4
-// CHECK2-NEXT:    [[TMP87:%.*]] = load i32, ptr [[SIZE_CASTED21]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX22:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[A]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP87]], ptr [[TMP88]], align 4
-// CHECK2-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP87]], ptr [[TMP89]], align 4
-// CHECK2-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP90]], align 4
-// CHECK2-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP91]], align 4
-// CHECK2-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX22]], ptr [[TMP92]], align 4
-// CHECK2-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 [[TMP51]], ptr [[SIZE_CASTED6]], align 4
+// CHECK2-NEXT:    [[TMP52:%.*]] = load i32, ptr [[SIZE_CASTED6]], align 4
+// CHECK2-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP56]], i32 0
+// CHECK2-NEXT:    [[TMP57:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP57]], i32 0
+// CHECK2-NEXT:    [[TMP58:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP59:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP59]], i32 0
+// CHECK2-NEXT:    [[TMP60:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP61:%.*]] = mul nuw i32 [[TMP60]], 4
+// CHECK2-NEXT:    [[TMP62:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP62]], i32 0
+// CHECK2-NEXT:    [[TMP63:%.*]] = sext i32 [[TMP61]] to i64
+// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES14]], ptr align 4 @.offload_sizes.1, i32 40, i1 false)
+// CHECK2-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP52]], ptr [[TMP64]], align 4
+// CHECK2-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP52]], ptr [[TMP65]], align 4
+// CHECK2-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP66]], align 4
+// CHECK2-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[TMP55]], ptr [[TMP67]], align 4
+// CHECK2-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX7]], ptr [[TMP68]], align 4
+// CHECK2-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP69]], align 4
+// CHECK2-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP70]], align 4
+// CHECK2-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP71]], align 4
+// CHECK2-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr null, ptr [[TMP72]], align 4
+// CHECK2-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP58]], ptr [[TMP73]], align 4
+// CHECK2-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[ARRAYIDX9]], ptr [[TMP74]], align 4
+// CHECK2-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES14]], i32 0, i32 3
+// CHECK2-NEXT:    store i64 [[TMP63]], ptr [[TMP75]], align 4
+// CHECK2-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr null, ptr [[TMP76]], align 4
+// CHECK2-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP77]], align 4
+// CHECK2-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP78]], align 4
+// CHECK2-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr null, ptr [[TMP79]], align 4
+// CHECK2-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES14]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP83:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP83]], ptr [[DOTCAPTURE_EXPR_16]], align 4
+// CHECK2-NEXT:    [[TMP84:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_16]], align 4
+// CHECK2-NEXT:    [[SUB18:%.*]] = sub nsw i32 [[TMP84]], 0
+// CHECK2-NEXT:    [[DIV19:%.*]] = sdiv i32 [[SUB18]], 1
+// CHECK2-NEXT:    [[SUB20:%.*]] = sub nsw i32 [[DIV19]], 1
+// CHECK2-NEXT:    store i32 [[SUB20]], ptr [[DOTCAPTURE_EXPR_17]], align 4
+// CHECK2-NEXT:    [[TMP85:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_17]], align 4
+// CHECK2-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP85]], 1
+// CHECK2-NEXT:    [[TMP86:%.*]] = zext i32 [[ADD21]] to i64
+// CHECK2-NEXT:    [[TMP87:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP87]], align 4
+// CHECK2-NEXT:    [[TMP88:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 5, ptr [[TMP88]], align 4
+// CHECK2-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP80]], ptr [[TMP89]], align 4
+// CHECK2-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP81]], ptr [[TMP90]], align 4
+// CHECK2-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[TMP82]], ptr [[TMP91]], align 4
+// CHECK2-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP92]], align 4
+// CHECK2-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 6
 // CHECK2-NEXT:    store ptr null, ptr [[TMP93]], align 4
-// CHECK2-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP96]], align 4
-// CHECK2-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 2, ptr [[TMP97]], align 4
-// CHECK2-NEXT:    [[TMP98:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP94]], ptr [[TMP98]], align 4
-// CHECK2-NEXT:    [[TMP99:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP95]], ptr [[TMP99]], align 4
-// CHECK2-NEXT:    [[TMP100:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP100]], align 4
-// CHECK2-NEXT:    [[TMP101:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP101]], align 4
-// CHECK2-NEXT:    [[TMP102:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP102]], align 4
-// CHECK2-NEXT:    [[TMP103:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP103]], align 4
-// CHECK2-NEXT:    [[TMP104:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 0, ptr [[TMP104]], align 8
-// CHECK2-NEXT:    [[TMP105:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP105]], align 8
-// CHECK2-NEXT:    [[TMP106:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP106]], align 4
-// CHECK2-NEXT:    [[TMP107:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP107]], align 4
-// CHECK2-NEXT:    [[TMP108:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP108]], align 4
-// CHECK2-NEXT:    [[TMP109:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78.region_id, ptr [[KERNEL_ARGS26]])
-// CHECK2-NEXT:    [[TMP110:%.*]] = icmp ne i32 [[TMP109]], 0
-// CHECK2-NEXT:    br i1 [[TMP110]], label [[OMP_OFFLOAD_FAILED27:%.*]], label [[OMP_OFFLOAD_CONT28:%.*]]
-// CHECK2:       omp_offload.failed27:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78(i32 [[TMP87]], ptr [[A]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT28]]
-// CHECK2:       omp_offload.cont28:
-// CHECK2-NEXT:    [[TMP111:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP111]], ptr [[SIZE_CASTED29]], align 4
-// CHECK2-NEXT:    [[TMP112:%.*]] = load i32, ptr [[SIZE_CASTED29]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX30:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i32 0, i32 3
-// CHECK2-NEXT:    [[TMP113:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP112]], ptr [[TMP113]], align 4
-// CHECK2-NEXT:    [[TMP114:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP112]], ptr [[TMP114]], align 4
-// CHECK2-NEXT:    [[TMP115:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP115]], align 4
-// CHECK2-NEXT:    [[TMP116:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP116]], align 4
-// CHECK2-NEXT:    [[TMP117:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX30]], ptr [[TMP117]], align 4
-// CHECK2-NEXT:    [[TMP118:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 1
+// CHECK2-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP94]], align 4
+// CHECK2-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 [[TMP86]], ptr [[TMP95]], align 8
+// CHECK2-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP96]], align 8
+// CHECK2-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP97]], align 4
+// CHECK2-NEXT:    [[TMP98:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP98]], align 4
+// CHECK2-NEXT:    [[TMP99:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP99]], align 4
+// CHECK2-NEXT:    [[TMP100:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73.region_id, ptr [[KERNEL_ARGS22]])
+// CHECK2-NEXT:    [[TMP101:%.*]] = icmp ne i32 [[TMP100]], 0
+// CHECK2-NEXT:    br i1 [[TMP101]], label [[OMP_OFFLOAD_FAILED23:%.*]], label [[OMP_OFFLOAD_CONT24:%.*]]
+// CHECK2:       omp_offload.failed23:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73(i32 [[TMP52]], ptr [[TMP53]], ptr [[TMP54]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT24]]
+// CHECK2:       omp_offload.cont24:
+// CHECK2-NEXT:    [[TMP102:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP102]], ptr [[SIZE_CASTED25]], align 4
+// CHECK2-NEXT:    [[TMP103:%.*]] = load i32, ptr [[SIZE_CASTED25]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX26:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[A]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP103]], ptr [[TMP104]], align 4
+// CHECK2-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP103]], ptr [[TMP105]], align 4
+// CHECK2-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP106]], align 4
+// CHECK2-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP107]], align 4
+// CHECK2-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX26]], ptr [[TMP108]], align 4
+// CHECK2-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP109]], align 4
+// CHECK2-NEXT:    [[TMP110:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP111:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP112:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP112]], align 4
+// CHECK2-NEXT:    [[TMP113:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 2, ptr [[TMP113]], align 4
+// CHECK2-NEXT:    [[TMP114:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP110]], ptr [[TMP114]], align 4
+// CHECK2-NEXT:    [[TMP115:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP111]], ptr [[TMP115]], align 4
+// CHECK2-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP116]], align 4
+// CHECK2-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP117]], align 4
+// CHECK2-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6
 // CHECK2-NEXT:    store ptr null, ptr [[TMP118]], align 4
-// CHECK2-NEXT:    [[TMP119:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP120:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP121]], align 4
-// CHECK2-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 2, ptr [[TMP122]], align 4
-// CHECK2-NEXT:    [[TMP123:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP119]], ptr [[TMP123]], align 4
-// CHECK2-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP120]], ptr [[TMP124]], align 4
-// CHECK2-NEXT:    [[TMP125:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr @.offload_sizes.5, ptr [[TMP125]], align 4
-// CHECK2-NEXT:    [[TMP126:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP126]], align 4
-// CHECK2-NEXT:    [[TMP127:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP127]], align 4
-// CHECK2-NEXT:    [[TMP128:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP128]], align 4
-// CHECK2-NEXT:    [[TMP129:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 0, ptr [[TMP129]], align 8
-// CHECK2-NEXT:    [[TMP130:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP130]], align 8
-// CHECK2-NEXT:    [[TMP131:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP131]], align 4
-// CHECK2-NEXT:    [[TMP132:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP132]], align 4
-// CHECK2-NEXT:    [[TMP133:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP133]], align 4
-// CHECK2-NEXT:    [[TMP134:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81.region_id, ptr [[KERNEL_ARGS34]])
-// CHECK2-NEXT:    [[TMP135:%.*]] = icmp ne i32 [[TMP134]], 0
-// CHECK2-NEXT:    br i1 [[TMP135]], label [[OMP_OFFLOAD_FAILED35:%.*]], label [[OMP_OFFLOAD_CONT36:%.*]]
-// CHECK2:       omp_offload.failed35:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81(i32 [[TMP112]], ptr [[A]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT36]]
-// CHECK2:       omp_offload.cont36:
+// CHECK2-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP119]], align 4
+// CHECK2-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 0, ptr [[TMP120]], align 8
+// CHECK2-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP121]], align 8
+// CHECK2-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP122]], align 4
+// CHECK2-NEXT:    [[TMP123:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP123]], align 4
+// CHECK2-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP124]], align 4
+// CHECK2-NEXT:    [[TMP125:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78.region_id, ptr [[KERNEL_ARGS30]])
+// CHECK2-NEXT:    [[TMP126:%.*]] = icmp ne i32 [[TMP125]], 0
+// CHECK2-NEXT:    br i1 [[TMP126]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]]
+// CHECK2:       omp_offload.failed31:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78(i32 [[TMP103]], ptr [[A]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT32]]
+// CHECK2:       omp_offload.cont32:
+// CHECK2-NEXT:    [[TMP127:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP127]], ptr [[SIZE_CASTED33]], align 4
+// CHECK2-NEXT:    [[TMP128:%.*]] = load i32, ptr [[SIZE_CASTED33]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX34:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i32 0, i32 3
+// CHECK2-NEXT:    [[TMP129:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP128]], ptr [[TMP129]], align 4
+// CHECK2-NEXT:    [[TMP130:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP128]], ptr [[TMP130]], align 4
+// CHECK2-NEXT:    [[TMP131:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP131]], align 4
+// CHECK2-NEXT:    [[TMP132:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP132]], align 4
+// CHECK2-NEXT:    [[TMP133:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX34]], ptr [[TMP133]], align 4
+// CHECK2-NEXT:    [[TMP134:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP134]], align 4
+// CHECK2-NEXT:    [[TMP135:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP136:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP137:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP137]], align 4
+// CHECK2-NEXT:    [[TMP138:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 2, ptr [[TMP138]], align 4
+// CHECK2-NEXT:    [[TMP139:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP135]], ptr [[TMP139]], align 4
+// CHECK2-NEXT:    [[TMP140:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP136]], ptr [[TMP140]], align 4
+// CHECK2-NEXT:    [[TMP141:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr @.offload_sizes.5, ptr [[TMP141]], align 4
+// CHECK2-NEXT:    [[TMP142:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP142]], align 4
+// CHECK2-NEXT:    [[TMP143:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP143]], align 4
+// CHECK2-NEXT:    [[TMP144:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP144]], align 4
+// CHECK2-NEXT:    [[TMP145:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 0, ptr [[TMP145]], align 8
+// CHECK2-NEXT:    [[TMP146:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP146]], align 8
+// CHECK2-NEXT:    [[TMP147:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP147]], align 4
+// CHECK2-NEXT:    [[TMP148:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP148]], align 4
+// CHECK2-NEXT:    [[TMP149:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP149]], align 4
+// CHECK2-NEXT:    [[TMP150:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81.region_id, ptr [[KERNEL_ARGS38]])
+// CHECK2-NEXT:    [[TMP151:%.*]] = icmp ne i32 [[TMP150]], 0
+// CHECK2-NEXT:    br i1 [[TMP151]], label [[OMP_OFFLOAD_FAILED39:%.*]], label [[OMP_OFFLOAD_CONT40:%.*]]
+// CHECK2:       omp_offload.failed39:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81(i32 [[TMP128]], ptr [[A]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT40]]
+// CHECK2:       omp_offload.cont40:
 // CHECK2-NEXT:    ret void
 //
 //
@@ -1855,7 +1902,7 @@ int main()
 // CHECK2-NEXT:    [[SIZE_CASTED:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META14:![0-9]+]], !align [[META15:![0-9]+]]
 // CHECK2-NEXT:    [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[TMP1]], ptr [[SIZE_CASTED]], align 4
 // CHECK2-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SIZE_CASTED]], align 4
@@ -1877,7 +1924,7 @@ int main()
 // CHECK2-NEXT:    store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META14]], !align [[META15]]
 // CHECK2-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[TMP0]], i32 0, i32 0
 // CHECK2-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[TMP0]], i32 0, i32 1
 // CHECK2-NEXT:    [[ARRAY_BEGIN:%.*]] = getelementptr inbounds [2 x i32], ptr [[A2]], i32 0, i32 0
@@ -1909,7 +1956,7 @@ int main()
 // CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[I]], align 4
 // CHECK2-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP9]], 1
 // CHECK2-NEXT:    store i32 [[INC]], ptr [[I]], align 4
-// CHECK2-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP10:![0-9]+]]
+// CHECK2-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP16:![0-9]+]]
 // CHECK2:       for.end:
 // CHECK2-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK2-NEXT:    store ptr [[A2]], ptr [[TMP10]], align 4
@@ -1996,7 +2043,7 @@ int main()
 // CHECK2-NEXT:    [[SIZE_CASTED:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META14]], !align [[META15]]
 // CHECK2-NEXT:    [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[TMP1]], ptr [[SIZE_CASTED]], align 4
 // CHECK2-NEXT:    [[TMP2:%.*]] = load i32, ptr [[SIZE_CASTED]], align 4
@@ -2018,7 +2065,7 @@ int main()
 // CHECK2-NEXT:    store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META14]], !align [[META15]]
 // CHECK2-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x i32], ptr [[TMP0]], i32 0, i32 3
 // CHECK2-NEXT:    store i32 0, ptr [[A1]], align 4
 // CHECK2-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
@@ -2039,7 +2086,7 @@ int main()
 // CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[I]], align 4
 // CHECK2-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP8]], 1
 // CHECK2-NEXT:    store i32 [[INC]], ptr [[I]], align 4
-// CHECK2-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP12:![0-9]+]]
+// CHECK2-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP18:![0-9]+]]
 // CHECK2:       for.end:
 // CHECK2-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK2-NEXT:    store ptr [[A1]], ptr [[TMP9]], align 4
diff --git a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
index eed1889f3c5cb..652f8eff8454a 100644
--- a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
+++ b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
@@ -33,15 +33,35 @@ typedef struct {
 MyObject *objects;
 #pragma omp end declare target
 
-// CHECK-DAG: [[SIZES0:@.+]] = private unnamed_addr constant [1 x i64] [i64 {{8|4}}]
-// CHECK-DAG: [[MAPS0:@.+]] = private unnamed_addr constant [1 x i64] [i64 17]
+// CHECK-DAG: [[SIZES0:@.+]] = private unnamed_addr constant [2 x i64] [i64 {{8|4}}, i64 {{8|4}}]
+// CHECK-DAG: [[MAPS0:@.+]] = private unnamed_addr constant [2 x i64] [i64 1, i64 16384]
 // CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [2 x i64] [i64 0, i64 4]
 // CHECK-DAG: [[MAPS1:@.+]] = private unnamed_addr constant [2 x i64] [i64 0, i64 281474976710673]
 // CHECK: @main
 int main(void) {
-// CHECK: [[BPTR0:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
-// CHECK: store ptr @objects, ptr [[BPTR0]],
-// CHECK: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 1, ptr %{{.+}}, ptr %{{.+}}, ptr [[SIZES0]], ptr [[MAPS0]], ptr null, ptr null)
+//
+//  &objects[0], &objects[1], 1 * sizeof(objects[0]), TO
+//  &objects, &objects[1], sizeof(objects), ATTACH
+//
+// CHECK-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[BPGEP:%.+]], ptr [[PGEP:%.+]], ptr [[SIZES0]], ptr [[MAPS0]], ptr null, ptr null)
+// CHECK-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+// CHECK-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+// CHECK-DAG: [[BP0:%.+]] = getelementptr inbounds {{.*}}ptr [[BP]], i32 0, i32 0
+// CHECK-DAG: [[P0:%.+]] = getelementptr inbounds {{.*}}ptr [[P]], i32 0, i32 0
+// CHECK-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
+// CHECK-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+// CHECK-DAG: [[RVAR0]] = load ptr, ptr @objects
+// CHECK-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 1
+// CHECK-DAG: [[RVAR00]] = load ptr, ptr @objects
+
+// CHECK-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CHECK-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CHECK-DAG: store ptr @objects, ptr [[BP1]]
+// CHECK-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CHECK-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 1
+// CHECK-DAG: [[RVAR1]] = load ptr, ptr @objects
+
 #pragma omp target enter data map(to : objects [1:1])
 // CHECK: [[OBJ:%.+]] = load ptr, ptr @objects,
 // CHECK: [[BPTR0:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
diff --git a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
index 19a523ee165c8..48a4fa120468a 100644
--- a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
@@ -11,9 +11,9 @@
 #ifndef HEADER
 #define HEADER
 
-// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [6 x i64] [i64 4, i64 16, i64 4, i64 4, i64 0, i64 4]
+// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 4, i64 16, i64 4, i64 8, i64 8, i64 4, i64 0, i64 4]
 // 64 = 0x40 = OMP_MAP_RETURN_PARAM
-// CHECK-DAG: [[MAPTYPES1:@.+]] = private unnamed_addr constant [6 x i64] [i64 67, i64 115, i64 51, i64 67, i64 67, i64 67]
+// CHECK-DAG: [[MAPTYPES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 67, i64 67, i64 3, i64 16384, i64 16384, i64 67, i64 67, i64 67]
 // CHECK-DAG: [[SIZES2:@.+]] = private unnamed_addr constant [6 x i64] [i64 0, i64 4, i64 16, i64 4, i64 4, i64 0]
 // 0 = OMP_MAP_NONE
 // 281474976710720 = 0x1000000000040 = OMP_MAP_MEMBER_OF | OMP_MAP_RETURN_PARAM
@@ -44,63 +44,86 @@ int main() {
 }
 
 // CHECK-LABEL: @main()
+//
+//  &a, &a, TO | FROM | RETURN_PARAM
+//  &p[0], &p[3], TO | FROM | RETURN_PARAM
+//  &p[0], &p[0], TO | FROM | RETURN_PARAM
+//  &p, &p[3], ATTACH
+//  &p, &p[0], ATTACH
+//  &ref_ptee(ref), &ref_ptee(ref), TO | FROM | RETURN_PARAM
+//  &arr, &arr[0], TO | FROM | ATTACH | RETURN_PARAM
+//
 // CHECK: [[A_ADDR:%.+]] = alloca float,
 // CHECK: [[PTR_ADDR:%.+]] = alloca ptr,
 // CHECK: [[REF_ADDR:%.+]] = alloca ptr,
 // CHECK: [[ARR_ADDR:%.+]] = alloca [4 x float],
-// CHECK: [[BPTRS:%.+]] = alloca [6 x ptr],
-// CHECK: [[PTRS:%.+]] = alloca [6 x ptr],
-// CHECK: [[MAP_PTRS:%.+]] = alloca [6 x ptr],
-// CHECK: [[SIZES:%.+]] = alloca [6 x i64],
+// CHECK: [[BPTRS:%.+]] = alloca [8 x ptr],
+// CHECK: [[PTRS:%.+]] = alloca [8 x ptr],
+// CHECK: [[MAP_PTRS:%.+]] = alloca [8 x ptr],
+// CHECK: [[SIZES:%.+]] = alloca [8 x i64],
 // CHECK: [[VLA_ADDR:%.+]] = alloca float, i64 %{{.+}},
-// CHECK: [[PTR:%.+]] = load ptr, ptr [[PTR_ADDR]],
-// CHECK-NEXT: [[ARR_IDX:%.+]] = getelementptr inbounds nuw float, ptr [[PTR]], i64 3
+// CHECK: [[P0:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK: [[P1:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK-NEXT: [[ARR_IDX:%.+]] = getelementptr inbounds nuw float, ptr [[P1]], i64 3
+// CHECK: [[P2:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK-NEXT: [[ARR_IDX1:%.+]] = getelementptr inbounds nuw float, ptr [[P2]], i64 3
+// CHECK: [[P3:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK: [[P4:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK-NEXT: [[ARR_IDX2:%.+]] = getelementptr inbounds float, ptr [[P4]], i64 0
 // CHECK: [[P5:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT: [[ARR_IDX1:%.+]] = getelementptr inbounds float, ptr [[P5]], i64 0
+// CHECK-NEXT: [[ARR_IDX3:%.+]] = getelementptr inbounds float, ptr [[P5]], i64 0
 // CHECK: [[P7:%.+]] = load ptr, ptr [[REF_ADDR]],
 // CHECK-NEXT: [[REF:%.+]] = load ptr, ptr [[REF_ADDR]],
-// CHECK-NEXT: [[ARR_IDX2:%.+]] = getelementptr inbounds nuw [4 x float], ptr [[ARR_ADDR]], i64 0, i64 0
+// CHECK-NEXT: [[ARR_IDX4:%.+]] = getelementptr inbounds nuw [4 x float], ptr [[ARR_ADDR]], i64 0, i64 0
 // CHECK: [[P10:%.+]] = mul nuw i64 {{.+}}, 4
 // CHECK-NEXT: [[ARR_IDX5:%.+]] = getelementptr inbounds float, ptr [[VLA_ADDR]], i64 0
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[SIZES]], ptr align 8 [[SIZES1]], i64 48, i1 false)
-// CHECK: [[BPTR0:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 0
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[SIZES]], ptr align 8 [[SIZES1]], i64 64, i1 false)
+// CHECK: [[BPTR0:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 0
 // CHECK: store ptr [[A_ADDR]], ptr [[BPTR0]],
-// CHECK: [[PTR0:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 0
+// CHECK: [[PTR0:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 0
 // CHECK: store ptr [[A_ADDR]], ptr [[PTR0]],
-// CHECK: [[BPTR1:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 1
-// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR1]],
-// CHECK: [[PTR1:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 1
+// CHECK: [[BPTR1:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 1
+// CHECK: store ptr [[P0]], ptr [[BPTR1]],
+// CHECK: [[PTR1:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 1
 // CHECK: store ptr [[ARR_IDX]], ptr [[PTR1]],
-// CHECK: [[BPTR2:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 2
-// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR2]],
-// CHECK: [[PTR2:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 2
-// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR2]],
-// CHECK: [[BPTR3:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 3
-// CHECK: store ptr [[P7]], ptr [[BPTR3]],
-// CHECK: [[PTR3:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 3
-// CHECK: store ptr [[REF]], ptr [[PTR3]],
-// CHECK: [[BPTR4:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 4
-// CHECK: store ptr [[ARR_ADDR]], ptr [[BPTR4]], align 
-// CHECK: [[PTR4:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 4
-// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR4]], align 8
-// CHECK: [[SIZE_PTR:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 4
+// CHECK: [[BPTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 2
+// CHECK: store ptr [[P3]], ptr [[BPTR2]],
+// CHECK: [[PTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 2
+// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR2]],
+// CHECK: [[BPTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 3
+// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR3]],
+// CHECK: [[PTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 3
+// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR3]],
+// CHECK: [[BPTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 4
+// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR4]], align
+// CHECK: [[PTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 4
+// CHECK: store ptr [[ARR_IDX3]], ptr [[PTR4]], align 8
+// CHECK: [[BPTR5:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 5
+// CHECK: store ptr [[P7]], ptr [[BPTR5]], align
+// CHECK: [[PTR5:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 5
+// CHECK: store ptr [[REF]], ptr [[PTR5]], align 8
+// CHECK: [[BPTR6:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 6
+// CHECK: store ptr [[ARR_ADDR]], ptr [[BPTR6]],
+// CHECK: [[PTR6:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 6
+// CHECK: store ptr [[ARR_IDX4]], ptr [[PTR6]],
+// CHECK: [[SIZE_PTR:%.+]] = getelementptr inbounds [8 x i64], ptr [[SIZES]], i32 0, i32 6
 // CHECK: store i64 [[P10:%.+]], ptr [[SIZE_PTR]], align 8
-// CHECK: [[MAP_PTR:%.+]] = getelementptr inbounds [6 x ptr], ptr [[MAP_PTRS]], i64 0, i64 4
+// CHECK: [[MAP_PTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[MAP_PTRS]], i64 0, i64 6
 // CHECK: store ptr null, ptr [[MAP_PTR]], align 8
-// CHECK: [[BPTR5:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 5
-// CHECK: store ptr [[VLA_ADDR]], ptr [[BPTR5]],
-// CHECK: [[PTR5:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 5
-// CHECK: store ptr [[ARR_IDX5]], ptr [[PTR5]],
+// CHECK: [[BPTR7:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 7
+// CHECK: store ptr [[VLA_ADDR]], ptr [[BPTR7]],
+// CHECK: [[PTR7:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 7
+// CHECK: store ptr [[ARR_IDX5]], ptr [[PTR7]],
 
-// CHECK: [[BPTR:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 0
-// CHECK: [[PTR:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 0
-// CHECK: [[SIZE:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 0
-// CHECK: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 6, ptr [[BPTR]], ptr [[PTR]], ptr [[SIZE]], ptr [[MAPTYPES1]], ptr null, ptr null)
+// CHECK: [[BPTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 0
+// CHECK: [[PTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 0
+// CHECK: [[SIZE:%.+]] = getelementptr inbounds [8 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 8, ptr [[BPTR]], ptr [[PTR]], ptr [[SIZE]], ptr [[MAPTYPES1]], ptr null, ptr null)
 // CHECK: [[A_REF:%.+]] = load ptr, ptr [[BPTR0]],
-// CHECK: [[REF_REF:%.+]] = load ptr, ptr [[BPTR3]],
+// CHECK: [[REF_REF:%.+]] = load ptr, ptr [[BPTR5]],
 // CHECK: store ptr [[REF_REF]], ptr [[TMP_REF_ADDR:%.+]],
-// CHECK: [[ARR_REF:%.+]] = load ptr, ptr [[BPTR4]],
-// CHECK: [[VLA_REF:%.+]] = load ptr, ptr [[BPTR5]],
+// CHECK: [[ARR_REF:%.+]] = load ptr, ptr [[BPTR6]],
+// CHECK: [[VLA_REF:%.+]] = load ptr, ptr [[BPTR7]],
 // CHECK: [[A:%.+]] = load float, ptr [[A_REF]],
 // CHECK: [[INC:%.+]] = fadd float [[A]], 1.000000e+00
 // CHECK: store float [[INC]], ptr [[A_REF]],
@@ -120,10 +143,10 @@ int main() {
 // CHECK: [[VLA0:%.+]] = load float, ptr [[VLA0_ADDR]],
 // CHECK: [[INC:%.+]] = fadd float [[VLA0]], 1.000000e+00
 // CHECK: store float [[INC]], ptr [[VLA0_ADDR]],
-// CHECK: [[BPTR:%.+]] = getelementptr inbounds [6 x ptr], ptr [[BPTRS]], i32 0, i32 0
-// CHECK: [[PTR:%.+]] = getelementptr inbounds [6 x ptr], ptr [[PTRS]], i32 0, i32 0
-// CHECK: [[SIZE:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 0
-// CHECK: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 -1, i32 6, ptr [[BPTR]], ptr [[PTR]], ptr [[SIZE]], ptr [[MAPTYPES1]], ptr null, ptr null)
+// CHECK: [[BPTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 0
+// CHECK: [[PTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 0
+// CHECK: [[SIZE:%.+]] = getelementptr inbounds [8 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 -1, i32 8, ptr [[BPTR]], ptr [[PTR]], ptr [[SIZE]], ptr [[MAPTYPES1]], ptr null, ptr null)
 
 // CHECK: foo
 // CHECK: [[BPTRS:%.+]] = alloca [6 x ptr],
diff --git a/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
index 6d1c0213d648c..906313a048deb 100644
--- a/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
@@ -22,18 +22,18 @@
 double *g;
 
 // CK1: @g ={{.*}} global ptr
-// CK1: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 19, i64 64]
-// CK1: [[MTYPE01:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE03:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE04:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE05:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE06:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE07:@.+]] = {{.*}}constant [1 x i64] [i64 67]
-// CK1: [[MTYPE08:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 3]
-// CK1: [[MTYPE09:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 67]
-// CK1: [[MTYPE10:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 67]
-// CK1: [[MTYPE11:@.+]] = {{.*}}constant [2 x i64] [i64 3, i64 64]
-// CK1: [[MTYPE12:@.+]] = {{.*}}constant [2 x i64] [i64 3, i64 64]
+// CK1: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE01:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE03:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE04:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE05:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE06:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE07:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
+// CK1: [[MTYPE08:@.+]] = {{.*}}constant [4 x i64] [i64 67, i64 16384, i64 3, i64 16384]
+// CK1: [[MTYPE09:@.+]] = {{.*}}constant [4 x i64] [i64 67, i64 16384, i64 67, i64 16384]
+// CK1: [[MTYPE10:@.+]] = {{.*}}constant [4 x i64] [i64 67, i64 16384, i64 67, i64 16384]
+// CK1: [[MTYPE11:@.+]] = {{.*}}constant [3 x i64] [i64 3, i64 16384, i64 64]
+// CK1: [[MTYPE12:@.+]] = {{.*}}constant [3 x i64] [i64 3, i64 16384, i64 64]
 
 // CK1-LABEL: @_Z3foo
 template<typename T>
@@ -41,8 +41,12 @@ void foo(float *&lr, T *&tr) {
   float *l;
   T *t;
 
+  // &g[0], &g[/*lb=*/0], 10 * sizeof(g[0]), TO | FROM | RETURN_PARAM
+  // &g, &g[/*lb=*/0], sizeof(g), ATTACH
+  //
   // CK1:     [[T:%.+]] = load ptr, ptr [[DECL:@g]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 1
+  // CK1:     [[T:%.+]] = load ptr, ptr [[DECL]],
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -50,7 +54,7 @@ void foo(float *&lr, T *&tr) {
   // CK1:     store ptr [[VAL]], ptr [[PVT:%.+]],
   // CK1:     [[TT:%.+]] = load ptr, ptr [[PVT]],
   // CK1:     getelementptr inbounds nuw double, ptr [[TT]], i32 1
-  #pragma omp target data map(g[:10]) use_device_ptr(g)
+  #pragma omp target data map(g[0:10]) use_device_ptr(g)
   {
     ++g;
   }
@@ -59,8 +63,11 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw double, ptr [[TTT]], i32 1
   ++g;
 
+  // &l[0], &l[/*lb=*/0], 10 * sizeof(l[0]), TO | FROM | RETURN_PARAM
+  // &l, &l[/*lb=*/0], sizeof(l), ATTACH
+  //
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -68,7 +75,7 @@ void foo(float *&lr, T *&tr) {
   // CK1:     store ptr [[VAL]], ptr [[PVT:%.+]],
   // CK1:     [[TT1:%.+]] = load ptr, ptr [[PVT]],
   // CK1:     getelementptr inbounds nuw float, ptr [[TT1]], i32 1
-  #pragma omp target data map(l[:10]) use_device_ptr(l)
+  #pragma omp target data map(l[0:10]) use_device_ptr(l)
   {
     ++l;
   }
@@ -90,7 +97,7 @@ void foo(float *&lr, T *&tr) {
   ++l;
 
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -112,7 +119,7 @@ void foo(float *&lr, T *&tr) {
 
   // CK1:     [[BTHEN]]:
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE04]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -145,9 +152,12 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw float, ptr [[TTT]], i32 1
   ++l;
 
+  // &(ref_ptee(lr)[0]), &(ref_ptee(lr)[/*lb=*/0]), 10 * sizeof(lr[0]), TO | FROM | RETURN_PARAM
+  // &(ref_ptee(lr)), &(ref_ptee(lr)[/*lb=*/0]), sizeof(ref_ptee(lr)), ATTACH
+  //
   // CK1:     [[T2:%.+]] = load ptr, ptr [[DECL:%.+]],
   // CK1:     [[T1:%.+]] = load ptr, ptr [[T2]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE05]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -167,8 +177,11 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw float, ptr [[TTTT]], i32 1
   ++lr;
 
+  // &t[0], &t[/*lb=*/0], 10 * sizeof(t[0]), TO | FROM | RETURN_PARAM
+  // &t, &t[/*lb=*/0], sizeof(t), ATTACH
+  //
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE06]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -185,9 +198,12 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw i32, ptr [[TTT]], i32 1
   ++t;
 
+  // &(ref_ptee(tr)[0]), &(ref_ptee(tr)[/*lb=*/0]), 10 * sizeof(tr[0]), TO | FROM | RETURN_PARAM
+  // &(ref_ptee(tr)), &(ref_ptee(tr)[/*lb=*/0]), sizeof(ref_ptee(tr)), ATTACH
+  //
   // CK1:     [[T2:%.+]] = load ptr, ptr [[DECL:%.+]],
   // CK1:     [[T1:%.+]] = load ptr, ptr [[T2]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE07]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -207,8 +223,13 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw i32, ptr [[TTTT]], i32 1
   ++tr;
 
+  // &l[0], &l[/*lb=*/0], 10 * sizeof(l[0]), TO | FROM [| RETURN_PARAM]
+  // &l, &l[/*lb=*/0], sizeof(l), ATTACH
+  // &t[0], &t[/*lb=*/0], 10 * sizeof(t[0]), TO | FROM [| RETURN_PARAM]
+  // &t, &t[/*lb=*/0], sizeof(t), ATTACH
+
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [4 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE08]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -266,8 +287,11 @@ void foo(float *&lr, T *&tr) {
   // CK1:     getelementptr inbounds nuw i32, ptr [[TTT]], i32 1
   ++l; ++t;
 
+  // &l[0], &l[/*lb=*/0], 10 * sizeof(l[0]), TO | FROM [| RETURN_PARAM]
+  // &l, &l[/*lb=*/0], sizeof(l), ATTACH
+  // &t[0], &t[/*lb=*/0], 0, RETURN_PARAM
   // CK1:     [[T1:%.+]] = load ptr, ptr [[DECL:%.+]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 1
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [3 x ptr], ptr %{{.+}}, i32 0, i32 2
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE11]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -286,7 +310,7 @@ void foo(float *&lr, T *&tr) {
 
   // CK1:     [[T2:%.+]] = load ptr, ptr [[DECL:%.+]],
   // CK1:     [[T1:%.+]] = load ptr, ptr [[T2]],
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 1
+  // CK1:     [[BP:%.+]] = getelementptr inbounds [3 x ptr], ptr %{{.+}}, i32 0, i32 2
   // CK1:     store ptr [[T1]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE12]]
   // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
@@ -333,7 +357,7 @@ void bar(float *&a, int *&b) {
 // CK2: [[ST:%.+]] = type { ptr, ptr }
 // CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 0, i64 281474976710739]
 // CK2: [[MTYPE01:@.+]] = {{.*}}constant [2 x i64] [i64 0, i64 281474976710739]
-// CK2: [[MTYPE02:@.+]] = {{.*}}constant [3 x i64] [i64 3, i64 0, i64 562949953421392]
+// CK2: [[MTYPE02:@.+]] = {{.*}}constant [4 x i64] [i64 3, i64 16384, i64 0, i64 844424930132048]
 // CK2: [[MTYPE03:@.+]] = {{.*}}constant [3 x i64] [i64 0, i64 281474976710739, i64 281474976710736]
 
 template <typename T>
@@ -385,7 +409,7 @@ struct ST {
     // CK2:     getelementptr inbounds nuw double, ptr [[TTTT]], i32 1
     b++;
 
-    // CK2:     [[BP:%.+]] = getelementptr inbounds [3 x ptr], ptr %{{.+}}, i32 0, i32 2
+    // CK2:     [[BP:%.+]] = getelementptr inbounds [4 x ptr], ptr %{{.+}}, i32 0, i32 3
     // CK2:     store ptr [[RVAL:%.+]], ptr [[BP]],
     // CK2:     call void @__tgt_target_data_begin{{.+}}[[MTYPE02]]
     // CK2:     [[VAL:%.+]] = load ptr, ptr [[BP]],
diff --git a/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp b/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
index 5da5806752cee..e6642a317caa6 100644
--- a/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
@@ -18,22 +18,41 @@
 // SIMD-ONLY1-NOT: {{__kmpc|__tgt}}
 #ifdef CK1
 
-// CK1: [[MTYPE00:@.+]] = {{.*}}constant [1 x i64] [i64 67]
+// CK1: [[MYSIZE00:@.+]] = {{.*}}constant [2 x i64] [i64 4, i64 {{8|4}}]
+// CK1: [[MTYPE00:@.+]] = {{.*}}constant [2 x i64] [i64 67, i64 16384]
 // CK1: [[MTYPE01:@.+]] = {{.*}}constant [1 x i64] [i64 288]
 // CK1: [[MTYPE02:@.+]] = {{.*}}constant [1 x i64] [i64 288]
 
 void add_one(float *b, int dm)
 {
-  // CK1:     [[BP:%.+]] = getelementptr inbounds [1 x ptr], ptr %{{.+}}, i32 0, i32 0
-  // CK1:     store ptr [[B_ADDR:%.+]], ptr [[BP]]
-  // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
-  // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP]],
+  // &B[0], &B[0], 1 * sizeof(B[0]), PARAM | TO | FROM
+  // &B, &B[0], sizeof(B), ATTACH
+
+  // CK1:     [[RB_1:%.*]] = load ptr, ptr [[B:%b.addr]]
+  // CK1:     [[RB_2:%.*]] = load ptr, ptr [[B]]
+  // CK1:     [[RB0_1:%.*]] = getelementptr inbounds nuw float, ptr [[RB_2]], i{{.*}} 0
+  // CK1:     [[RB_3:%.*]] = load ptr, ptr [[B]]
+  // CK1:     [[RB0_2:%.*]] = getelementptr inbounds nuw float, ptr [[RB_3]], i{{.*}} 0
+
+  // CK1:     [[BP0:%.+]] = getelementptr inbounds [2 x ptr], ptr [[BP:%.offload_baseptrs.*]], i32 0, i32 0
+  // CK1:     store ptr [[RB_1]], ptr [[BP0]]
+  // CK1:     [[P0:%.+]] = getelementptr inbounds [2 x ptr], ptr [[P:%.offload_ptrs.*]], i32 0, i32 0
+  // CK1:     store ptr [[RB0_1]], ptr [[P0]]
+
+  // CK1:     [[BP1:%.+]] = getelementptr inbounds [2 x ptr], ptr [[BP]], i32 0, i32 1
+  // CK1:     store ptr [[B]], ptr [[BP1]]
+  // CK1:     [[P1:%.+]] = getelementptr inbounds [2 x ptr], ptr [[P]], i32 0, i32 1
+  // CK1:     store ptr [[RB0_2]], ptr [[P1]]
+
+  // CK1:     call void @__tgt_target_data_begin{{.+}}ptr [[MYSIZE00]], ptr [[MTYPE00]]
+
+  // CK1:     [[VAL:%.+]] = load ptr, ptr [[BP0]],
   // CK1-NOT: store ptr [[VAL]], ptr {{%.+}},
   // CK1:     store ptr [[VAL]], ptr [[PVT:%.+]],
   // CK1:     [[TT:%.+]] = load ptr, ptr [[PVT]],
   // CK1:     call i32 @__tgt_target{{.+}}
   // CK1:     call i32 @__tgt_target{{.+}}
-  // CK1:     call void @__tgt_target_data_end{{.+}}[[MTYPE00]]
+  // CK1:     call void @__tgt_target_data_end{{.+}}ptr [[MYSIZE00]], ptr [[MTYPE00]]
 #pragma omp target data map(tofrom:b[:1]) use_device_ptr(b) if(dm == 0)
   {
 #pragma omp target is_device_ptr(b)
diff --git a/clang/test/OpenMP/target_map_codegen_18.inc b/clang/test/OpenMP/target_map_codegen_18.inc
index 2930521975da8..a3a716b8fc8a1 100644
--- a/clang/test/OpenMP/target_map_codegen_18.inc
+++ b/clang/test/OpenMP/target_map_codegen_18.inc
@@ -63,32 +63,34 @@
 // CK19-NOUSE: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 2]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE10:@.+]] = private {{.*}}constant [1 x i64] [i64 240]
-// CK19-USE: [[MTYPE10:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK19-NOUSE: [[MTYPE10:@.+]] = private {{.*}}constant [1 x i64] [i64 3]
+// CK19: [[SIZE10:@.+]] = private {{.*}}constant [2 x i64] [i64 240, i64 {{4|8}}]
+// CK19-USE: [[MTYPE10:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
+// CK19-NOUSE: [[MTYPE10:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE11:@.+]] = private {{.*}}constant [1 x i64] [i64 240]
-// CK19-USE: [[MTYPE11:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
-// CK19-NOUSE: [[MTYPE11:@.+]] = private {{.*}}constant [1 x i64] zeroinitializer
+// CK19: [[SIZE11:@.+]] = private {{.*}}constant [2 x i64] [i64 240, i64 {{4|8}}]
+// CK19-USE: [[MTYPE11:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 16384]
+// CK19-NOUSE: [[MTYPE11:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE12:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
-// CK19-USE: [[MTYPE12:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
-// CK19-NOUSE: [[MTYPE12:@.+]] = private {{.*}}constant [1 x i64] [i64 1]
+// CK19: [[SIZE12:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK19-USE: [[MTYPE12:@.+]] = private {{.*}}constant [2 x i64] [i64 33, i64 16384]
+// CK19-NOUSE: [[MTYPE12:@.+]] = private {{.*}}constant [2 x i64] [i64 1, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19-USE: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 32]
-// CK19-NOUSE: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] zeroinitializer
+// CK19: [[SIZE13:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 {{4|8}}]
+// CK19-USE: [[MTYPE13:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 16384]
+// CK19-NOUSE: [[MTYPE13:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19-USE: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 33]
-// CK19-NOUSE: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 1]
+// CK19: [[SIZE14:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 {{4|8}}]
+// CK19-USE: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 33, i64 16384]
+// CK19-NOUSE: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 1, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE15:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
-// CK19-USE: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
-// CK19-NOUSE: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 2]
+// CK19: [[SIZE15:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK19-USE: [[MTYPE15:@.+]] = private {{.*}}constant [2 x i64] [i64 34, i64 16384]
+// CK19-NOUSE: [[MTYPE15:@.+]] = private {{.*}}constant [2 x i64] [i64 2, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK19-USE: [[SIZE16:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 0]
@@ -527,6 +529,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 10
+
+  //  &pa[0], &pa[20], 60 * sizeof(pa[0]), TO | FROM [| PARAM]
+  //  &pa, &pa[20], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -543,6 +549,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 20
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 20
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL10:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL10:@.+]]()
   #pragma omp target map(tofrom:pa[20:60])
@@ -553,6 +567,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 11
+
+  //  &pa[0], &pa[/*lb=*/0], 60 * sizeof(pa[0]), ALLOC [| PARAM]
+  //  &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -569,6 +587,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 0
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 0
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL11:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL11:@.+]]()
   #pragma omp target map(alloc:pa[:60])
@@ -579,6 +605,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 12
+
+  //  &pa[0], &pa[15], 1 * sizeof(pa[0]), TO [| PARAM]
+  //  &pa, &pa[15], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -595,6 +625,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 15
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 15
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL12:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL12:@.+]]()
   #pragma omp target map(to:pa[15])
@@ -605,6 +643,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 13
+
+  //  &pa[0], &pa[ii-23], ii * sizeof(pa[0]), ALLOC [| PARAM]
+  //  &pa, &pa[ii-23], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -627,6 +669,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} %{{.*}}
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} %{{.*}}
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL13:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL13:@.+]]()
   #pragma omp target map(alloc:pa[ii-23:ii])
@@ -637,6 +687,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 14
+
+  //  &pa[0], &pa[/*lb=*/0], ii * sizeof(pa[0]), ALLOC [| PARAM]
+  //  &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -659,6 +713,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 0
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 0
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL14:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL14:@.+]]()
   #pragma omp target map(to:pa[:ii])
@@ -669,6 +731,10 @@ void explicit_maps_single (int ii){
   }
 
   // Region 15
+
+  //  &pa[0], &pa[ii + 12], 1 * sizeof(pa[0]), TO [| PARAM]
+  //  &pa, &pa[ii + 12], sizeof(pa), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -685,6 +751,14 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} %{{.*}}
   // CK19-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+  // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+  // CK19-DAG: store ptr [[VAR0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+  // CK19-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} %{{.*}}
+  // CK19-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
   // CK19-USE: call void [[CALL15:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL15:@.+]]()
   #pragma omp target map(from:pa[ii+12])
diff --git a/clang/test/OpenMP/target_map_codegen_19.cpp b/clang/test/OpenMP/target_map_codegen_19.cpp
index 1d6c781a09905..942545cb2e58e 100644
--- a/clang/test/OpenMP/target_map_codegen_19.cpp
+++ b/clang/test/OpenMP/target_map_codegen_19.cpp
@@ -46,8 +46,8 @@
 // CK20: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
 
 // CK20-LABEL: @.__omp_offloading_{{.*}}explicit_maps_references_and_function_args{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK20: [[SIZE03:@.+]] = private {{.*}}constant [1 x i64] [i64 12]
-// CK20: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 34]
+// CK20: [[SIZE03:@.+]] = private {{.*}}constant [2 x i64] [i64 12, i64 {{4|8}}]
+// CK20: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 34, i64 16384]
 
 // CK20-LABEL: explicit_maps_references_and_function_args{{.*}}(
 void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], float *d){
@@ -126,6 +126,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f
   }
 
 // Region 03
+//
+//  &d[0], &d[2], 3 * sizeof(d[0]), FROM | PARAM
+//  &d, &d[2], sizeof(d), ATTACH
+//
 // CK20-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK20-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK20-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -142,6 +146,13 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f
 // CK20-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 2
 // CK20-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+// CK20-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK20-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK20-DAG: store ptr [[VAR0]], ptr [[BP1]]
+// CK20-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK20-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 2
+// CK20-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
 // CK20: call void [[CALL03:@.+]](ptr {{[^,]+}})
 #pragma omp target map(from \
                        : d [2:3])
diff --git a/clang/test/OpenMP/target_map_codegen_20.cpp b/clang/test/OpenMP/target_map_codegen_20.cpp
index 7ad2019b56ba4..4514a7f65cf87 100644
--- a/clang/test/OpenMP/target_map_codegen_20.cpp
+++ b/clang/test/OpenMP/target_map_codegen_20.cpp
@@ -69,9 +69,9 @@
 // CK21-NOUSE: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 3]
 
 // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK21: [[SIZE01:@.+]] = private {{.*}}constant [1 x i64] [i64 492]
-// CK21-USE: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
-// CK21-NOUSE: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 3]
+// CK21: [[SIZE01:@.+]] = private {{.*}}constant [2 x i64] [i64 492, i64 {{4|8}}]
+// CK21-USE: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
+// CK21-NOUSE: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
 
 // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 500]
@@ -130,6 +130,10 @@ struct CC {
     }
 
 // Region 01
+//
+//   &lb[0], &lb[/*lower_bound=*/0], X * sizeof(T), (TO | FROM) / (TO | FROM | PARAM)
+//   &lb, &lb[/*lower_bound=*/0], sizeof(T*), ATTACH
+//
 // CK21-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK21-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK21-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -140,11 +144,18 @@ struct CC {
 
 // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK21-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
-// CK21-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK21-DAG: [[RVAR0]] = load ptr, ptr [[VAR0:%[^,]+]]
-// CK21-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 0
-// CK21-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
+// CK21-DAG: store ptr [[RLB:%.+]], ptr [[BP0]]
+// CK21-DAG: store ptr [[RLB0:%.+]], ptr [[P0]]
+// CK21-DAG: [[RLB]] = load ptr, ptr %lb
+// CK21-DAG: [[RLB0]] = getelementptr {{.*}}ptr [[RLB_1:%.+]], i{{.+}} 0
+// CK21-DAG: [[RLB_1]] = load ptr, ptr %lb
+
+// CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK21-DAG: store ptr %lb, ptr [[BP1]]
+// CK21-DAG: store ptr [[RLB0_1:%.+]], ptr [[P1]]
+// CK21-DAG: [[RLB0_1]] = getelementptr {{.*}}ptr [[RLB_2:%.+]], i{{.+}} 0
+// CK21-DAG: [[RLB_2]] = load ptr, ptr %lb
 
 // CK21-USE: call void [[CALL01:@.+]](ptr {{[^,]+}})
 // CK21-NOUSE: call void [[CALL01:@.+]]()
diff --git a/clang/test/OpenMP/target_map_codegen_21.cpp b/clang/test/OpenMP/target_map_codegen_21.cpp
index f5c517692d8c8..b3e94112624dd 100644
--- a/clang/test/OpenMP/target_map_codegen_21.cpp
+++ b/clang/test/OpenMP/target_map_codegen_21.cpp
@@ -53,8 +53,8 @@
 // CK22: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK22: [[SIZE04:@.+]] = private {{.*}}constant [1 x i64] [i64 20]
-// CK22: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 51]
+// CK22: [[SIZE04:@.+]] = private {{.*}}constant [2 x i64] [i64 20, i64 {{4|8}}]
+// CK22: [[MTYPE04:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK22: [[SIZE05:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
@@ -73,8 +73,8 @@
 // CK22: [[MTYPE08:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK22: [[SIZE09:@.+]] = private {{.*}}constant [1 x i64] [i64 20]
-// CK22: [[MTYPE09:@.+]] = private {{.*}}constant [1 x i64] [i64 51]
+// CK22: [[SIZE09:@.+]] = private {{.*}}constant [2 x i64] [i64 20, i64 {{4|8}}]
+// CK22: [[MTYPE09:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK22: [[SIZE10:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
@@ -93,8 +93,8 @@
 // CK22: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK22-LABEL: @.__omp_offloading_{{.*}}explicit_maps_globals{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK22: [[SIZE14:@.+]] = private {{.*}}constant [1 x i64] [i64 20]
-// CK22: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 51]
+// CK22: [[SIZE14:@.+]] = private {{.*}}constant [2 x i64] [i64 20, i64 {{4|8}}]
+// CK22: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 int a;
 int c[100];
@@ -192,6 +192,10 @@ int explicit_maps_globals(void){
   { c[3]+=1; }
 
 // Region 04
+//
+//  &d[0], &d[2], 5 * sizeof(d[0]), TO | FROM | PARAM
+//  &d, &d[2], sizeof(d), ATTACH
+//
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -202,11 +206,19 @@ int explicit_maps_globals(void){
 
 // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK22-DAG: store ptr @d, ptr [[BP0]]
+// CK22-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
 // CK22-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+// CK22-DAG: [[RVAR0]] = load ptr, ptr @d
 // CK22-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 2
 // CK22-DAG: [[RVAR00]] = load ptr, ptr @d
 
+// CK22-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: store ptr @d, ptr [[BP1]]
+// CK22-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK22-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 2
+// CK22-DAG: [[RVAR1]] = load ptr, ptr @d
+
 // CK22: call void [[CALL04:@.+]](ptr {{[^,]+}})
 #pragma omp target map(d [2:5])
   { d[3]+=1; }
@@ -284,6 +296,10 @@ int explicit_maps_globals(void){
   { sc[3].fa+=1; }
 
 // Region 09
+//
+//  &sd[0], &sd[2], 5 * sizeof(sd[0]), TO | FROM | ATTACH
+//  &sd, &sd[2], sizeof(sd), ATTACH
+//
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -294,11 +310,19 @@ int explicit_maps_globals(void){
 
 // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK22-DAG: store ptr @sd, ptr [[BP0]]
+// CK22-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
 // CK22-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+// CK22-DAG: [[RVAR0]] = load ptr, ptr @sd
 // CK22-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 2
 // CK22-DAG: [[RVAR00]] = load ptr, ptr @sd
 
+// CK22-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: store ptr @sd, ptr [[BP1]]
+// CK22-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK22-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 2
+// CK22-DAG: [[RVAR1]] = load ptr, ptr @sd
+
 // CK22: call void [[CALL09:@.+]](ptr {{[^,]+}})
 #pragma omp target map(sd [2:5])
   { sd[3].fa+=1; }
@@ -376,6 +400,10 @@ int explicit_maps_globals(void){
   { stc[3].fa+=1; }
 
 // Region 14
+//
+//  &std[0], &std[2], 5 * sizeof(std[0]), TO | FROM | ATTACH
+//  &std, &std[2], sizeof(std), ATTACH
+//
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -386,11 +414,19 @@ int explicit_maps_globals(void){
 
 // CK22-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK22-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK22-DAG: store ptr @std, ptr [[BP0]]
+// CK22-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
 // CK22-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+// CK22-DAG: [[RVAR0]] = load ptr, ptr @std
 // CK22-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 2
 // CK22-DAG: [[RVAR00]] = load ptr, ptr @std
 
+// CK22-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK22-DAG: store ptr @std, ptr [[BP1]]
+// CK22-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK22-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 2
+// CK22-DAG: [[RVAR1]] = load ptr, ptr @std
+
 // CK22: call void [[CALL14:@.+]](ptr {{[^,]+}})
 #pragma omp target map(std [2:5])
   { std[3].fa+=1; }
diff --git a/clang/test/OpenMP/target_map_codegen_22.cpp b/clang/test/OpenMP/target_map_codegen_22.cpp
index 06028b23e9378..6c17a847d47b4 100644
--- a/clang/test/OpenMP/target_map_codegen_22.cpp
+++ b/clang/test/OpenMP/target_map_codegen_22.cpp
@@ -54,8 +54,8 @@
 // CK23: [[MTYPE04:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK23-LABEL: @.__omp_offloading_{{.*}}explicit_maps_inside_captured{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK23: [[SIZE05:@.+]] = private {{.*}}constant [1 x i64] [i64 16]
-// CK23: [[MTYPE05:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK23: [[SIZE05:@.+]] = private {{.*}}constant [2 x i64] [i64 16, i64 {{4|8}}]
+// CK23: [[MTYPE05:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK23-LABEL: explicit_maps_inside_captured{{.*}}(
 int explicit_maps_inside_captured(int a){
@@ -175,6 +175,10 @@ int explicit_maps_inside_captured(int a){
       { c[3]+=1; }
 
 // Region 05
+//
+// &d[0], &d[2], 4 * sizeof(d[0]), TO | FROM
+// &d, &d[2], sizeof(d), ATTACH
+//
 // CK23-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK23-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK23-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -195,6 +199,16 @@ int explicit_maps_inside_captured(int a){
 // CK23-DAG: [[VAR00]] = load ptr, ptr [[CAP00:%[^,]+]]
 // CK23-DAG: [[CAP00]] = getelementptr inbounds nuw %class.anon,
 
+// CK23-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK23-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK23-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
+// CK23-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK23-DAG: [[VAR1]] = load ptr, ptr [[CAP1:%[^,]+]]
+// CK23-DAG: [[CAP1]] = getelementptr inbounds nuw %class.anon,
+// CK23-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 2
+// CK23-DAG: [[RVAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK23-DAG: [[VAR11]] = load ptr, ptr [[CAP11:%[^,]+]]
+// CK23-DAG: [[CAP11]] = getelementptr inbounds nuw %class.anon,
 // CK23: call void [[CALL05:@.+]](ptr {{[^,]+}})
 #pragma omp target map(d [2:4])
       { d[3]+=1; }
diff --git a/clang/test/OpenMP/target_map_codegen_26.cpp b/clang/test/OpenMP/target_map_codegen_26.cpp
index 2bc1092685ac3..b327a8f35ce7e 100644
--- a/clang/test/OpenMP/target_map_codegen_26.cpp
+++ b/clang/test/OpenMP/target_map_codegen_26.cpp
@@ -38,16 +38,16 @@
 // CK27: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 544]
 
 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK27: [[SIZE01:@.+]] = private {{.*}}constant [1 x i64] zeroinitializer
-// CK27: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27: [[SIZE01:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 {{8|4}}]
+// CK27: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK27: [[SIZE02:@.+]] = private {{.*}}constant [1 x i64] zeroinitializer
-// CK27: [[MTYPE02:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64  {{8|4}}]
+// CK27: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK27: [[SIZE03:@.+]] = private {{.*}}constant [1 x i64] zeroinitializer
-// CK27: [[MTYPE03:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK27: [[SIZE03:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64  {{8|4}}]
+// CK27: [[MTYPE03:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK27-LABEL: @.__omp_offloading_{{.*}}zero_size_section_and_private_maps{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
@@ -71,6 +71,12 @@ void zero_size_section_and_private_maps (int ii){
   int *pa;
 
 // Region 00
+//
+//   &pa, &pa, sizeof(pa), IMPLICIT | PARAM
+//
+// FIXME: This looks like a bug. The implicit map on a pointer
+// should be identical to pa[0:0]
+//
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -91,6 +97,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 01
+//
+//   &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
+//   &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+//
+// Can be optimized to:
+//   &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
+//
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -107,6 +120,13 @@ void zero_size_section_and_private_maps (int ii){
 // CK27-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 0
 // CK27-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+// CK27-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: store ptr [[VAR0]], ptr [[BP1]]
+// CK27-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK27-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 0
+// CK27-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
 // CK27: call void [[CALL01:@.+]](ptr {{[^,]+}})
 #pragma omp target map(pa[:0])
   {
@@ -114,6 +134,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 02
+//
+//   &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
+//   &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+//
+// Can be optimized to:
+//   &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
+//
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -130,6 +157,13 @@ void zero_size_section_and_private_maps (int ii){
 // CK27-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} 0
 // CK27-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+// CK27-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: store ptr [[VAR0]], ptr [[BP1]]
+// CK27-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK27-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 0
+// CK27-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
 // CK27: call void [[CALL02:@.+]](ptr {{[^,]+}})
 #pragma omp target map(pa [0:0])
   {
@@ -137,6 +171,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 03
+//
+//   &pa[0], &pa[ii], /*size=*/0, TO | FROM | PARAM
+//   &pa, &pa[ii], sizeof(pa), ATTACH
+//
+// Can be optimized to:
+//   &pa[ii], &pa[ii], /*size=*/0, TO | FROM | PARAM
+//
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -153,6 +194,13 @@ void zero_size_section_and_private_maps (int ii){
 // CK27-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[RVAR00:%.+]], i{{.+}} %{{.+}}
 // CK27-DAG: [[RVAR00]] = load ptr, ptr [[VAR0]]
 
+// CK27-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK27-DAG: store ptr [[VAR0]], ptr [[BP1]]
+// CK27-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK27-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} %{{.+}}
+// CK27-DAG: [[RVAR1]] = load ptr, ptr [[VAR0]]
+
 // CK27: call void [[CALL03:@.+]](ptr {{[^,]+}})
 #pragma omp target map(pa [ii:0])
   {
diff --git a/clang/test/OpenMP/target_map_codegen_27.cpp b/clang/test/OpenMP/target_map_codegen_27.cpp
index bfe75bca481be..5f24ba97ba0a0 100644
--- a/clang/test/OpenMP/target_map_codegen_27.cpp
+++ b/clang/test/OpenMP/target_map_codegen_27.cpp
@@ -38,8 +38,8 @@
 // CK28: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK28-LABEL: @.__omp_offloading_{{.*}}explicit_maps_pointer_references{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK28: [[SIZE01:@.+]] = private {{.*}}constant [1 x i64] [i64 400]
-// CK28: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK28: [[SIZE01:@.+]] = private {{.*}}constant [2 x i64] [i64 400, i64 {{4|8}}]
+// CK28: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK28-LABEL: explicit_maps_pointer_references{{.*}}(
 void explicit_maps_pointer_references (int *p){
@@ -68,6 +68,10 @@ void explicit_maps_pointer_references (int *p){
   }
 
 // Region 01
+//
+// &(ref_ptee(a)[0]), &(ref_ptee(a)[2]), 100 * sizeof(int), TO | FROM | PARAM
+// &(ref_ptee(a)), &(ref_ptee(a)[2]), sizeof(ref_ptee(a)), ATTACH
+//
 // CK28-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK28-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK28-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -78,13 +82,22 @@ void explicit_maps_pointer_references (int *p){
 
 // CK28-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK28-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK28-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK28-DAG: store ptr [[VAR1:%.+]], ptr [[P0]]
-// CK28-DAG: [[VAR0]] = load ptr, ptr [[VAR00:%.+]],
-// CK28-DAG: [[VAR00]] = load ptr, ptr [[VAR000:%.+]],
-// CK28-DAG: [[VAR1]] = getelementptr inbounds nuw i32, ptr [[VAR11:%.+]], i{{64|32}} 2
-// CK28-DAG: [[VAR11]] = load ptr, ptr [[VAR111:%.+]],
-// CK28-DAG: [[VAR111]] = load ptr, ptr [[VAR1111:%.+]],
+// CK28-DAG: store ptr [[RRA:%.+]], ptr [[BP0]]
+// CK28-DAG: store ptr [[RRA2:%.+]], ptr [[P0]]
+// CK28-DAG: [[RRA]] = load ptr, ptr [[RA:%.+]],
+// CK28-DAG: [[RA]] = load ptr, ptr [[A:%.+]],
+// CK28-DAG: [[RRA2]] = getelementptr inbounds nuw i32, ptr [[RRA_1:%.+]], i{{64|32}} 2
+// CK28-DAG: [[RRA_1]] = load ptr, ptr [[RA_1:%.+]],
+// CK28-DAG: [[RA_1]] = load ptr, ptr [[A]]
+
+// CK28-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK28-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK28-DAG: store ptr [[RA_2:%.+]], ptr [[BP1]]
+// CK28-DAG: store ptr [[RRA2_2:%.+]], ptr [[P1]]
+// CK28-DAG: [[RA_2]] = load ptr, ptr [[A]]
+// CK28-DAG: [[RRA2_2]] = getelementptr inbounds nuw i32, ptr [[RRA_2:%.+]], i{{64|32}} 2
+// CK28-DAG: [[RRA_2]] = load ptr, ptr [[RA_3:%.+]],
+// CK28-DAG: [[RA_3]] = load ptr, ptr [[A]]
 
 // CK28: call void [[CALL01:@.+]](ptr {{[^,]+}})
 #pragma omp target map(a [2:100])
diff --git a/clang/test/OpenMP/target_task_affinity_codegen.cpp b/clang/test/OpenMP/target_task_affinity_codegen.cpp
index 53960cee4b730..f45d532c7b8d4 100644
--- a/clang/test/OpenMP/target_task_affinity_codegen.cpp
+++ b/clang/test/OpenMP/target_task_affinity_codegen.cpp
@@ -1,4 +1,4 @@
-// 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 _
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*"
 // Test host codegen.
 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1
 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-pch -o %t %s
@@ -37,11 +37,11 @@
 int main() {
   int *A;
   int *B;
-  #pragma omp target data map(tofrom: A[0:1024])
+  #pragma omp target data map(tofrom: A[0:1024]) // (1)
 
-#pragma omp target data use_device_ptr(A)
+ #pragma omp target data use_device_ptr(A) // (2)
 {
-  #pragma omp target defaultmap(none) is_device_ptr(A) map(tofrom: B[0:1024])
+  #pragma omp target defaultmap(none) is_device_ptr(A) map(tofrom: B[0:1024]) // (3)
   {
     #pragma omp task shared(B) affinity(A[0:1024])
       {
@@ -56,106 +56,152 @@ int main() {
 }
 
 #endif
+
+// Expected Maps:
+// (1):
+//   &A[0], &A[/*lb=*/0], 1024 * sizeof(A[0]), TO | FROM
+//   &A, &A[/*lb=*/0], sizeof(A), ATTACH
+// (2):
+//
+//   &A[0], &A[0], sizeof(A), RETURN_PARAM
+// (3):
+//   &B[0], &B[/*lb=*/0], 1024 * sizeof(B[0]), TO | FROM | PARAM
+//   &B, &B[/*lb=*/0], sizeof(B), ATTACH
+//   &A[0], &A[0], sizeof(A[0]), LITERAL | PARAM
+
+// TODO: Update the test to limit the checks to relevant lines only.
+
+//.
+// CHECK1: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4096, i64 8]
+// CHECK1: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 3, i64 16384]
+// CHECK1: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] zeroinitializer
+// CHECK1: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 64]
+// CHECK1: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 4096, i64 8, i64 8]
+// CHECK1: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 35, i64 16384, i64 288]
+//.
+// CHECK3: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4096, i64 4]
+// CHECK3: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 3, i64 16384]
+// CHECK3: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] zeroinitializer
+// CHECK3: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 64]
+// CHECK3: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 4096, i64 4, i64 4]
+// CHECK3: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 35, i64 16384, i64 288]
+//.
 // CHECK1-LABEL: define {{[^@]+}}@main
 // CHECK1-SAME: () #[[ATTR0:[0-9]+]] {
 // CHECK1-NEXT:  entry:
 // CHECK1-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
 // CHECK1-NEXT:    [[A:%.*]] = alloca ptr, align 8
 // CHECK1-NEXT:    [[B:%.*]] = alloca ptr, align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS1:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS2:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS3:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 8
 // CHECK1-NEXT:    [[TMP0:%.*]] = alloca ptr, align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [2 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [2 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [2 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [3 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [3 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [3 x ptr], align 8
 // CHECK1-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
 // CHECK1-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK1-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[A]], align 8
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[A]], align 8
 // CHECK1-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
-// CHECK1-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK1-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
-// CHECK1-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP5]], align 8
-// CHECK1-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP6]], ptr [[TMP7]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[A]], align 8
-// CHECK1-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[TMP9]], align 8
-// CHECK1-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[TMP10]], align 8
-// CHECK1-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS3]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP11]], align 8
-// CHECK1-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP9]], align 8
-// CHECK1-NEXT:    store ptr [[TMP14]], ptr [[TMP0]], align 8
-// CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[TMP0]], align 8
-// CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP18]], i64 0
-// CHECK1-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP17]], ptr [[TMP19]], align 8
-// CHECK1-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP20]], align 8
-// CHECK1-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP21]], align 8
-// CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[TMP16]], ptr [[TMP22]], align 8
-// CHECK1-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[TMP16]], ptr [[TMP23]], align 8
-// CHECK1-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i64 0, i64 1
-// CHECK1-NEXT:    store ptr null, ptr [[TMP24]], align 8
-// CHECK1-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP27:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK1-NEXT:    store i32 3, ptr [[TMP27]], align 4
-// CHECK1-NEXT:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK1-NEXT:    store i32 2, ptr [[TMP28]], align 4
-// CHECK1-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK1-NEXT:    store ptr [[TMP25]], ptr [[TMP29]], align 8
-// CHECK1-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK1-NEXT:    store ptr [[TMP26]], ptr [[TMP30]], align 8
-// CHECK1-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK1-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP31]], align 8
-// CHECK1-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK1-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP32]], align 8
-// CHECK1-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK1-NEXT:    store ptr null, ptr [[TMP33]], align 8
-// CHECK1-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK1-NEXT:    store ptr null, ptr [[TMP34]], align 8
-// CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK1-NEXT:    store i64 0, ptr [[TMP35]], align 8
-// CHECK1-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK1-NEXT:    store i64 0, ptr [[TMP36]], align 8
-// CHECK1-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK1-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP37]], align 4
-// CHECK1-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK1-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP38]], align 4
-// CHECK1-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK1-NEXT:    store i32 0, ptr [[TMP39]], align 4
-// CHECK1-NEXT:    [[TMP40:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
-// CHECK1-NEXT:    [[TMP41:%.*]] = icmp ne i32 [[TMP40]], 0
-// CHECK1-NEXT:    br i1 [[TMP41]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK1-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[A]], align 8
+// CHECK1-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP3]], i64 0
+// CHECK1-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK1-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK1-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP6]], align 8
+// CHECK1-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[A]], ptr [[TMP7]], align 8
+// CHECK1-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
+// CHECK1-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK1-NEXT:    store ptr null, ptr [[TMP9]], align 8
+// CHECK1-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP10]], ptr [[TMP11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[A]], align 8
+// CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP12]], ptr [[TMP13]], align 8
+// CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP12]], ptr [[TMP14]], align 8
+// CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP15]], align 8
+// CHECK1-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP16]], ptr [[TMP17]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP13]], align 8
+// CHECK1-NEXT:    store ptr [[TMP18]], ptr [[TMP0]], align 8
+// CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK1-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK1-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP22]], i64 0
+// CHECK1-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK1-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP23]], i64 0
+// CHECK1-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP21]], ptr [[TMP24]], align 8
+// CHECK1-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP25]], align 8
+// CHECK1-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP26]], align 8
+// CHECK1-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[B]], ptr [[TMP27]], align 8
+// CHECK1-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP28]], align 8
+// CHECK1-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 1
+// CHECK1-NEXT:    store ptr null, ptr [[TMP29]], align 8
+// CHECK1-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP20]], ptr [[TMP30]], align 8
+// CHECK1-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP20]], ptr [[TMP31]], align 8
+// CHECK1-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 2
+// CHECK1-NEXT:    store ptr null, ptr [[TMP32]], align 8
+// CHECK1-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK1-NEXT:    store i32 3, ptr [[TMP35]], align 4
+// CHECK1-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK1-NEXT:    store i32 3, ptr [[TMP36]], align 4
+// CHECK1-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP33]], ptr [[TMP37]], align 8
+// CHECK1-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK1-NEXT:    store ptr [[TMP34]], ptr [[TMP38]], align 8
+// CHECK1-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK1-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP39]], align 8
+// CHECK1-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK1-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP40]], align 8
+// CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK1-NEXT:    store ptr null, ptr [[TMP41]], align 8
+// CHECK1-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK1-NEXT:    store ptr null, ptr [[TMP42]], align 8
+// CHECK1-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK1-NEXT:    store i64 0, ptr [[TMP43]], align 8
+// CHECK1-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK1-NEXT:    store i64 0, ptr [[TMP44]], align 8
+// CHECK1-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK1-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP45]], align 4
+// CHECK1-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK1-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
+// CHECK1-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK1-NEXT:    store i32 0, ptr [[TMP47]], align 4
+// CHECK1-NEXT:    [[TMP48:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
+// CHECK1-NEXT:    [[TMP49:%.*]] = icmp ne i32 [[TMP48]], 0
+// CHECK1-NEXT:    br i1 [[TMP49]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK1:       omp_offload.failed:
-// CHECK1-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP15]], ptr [[TMP16]]) #[[ATTR1:[0-9]+]]
+// CHECK1-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP19]], ptr [[TMP20]]) #[[ATTR1:[0-9]+]]
 // CHECK1-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK1:       omp_offload.cont:
-// CHECK1-NEXT:    [[TMP42:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP42]], ptr [[TMP43]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP45:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP44]], ptr [[TMP45]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP52]], ptr [[TMP53]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
 // CHECK1-NEXT:    ret i32 0
 //
 //
@@ -237,44 +283,44 @@ int main() {
 // CHECK1-NEXT:    [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
 // CHECK1-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
-// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META4:![0-9]+]])
-// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META7:![0-9]+]])
-// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
-// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]])
-// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META13:![0-9]+]]
-// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META13]]
+// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META5:![0-9]+]])
+// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
+// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
+// CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
+// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META14:![0-9]+]]
+// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]]
 // CHECK1-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR1]]
-// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META13]]
-// CHECK1-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META13]]
+// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META14]]
+// CHECK1-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META14]]
 // CHECK1-NEXT:    br label [[FOR_COND_I:%.*]]
 // CHECK1:       for.cond.i:
-// CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META13]]
+// CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
 // CHECK1-NEXT:    [[CMP_I:%.*]] = icmp slt i32 [[TMP13]], 1024
 // CHECK1-NEXT:    br i1 [[CMP_I]], label [[FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]]
 // CHECK1:       for.body.i:
 // CHECK1-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP12]], align 8
-// CHECK1-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META13]]
+// CHECK1-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
 // CHECK1-NEXT:    [[IDXPROM_I:%.*]] = sext i32 [[TMP15]] to i64
 // CHECK1-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 [[IDXPROM_I]]
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4
 // CHECK1-NEXT:    [[MUL_I:%.*]] = mul nsw i32 2, [[TMP16]]
-// CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 8
+// CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 8, !nonnull [[META15:![0-9]+]], !align [[META16:![0-9]+]]
 // CHECK1-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8
-// CHECK1-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META13]]
+// CHECK1-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
 // CHECK1-NEXT:    [[IDXPROM1_I:%.*]] = sext i32 [[TMP19]] to i64
 // CHECK1-NEXT:    [[ARRAYIDX2_I:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i64 [[IDXPROM1_I]]
 // CHECK1-NEXT:    store i32 [[MUL_I]], ptr [[ARRAYIDX2_I]], align 4
-// CHECK1-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META13]]
+// CHECK1-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
 // CHECK1-NEXT:    [[INC_I:%.*]] = add nsw i32 [[TMP20]], 1
-// CHECK1-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META13]]
-// CHECK1-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP14:![0-9]+]]
+// CHECK1-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK1-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP17:![0-9]+]]
 // CHECK1:       .omp_outlined..exit:
 // CHECK1-NEXT:    ret i32 0
 //
@@ -285,100 +331,116 @@ int main() {
 // CHECK3-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
 // CHECK3-NEXT:    [[A:%.*]] = alloca ptr, align 4
 // CHECK3-NEXT:    [[B:%.*]] = alloca ptr, align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS1:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS2:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS3:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 4
 // CHECK3-NEXT:    [[TMP0:%.*]] = alloca ptr, align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [2 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [2 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [2 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [3 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [3 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [3 x ptr], align 4
 // CHECK3-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
 // CHECK3-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK3-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[A]], align 4
 // CHECK3-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[A]], align 4
 // CHECK3-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i32 0
-// CHECK3-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP1]], ptr [[TMP3]], align 4
-// CHECK3-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 4
-// CHECK3-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP5]], align 4
-// CHECK3-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP6]], ptr [[TMP7]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[A]], align 4
-// CHECK3-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP8]], ptr [[TMP9]], align 4
-// CHECK3-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP8]], ptr [[TMP10]], align 4
-// CHECK3-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS3]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP11]], align 4
-// CHECK3-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP9]], align 4
-// CHECK3-NEXT:    store ptr [[TMP14]], ptr [[TMP0]], align 4
-// CHECK3-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[TMP0]], align 4
-// CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP18]], i32 0
-// CHECK3-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP17]], ptr [[TMP19]], align 4
-// CHECK3-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP20]], align 4
-// CHECK3-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[TMP16]], ptr [[TMP22]], align 4
-// CHECK3-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[TMP16]], ptr [[TMP23]], align 4
-// CHECK3-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr null, ptr [[TMP24]], align 4
-// CHECK3-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP27:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK3-NEXT:    store i32 3, ptr [[TMP27]], align 4
-// CHECK3-NEXT:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK3-NEXT:    store i32 2, ptr [[TMP28]], align 4
-// CHECK3-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK3-NEXT:    store ptr [[TMP25]], ptr [[TMP29]], align 4
-// CHECK3-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK3-NEXT:    store ptr [[TMP26]], ptr [[TMP30]], align 4
-// CHECK3-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK3-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP31]], align 4
-// CHECK3-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK3-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP32]], align 4
-// CHECK3-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK3-NEXT:    store ptr null, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK3-NEXT:    store ptr null, ptr [[TMP34]], align 4
-// CHECK3-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK3-NEXT:    store i64 0, ptr [[TMP35]], align 8
-// CHECK3-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK3-NEXT:    store i64 0, ptr [[TMP36]], align 8
-// CHECK3-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK3-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP37]], align 4
-// CHECK3-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK3-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP38]], align 4
-// CHECK3-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK3-NEXT:    store i32 0, ptr [[TMP39]], align 4
-// CHECK3-NEXT:    [[TMP40:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
-// CHECK3-NEXT:    [[TMP41:%.*]] = icmp ne i32 [[TMP40]], 0
-// CHECK3-NEXT:    br i1 [[TMP41]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK3-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[A]], align 4
+// CHECK3-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP3]], i32 0
+// CHECK3-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP1]], ptr [[TMP4]], align 4
+// CHECK3-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 4
+// CHECK3-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP6]], align 4
+// CHECK3-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[A]], ptr [[TMP7]], align 4
+// CHECK3-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 4
+// CHECK3-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr null, ptr [[TMP9]], align 4
+// CHECK3-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP10]], ptr [[TMP11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[A]], align 4
+// CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP12]], ptr [[TMP13]], align 4
+// CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP12]], ptr [[TMP14]], align 4
+// CHECK3-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP15]], align 4
+// CHECK3-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP16]], ptr [[TMP17]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP13]], align 4
+// CHECK3-NEXT:    store ptr [[TMP18]], ptr [[TMP0]], align 4
+// CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[B]], align 4
+// CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[TMP0]], align 4
+// CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[B]], align 4
+// CHECK3-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[B]], align 4
+// CHECK3-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP22]], i32 0
+// CHECK3-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[B]], align 4
+// CHECK3-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP23]], i32 0
+// CHECK3-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP21]], ptr [[TMP24]], align 4
+// CHECK3-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP25]], align 4
+// CHECK3-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP26]], align 4
+// CHECK3-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[B]], ptr [[TMP27]], align 4
+// CHECK3-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP28]], align 4
+// CHECK3-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr null, ptr [[TMP29]], align 4
+// CHECK3-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP20]], ptr [[TMP30]], align 4
+// CHECK3-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP20]], ptr [[TMP31]], align 4
+// CHECK3-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr null, ptr [[TMP32]], align 4
+// CHECK3-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK3-NEXT:    store i32 3, ptr [[TMP35]], align 4
+// CHECK3-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK3-NEXT:    store i32 3, ptr [[TMP36]], align 4
+// CHECK3-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP33]], ptr [[TMP37]], align 4
+// CHECK3-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK3-NEXT:    store ptr [[TMP34]], ptr [[TMP38]], align 4
+// CHECK3-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK3-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP39]], align 4
+// CHECK3-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK3-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP40]], align 4
+// CHECK3-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK3-NEXT:    store ptr null, ptr [[TMP41]], align 4
+// CHECK3-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK3-NEXT:    store ptr null, ptr [[TMP42]], align 4
+// CHECK3-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK3-NEXT:    store i64 0, ptr [[TMP43]], align 8
+// CHECK3-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK3-NEXT:    store i64 0, ptr [[TMP44]], align 8
+// CHECK3-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK3-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP45]], align 4
+// CHECK3-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK3-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
+// CHECK3-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK3-NEXT:    store i32 0, ptr [[TMP47]], align 4
+// CHECK3-NEXT:    [[TMP48:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
+// CHECK3-NEXT:    [[TMP49:%.*]] = icmp ne i32 [[TMP48]], 0
+// CHECK3-NEXT:    br i1 [[TMP49]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK3:       omp_offload.failed:
-// CHECK3-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP15]], ptr [[TMP16]]) #[[ATTR1:[0-9]+]]
+// CHECK3-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP19]], ptr [[TMP20]]) #[[ATTR1:[0-9]+]]
 // CHECK3-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK3:       omp_offload.cont:
-// CHECK3-NEXT:    [[TMP42:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP42]], ptr [[TMP43]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP45:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP44]], ptr [[TMP45]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP52]], ptr [[TMP53]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
 // CHECK3-NEXT:    ret i32 0
 //
 //
@@ -460,42 +522,42 @@ int main() {
 // CHECK3-NEXT:    [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4
 // CHECK3-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
-// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META5:![0-9]+]])
-// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
-// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
-// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
-// CHECK3-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META14:![0-9]+]]
-// CHECK3-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
+// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
+// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]])
+// CHECK3-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META13:![0-9]+]])
+// CHECK3-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META15:![0-9]+]]
+// CHECK3-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR1]]
-// CHECK3-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    br label [[FOR_COND_I:%.*]]
 // CHECK3:       for.cond.i:
-// CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    [[CMP_I:%.*]] = icmp slt i32 [[TMP13]], 1024
 // CHECK3-NEXT:    br i1 [[CMP_I]], label [[FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]]
 // CHECK3:       for.body.i:
 // CHECK3-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP12]], align 4
-// CHECK3-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i32 [[TMP15]]
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4
 // CHECK3-NEXT:    [[MUL_I:%.*]] = mul nsw i32 2, [[TMP16]]
-// CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 4
+// CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 4, !nonnull [[META16:![0-9]+]], !align [[META17:![0-9]+]]
 // CHECK3-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 4
-// CHECK3-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i32 [[TMP19]]
 // CHECK3-NEXT:    store i32 [[MUL_I]], ptr [[ARRAYIDX1_I]], align 4
-// CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK3-NEXT:    [[INC_I:%.*]] = add nsw i32 [[TMP20]], 1
-// CHECK3-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META14]]
-// CHECK3-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP15:![0-9]+]]
+// CHECK3-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK3-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP18:![0-9]+]]
 // CHECK3:       .omp_outlined..exit:
 // CHECK3-NEXT:    ret i32 0
 //
@@ -650,44 +712,44 @@ int main() {
 // CHECK9-NEXT:    [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
 // CHECK9-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
 // CHECK9-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
-// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META5:![0-9]+]])
-// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
-// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
-// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
-// CHECK9-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META14:![0-9]+]]
-// CHECK9-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META14]]
+// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
+// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
+// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]])
+// CHECK9-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META13:![0-9]+]])
+// CHECK9-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META15:![0-9]+]]
+// CHECK9-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META15]]
 // CHECK9-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR3:[0-9]+]]
-// CHECK9-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META14]]
-// CHECK9-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK9-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META15]]
+// CHECK9-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK9-NEXT:    br label [[FOR_COND_I:%.*]]
 // CHECK9:       for.cond.i:
-// CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK9-NEXT:    [[CMP_I:%.*]] = icmp slt i32 [[TMP13]], 1024
 // CHECK9-NEXT:    br i1 [[CMP_I]], label [[FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]]
 // CHECK9:       for.body.i:
 // CHECK9-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP12]], align 8
-// CHECK9-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK9-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK9-NEXT:    [[IDXPROM_I:%.*]] = sext i32 [[TMP15]] to i64
 // CHECK9-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 [[IDXPROM_I]]
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4
 // CHECK9-NEXT:    [[MUL_I:%.*]] = mul nsw i32 2, [[TMP16]]
-// CHECK9-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 8
+// CHECK9-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 8, !nonnull [[META16:![0-9]+]], !align [[META17:![0-9]+]]
 // CHECK9-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 8
-// CHECK9-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK9-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK9-NEXT:    [[IDXPROM1_I:%.*]] = sext i32 [[TMP19]] to i64
 // CHECK9-NEXT:    [[ARRAYIDX2_I:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i64 [[IDXPROM1_I]]
 // CHECK9-NEXT:    store i32 [[MUL_I]], ptr [[ARRAYIDX2_I]], align 4
-// CHECK9-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META14]]
+// CHECK9-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
 // CHECK9-NEXT:    [[INC_I:%.*]] = add nsw i32 [[TMP20]], 1
-// CHECK9-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META14]]
-// CHECK9-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP15:![0-9]+]]
+// CHECK9-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK9-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP18:![0-9]+]]
 // CHECK9:       .omp_outlined..exit:
 // CHECK9-NEXT:    ret i32 0
 //
@@ -772,42 +834,42 @@ int main() {
 // CHECK11-NEXT:    [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
 // CHECK11-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 4
 // CHECK11-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
-// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
-// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META9:![0-9]+]])
-// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META11:![0-9]+]])
-// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META13:![0-9]+]])
-// CHECK11-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META15:![0-9]+]]
-// CHECK11-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META7:![0-9]+]])
+// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
+// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META12:![0-9]+]])
+// CHECK11-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META14:![0-9]+]])
+// CHECK11-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META16:![0-9]+]]
+// CHECK11-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR3:[0-9]+]]
-// CHECK11-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    store i32 0, ptr [[I_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    br label [[FOR_COND_I:%.*]]
 // CHECK11:       for.cond.i:
-// CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    [[CMP_I:%.*]] = icmp slt i32 [[TMP13]], 1024
 // CHECK11-NEXT:    br i1 [[CMP_I]], label [[FOR_BODY_I:%.*]], label [[DOTOMP_OUTLINED__EXIT:%.*]]
 // CHECK11:       for.body.i:
 // CHECK11-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP12]], align 4
-// CHECK11-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    [[TMP15:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    [[ARRAYIDX_I:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i32 [[TMP15]]
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX_I]], align 4
 // CHECK11-NEXT:    [[MUL_I:%.*]] = mul nsw i32 2, [[TMP16]]
-// CHECK11-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 4
+// CHECK11-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP9]], align 4, !nonnull [[META17:![0-9]+]], !align [[META18:![0-9]+]]
 // CHECK11-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP17]], align 4
-// CHECK11-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    [[TMP19:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    [[ARRAYIDX1_I:%.*]] = getelementptr inbounds i32, ptr [[TMP18]], i32 [[TMP19]]
 // CHECK11-NEXT:    store i32 [[MUL_I]], ptr [[ARRAYIDX1_I]], align 4
-// CHECK11-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META15]]
+// CHECK11-NEXT:    [[TMP20:%.*]] = load i32, ptr [[I_I]], align 4, !noalias [[META16]]
 // CHECK11-NEXT:    [[INC_I:%.*]] = add nsw i32 [[TMP20]], 1
-// CHECK11-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META15]]
-// CHECK11-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP16:![0-9]+]]
+// CHECK11-NEXT:    store i32 [[INC_I]], ptr [[I_I]], align 4, !noalias [[META16]]
+// CHECK11-NEXT:    br label [[FOR_COND_I]], !llvm.loop [[LOOP19:![0-9]+]]
 // CHECK11:       .omp_outlined..exit:
 // CHECK11-NEXT:    ret i32 0
 //
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
index 6e1bce12af8e4..1702992368132 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
@@ -239,6 +239,9 @@ enum class OpenMPOffloadMappingFlags : uint64_t {
   // dynamic.
   // This is an OpenMP extension for the sake of OpenACC support.
   OMP_MAP_OMPX_HOLD = 0x2000,
+  /// Attach the pointer to the device address of the array section.
+  /// Used when mapping array sections on pointers.
+  OMP_MAP_ATTACH = 0x4000,
   /// Signal that the runtime library should use args as an array of
   /// descriptor_dim pointers and use args_size as dims. Used when we have
   /// non-contiguous list items in target update directive

>From 6ba75e1f48584fc6ecfacbb46b0c9686b4ae3862 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 24 Jun 2025 19:24:59 -0700
Subject: [PATCH 05/66] [WIP] Commit some more non-debug print changes.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp     | 213 ++++++++++++----------
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp |   6 +
 2 files changed, 126 insertions(+), 93 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 69d14f03b6af3..1db4f7cb49ae0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7289,7 +7289,6 @@ class MappableExprsHandler {
     // components.
     bool IsExpressionFirstInfo = true;
     bool FirstPointerInComplexData = false;
-    bool SkipStandalonePtrMapping = false;
     Address BP = Address::invalid();
     const Expr *AssocExpr = I->getAssociatedExpression();
     const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
@@ -7299,9 +7298,11 @@ class MappableExprsHandler {
     // ATTACH entries are generated based solely on array section presence
 
     // Track info for ATTACH entry generation
-    bool ShouldGenerateAttachEntry = false;
     Address AttachBaseAddr = Address::invalid();
     Address AttachFirstElemAddr = Address::invalid();
+
+    // Find the component that should use ATTACH-style mapping.
+    auto AttachInfo = findAttachComponent(Components);
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
@@ -7631,40 +7632,25 @@ class MappableExprsHandler {
           break;
         }
         llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
-        // Check if this is an array section or subscript on a standalone pointer (not struct member)
-        bool IsArraySectionOnPointer = false;
         
         // Lambda to handle BP loading for global pointers
-        auto LoadGlobalPointerIfNeeded = [&]() {
-          if (FirstPointerInComplexData) {
-            QualType Ty = Components.rbegin()
-                              ->getAssociatedDeclaration()
-                              ->getType()
-                              .getNonReferenceType();
-            BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-            FirstPointerInComplexData = false;
-          }
-        };
-        
-        // Check if we should use ATTACH-style mapping for this expression
-        IsArraySectionOnPointer = shouldUseAttachStyleMapping(I->getAssociatedExpression(), EncounteredME != nullptr);
-        
-        if (IsArraySectionOnPointer) {
-          // For global pointers, load the pointer value so BP points to &p[0] instead of &p
-          LoadGlobalPointerIfNeeded();
-          // Set flags for ATTACH entry generation (only for the first array section/subscript we encounter)
-          if (!ShouldGenerateAttachEntry) {
-            ShouldGenerateAttachEntry = true;
-            if (OASE) {
-              AttachBaseAddr = CGF.EmitLValue(OASE->getBase()).getAddress();
-              AttachFirstElemAddr = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
-            } else if (ASE) {
-              AttachBaseAddr = CGF.EmitLValue(ASE->getBase()).getAddress();
-              AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
-            }
-          }
-        }
-        
+//         auto LoadGlobalPointerIfNeeded = [&]() {
+//           if (FirstPointerInComplexData) {
+//             llvm::errs() << "DEBUG generateInfoForComponentList: LoadGlobalPointerIfNeeded - updating BP\n";
+//             llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+//             QualType Ty = Components.rbegin()
+//                               ->getAssociatedDeclaration()
+//                               ->getType()
+//                               .getNonReferenceType();
+//             BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+//             llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+//             FirstPointerInComplexData = false;
+//           }
+//         };
+//         (void) LoadGlobalPointerIfNeeded;
+//
+// //        if (IsAttachablePointeeExpr)
+//   //        LoadGlobalPointerIfNeeded();
         // Skip adding an entry in the CurInfo of this combined entry if the
         // whole struct is currently being mapped. The struct needs to be added
         // in the first position before any data internal to the struct is being
@@ -7710,8 +7696,8 @@ class MappableExprsHandler {
           // (there is a set of entries for each capture).
           // Don't use PTR_AND_OBJ when we have array sections/subscripts on pointers
           bool AddPtrFlag = (!IsExpressionFirstInfo || RequiresReference ||
-                             FirstPointerInComplexData || IsMemberReference) &&
-                            !IsArraySectionOnPointer;
+                             FirstPointerInComplexData || IsMemberReference); //&&
+                            // !IsAttachablePointeeExpr;
           OpenMPOffloadMappingFlags Flags =
               getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
                              AddPtrFlag, IsCaptureFirstInfo && !RequiresReference,
@@ -7781,6 +7767,24 @@ class MappableExprsHandler {
         if (IsFinalArraySection || IsNonContiguous)
           PartialStruct.IsArraySection = true;
 
+        if (Next == CE) {
+          // Generate ATTACH entry for array sections and subscripts on standalone
+          // pointers Info was already collected during the main component loop
+          // Check if we should use ATTACH-style mapping for this expression
+          bool IsAttachablePointeeExpr = AttachInfo.IsValid && AttachInfo.BasePtrDecl && AttachInfo.BasePtrDecl == BaseDecl;
+          if (IsAttachablePointeeExpr) {
+            // Use BasePtrExpr for AttachBaseAddr
+            AttachBaseAddr = CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
+            if (OASE) {
+              AttachFirstElemAddr = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+            } else if (ASE) {
+              AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
+            } else if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
+               AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
+               llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+          }
+        }
+
         // If we have a final array section, we are done with this expression.
         if (IsFinalArraySection)
           break;
@@ -7807,20 +7811,12 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
-    // Generate ATTACH entry for array sections and subscripts on standalone
-    // pointers Info was already collected during the main component loop
-
-    if (ShouldGenerateAttachEntry && AttachBaseAddr.isValid() &&
-        AttachFirstElemAddr.isValid()) {
+    // Don't do this yet for member-exprs, like map(s.p[0:10])
+    if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
       // Generate ATTACH entry: &pointer, &pointer[idx], sizeof(pointer), ATTACH
-      // Since this is for standalone pointers only, we use CombinedInfo
-      CombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
-      CombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
-      CombinedInfo.DevicePtrDecls.push_back(nullptr);
-      CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
-      CombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
-      // Size is the size of the pointer itself - use pointer size, not BaseDecl
-      // size
+      // Use StructBaseCombinedInfo if mapping whole struct, otherwise use CombinedInfo
+      
+      // Size is the size of the pointer itself - use pointer size, not BaseDecl size
       llvm::Value *PointerSize = CGF.Builder.CreateIntCast(
           llvm::ConstantInt::get(
               CGF.CGM.SizeTy,
@@ -7831,8 +7827,15 @@ class MappableExprsHandler {
       CombinedInfo.Sizes.push_back(PointerSize);
       // ATTACH flag
       CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
-      CombinedInfo.Mappers.push_back(nullptr);
-      CombinedInfo.NonContigInfo.Dims.push_back(1);
+      StructBaseCombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
+      StructBaseCombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
+      StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr);
+      StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+      StructBaseCombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
+      StructBaseCombinedInfo.Sizes.push_back(PointerSize);
+      StructBaseCombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
+      StructBaseCombinedInfo.Mappers.push_back(nullptr);
+      StructBaseCombinedInfo.NonContigInfo.Dims.push_back(1);
     }
 
     if (!IsNonContiguous)
@@ -8108,47 +8111,88 @@ class MappableExprsHandler {
     }
   }
 
-  /// Helper to check if we should use ATTACH-style mapping for single-level
-  /// pointers This is used for both ATTACH generation and use_device_ptr
-  /// consistency
-  static bool shouldUseAttachStyleMapping(const Expr *E,
-                                          bool IsInStructContext) {
-    if (IsInStructContext)
-    const Expr *BaseExpr = nullptr;
-    if (const auto *OASE = dyn_cast<ArraySectionExpr>(E)) {
-      if (!ArraySectionExpr::getBaseOriginalType(OASE->getBase())
-               .getCanonicalType()
+/// Result structure for findAttachComponent
+struct AttachInfo {
+  const Expr *BasePtrExpr = nullptr;  // The pointer expression
+  const ValueDecl *BasePtrDecl = nullptr;  // The pointer decl, if any
+  const Expr *PteeExpr = nullptr;     // The array section/subscript expression
+  bool IsValid = false;
+};
+
+static AttachInfo findAttachComponent(
+      OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
                ->isAnyPointerType())
         return false;
       BaseExpr = OASE->getBase();
-    } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
-      if (!ArraySectionExpr::getBaseOriginalType(ASE->getBase())
+  const auto *Begin = Components.begin();
+  const auto *End = Components.end();
                .getCanonicalType()
                ->isAnyPointerType())
         return false;
       BaseExpr = ASE->getBase();
     } else {
-      return false;
+  for (const auto *I = Begin; I != End; ++I) {
+    // Check if current component is an array section or subscript
+    const Expr *CurrentExpr = I->getAssociatedExpression();
+    if (!CurrentExpr) {
+      break;
     }
 
-    // Only handle simple variable references to single-level pointers
-    // Skip complex expressions like (*q)[3:10] and multi-level pointers like
-    // q[1][3:5]
-    if (const auto *DRE =
+    // For something like p->s[1].q[10], the pointee should be "p->s[1].q",
+    // while base-ptr would be p.
+    const auto *ME = dyn_cast<MemberExpr>(CurrentExpr);
+    if (ME) {
             dyn_cast<DeclRefExpr>(BaseExpr->IgnoreParenImpCasts())) {
-      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+      if (!ME->isArrow()) {
         // Check that the original declaration is a single-level pointer, not
-        // pointer-to-pointer
-        QualType DeclType =
-            VD->getType().getNonReferenceType().getCanonicalType();
-        bool result = DeclType->isPointerType() &&
-               !DeclType->getPointeeType()->isPointerType();
-        return result;
+        PreviousMemberExpr = CurrentExpr;  // Track this as potential PteeExpr
+        continue;
       }
     }
     return false;
+    const auto *OASE = dyn_cast<ArraySectionExpr>(CurrentExpr);
+    const auto *ASE = dyn_cast<ArraySubscriptExpr>(CurrentExpr);
+
+    if (!OASE && !ASE && !ME) {
+      break;
+    }
+
+    // Check if the next component (in forward direction) has a pointer type
+    const auto *NextI = std::next(I);
+    if (NextI == End) {
+      // Check if the next component (in forward direction) has a pointer type
+      break;
+    }
+
+   // Get the type of the next component
+   QualType NextType;
+   if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
+     NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
+   } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
+     NextType = NextExpr->getType().getNonReferenceType().getCanonicalType();
+   } else {
+     break;
+   }
+
+   // Stop if the next component is a pointer type - this means we found our component
+   if (!NextType->isPointerType())
+     continue;
+
+      llvm::errs() << "DEBUG findAttachComponent: Next component not pointer type, continuing\n";
+    }
   }
 
+   // Get the pointer expression (NextRI) and use the candidate PteeExpr
+   const Expr *BasePtrExpr = NextI->getAssociatedExpression();
+   const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
+   const Expr *PteeExpr = CurrentExpr;
+
+   return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
+ }
+
+  return AttachInfo{};
+}
+
   /// Generate all the base pointers, section pointers, sizes, map types, and
   /// mappers for the extracted mappable expressions (all included in \a
   /// CombinedInfo). Also, for each item that relates with a device pointer, a
@@ -8303,24 +8347,7 @@ class MappableExprsHandler {
           }
         };
 
-    // Helper to check if a component list uses ATTACH-style mapping for
-    // single-level pointers
-    auto ComponentListUsesAttachStyleMapping =
-        [](const auto &Components) -> bool {
-      if (Components.empty())
-        return false;
-
-      // Check if any component uses ATTACH-style mapping
-      for (const auto &Component : Components) {
-        const Expr *E = Component.getAssociatedExpression();
-        if (E && shouldUseAttachStyleMapping(E, false)) {
-          return true;
-        }
-      }
-      return false;
-    };
-
-    auto &&IsMapInfoExist = [&Info, &ComponentListUsesAttachStyleMapping](CodeGenFunction &CGF, const ValueDecl *VD,
+    auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF, const ValueDecl *VD,
                                     const Expr *IE, bool IsDevAddr) -> bool {
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index ddc9c5392f922..2ce42e316bbce 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -9887,6 +9887,12 @@ void OpenMPIRBuilder::setCorrectMemberOfFlag(
           omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF))
     return;
 
+  // Entries with ATTACH are not members-of anything. They are handled
+  // separately by the runtime after other maps have been handled.
+  if (static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>>(
+          Flags & omp::OpenMPOffloadMappingFlags::OMP_MAP_ATTACH))
+    return;
+
   // Reset the placeholder value to prepare the flag for the assignment of the
   // proper MEMBER_OF value.
   Flags &= ~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;

>From 001da09d8534d7d25364d6ed7ba3a433ef366ff1 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 2 Jul 2025 00:32:33 -0700
Subject: [PATCH 06/66] [NFC][Clang] Refactor mapinfo generation for captured
 vars on target.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 127 +++++++++++++++++---------
 1 file changed, 86 insertions(+), 41 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index f126feb214b6a..e9c3dece1a501 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6801,6 +6801,11 @@ class MappableExprsHandler {
       llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
   using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
   using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
+  using MapData =
+      std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
+                 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>,
+                 bool /*IsImplicit*/, const ValueDecl *, const Expr *>;
+  using MapDataArrayTy = SmallVector<MapData, 4>;
 
   /// This structure contains combined information generated for mappable
   /// clauses, including base pointers, pointers, sizes, map types, user-defined
@@ -8514,6 +8519,7 @@ class MappableExprsHandler {
                          const StructRangeInfoTy &PartialStruct, bool IsMapThis,
                          llvm::OpenMPIRBuilder &OMPBuilder,
                          const ValueDecl *VD = nullptr,
+                         unsigned OffsetForMemberOfFlag = 0,
                          bool NotTargetParams = true) const {
     if (CurTypes.size() == 1 &&
         ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
@@ -8601,8 +8607,8 @@ class MappableExprsHandler {
     // All other current entries will be MEMBER_OF the combined entry
     // (except for PTR_AND_OBJ entries which do not have a placeholder value
     // 0xFFFF in the MEMBER_OF field).
-    OpenMPOffloadMappingFlags MemberOfFlag =
-        OMPBuilder.getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
+    OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
+        OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
   }
@@ -8745,11 +8751,13 @@ class MappableExprsHandler {
     }
   }
 
-  /// Generate the base pointers, section pointers, sizes, map types, and
-  /// mappers associated to a given capture (all included in \a CombinedInfo).
-  void generateInfoForCapture(const CapturedStmt::Capture *Cap,
-                              llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
-                              StructRangeInfoTy &PartialStruct) const {
+  /// For a capture that has an associated clause, generate the base pointers,
+  /// section pointers, sizes, map types, and mappers (all included in
+  /// \a CurCaptureVarInfo).
+  void generateInfoForCaptureFromClauseInfo(
+      const CapturedStmt::Capture *Cap, llvm::Value *Arg,
+      MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
+      unsigned OffsetForMemberOfFlag) const {
     assert(!Cap->capturesVariableArrayType() &&
            "Not expecting to generate map info for a variable array type!");
 
@@ -8767,26 +8775,22 @@ class MappableExprsHandler {
     // pass the pointer by value. If it is a reference to a declaration, we just
     // pass its value.
     if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
-      CombinedInfo.Exprs.push_back(VD);
-      CombinedInfo.BasePointers.emplace_back(Arg);
-      CombinedInfo.DevicePtrDecls.emplace_back(VD);
-      CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
-      CombinedInfo.Pointers.push_back(Arg);
-      CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
+      CurCaptureVarInfo.Exprs.push_back(VD);
+      CurCaptureVarInfo.BasePointers.emplace_back(Arg);
+      CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
+      CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
+      CurCaptureVarInfo.Pointers.push_back(Arg);
+      CurCaptureVarInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
           CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
           /*isSigned=*/true));
-      CombinedInfo.Types.push_back(
+      CurCaptureVarInfo.Types.push_back(
           OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
           OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
-      CombinedInfo.Mappers.push_back(nullptr);
+      CurCaptureVarInfo.Mappers.push_back(nullptr);
       return;
     }
 
-    using MapData =
-        std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
-                   OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool,
-                   const ValueDecl *, const Expr *>;
-    SmallVector<MapData, 4> DeclComponentLists;
+    MapDataArrayTy DeclComponentLists;
     // For member fields list in is_device_ptr, store it in
     // DeclComponentLists for generating components info.
     static const OpenMPMapModifierKind Unknown = OMPC_MAP_MODIFIER_unknown;
@@ -8855,6 +8859,51 @@ class MappableExprsHandler {
       return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
     });
 
+    auto GenerateInfoForComponentLists =
+        [&](ArrayRef<MapData> DeclComponentLists,
+            bool IsEligibleForTargetParamFlag) {
+          MapCombinedInfoTy CurInfoForComponentLists;
+          StructRangeInfoTy PartialStruct;
+
+          if (DeclComponentLists.empty())
+            return;
+
+          generateInfoForCaptureFromComponentLists(
+              VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
+              IsEligibleForTargetParamFlag,
+              /*AreBothBasePtrAndPteeMapped=*/HasMapBasePtr && HasMapArraySec);
+
+          // If there is an entry in PartialStruct it means we have a
+          // struct with individual members mapped. Emit an extra combined
+          // entry.
+          if (PartialStruct.Base.isValid()) {
+            CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
+            emitCombinedEntry(
+                CurCaptureVarInfo, CurInfoForComponentLists.Types,
+                PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
+                OffsetForMemberOfFlag,
+                /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
+          }
+
+          // Return if we didn't add any entries.
+          if (CurInfoForComponentLists.BasePointers.empty())
+            return;
+
+          CurCaptureVarInfo.append(CurInfoForComponentLists);
+        };
+
+    GenerateInfoForComponentLists(DeclComponentLists,
+                                  /*IsEligibleForTargetParamFlag=*/true);
+  }
+
+  /// Generate the base pointers, section pointers, sizes, map types, and
+  /// mappers associated to \a DeclComponentLists for a given capture
+  /// \a VD (all included in \a CurComponentListInfo).
+  void generateInfoForCaptureFromComponentLists(
+      const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
+      MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
+      bool IsListEligibleForTargetParamFlag,
+      bool AreBothBasePtrAndPteeMapped = false) const {
     // Find overlapping elements (including the offset from the base element).
     llvm::SmallDenseMap<
         const MapData *,
@@ -8978,7 +9027,7 @@ class MappableExprsHandler {
 
     // Associated with a capture, because the mapping flags depend on it.
     // Go through all of the elements with the overlapped elements.
-    bool IsFirstComponentList = true;
+    bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
     MapCombinedInfoTy StructBaseCombinedInfo;
     for (const auto &Pair : OverlappedData) {
       const MapData &L = *Pair.getFirst();
@@ -8993,11 +9042,11 @@ class MappableExprsHandler {
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
           OverlappedComponents = Pair.getSecond();
       generateInfoForComponentList(
-          MapType, MapModifiers, {}, Components, CombinedInfo,
-          StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
-          IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
+          MapType, MapModifiers, {}, Components, CurComponentListInfo,
+          StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
+          /*GenerateAllInfoForClauses*/ false, Mapper,
           /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
-      IsFirstComponentList = false;
+      AddTargetParamFlag = false;
     }
     // Go through other elements without overlapped elements.
     for (const MapData &L : DeclComponentLists) {
@@ -9012,12 +9061,12 @@ class MappableExprsHandler {
       auto It = OverlappedData.find(&L);
       if (It == OverlappedData.end())
         generateInfoForComponentList(
-            MapType, MapModifiers, {}, Components, CombinedInfo,
-            StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
+            MapType, MapModifiers, {}, Components, CurComponentListInfo,
+            StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
             IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
             /*ForDeviceAddr=*/false, VD, VarRef,
-            /*OverlappedElements*/ {}, HasMapBasePtr && HasMapArraySec);
-      IsFirstComponentList = false;
+            /*OverlappedElements*/ {}, AreBothBasePtrAndPteeMapped);
+      AddTargetParamFlag = false;
     }
   }
 
@@ -9496,7 +9545,6 @@ static void genMapInfoForCaptures(
                                             CE = CS.capture_end();
        CI != CE; ++CI, ++RI, ++CV) {
     MappableExprsHandler::MapCombinedInfoTy CurInfo;
-    MappableExprsHandler::StructRangeInfoTy PartialStruct;
 
     // VLA sizes are passed to the outlined region by copy and do not have map
     // information associated.
@@ -9517,13 +9565,18 @@ static void genMapInfoForCaptures(
     } else {
       // If we have any information in the map clause, we use it, otherwise we
       // just do a default mapping.
-      MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
+      MEHandler.generateInfoForCaptureFromClauseInfo(
+          CI, *CV, CurInfo, OMPBuilder,
+          /*OffsetForMemberOfFlag=*/CombinedInfo.BasePointers.size());
+
       if (!CI->capturesThis())
         MappedVarSet.insert(CI->getCapturedVar());
       else
         MappedVarSet.insert(nullptr);
-      if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
+
+      if (CurInfo.BasePointers.empty())
         MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
+
       // Generate correct mapping for variables captured by reference in
       // lambdas.
       if (CI->capturesVariable())
@@ -9531,7 +9584,7 @@ static void genMapInfoForCaptures(
                                                 CurInfo, LambdaPointers);
     }
     // We expect to have at least an element of information for this capture.
-    assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&
+    assert(!CurInfo.BasePointers.empty() &&
            "Non-existing map pointer for capture!");
     assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
            CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
@@ -9539,14 +9592,6 @@ static void genMapInfoForCaptures(
            CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
            "Inconsistent map information sizes!");
 
-    // If there is an entry in PartialStruct it means we have a struct with
-    // individual members mapped. Emit an extra combined entry.
-    if (PartialStruct.Base.isValid()) {
-      CombinedInfo.append(PartialStruct.PreliminaryMapData);
-      MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
-                                  CI->capturesThis(), OMPBuilder, nullptr,
-                                  /*NotTargetParams*/ false);
-    }
 
     // We need to append the results of this capture to what we already have.
     CombinedInfo.append(CurInfo);

>From 1ebb7a92ec0ae94771d22e27831253597ecfaf1e Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 2 Jul 2025 01:34:59 -0700
Subject: [PATCH 07/66] Handle mapping of captured pointers before any
 dereference of them.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 50 ++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index e9c3dece1a501..b34be04d4559b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8892,8 +8892,56 @@ class MappableExprsHandler {
           CurCaptureVarInfo.append(CurInfoForComponentLists);
         };
 
-    GenerateInfoForComponentLists(DeclComponentLists,
+    // Next, we break-down the lists of components into lists that should be
+    // handled together.
+    //
+    // For now, we handle maps on pointers by themselves, and everything else
+    // together.
+    //
+    // TODO: Do this based on which lists have the same attachable-base-pointer
+    // e.g. The map clauses below, which are present on the same construct,
+    // should be handled grouped together based on their
+    // attachable-base-pointers:
+    //   map-clause                | attachable-base-pointer
+    //   --------------------------+------------------------
+    //   map(p, ps)                | none
+    //   map(p[0])                 | p
+    //   map(p[0]->b, p[0]->c)     | p[0]
+    //   map(ps->d, ps->e, ps->pt) | ps
+    //   map(ps->pt->d, ps->pt->e) | ps->pt
+
+    MapDataArrayTy ListsThatMapPointerVDItself;
+    MapDataArrayTy RemainingLists;
+    bool IsVDPointerType = VD && VD->getType()->isPointerType();
+
+    for (const MapData &L : DeclComponentLists) {
+      if (IsVDPointerType) {
+        OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+            std::get<0>(L);
+        bool IsMapOfPointerVD =
+            Components.size() == 1 &&
+            Components[0].getAssociatedDeclaration() &&
+            Components[0].getAssociatedDeclaration()->getCanonicalDecl() == VD;
+        if (IsMapOfPointerVD) {
+          ListsThatMapPointerVDItself.push_back(L);
+          continue;
+        }
+      }
+      RemainingLists.push_back(L);
+    }
+
+    // If VD is a pointer, and there are component-lists mapping VD itself,
+    // like: `int *p; ... map(p)`, we handle them first, and
+    // the first one from the should get the TARGET_PARAM flag.
+    GenerateInfoForComponentLists(ListsThatMapPointerVDItself,
                                   /*IsEligibleForTargetParamFlag=*/true);
+    // Then we handle all the other lists together. Note that since we already
+    // added TARGET_PARAM for the pointer case, we shouldn't add it again if
+    // if there are other lists that get handled here, for example, the list
+    // for `map(p[0:10]` in `int *p; ... map(p, p[0:10])`.
+    GenerateInfoForComponentLists(
+        RemainingLists,
+        /*IsEligibleForTargetParamFlag=*/ListsThatMapPointerVDItself.empty());
   }
 
   /// Generate the base pointers, section pointers, sizes, map types, and

>From 7799d0a97459abc5a3202bb137ef14cdde1a917b Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 2 Jul 2025 11:42:31 -0700
Subject: [PATCH 08/66] No need to change the sorting since we now handle
 mapping of pointers before their derefs.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index b34be04d4559b..3b6db4b62fbd9 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8833,19 +8833,8 @@ class MappableExprsHandler {
         ++EI;
       }
     }
-    llvm::stable_sort(DeclComponentLists, [VD](const MapData &LHS,
-                                               const MapData &RHS) {
-      // For cases like map(p, p[0], p[0][0]), the shortest map, like map(p)
-      // in this case, should be handled first, to ensure that it gets the
-      // TARGET_PARAM flag.
-      OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
-          std::get<0>(LHS);
-      OMPClauseMappableExprCommon::MappableExprComponentListRef ComponentsR =
-          std::get<0>(RHS);
-      if (VD && VD->getType()->isAnyPointerType() &&
-          Components.size() != ComponentsR.size())
-        return Components.size() < ComponentsR.size();
-
+    llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
+                                             const MapData &RHS) {
       ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
       OpenMPMapClauseKind MapType = std::get<1>(RHS);
       bool HasPresent =

>From 9f61909419939491c12384f471df05a504068054 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 2 Jul 2025 00:32:33 -0700
Subject: [PATCH 09/66] [NFC][Clang] Refactor mapinfo generation for captured
 vars on target.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 127 +++++++++++++++++---------
 1 file changed, 86 insertions(+), 41 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 8ccc37ef98a74..1964f91797be2 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6801,6 +6801,11 @@ class MappableExprsHandler {
       llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
   using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
   using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
+  using MapData =
+      std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
+                 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>,
+                 bool /*IsImplicit*/, const ValueDecl *, const Expr *>;
+  using MapDataArrayTy = SmallVector<MapData, 4>;
 
   /// This structure contains combined information generated for mappable
   /// clauses, including base pointers, pointers, sizes, map types, user-defined
@@ -8496,6 +8501,7 @@ class MappableExprsHandler {
                          const StructRangeInfoTy &PartialStruct, bool IsMapThis,
                          llvm::OpenMPIRBuilder &OMPBuilder,
                          const ValueDecl *VD = nullptr,
+                         unsigned OffsetForMemberOfFlag = 0,
                          bool NotTargetParams = true) const {
     if (CurTypes.size() == 1 &&
         ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
@@ -8583,8 +8589,8 @@ class MappableExprsHandler {
     // All other current entries will be MEMBER_OF the combined entry
     // (except for PTR_AND_OBJ entries which do not have a placeholder value
     // 0xFFFF in the MEMBER_OF field).
-    OpenMPOffloadMappingFlags MemberOfFlag =
-        OMPBuilder.getMemberOfFlag(CombinedInfo.BasePointers.size() - 1);
+    OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
+        OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
   }
@@ -8727,11 +8733,13 @@ class MappableExprsHandler {
     }
   }
 
-  /// Generate the base pointers, section pointers, sizes, map types, and
-  /// mappers associated to a given capture (all included in \a CombinedInfo).
-  void generateInfoForCapture(const CapturedStmt::Capture *Cap,
-                              llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
-                              StructRangeInfoTy &PartialStruct) const {
+  /// For a capture that has an associated clause, generate the base pointers,
+  /// section pointers, sizes, map types, and mappers (all included in
+  /// \a CurCaptureVarInfo).
+  void generateInfoForCaptureFromClauseInfo(
+      const CapturedStmt::Capture *Cap, llvm::Value *Arg,
+      MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
+      unsigned OffsetForMemberOfFlag) const {
     assert(!Cap->capturesVariableArrayType() &&
            "Not expecting to generate map info for a variable array type!");
 
@@ -8749,26 +8757,22 @@ class MappableExprsHandler {
     // pass the pointer by value. If it is a reference to a declaration, we just
     // pass its value.
     if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
-      CombinedInfo.Exprs.push_back(VD);
-      CombinedInfo.BasePointers.emplace_back(Arg);
-      CombinedInfo.DevicePtrDecls.emplace_back(VD);
-      CombinedInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
-      CombinedInfo.Pointers.push_back(Arg);
-      CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
+      CurCaptureVarInfo.Exprs.push_back(VD);
+      CurCaptureVarInfo.BasePointers.emplace_back(Arg);
+      CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
+      CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
+      CurCaptureVarInfo.Pointers.push_back(Arg);
+      CurCaptureVarInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
           CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
           /*isSigned=*/true));
-      CombinedInfo.Types.push_back(
+      CurCaptureVarInfo.Types.push_back(
           OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
           OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
-      CombinedInfo.Mappers.push_back(nullptr);
+      CurCaptureVarInfo.Mappers.push_back(nullptr);
       return;
     }
 
-    using MapData =
-        std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
-                   OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool,
-                   const ValueDecl *, const Expr *>;
-    SmallVector<MapData, 4> DeclComponentLists;
+    MapDataArrayTy DeclComponentLists;
     // For member fields list in is_device_ptr, store it in
     // DeclComponentLists for generating components info.
     static const OpenMPMapModifierKind Unknown = OMPC_MAP_MODIFIER_unknown;
@@ -8826,6 +8830,51 @@ class MappableExprsHandler {
       return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
     });
 
+    auto GenerateInfoForComponentLists =
+        [&](ArrayRef<MapData> DeclComponentLists,
+            bool IsEligibleForTargetParamFlag) {
+          MapCombinedInfoTy CurInfoForComponentLists;
+          StructRangeInfoTy PartialStruct;
+
+          if (DeclComponentLists.empty())
+            return;
+
+          generateInfoForCaptureFromComponentLists(
+              VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
+              IsEligibleForTargetParamFlag,
+              /*AreBothBasePtrAndPteeMapped=*/HasMapBasePtr && HasMapArraySec);
+
+          // If there is an entry in PartialStruct it means we have a
+          // struct with individual members mapped. Emit an extra combined
+          // entry.
+          if (PartialStruct.Base.isValid()) {
+            CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
+            emitCombinedEntry(
+                CurCaptureVarInfo, CurInfoForComponentLists.Types,
+                PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
+                OffsetForMemberOfFlag,
+                /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
+          }
+
+          // Return if we didn't add any entries.
+          if (CurInfoForComponentLists.BasePointers.empty())
+            return;
+
+          CurCaptureVarInfo.append(CurInfoForComponentLists);
+        };
+
+    GenerateInfoForComponentLists(DeclComponentLists,
+                                  /*IsEligibleForTargetParamFlag=*/true);
+  }
+
+  /// Generate the base pointers, section pointers, sizes, map types, and
+  /// mappers associated to \a DeclComponentLists for a given capture
+  /// \a VD (all included in \a CurComponentListInfo).
+  void generateInfoForCaptureFromComponentLists(
+      const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
+      MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
+      bool IsListEligibleForTargetParamFlag,
+      bool AreBothBasePtrAndPteeMapped = false) const {
     // Find overlapping elements (including the offset from the base element).
     llvm::SmallDenseMap<
         const MapData *,
@@ -8949,7 +8998,7 @@ class MappableExprsHandler {
 
     // Associated with a capture, because the mapping flags depend on it.
     // Go through all of the elements with the overlapped elements.
-    bool IsFirstComponentList = true;
+    bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
     MapCombinedInfoTy StructBaseCombinedInfo;
     for (const auto &Pair : OverlappedData) {
       const MapData &L = *Pair.getFirst();
@@ -8964,11 +9013,11 @@ class MappableExprsHandler {
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
           OverlappedComponents = Pair.getSecond();
       generateInfoForComponentList(
-          MapType, MapModifiers, {}, Components, CombinedInfo,
-          StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
-          IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
+          MapType, MapModifiers, {}, Components, CurComponentListInfo,
+          StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
+          /*GenerateAllInfoForClauses*/ false, Mapper,
           /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
-      IsFirstComponentList = false;
+      AddTargetParamFlag = false;
     }
     // Go through other elements without overlapped elements.
     for (const MapData &L : DeclComponentLists) {
@@ -8983,12 +9032,12 @@ class MappableExprsHandler {
       auto It = OverlappedData.find(&L);
       if (It == OverlappedData.end())
         generateInfoForComponentList(
-            MapType, MapModifiers, {}, Components, CombinedInfo,
-            StructBaseCombinedInfo, PartialStruct, IsFirstComponentList,
+            MapType, MapModifiers, {}, Components, CurComponentListInfo,
+            StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
             IsImplicit, /*GenerateAllInfoForClauses*/ false, Mapper,
             /*ForDeviceAddr=*/false, VD, VarRef,
-            /*OverlappedElements*/ {}, HasMapBasePtr && HasMapArraySec);
-      IsFirstComponentList = false;
+            /*OverlappedElements*/ {}, AreBothBasePtrAndPteeMapped);
+      AddTargetParamFlag = false;
     }
   }
 
@@ -9467,7 +9516,6 @@ static void genMapInfoForCaptures(
                                             CE = CS.capture_end();
        CI != CE; ++CI, ++RI, ++CV) {
     MappableExprsHandler::MapCombinedInfoTy CurInfo;
-    MappableExprsHandler::StructRangeInfoTy PartialStruct;
 
     // VLA sizes are passed to the outlined region by copy and do not have map
     // information associated.
@@ -9488,13 +9536,18 @@ static void genMapInfoForCaptures(
     } else {
       // If we have any information in the map clause, we use it, otherwise we
       // just do a default mapping.
-      MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct);
+      MEHandler.generateInfoForCaptureFromClauseInfo(
+          CI, *CV, CurInfo, OMPBuilder,
+          /*OffsetForMemberOfFlag=*/CombinedInfo.BasePointers.size());
+
       if (!CI->capturesThis())
         MappedVarSet.insert(CI->getCapturedVar());
       else
         MappedVarSet.insert(nullptr);
-      if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid())
+
+      if (CurInfo.BasePointers.empty())
         MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
+
       // Generate correct mapping for variables captured by reference in
       // lambdas.
       if (CI->capturesVariable())
@@ -9502,7 +9555,7 @@ static void genMapInfoForCaptures(
                                                 CurInfo, LambdaPointers);
     }
     // We expect to have at least an element of information for this capture.
-    assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) &&
+    assert(!CurInfo.BasePointers.empty() &&
            "Non-existing map pointer for capture!");
     assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
            CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
@@ -9510,14 +9563,6 @@ static void genMapInfoForCaptures(
            CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
            "Inconsistent map information sizes!");
 
-    // If there is an entry in PartialStruct it means we have a struct with
-    // individual members mapped. Emit an extra combined entry.
-    if (PartialStruct.Base.isValid()) {
-      CombinedInfo.append(PartialStruct.PreliminaryMapData);
-      MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
-                                  CI->capturesThis(), OMPBuilder, nullptr,
-                                  /*NotTargetParams*/ false);
-    }
 
     // We need to append the results of this capture to what we already have.
     CombinedInfo.append(CurInfo);

>From 526157851221dcf100359fcca6f85d79536042f1 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Thu, 3 Jul 2025 07:02:40 -0700
Subject: [PATCH 10/66] Minor clang-format fix.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 1964f91797be2..a5f2f0efa2c3b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9563,7 +9563,6 @@ static void genMapInfoForCaptures(
            CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
            "Inconsistent map information sizes!");
 
-
     // We need to append the results of this capture to what we already have.
     CombinedInfo.append(CurInfo);
   }

>From 145160b4f79620d2dee7ce38598f35584ea7ad5a Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Thu, 3 Jul 2025 10:08:14 -0700
Subject: [PATCH 11/66] [NFC][OpenMP] Add tests for mapping pointers and their
 dereferences.

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.
---
 ...arget_map_both_pointer_pointee_codegen.cpp | 355 ++++++++++--------
 ...ap_both_pointer_pointee_codegen_global.cpp | 212 +++++++++++
 .../OpenMP/target_map_ptr_and_star_global.cpp | 161 ++++++++
 .../OpenMP/target_map_ptr_and_star_local.cpp  | 167 ++++++++
 ...target_map_structptr_and_member_global.cpp | 275 ++++++++++++++
 .../target_map_structptr_and_member_local.cpp | 278 ++++++++++++++
 .../test/mapping/map_ptr_and_star_global.c    |  83 ++++
 offload/test/mapping/map_ptr_and_star_local.c |  83 ++++
 .../mapping/map_ptr_and_subscript_global.c    |  83 ++++
 .../mapping/map_ptr_and_subscript_local.c     |  83 ++++
 .../mapping/map_structptr_and_member_global.c |  88 +++++
 .../mapping/map_structptr_and_member_local.c  |  87 +++++
 12 files changed, 1799 insertions(+), 156 deletions(-)
 create mode 100644 clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
 create mode 100644 clang/test/OpenMP/target_map_ptr_and_star_global.cpp
 create mode 100644 clang/test/OpenMP/target_map_ptr_and_star_local.cpp
 create mode 100644 clang/test/OpenMP/target_map_structptr_and_member_global.cpp
 create mode 100644 clang/test/OpenMP/target_map_structptr_and_member_local.cpp
 create mode 100644 offload/test/mapping/map_ptr_and_star_global.c
 create mode 100644 offload/test/mapping/map_ptr_and_star_local.c
 create mode 100644 offload/test/mapping/map_ptr_and_subscript_global.c
 create mode 100644 offload/test/mapping/map_ptr_and_subscript_local.c
 create mode 100644 offload/test/mapping/map_structptr_and_member_global.c
 create mode 100644 offload/test/mapping/map_structptr_and_member_local.c

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..7ad142e51fc09 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -1,4 +1,4 @@
-// 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 _
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*"
 // 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
@@ -7,168 +7,211 @@
 #ifndef HEADER
 #define HEADER
 
-extern void *malloc (int __size) throw () __attribute__ ((__malloc__));
+void f1() {
+  int *ptr;
+  // &ptr, &ptr, sizeof(ptr), TO | PARAM
+  #pragma omp target map(ptr)
+    ptr[1] = 5;
+}
 
-void foo() {
-  int *ptr = (int *) malloc(3 * sizeof(int));
+void f2() {
+  int *ptr;
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM
+  #pragma omp target map(ptr[2])
+    ptr[1] = 6;
+}
 
+void f3() {
+  int *ptr;
+  // &ptr, &ptr[0], sizeof(ptr[0:2]), TO | FROM | PARAM | PTR_AND_OBJ
   #pragma omp target map(ptr, ptr[0:2])
-  {
-    ptr[1] = 6;
-  }
+    ptr[1] = 7;
+}
+
+void f4() {
+  int *ptr;
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
   #pragma omp target map(ptr, ptr[2])
-  {
     ptr[2] = 8;
-  }
-  #pragma omp target data map(ptr, ptr[2])
-  {
+}
+
+void f5() {
+  int *ptr;
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+ #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 9;
-  }
+}
+
+void f6() {
+  int *ptr;
+  // &ptr, &ptr[0], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target data map(ptr, ptr[2])
+    ptr[2] = 10;
 }
 #endif
-// CHECK-LABEL: define {{[^@]+}}@_Z3foov
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+//.
+// CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS9:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS10:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS11:%.*]] = alloca [1 x ptr], align 8
-// CHECK-NEXT:    [[CALL:%.*]] = call noalias noundef ptr @_Z6malloci(i32 noundef signext 12) #[[ATTR3:[0-9]+]]
-// CHECK-NEXT:    store ptr [[CALL]], ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP4]], align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP7]], align 4
-// CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP8]], align 4
-// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP5]], ptr [[TMP9]], align 8
-// CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP10]], align 8
-// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes, ptr [[TMP11]], align 8
-// CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP12]], align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP13]], align 8
-// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP14]], align 8
-// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP15]], align 8
-// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP16]], align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP17]], align 4
-// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP18]], align 4
-// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP19]], align 4
-// CHECK-NEXT:    [[TMP20:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15.region_id, ptr [[KERNEL_ARGS]])
-// CHECK-NEXT:    [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0
-// CHECK-NEXT:    br i1 [[TMP21]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
-// CHECK:       omp_offload.failed:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15(ptr [[TMP0]]) #[[ATTR3]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT]]
-// CHECK:       omp_offload.cont:
-// CHECK-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP23]], i64 2
-// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP24]], align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP25]], align 8
-// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP26]], align 8
-// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP29]], align 4
-// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP30]], align 4
-// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP27]], ptr [[TMP31]], align 8
-// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP28]], ptr [[TMP32]], align 8
-// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes.1, ptr [[TMP33]], align 8
-// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP34]], align 8
-// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP35]], align 8
-// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP36]], align 8
-// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP37]], align 8
-// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP38]], align 8
-// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP39]], align 4
-// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP40]], align 4
-// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP41]], align 4
-// CHECK-NEXT:    [[TMP42:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19.region_id, ptr [[KERNEL_ARGS5]])
-// CHECK-NEXT:    [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0
-// CHECK-NEXT:    br i1 [[TMP43]], label [[OMP_OFFLOAD_FAILED6:%.*]], label [[OMP_OFFLOAD_CONT7:%.*]]
-// CHECK:       omp_offload.failed6:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19(ptr [[TMP22]]) #[[ATTR3]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT7]]
-// CHECK:       omp_offload.cont7:
-// CHECK-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds i32, ptr [[TMP44]], i64 2
-// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[TMP45]], align 8
-// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP46]], align 8
-// CHECK-NEXT:    [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS11]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP47]], align 8
-// CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP48]], ptr [[TMP49]], ptr @.offload_sizes.3, ptr @.offload_maptypes.4, ptr null, ptr null)
-// CHECK-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX12:%.*]] = getelementptr inbounds i32, ptr [[TMP50]], i64 2
-// CHECK-NEXT:    store i32 9, ptr [[ARRAYIDX12]], align 4
-// CHECK-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0
-// CHECK-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP51]], ptr [[TMP52]], ptr @.offload_sizes.3, ptr @.offload_maptypes.4, ptr null, ptr null)
-// CHECK-NEXT:    ret void
-//
-//
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l15
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2:[0-9]+]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
-// CHECK-NEXT:    store i32 6, ptr [[ARRAYIDX]], align 4
-// CHECK-NEXT:    ret void
-//
-//
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3foov_l19
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR2]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK-NEXT:    store i32 8, ptr [[ARRAYIDX]], align 4
-// CHECK-NEXT:    ret void
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR:%.*]], ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l13
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
+// CHECK:    store i32 5, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f2v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f3v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l27
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 7, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f4v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l34
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f5v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
+// CHECK:    store i32 9, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
new file mode 100644
index 0000000000000..8f0f27e6f8e94
--- /dev/null
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -0,0 +1,212 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*"
+// 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
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+int *ptr;
+
+void f1() {
+  // &ptr, &ptr, sizeof(ptr), TO | PARAM
+  #pragma omp target map(ptr)
+    ptr[1] = 5;
+}
+
+void f2() {
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target map(ptr[2])
+    ptr[1] = 6;
+}
+
+void f3() {
+  // &ptr, &ptr[0], sizeof(ptr[0:2]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target map(ptr, ptr[0:2])
+    ptr[1] = 7;
+}
+
+void f4() {
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target map(ptr, ptr[2])
+    ptr[2] = 8;
+}
+
+void f5() {
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+ #pragma omp target data map(ptr[2], ptr)
+    ptr[2] = 9;
+}
+
+void f6() {
+  // &ptr, &ptr[0], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target data map(ptr, ptr[2])
+    ptr[2] = 10;
+}
+#endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+//.
+// CHECK-LABEL: define {{[^@]+}}@_Z2f1v
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l14
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
+// CHECK:    store i32 5, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f2v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f3v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l26
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 7, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f4v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l32
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f5v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
+// CHECK:    store i32 9, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    ret void
+//
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
new file mode 100644
index 0000000000000..84899cb8e4fad
--- /dev/null
+++ b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
@@ -0,0 +1,161 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*"
+// 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
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+int *ptr;
+void f1() {
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  #pragma omp target map(ptr)
+    ptr[1] = 6;
+}
+
+void f2() {
+  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PARAM | PTR_AND_OBJ
+  #pragma omp target map(*ptr)
+    ptr[1] = 6;
+}
+
+void f3() {
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
+  #pragma omp target map(ptr, *ptr)
+    ptr[1] = 6;
+}
+
+void f4() {
+  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ | PARAM
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  #pragma omp target map(*ptr, ptr)
+    ptr[2] = 8;
+}
+
+#endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x33]], i64 [[#0x3]]]
+//.
+// CHECK-LABEL: define {{[^@]+}}@_Z2f1v
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l13
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f2v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l19
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f3v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l26
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f4v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l33
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
new file mode 100644
index 0000000000000..246c0c5f99a68
--- /dev/null
+++ b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
@@ -0,0 +1,167 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-globals --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*"
+// 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
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+void f1() {
+  int *ptr;
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  #pragma omp target map(ptr)
+    ptr[1] = 6;
+}
+
+void f2() {
+  int *ptr;
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM | PARAM
+  #pragma omp target map(*ptr)
+    ptr[1] = 6;
+}
+
+void f3() {
+  int *ptr;
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  #pragma omp target map(ptr, *ptr)
+    ptr[1] = 6;
+}
+
+void f4() {
+  int *ptr;
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  #pragma omp target map(*ptr, ptr)
+    ptr[2] = 8;
+}
+
+#endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
+//.
+// CHECK-LABEL: define {{[^@]+}}@_Z2f1v
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR:%.*]], ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l13
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f2v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f3v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP2]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f4v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
new file mode 100644
index 0000000000000..523f88dc8dba3
--- /dev/null
+++ b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
@@ -0,0 +1,275 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*" --version 5
+// 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
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct S {
+  short x;
+  int y;
+  int *p;
+};
+
+S s, *ps;
+
+void f1() {
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  #pragma omp target map(to: ps)
+    ps->y = 5;
+}
+
+void f2() {
+  // &ps[0], &ps->y, sizeof(ps->y), TO | PARAM
+  #pragma omp target map(to: ps->y)
+    ps->y = 6;
+}
+
+void f3() {
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps, ps->y)
+    ps->y = 7;
+}
+
+void f4() {
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps->y, ps)
+    ps->y = 8;
+}
+
+void f5() {
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps->y, ps, ps->x)
+    ps->y = 9;
+}
+
+#endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 0, i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 8, i64 2]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+//.
+// CHECK-LABEL: define dso_local void @_Z2f1v(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l20(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13:![0-9]+]], !align [[META14:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    store i32 5, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f2v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l26(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 6, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f3v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
+// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.3, i64 24, i1 false)
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ps, ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr @ps, ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l34(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 7, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f4v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
+// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.5, i64 24, i1 false)
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l42(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 8, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f5v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[TMP4:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
+// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP8:%.*]] = sub i64 [[TMP6]], [[TMP7]]
+// CHECK:    [[TMP9:%.*]] = sdiv exact i64 [[TMP8]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP9]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP3]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l51(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 9, ptr [[Y]], align 4
+// CHECK:    ret void
+//
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
new file mode 100644
index 0000000000000..b366f331941b7
--- /dev/null
+++ b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
@@ -0,0 +1,278 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --filter-out-after "getelem.*kernel" --filter-out "= alloca.*" --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*" --version 5
+// 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
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+struct S {
+  short x;
+  int y;
+  int *p;
+};
+
+void f1() {
+  S s, *ps;
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  #pragma omp target map(to: ps)
+    ps->y = 5;
+}
+
+void f2() {
+  S s, *ps;
+  // &ps[0], &ps->y, sizeof(ps->y), TO | PARAM
+  #pragma omp target map(to: ps->y)
+    ps->y = 6;
+}
+
+void f3() {
+  S s, *ps;
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps, ps->y)
+    ps->y = 7;
+}
+
+void f4() {
+  S s, *ps;
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps->y, ps)
+    ps->y = 8;
+}
+
+void f5() {
+  S s, *ps;
+  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(1)
+  #pragma omp target map(to: ps->y, ps, ps->x)
+    ps->y = 9;
+}
+
+#endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 0, i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 8, i64 2]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+//.
+// CHECK-LABEL: define dso_local void @_Z2f1v(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS:%.*]], ptr [[TMP0]], align 8
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f1v_l19(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13:![0-9]+]], !align [[META14:![0-9]+]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    store i32 5, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f2v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l26(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 6, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f3v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
+// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.3, i64 24, i1 false)
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PS]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PS]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l35(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 7, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f4v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
+// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.5, i64 24, i1 false)
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l44(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 8, ptr [[Y]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define dso_local void @_Z2f5v(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[TMP4:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
+// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64
+// CHECK:    [[TMP8:%.*]] = sub i64 [[TMP6]], [[TMP7]]
+// CHECK:    [[TMP9:%.*]] = sdiv exact i64 [[TMP8]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    store i64 [[TMP9]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP3]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l54(
+// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:  [[ENTRY:.*:]]
+// CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    store i32 9, ptr [[Y]], align 4
+// CHECK:    ret void
+//
diff --git a/offload/test/mapping/map_ptr_and_star_global.c b/offload/test/mapping/map_ptr_and_star_global.c
new file mode 100644
index 0000000000000..c09dc7fff6c17
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_star_global.c
@@ -0,0 +1,83 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+int *p;
+
+void f1() {
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to : p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *x0_mappedptr =
+      (int *)omp_get_mapped_ptr(&x[0], omp_get_default_device());
+  int *x0_hostaddr = &x[0];
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("x0_mappedptr %s null\n", x0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: x0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(*p) map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : *p, p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+#pragma omp target map(to : p, *p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
+           x0_hostaddr == &p[-1]);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    {{[0-9]+}} 0 0 0
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p)                                     \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
+           x0_hostaddr == &p[-2]);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : p[0 : 5], p)
+}
+
+int main() { f1(); }
diff --git a/offload/test/mapping/map_ptr_and_star_local.c b/offload/test/mapping/map_ptr_and_star_local.c
new file mode 100644
index 0000000000000..57a9359b6b857
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_star_local.c
@@ -0,0 +1,83 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+
+void f1() {
+  int *p;
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to : p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *x0_mappedptr =
+      (int *)omp_get_mapped_ptr(&x[0], omp_get_default_device());
+  int *x0_hostaddr = &x[0];
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("x0_mappedptr %s null\n", x0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: x0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(*p) map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : *p, p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+#pragma omp target map(to : p, *p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
+           x0_hostaddr == &p[-1]);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    {{[0-9]+}} 0 0 0
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p)                                     \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
+           x0_hostaddr == &p[-2]);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : p[0 : 5], p)
+}
+
+int main() { f1(); }
diff --git a/offload/test/mapping/map_ptr_and_subscript_global.c b/offload/test/mapping/map_ptr_and_subscript_global.c
new file mode 100644
index 0000000000000..a3a10b6c9b212
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_subscript_global.c
@@ -0,0 +1,83 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+int *p;
+
+void f1() {
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to : p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *x0_mappedptr =
+      (int *)omp_get_mapped_ptr(&x[0], omp_get_default_device());
+  int *x0_hostaddr = &x[0];
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("x0_mappedptr %s null\n", x0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: x0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(p[0]) map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : p[0], p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+#pragma omp target map(to : p, p[0])                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
+           x0_hostaddr == &p[-1]);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    111 0 0 0
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p)                                     \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
+           x0_hostaddr == &p[-2]);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : p[0 : 5], p)
+}
+
+int main() { f1(); }
diff --git a/offload/test/mapping/map_ptr_and_subscript_local.c b/offload/test/mapping/map_ptr_and_subscript_local.c
new file mode 100644
index 0000000000000..bb44999541a7b
--- /dev/null
+++ b/offload/test/mapping/map_ptr_and_subscript_local.c
@@ -0,0 +1,83 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+int x[10];
+
+void f1() {
+  int *p;
+  p = &x[0];
+  p[0] = 111;
+  p[1] = 222;
+  p[2] = 333;
+  p[3] = 444;
+
+#pragma omp target enter data map(to : p)
+#pragma omp target enter data map(to : p[0 : 5])
+
+  int **p_mappedptr = (int **)omp_get_mapped_ptr(&p, omp_get_default_device());
+  int *x0_mappedptr =
+      (int *)omp_get_mapped_ptr(&x[0], omp_get_default_device());
+  int *x0_hostaddr = &x[0];
+
+  printf("p_mappedptr %s null\n", p_mappedptr == (int **)NULL ? "==" : "!=");
+  printf("x0_mappedptr %s null\n", x0_mappedptr == (int *)NULL ? "==" : "!=");
+
+// CHECK: p_mappedptr != null
+// CHECK: x0_mappedptr != null
+
+// p is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(p[0]) map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+// For the remaining constructs, p is not firstprivate, so its address will
+// be the same as the mapped address, and changes to p will be visible to any
+// subsequent regions.
+#pragma omp target map(to : p[0], p)                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
+           x0_hostaddr == &p[0]);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    p++;
+  }
+
+#pragma omp target map(to : p, p[0])                                           \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
+           x0_hostaddr == &p[-1]);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    111 0 0 0
+    p++;
+  }
+
+#pragma omp target map(present, alloc : p)                                     \
+    map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
+  {
+    printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
+           x0_hostaddr == &p[-2]);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:p) should not bring back p, because p is an
+  // attached pointer. So, it should still point to the same original
+  // location, &x[0], on host.
+#pragma omp target exit data map(always, from : p)
+  printf("%d %d\n", p[0], p == &x[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : p[0 : 5], p)
+}
+
+int main() { f1(); }
diff --git a/offload/test/mapping/map_structptr_and_member_global.c b/offload/test/mapping/map_structptr_and_member_global.c
new file mode 100644
index 0000000000000..10e72e070dbc5
--- /dev/null
+++ b/offload/test/mapping/map_structptr_and_member_global.c
@@ -0,0 +1,88 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+typedef struct {
+  short x;
+  int *p;
+  long y;
+} S;
+
+S s[10], *ps;
+
+void f1() {
+  ps = &s[0];
+  s[0].x = 111;
+  s[1].x = 222;
+  s[2].x = 333;
+  s[3].x = 444;
+
+#pragma omp target enter data map(to : s)
+#pragma omp target enter data map(to : ps, ps->x)
+
+  S **ps_mappedptr = (S **)omp_get_mapped_ptr(&ps, omp_get_default_device());
+  short *s0_mappedptr =
+      (short *)omp_get_mapped_ptr(&s[0].x, omp_get_default_device());
+  short *s0_hostaddr = &s[0].x;
+
+  printf("ps_mappedptr %s null\n", ps_mappedptr == (S **)NULL ? "==" : "!=");
+  printf("s0_mappedptr %s null\n", s0_mappedptr == (short *)NULL ? "==" : "!=");
+
+// CHECK: ps_mappedptr != null
+// CHECK: s0_mappedptr != null
+
+// ps is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(ps->x) map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
+           s0_hostaddr == &ps->x);
+    // CHECK: 111 0 1 0
+    ps++;
+  }
+
+// For the remaining constructs, ps is not firstprivate, so its address will
+// be the same as the mapped address, and changes to ps will be visible to any
+// subsequent regions.
+#pragma omp target map(to : ps->x, ps)                                         \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
+           s0_hostaddr == &ps->x);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    ps++;
+  }
+
+#pragma omp target map(to : ps, ps->x)                                         \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
+           s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    111 0 0 0
+    ps++;
+  }
+
+#pragma omp target map(present, alloc : ps)                                    \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
+           s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:ps) should not bring back ps, because ps is an
+  // attached pointer. So, it should still point to the same original
+  // location, &s[0], on host.
+#pragma omp target exit data map(always, from : ps)
+  printf("%d %d\n", ps->x, ps == &s[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : ps, s)
+}
+
+int main() { f1(); }
diff --git a/offload/test/mapping/map_structptr_and_member_local.c b/offload/test/mapping/map_structptr_and_member_local.c
new file mode 100644
index 0000000000000..9e59551ad3d6c
--- /dev/null
+++ b/offload/test/mapping/map_structptr_and_member_local.c
@@ -0,0 +1,87 @@
+// RUN: %libomptarget-compilexx-run-and-check-generic
+
+#include <omp.h>
+#include <stdio.h>
+
+typedef struct {
+  short x;
+  int *p;
+  long y;
+} S;
+
+void f1() {
+  S s[10], *ps;
+  ps = &s[0];
+  s[0].x = 111;
+  s[1].x = 222;
+  s[2].x = 333;
+  s[3].x = 444;
+
+#pragma omp target enter data map(to : s)
+#pragma omp target enter data map(to : ps, ps->x)
+
+  S **ps_mappedptr = (S **)omp_get_mapped_ptr(&ps, omp_get_default_device());
+  short *s0_mappedptr =
+      (short *)omp_get_mapped_ptr(&s[0].x, omp_get_default_device());
+  short *s0_hostaddr = &s[0].x;
+
+  printf("ps_mappedptr %s null\n", ps_mappedptr == (S **)NULL ? "==" : "!=");
+  printf("s0_mappedptr %s null\n", s0_mappedptr == (short *)NULL ? "==" : "!=");
+
+// CHECK: ps_mappedptr != null
+// CHECK: s0_mappedptr != null
+
+// ps is predetermined firstprivate, so its address will be different from
+// the mapped address for this construct. So, any changes to p within the
+// region will not be visible after the construct.
+#pragma omp target map(ps->x) map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
+           s0_hostaddr == &ps->x);
+    // CHECK: 111 0 1 0
+    ps++;
+  }
+
+// For the remaining constructs, ps is not firstprivate, so its address will
+// be the same as the mapped address, and changes to ps will be visible to any
+// subsequent regions.
+#pragma omp target map(to : ps->x, ps)                                         \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
+           s0_hostaddr == &ps->x);
+    // EXPECTED: 111 1 1 0
+    // CHECK:    111 0 1 0
+    ps++;
+  }
+
+#pragma omp target map(to : ps, ps->x)                                         \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
+           s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
+    // EXPECTED: 222 1 1 0
+    // CHECK:    111 0 0 0
+    ps++;
+  }
+
+#pragma omp target map(present, alloc : ps)                                    \
+    map(to : ps_mappedptr, s0_mappedptr, s0_hostaddr)
+  {
+    printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
+           s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
+    // EXPECTED: 333 1 1 0
+    // CHECK:    111 1 0 0
+  }
+
+  // The following map(from:ps) should not bring back ps, because ps is an
+  // attached pointer. So, it should still point to the same original
+  // location, &s[0], on host.
+#pragma omp target exit data map(always, from : ps)
+  printf("%d %d\n", ps->x, ps == &s[0]);
+  // CHECK: 111 1
+
+#pragma omp target exit data map(delete : ps, s)
+}
+
+int main() { f1(); }

>From 15e7d50aefdf8c5dd631ff2ac236c89038f74674 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Thu, 3 Jul 2025 10:50:31 -0700
Subject: [PATCH 12/66] Minor clang-format fix.

---
 offload/test/mapping/map_ptr_and_star_global.c | 4 ++--
 offload/test/mapping/map_ptr_and_star_local.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/offload/test/mapping/map_ptr_and_star_global.c b/offload/test/mapping/map_ptr_and_star_global.c
index c09dc7fff6c17..c3b0dd2f49e6b 100644
--- a/offload/test/mapping/map_ptr_and_star_global.c
+++ b/offload/test/mapping/map_ptr_and_star_global.c
@@ -41,7 +41,7 @@ void f1() {
 // For the remaining constructs, p is not firstprivate, so its address will
 // be the same as the mapped address, and changes to p will be visible to any
 // subsequent regions.
-#pragma omp target map(to : *p, p)                                           \
+#pragma omp target map(to : *p, p)                                             \
     map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
@@ -51,7 +51,7 @@ void f1() {
     p++;
   }
 
-#pragma omp target map(to : p, *p)                                           \
+#pragma omp target map(to : p, *p)                                             \
     map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
diff --git a/offload/test/mapping/map_ptr_and_star_local.c b/offload/test/mapping/map_ptr_and_star_local.c
index 57a9359b6b857..f0ca84d1cc4dd 100644
--- a/offload/test/mapping/map_ptr_and_star_local.c
+++ b/offload/test/mapping/map_ptr_and_star_local.c
@@ -41,7 +41,7 @@ void f1() {
 // For the remaining constructs, p is not firstprivate, so its address will
 // be the same as the mapped address, and changes to p will be visible to any
 // subsequent regions.
-#pragma omp target map(to : *p, p)                                           \
+#pragma omp target map(to : *p, p)                                             \
     map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
@@ -51,7 +51,7 @@ void f1() {
     p++;
   }
 
-#pragma omp target map(to : p, *p)                                           \
+#pragma omp target map(to : p, *p)                                             \
     map(to : p_mappedptr, x0_mappedptr, x0_hostaddr)
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],

>From b1540b3d28f5fc65d3fc8a79e031bdb3fbfe010f Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 7 Jul 2025 10:30:39 -0700
Subject: [PATCH 13/66] Minor NFC update to a test.

---
 ...arget_map_both_pointer_pointee_codegen.cpp | 63 ++++++++++++++----
 ...ap_both_pointer_pointee_codegen_global.cpp | 66 +++++++++++++++----
 2 files changed, 103 insertions(+), 26 deletions(-)

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 262e343401d16..d5ca0e366d7bf 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -39,19 +39,27 @@ void f4() {
 
 void f5() {
   int *ptr;
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
- #pragma omp target data map(ptr[2], ptr)
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  #pragma omp target map(ptr[2], ptr)
     ptr[2] = 9;
 }
 
 void f6() {
   int *ptr;
   // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
-  //   FIXME: PARAM seems to be redundant here.
+  // TODO: PARAM should not be needed here.
   #pragma omp target data map(ptr, ptr[2])
     ptr[2] = 10;
 }
-#endif
+
+void f7() {
+  int *ptr;
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // TODO: PARAM should not be needed here.
+  #pragma omp target data map(ptr[2], ptr)
+    ptr[2] = 11;
+}
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
@@ -65,6 +73,8 @@ void f6() {
 // CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -84,7 +94,7 @@ void f6() {
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13:![0-9]+]], !align [[META14:![0-9]+]]
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 5, ptr [[ARRAYIDX]], align 4
@@ -177,6 +187,33 @@ void f6() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l41
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 9, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
 // CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
@@ -186,17 +223,17 @@ void f6() {
 // CHECK:    store ptr null, ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 9, ptr [[ARRAYIDX1]], align 4
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-LABEL: define {{[^@]+}}@_Z2f7v
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
@@ -209,13 +246,13 @@ void f6() {
 // CHECK:    store ptr null, ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
-
+#endif
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
index 8f0f27e6f8e94..02c53202e22dc 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -22,28 +22,39 @@ void f2() {
 }
 
 void f3() {
-  // &ptr, &ptr[0], sizeof(ptr[0:2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[0], 2 * sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
   #pragma omp target map(ptr, ptr[0:2])
     ptr[1] = 7;
 }
 
 void f4() {
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
   #pragma omp target map(ptr, ptr[2])
     ptr[2] = 8;
 }
 
 void f5() {
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
- #pragma omp target data map(ptr[2], ptr)
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  #pragma omp target map(ptr[2], ptr)
     ptr[2] = 9;
 }
 
 void f6() {
-  // &ptr, &ptr[0], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // TODO: PARAM should not be needed here.
   #pragma omp target data map(ptr, ptr[2])
     ptr[2] = 10;
 }
+
+void f7() {
+  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // TODO: PARAM should not be needed here.
+  #pragma omp target data map(ptr[2], ptr)
+    ptr[2] = 11;
+}
 #endif
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
@@ -58,6 +69,8 @@ void f6() {
 // CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -77,7 +90,7 @@ void f6() {
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11:![0-9]+]], !align [[META12:![0-9]+]]
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13:![0-9]+]], !align [[META14:![0-9]+]]
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 5, ptr [[ARRAYIDX]], align 4
@@ -169,6 +182,33 @@ void f6() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l38
+// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK:  entry:
+// CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    store i32 9, ptr [[ARRAYIDX]], align 4
+// CHECK:    ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK:  entry:
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
 // CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
@@ -178,17 +218,17 @@ void f6() {
 // CHECK:    store ptr null, ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 9, ptr [[ARRAYIDX1]], align 4
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.7, ptr @.offload_maptypes.8, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@_Z2f6v
+// CHECK-LABEL: define {{[^@]+}}@_Z2f7v
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
@@ -201,12 +241,12 @@ void f6() {
 // CHECK:    store ptr null, ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //

>From f1746b6b58af3e9609deb4c348de0838129d5523 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 7 Jul 2025 14:56:07 -0700
Subject: [PATCH 14/66] Update tests with the current output.

---
 ...arget_map_both_pointer_pointee_codegen.cpp | 116 +++++----
 ...ap_both_pointer_pointee_codegen_global.cpp | 114 +++++----
 .../OpenMP/target_map_ptr_and_star_global.cpp |  78 +++---
 .../OpenMP/target_map_ptr_and_star_local.cpp  |  76 +++---
 ...target_map_structptr_and_member_global.cpp | 240 ++++++++----------
 .../target_map_structptr_and_member_local.cpp | 240 ++++++++----------
 .../test/mapping/map_ptr_and_star_global.c    |   9 +-
 offload/test/mapping/map_ptr_and_star_local.c |   9 +-
 .../mapping/map_ptr_and_subscript_global.c    |  11 +-
 .../mapping/map_ptr_and_subscript_local.c     |  11 +-
 .../mapping/map_structptr_and_member_global.c |   9 +-
 .../mapping/map_structptr_and_member_local.c  |   9 +-
 12 files changed, 444 insertions(+), 478 deletions(-)

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 d5ca0e366d7bf..8a167a19ddbc9 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -60,17 +60,18 @@ void f7() {
   #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 11;
 }
+#endif
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 8]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 // CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
@@ -133,25 +134,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 0
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l27
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 7, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -160,25 +167,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l34
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -187,25 +200,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l41
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l44
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 9, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -255,4 +274,3 @@ void f7() {
 // CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
-#endif
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
index 02c53202e22dc..e39d602dca316 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -61,12 +61,12 @@ void f7() {
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 8]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 // CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
@@ -128,25 +128,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 0
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l26
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l27
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 7, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -155,25 +161,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l32
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l34
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -182,25 +194,31 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l38
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l41
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 9, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
index 84899cb8e4fad..40d3cd24ac08f 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
@@ -28,8 +28,8 @@ void f3() {
 }
 
 void f4() {
-  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ | PARAM
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
   #pragma omp target map(*ptr, ptr)
     ptr[2] = 8;
 }
@@ -42,8 +42,8 @@ void f4() {
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
 // CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
 // CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x33]], i64 [[#0x3]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -100,30 +100,30 @@ void f4() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l26
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -132,30 +132,30 @@ void f4() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l33
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
index 246c0c5f99a68..2eff1727e0e46 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
@@ -31,8 +31,8 @@ void f3() {
 
 void f4() {
   int *ptr;
-  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
   #pragma omp target map(*ptr, ptr)
     ptr[2] = 8;
 }
@@ -45,7 +45,7 @@ void f4() {
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
 // CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
 // CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
 // CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
@@ -105,30 +105,30 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
 // CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP2]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 1
 // CHECK:    store i32 6, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
@@ -138,30 +138,30 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
-// CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
+// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8, !nonnull [[META11]], !align [[META12]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    store i32 8, ptr [[ARRAYIDX]], align 4
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
index 523f88dc8dba3..dc2df3849f299 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
@@ -28,26 +28,24 @@ void f2() {
 }
 
 void f3() {
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps->y, sizeof(ps->y), TO
   #pragma omp target map(to: ps, ps->y)
     ps->y = 7;
 }
 
 void f4() {
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps->y, sizeof(ps->y), TO
   #pragma omp target map(to: ps->y, ps)
     ps->y = 8;
 }
 
 void f5() {
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
-  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
+  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -58,12 +56,12 @@ void f5() {
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 0, i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 8]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 8, i64 2]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 8, i64 0, i64 4, i64 2]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]]]
 //.
 // CHECK-LABEL: define dso_local void @_Z2f1v(
 // CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
@@ -123,46 +121,31 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
-// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.3, i64 24, i1 false)
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ps, ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr @ps, ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP1]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l34(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l33(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 7, ptr [[Y]], align 4
 // CHECK:    ret void
 //
@@ -172,46 +155,31 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
-// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.5, i64 24, i1 false)
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l42(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l40(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 8, ptr [[Y]], align 4
 // CHECK:    ret void
 //
@@ -221,55 +189,55 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[TMP4:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
-// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP8:%.*]] = sub i64 [[TMP6]], [[TMP7]]
-// CHECK:    [[TMP9:%.*]] = sdiv exact i64 [[TMP8]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
+// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP9]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP3]], ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP22]], align 8
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP26:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l51(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l49(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 9, ptr [[Y]], align 4
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
index b366f331941b7..44a982680bb8b 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
@@ -29,28 +29,26 @@ void f2() {
 
 void f3() {
   S s, *ps;
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps->y, sizeof(ps->y), TO
   #pragma omp target map(to: ps, ps->y)
     ps->y = 7;
 }
 
 void f4() {
   S s, *ps;
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps->y, sizeof(ps->y), TO
   #pragma omp target map(to: ps->y, ps)
     ps->y = 8;
 }
 
 void f5() {
   S s, *ps;
-  // &ps[0], &ps[0], sizeof(ps[0]), PARAM | ALLOC
-  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(1)
-  // &ps, &ps, sizeof(ps), TO | MEMBER_OF(1)
-  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(1)
+  // &ps, &ps, sizeof(ps), TO | PARAM
+  // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
+  // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
+  // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -61,12 +59,12 @@ void f5() {
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 0, i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 8]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 8, i64 2]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 8, i64 0, i64 4, i64 2]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]]]
 //.
 // CHECK-LABEL: define dso_local void @_Z2f1v(
 // CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
@@ -126,46 +124,31 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
-// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.3, i64 24, i1 false)
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PS]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PS]], ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP1]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l35(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l34(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 7, ptr [[Y]], align 4
 // CHECK:    ret void
 //
@@ -175,46 +158,31 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP6:%.*]] = sub i64 [[TMP4]], [[TMP5]]
-// CHECK:    [[TMP7:%.*]] = sdiv exact i64 [[TMP6]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.5, i64 24, i1 false)
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP7]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l44(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l42(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 8, ptr [[Y]], align 4
 // CHECK:    ret void
 //
@@ -224,55 +192,55 @@ void f5() {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[TMP4:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr [[STRUCT_S]], ptr [[TMP1]], i32 1
-// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
-// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP1]] to i64
-// CHECK:    [[TMP8:%.*]] = sub i64 [[TMP6]], [[TMP7]]
-// CHECK:    [[TMP9:%.*]] = sdiv exact i64 [[TMP8]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
+// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    store i64 [[TMP9]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP3]], ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP22]], align 8
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP26:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l54(
-// CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l52(
+// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
-// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8
-// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP0]], i32 0, i32 1
+// CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS_ADDR]], align 8, !nonnull [[META13]], !align [[META14]]
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    store i32 9, ptr [[Y]], align 4
 // CHECK:    ret void
 //
diff --git a/offload/test/mapping/map_ptr_and_star_global.c b/offload/test/mapping/map_ptr_and_star_global.c
index c3b0dd2f49e6b..255e2dee6512e 100644
--- a/offload/test/mapping/map_ptr_and_star_global.c
+++ b/offload/test/mapping/map_ptr_and_star_global.c
@@ -46,8 +46,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
            x0_hostaddr == &p[0]);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 0 1 0
+    // CHECK:    111 1 1 0
     p++;
   }
 
@@ -56,8 +55,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
            x0_hostaddr == &p[-1]);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    {{[0-9]+}} 0 0 0
+    // CHECK:    222 1 1 0
     p++;
   }
 
@@ -66,8 +64,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
            x0_hostaddr == &p[-2]);
-    // EXPECTED: 333 1 1 0
-    // CHECK:    111 1 0 0
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:p) should not bring back p, because p is an
diff --git a/offload/test/mapping/map_ptr_and_star_local.c b/offload/test/mapping/map_ptr_and_star_local.c
index f0ca84d1cc4dd..0d2d689ec9912 100644
--- a/offload/test/mapping/map_ptr_and_star_local.c
+++ b/offload/test/mapping/map_ptr_and_star_local.c
@@ -47,7 +47,7 @@ void f1() {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
            x0_hostaddr == &p[0]);
     // EXPECTED: 111 1 1 0
-    // CHECK:    111 0 1 0
+    // CHECK:    111 1 0 1
     p++;
   }
 
@@ -57,7 +57,7 @@ void f1() {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
            x0_hostaddr == &p[-1]);
     // EXPECTED: 222 1 1 0
-    // CHECK:    {{[0-9]+}} 0 0 0
+    // CHECK:    222 1 0 1
     p++;
   }
 
@@ -67,7 +67,7 @@ void f1() {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
            x0_hostaddr == &p[-2]);
     // EXPECTED: 333 1 1 0
-    // CHECK:    111 1 0 0
+    // CHECK:    333 1 0 1
   }
 
   // The following map(from:p) should not bring back p, because p is an
@@ -75,7 +75,8 @@ void f1() {
   // location, &x[0], on host.
 #pragma omp target exit data map(always, from : p)
   printf("%d %d\n", p[0], p == &x[0]);
-  // CHECK: 111 1
+  // EXPECTED:   111 1
+  // CHECK:      333 0
 
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
diff --git a/offload/test/mapping/map_ptr_and_subscript_global.c b/offload/test/mapping/map_ptr_and_subscript_global.c
index 09b41d2b0f959..63486773a68ec 100644
--- a/offload/test/mapping/map_ptr_and_subscript_global.c
+++ b/offload/test/mapping/map_ptr_and_subscript_global.c
@@ -46,8 +46,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
            x0_hostaddr == &p[0]);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 1 1 1
+    // CHECK:    111 1 1 0
     p++;
   }
 
@@ -56,8 +55,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
            x0_hostaddr == &p[-1]);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    222 1 1 1
+    // CHECK:    222 1 1 0
     p++;
   }
 
@@ -66,8 +64,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
            x0_hostaddr == &p[-2]);
-    // EXPECTED: 333 1 1 0
-    // CHECK:    333 1 1 1
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:p) should not bring back p, because p is an
@@ -75,7 +72,7 @@ void f1() {
   // location, &x[0], on host.
 #pragma omp target exit data map(always, from : p)
   printf("%d %d\n", p[0], p == &x[0]);
-  // CHECK: 333 1
+  // CHECK: 111 1
 
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
diff --git a/offload/test/mapping/map_ptr_and_subscript_local.c b/offload/test/mapping/map_ptr_and_subscript_local.c
index fd874753c9fd2..59c05fa876d96 100644
--- a/offload/test/mapping/map_ptr_and_subscript_local.c
+++ b/offload/test/mapping/map_ptr_and_subscript_local.c
@@ -46,8 +46,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
            x0_hostaddr == &p[0]);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 1 1 1
+    // CHECK:    111 1 1 0
     p++;
   }
 
@@ -56,8 +55,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
            x0_hostaddr == &p[-1]);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    222 1 1 1
+    // CHECK:    222 1 1 0
     p++;
   }
 
@@ -66,8 +64,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
            x0_hostaddr == &p[-2]);
-    // EXPECTED: 333 1 1 0
-    // CHECK:    333 1 1 1
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:p) should not bring back p, because p is an
@@ -75,7 +72,7 @@ void f1() {
   // location, &x[0], on host.
 #pragma omp target exit data map(always, from : p)
   printf("%d %d\n", p[0], p == &x[0]);
-  // CHECK: 333 1
+  // CHECK: 111 1
 
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
diff --git a/offload/test/mapping/map_structptr_and_member_global.c b/offload/test/mapping/map_structptr_and_member_global.c
index 10e72e070dbc5..f2fae005b79ab 100644
--- a/offload/test/mapping/map_structptr_and_member_global.c
+++ b/offload/test/mapping/map_structptr_and_member_global.c
@@ -52,7 +52,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
            s0_hostaddr == &ps->x);
     // EXPECTED: 111 1 1 0
-    // CHECK:    111 0 1 0
+    // CHECK:    111 1 0 1
     ps++;
   }
 
@@ -62,7 +62,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
     // EXPECTED: 222 1 1 0
-    // CHECK:    111 0 0 0
+    // CHECK:    222 1 0 1
     ps++;
   }
 
@@ -72,7 +72,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
     // EXPECTED: 333 1 1 0
-    // CHECK:    111 1 0 0
+    // CHECK:    333 1 0 1
   }
 
   // The following map(from:ps) should not bring back ps, because ps is an
@@ -80,7 +80,8 @@ void f1() {
   // location, &s[0], on host.
 #pragma omp target exit data map(always, from : ps)
   printf("%d %d\n", ps->x, ps == &s[0]);
-  // CHECK: 111 1
+  // EXPECTED:   111 1
+  // CHECK:      333 0
 
 #pragma omp target exit data map(delete : ps, s)
 }
diff --git a/offload/test/mapping/map_structptr_and_member_local.c b/offload/test/mapping/map_structptr_and_member_local.c
index 9e59551ad3d6c..a9db3eefbc54f 100644
--- a/offload/test/mapping/map_structptr_and_member_local.c
+++ b/offload/test/mapping/map_structptr_and_member_local.c
@@ -51,7 +51,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
            s0_hostaddr == &ps->x);
     // EXPECTED: 111 1 1 0
-    // CHECK:    111 0 1 0
+    // CHECK:    111 1 0 1
     ps++;
   }
 
@@ -61,7 +61,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
     // EXPECTED: 222 1 1 0
-    // CHECK:    111 0 0 0
+    // CHECK:    222 1 0 1
     ps++;
   }
 
@@ -71,7 +71,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
     // EXPECTED: 333 1 1 0
-    // CHECK:    111 1 0 0
+    // CHECK:    333 1 0 1
   }
 
   // The following map(from:ps) should not bring back ps, because ps is an
@@ -79,7 +79,8 @@ void f1() {
   // location, &s[0], on host.
 #pragma omp target exit data map(always, from : ps)
   printf("%d %d\n", ps->x, ps == &s[0]);
-  // CHECK: 111 1
+  // EXPECTED:   111 1
+  // CHECK:      333 0
 
 #pragma omp target exit data map(delete : ps, s)
 }

>From 3ce181f8057b417b5aae848dbcf269125b9d7f92 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 7 Jul 2025 18:47:57 -0700
Subject: [PATCH 15/66] Fix findAttachComponent

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 34 ++-------------------------
 1 file changed, 2 insertions(+), 32 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 2c8ee5159d322..cf56b27813b09 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8126,16 +8126,10 @@ struct AttachInfo {
 
 static AttachInfo findAttachComponent(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
-               ->isAnyPointerType())
-        return false;
-      BaseExpr = OASE->getBase();
+
   const auto *Begin = Components.begin();
   const auto *End = Components.end();
-               .getCanonicalType()
-               ->isAnyPointerType())
-        return false;
-      BaseExpr = ASE->getBase();
-    } else {
+
   for (const auto *I = Begin; I != End; ++I) {
     // Check if current component is an array section or subscript
     const Expr *CurrentExpr = I->getAssociatedExpression();
@@ -8143,29 +8137,9 @@ static AttachInfo findAttachComponent(
       break;
     }
 
-    // For something like p->s[1].q[10], the pointee should be "p->s[1].q",
-    // while base-ptr would be p.
-    const auto *ME = dyn_cast<MemberExpr>(CurrentExpr);
-    if (ME) {
-            dyn_cast<DeclRefExpr>(BaseExpr->IgnoreParenImpCasts())) {
-      if (!ME->isArrow()) {
-        // Check that the original declaration is a single-level pointer, not
-        PreviousMemberExpr = CurrentExpr;  // Track this as potential PteeExpr
-        continue;
-      }
-    }
-    return false;
-    const auto *OASE = dyn_cast<ArraySectionExpr>(CurrentExpr);
-    const auto *ASE = dyn_cast<ArraySubscriptExpr>(CurrentExpr);
-
-    if (!OASE && !ASE && !ME) {
-      break;
-    }
-
     // Check if the next component (in forward direction) has a pointer type
     const auto *NextI = std::next(I);
     if (NextI == End) {
-      // Check if the next component (in forward direction) has a pointer type
       break;
     }
 
@@ -8183,10 +8157,6 @@ static AttachInfo findAttachComponent(
    if (!NextType->isPointerType())
      continue;
 
-      llvm::errs() << "DEBUG findAttachComponent: Next component not pointer type, continuing\n";
-    }
-  }
-
    // Get the pointer expression (NextRI) and use the candidate PteeExpr
    const Expr *BasePtrExpr = NextI->getAssociatedExpression();
    const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();

>From 50c8d0eef8afe28eed4fc8acb316450f8db0b0d4 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 8 Jul 2025 03:22:03 -0700
Subject: [PATCH 16/66] Fix build issues, keep debug prints

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 391 ++++++++++++++++++++++++--
 1 file changed, 366 insertions(+), 25 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index cf56b27813b09..a49efc310ec34 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/APValue.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/StmtOpenMP.h"
 #include "clang/AST/StmtVisitor.h"
@@ -6914,10 +6915,16 @@ class MappableExprsHandler {
   llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
 
   llvm::Value *getExprTypeSize(const Expr *E) const {
+    // DEBUG: Print entry information
+    llvm::errs() << "DEBUG getExprTypeSize: ENTRY\n";
+    llvm::errs() << "  Expression: ";
+    E->dump();
+    
     QualType ExprTy = E->getType().getCanonicalType();
 
     // Calculate the size for array shaping expression.
     if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
+      llvm::errs() << "DEBUG getExprTypeSize: Handling OMPArrayShapingExpr\n";
       llvm::Value *Size =
           CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType());
       for (const Expr *SE : OAE->getDimensions()) {
@@ -6927,6 +6934,7 @@ class MappableExprsHandler {
                                       SE->getExprLoc());
         Size = CGF.Builder.CreateNUWMul(Size, Sz);
       }
+      llvm::errs() << "DEBUG getExprTypeSize: Returning size for ArrayShapingExpr\n";
       return Size;
     }
 
@@ -6938,6 +6946,7 @@ class MappableExprsHandler {
     // do the calculation based on the length of the section instead of relying
     // on CGF.getTypeSize(E->getType()).
     if (const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
+      llvm::errs() << "DEBUG getExprTypeSize: Handling ArraySectionExpr\n";
       QualType BaseTy = ArraySectionExpr::getBaseOriginalType(
                             OAE->getBase()->IgnoreParenImpCasts())
                             .getCanonicalType();
@@ -6946,8 +6955,10 @@ class MappableExprsHandler {
       // not specified too, that means we are using the whole length of the
       // base.
       if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
-          !OAE->getLowerBound())
+          !OAE->getLowerBound()) {
+        llvm::errs() << "DEBUG getExprTypeSize: Using whole length of base for ArraySection\n";
         return CGF.getTypeSize(BaseTy);
+      }
 
       llvm::Value *ElemSize;
       if (const auto *PTy = BaseTy->getAs<PointerType>()) {
@@ -6960,8 +6971,10 @@ class MappableExprsHandler {
 
       // If we don't have a length at this point, that is because we have an
       // array section with a single element.
-      if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
+      if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) {
+        llvm::errs() << "DEBUG getExprTypeSize: Single element ArraySection\n";
         return ElemSize;
+      }
 
       if (const Expr *LenExpr = OAE->getLength()) {
         llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
@@ -6996,6 +7009,14 @@ class MappableExprsHandler {
       OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
       ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit,
       bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const {
+    // DEBUG: Print entry information
+    llvm::errs() << "DEBUG getMapTypeBits: ENTRY\n";
+    llvm::errs() << "  MapType: " << MapType << "\n";
+    llvm::errs() << "  IsImplicit: " << IsImplicit << "\n";
+    llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
+    llvm::errs() << "  AddIsTargetParamFlag: " << AddIsTargetParamFlag << "\n";
+    llvm::errs() << "  IsNonContiguous: " << IsNonContiguous << "\n";
+    
     OpenMPOffloadMappingFlags Bits =
         IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
                    : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
@@ -7038,21 +7059,33 @@ class MappableExprsHandler {
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
     if (IsNonContiguous)
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
+    
+    // DEBUG: Print final flags
+    llvm::errs() << "DEBUG getMapTypeBits: Final bits = " << static_cast<unsigned>(Bits) << "\n";
     return Bits;
   }
 
   /// Return true if the provided expression is a final array section. A
   /// final array section, is one whose length can't be proved to be one.
   bool isFinalArraySectionExpression(const Expr *E) const {
+    // DEBUG: Print entry information
+    llvm::errs() << "DEBUG isFinalArraySectionExpression: ENTRY\n";
+    llvm::errs() << "  Expression: ";
+    E->dump();
+    
     const auto *OASE = dyn_cast<ArraySectionExpr>(E);
 
     // It is not an array section and therefore not a unity-size one.
-    if (!OASE)
+    if (!OASE) {
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: Not ArraySectionExpr, returning false\n";
       return false;
+    }
 
     // An array section with no colon always refer to a single element.
-    if (OASE->getColonLocFirst().isInvalid())
+    if (OASE->getColonLocFirst().isInvalid()) {
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: No colon, single element, returning false\n";
       return false;
+    }
 
     const Expr *Length = OASE->getLength();
 
@@ -7073,11 +7106,16 @@ class MappableExprsHandler {
 
     // Check if the length evaluates to 1.
     Expr::EvalResult Result;
-    if (!Length->EvaluateAsInt(Result, CGF.getContext()))
+    if (!Length->EvaluateAsInt(Result, CGF.getContext())) {
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: Cannot evaluate length as int, returning true\n";
       return true; // Can have more that size 1.
+    }
 
     llvm::APSInt ConstLength = Result.Val.getInt();
-    return ConstLength.getSExtValue() != 1;
+    bool result = ConstLength.getSExtValue() != 1;
+    llvm::errs() << "DEBUG isFinalArraySectionExpression: Length = " << ConstLength.getSExtValue() 
+                 << ", returning " << result << "\n";
+    return result;
   }
 
   /// Generate the base pointers, section pointers, sizes, map type bits, and
@@ -7097,6 +7135,25 @@ class MappableExprsHandler {
       const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
           OverlappedElements = {}) const {
+    
+    // DEBUG: Print function entry information
+    llvm::errs() << "DEBUG generateInfoForComponentList: ENTRY\n";
+    llvm::errs() << "  MapType: " << MapType << "\n";
+    llvm::errs() << "  IsFirstComponentList: " << IsFirstComponentList << "\n";
+    llvm::errs() << "  IsImplicit: " << IsImplicit << "\n";
+    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses << "\n";
+    llvm::errs() << "  ForDeviceAddr: " << ForDeviceAddr << "\n";
+    llvm::errs() << "  Components.size(): " << Components.size() << "\n";
+    if (BaseDecl) {
+      llvm::errs() << "  BaseDecl: " << BaseDecl->getNameAsString() << "\n";
+    }
+    if (MapExpr) {
+      llvm::errs() << "  MapExpr: ";
+      MapExpr->dump();
+    }
+    
+
+    Expr *PossibleBasePtr = nullptr;
     // The following summarizes what has to be generated for each map and the
     // types below. The generated information is expressed in this order:
     // base pointer, section pointer, size, flags
@@ -7289,6 +7346,24 @@ class MappableExprsHandler {
     auto CI = Components.rbegin();
     auto CE = Components.rend();
     auto I = CI;
+    
+    // DEBUG: Print what I initially points to
+    llvm::errs() << "DEBUG generateInfoForComponentList: Initial iterator I points to:\n";
+    if (I != CE) {
+      if (I->getAssociatedDeclaration()) {
+        llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
+      } else {
+        llvm::errs() << "  AssociatedDeclaration: nullptr\n";
+      }
+      if (I->getAssociatedExpression()) {
+        llvm::errs() << "  AssociatedExpression: ";
+        I->getAssociatedExpression()->dump();
+      } else {
+        llvm::errs() << "  AssociatedExpression: nullptr\n";
+      }
+    } else {
+      llvm::errs() << "  I is already at end (CE)\n";
+    }
 
     // Track if the map information being generated is the first for a list of
     // components.
@@ -7308,24 +7383,34 @@ class MappableExprsHandler {
 
     // Find the component that should use ATTACH-style mapping.
     auto AttachInfo = findAttachComponent(Components);
+
+    llvm::errs() << "DEBUG generateInfoForComponentList: Computing initial BP\n";
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
+      llvm::errs() << "  Case: MemberExpr - using LoadCXXThisAddress\n";
       BP = CGF.LoadCXXThisAddress();
+      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
                (OASE &&
                 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
+      llvm::errs() << "  Case: ArrayExpr with CXXThisExpr base - using EmitOMPSharedLValue\n";
       BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
+      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else if (OAShE &&
                isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
+      llvm::errs() << "  Case: OMPArrayShapingExpr with CXXThisExpr base\n";
       BP = Address(
           CGF.EmitScalarExpr(OAShE->getBase()),
           CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
           CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
+      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else {
       // The base is the reference to the variable.
       // BP = &Var.
+      llvm::errs() << "  Case: Standard variable reference - using EmitOMPSharedLValue\n";
       BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
+      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
       if (const auto *VD =
               dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
         if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
@@ -7334,8 +7419,10 @@ class MappableExprsHandler {
               ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
                 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
                CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
+            llvm::errs() << "  Found declare target variable - updating BP\n";
             RequiresReference = true;
             BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
+            llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           }
         }
       }
@@ -7349,13 +7436,41 @@ class MappableExprsHandler {
         // No need to generate individual map information for the pointer, it
         // can be associated with the combined storage if shared memory mode is
         // active or the base declaration is not global variable.
+        llvm::errs() << "  Pointer dereferencing case - updating BP\n";
+        llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
         if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
-            !VD || VD->hasLocalStorage())
+            !VD || VD->hasLocalStorage() || (AttachInfo.IsValid && VD == AttachInfo.BasePtrDecl)) {
+          llvm::errs() << "  Loading pointer value\n";
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-        else
+          llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+        } else {
+          llvm::errs() << "  Setting FirstPointerInComplexData=true\n";
           FirstPointerInComplexData = true;
+        }
+
+        if (I->getAssociatedExpression()->getType()->isAnyPointerType() && std::next(I) != CE)
+          PossibleBasePtr = I->getAssociatedExpression();
+
+
         ++I;
+        // DEBUG: Print what I now points to after increment
+        if (I != CE) {
+          llvm::errs() << "DEBUG generateInfoForComponentList: After increment, I now points to component with:\n";
+          if (I->getAssociatedDeclaration()) {
+            llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
+          } else {
+            llvm::errs() << "  AssociatedDeclaration: nullptr\n";
+          }
+          if (I->getAssociatedExpression()) {
+            llvm::errs() << "  AssociatedExpression: ";
+            I->getAssociatedExpression()->dump();
+          } else {
+            llvm::errs() << "  AssociatedExpression: nullptr\n";
+          }
+        } else {
+          llvm::errs() << "DEBUG generateInfoForComponentList: After increment, I reached end (CE)\n";
+        }
       }
     }
 
@@ -7400,35 +7515,65 @@ class MappableExprsHandler {
     // CombinedInfo list and instead add an entry to the StructBaseCombinedInfo
     // list only when generating all info for clauses.
     bool IsMappingWholeStruct = true;
+    llvm::errs() << "DEBUG generateInfoForComponentList: Checking IsMappingWholeStruct logic\n";
+    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses << "\n";
+    
     if (!GenerateAllInfoForClauses) {
+      llvm::errs() << "  Setting IsMappingWholeStruct=false (GenerateAllInfoForClauses=false)\n";
       IsMappingWholeStruct = false;
     } else {
+      llvm::errs() << "  Scanning components for MemberExpr...\n";
       for (auto TempI = I; TempI != CE; ++TempI) {
         const MemberExpr *PossibleME =
             dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
+        // Only consider non-arrow member expressions as whole struct mapping
+        // Arrow member expressions (like sp->x) are pointer-to-struct access, not struct mapping
+        // if (PossibleME && !PossibleME->isArrow()) {
         if (PossibleME) {
+          llvm::errs() << "  Found PossibleME (non-arrow) - setting IsMappingWholeStruct=false: "; 
+          PossibleME->dump();
           IsMappingWholeStruct = false;
           break;
         }
       }
     }
+    llvm::errs() << "  Final IsMappingWholeStruct: " << IsMappingWholeStruct << "\n";
 
     for (; I != CE; ++I) {
+      // DEBUG: Print component processing information
+      llvm::errs() << "DEBUG generateInfoForComponentList: Processing component " 
+                   << std::distance(Components.rbegin(), I) << "/" << Components.size() << "\n";
+      if (I->getAssociatedDeclaration()) {
+        llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
+      }
+      if (I->getAssociatedExpression()) {
+        llvm::errs() << "  AssociatedExpression: ";
+        I->getAssociatedExpression()->dump();
+      }
+      
       // If the current component is member of a struct (parent struct) mark it.
       if (!EncounteredME) {
         EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
         // If we encounter a PTR_AND_OBJ entry from now on it should be marked
         // as MEMBER_OF the parent struct.
+        // However, for pointer-to-struct member access (like sp->x), we should NOT
+        // set ShouldBeMemberOf because this is not mapping a struct field but accessing
+        // through a pointer.
+        // if (EncounteredME && !EncounteredME->isArrow()) {
         if (EncounteredME) {
+          llvm::errs() << "DEBUG generateInfoForComponentList: Encountered MemberExpr (non-arrow), setting ShouldBeMemberOf=true\n";
           ShouldBeMemberOf = true;
           // Do not emit as complex pointer if this is actually not array-like
           // expression.
           if (FirstPointerInComplexData) {
+            llvm::errs() << "  FirstPointerInComplexData case - updating BP in MemberExpr\n";
+            llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             QualType Ty = std::prev(I)
                               ->getAssociatedDeclaration()
                               ->getType()
                               .getNonReferenceType();
             BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+            llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             FirstPointerInComplexData = false;
           }
         }
@@ -7447,6 +7592,9 @@ class MappableExprsHandler {
       bool IsFinalArraySection =
           !IsNonContiguous &&
           isFinalArraySectionExpression(I->getAssociatedExpression());
+      
+      // DEBUG: Print array section information
+      llvm::errs() << "DEBUG generateInfoForComponentList: IsFinalArraySection: " << IsFinalArraySection << "\n";
 
       // If we have a declaration for the mapping use that, otherwise use
       // the base declaration of the map clause.
@@ -7455,10 +7603,20 @@ class MappableExprsHandler {
                                      : BaseDecl;
       MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
                                                : MapExpr;
+      
+      // DEBUG: Print mapping declaration and expression
+      llvm::errs() << "DEBUG generateInfoForComponentList: MapDecl: ";
+      if (MapDecl) {
+        llvm::errs() << MapDecl->getNameAsString() << "\n";
+      } else {
+        llvm::errs() << "nullptr\n";
+      }
 
       // Get information on whether the element is a pointer. Have to do a
       // special treatment for array sections given that they are built-in
       // types.
+      llvm::errs() << "DEBUG generateInfoForComponentList: Analyzing expression types\n";
+      
       const auto *OASE =
           dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
       const auto *ASE =
@@ -7467,6 +7625,13 @@ class MappableExprsHandler {
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
       const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
       const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
+      
+      llvm::errs() << "  OASE (ArraySectionExpr): " << (OASE ? "yes" : "no") << "\n";
+      llvm::errs() << "  ASE (ArraySubscriptExpr): " << (ASE ? "yes" : "no") << "\n";
+      llvm::errs() << "  OAShE (OMPArrayShapingExpr): " << (OAShE ? "yes" : "no") << "\n";
+      llvm::errs() << "  UO (UnaryOperator): " << (UO ? "yes" : "no") << "\n";
+      llvm::errs() << "  BO (BinaryOperator): " << (BO ? "yes" : "no") << "\n";
+      
       bool IsPointer =
           OAShE ||
           (OASE && ArraySectionExpr::getBaseOriginalType(OASE)
@@ -7479,12 +7644,27 @@ class MappableExprsHandler {
       bool IsNonDerefPointer = IsPointer &&
                                !(UO && UO->getOpcode() != UO_Deref) && !BO &&
                                !IsNonContiguous;
+      
+      llvm::errs() << "  IsPointer: " << IsPointer << "\n";
+      llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
+      llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
 
-      if (OASE)
+      if (OASE) {
         ++DimSize;
+        llvm::errs() << "  Incremented DimSize to: " << DimSize << "\n";
+      }
 
+      llvm::errs() << "DEBUG generateInfoForComponentList: Checking entry generation condition\n";
+      llvm::errs() << "  Next == CE: " << (Next == CE) << "\n";
+      llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
+      llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
+      llvm::errs() << "  IsFinalArraySection: " << IsFinalArraySection << "\n";
+      if (I->getAssociatedExpression()->getType()->isAnyPointerType() && std::next(I) != CE) {
+        PossibleBasePtr = I->getAssociatedExpression();
+      }
       if (Next == CE || IsMemberReference || IsNonDerefPointer ||
           IsFinalArraySection) {
+        llvm::errs() << "  CONDITION MET: Generating address and size info\n";
         // If this is not the last component, we expect the pointer to be
         // associated with an array expression or member expression.
         assert((Next == CE ||
@@ -7516,30 +7696,49 @@ class MappableExprsHandler {
           }
           return BaseLV;
         };
+        llvm::errs() << "DEBUG generateInfoForComponentList: Emitting addresses\n";
         if (OAShE) {
+          llvm::errs() << "  Handling OMPArrayShapingExpr\n";
           LowestElem = LB =
               Address(CGF.EmitScalarExpr(OAShE->getBase()),
                       CGF.ConvertTypeForMem(
                           OAShE->getBase()->getType()->getPointeeType()),
                       CGF.getContext().getTypeAlignInChars(
                           OAShE->getBase()->getType()));
+          llvm::errs() << "  LowestElem = LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         } else if (IsMemberReference) {
+          llvm::errs() << "  Handling MemberReference\n";
           const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
           LValue BaseLVal = EmitMemberExprBase(CGF, ME);
           LowestElem = CGF.EmitLValueForFieldInitialization(
                               BaseLVal, cast<FieldDecl>(MapDecl))
                            .getAddress();
+          llvm::errs() << "  LowestElem = "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType())
                    .getAddress();
+          llvm::errs() << "  LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         } else {
+          llvm::errs() << "  Handling standard case - EmitOMPSharedLValue\n";
           LowestElem = LB =
               CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
                   .getAddress();
+          llvm::errs() << "  LowestElem = LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         }
 
         // If this component is a pointer inside the base struct then we don't
         // need to create any entry for it - it will be combined with the object
         // it is pointing to into a single PTR_AND_OBJ entry.
+        llvm::errs() << "DEBUG generateInfoForComponentList: Checking IsMemberPointerOrAddr\n";
+        llvm::errs() << "  EncounteredME: " << (EncounteredME ? "yes" : "no") << "\n";
+        llvm::errs() << "  ForDeviceAddr: " << ForDeviceAddr << "\n";
+        llvm::errs() << "  IsPrevMemberReference: " << IsPrevMemberReference << "\n";
+        if (EncounteredME) {
+          llvm::errs() << "  I->getAssociatedExpression() == EncounteredME: " << (I->getAssociatedExpression() == EncounteredME) << "\n";
+        }
+        if (Next != CE) {
+          llvm::errs() << "  Next->getAssociatedExpression()->getType()->isPointerType(): " << Next->getAssociatedExpression()->getType()->isPointerType() << "\n";
+        }
+        
         bool IsMemberPointerOrAddr =
             EncounteredME &&
             (((IsPointer || ForDeviceAddr) &&
@@ -7547,6 +7746,8 @@ class MappableExprsHandler {
              (IsPrevMemberReference && !IsPointer) ||
              (IsMemberReference && Next != CE &&
               !Next->getAssociatedExpression()->getType()->isPointerType()));
+        
+        llvm::errs() << "  IsMemberPointerOrAddr: " << IsMemberPointerOrAddr << "\n";
         if (!OverlappedElements.empty() && Next == CE) {
           // Handle base element with the info for overlapped elements.
           assert(!PartialStruct.Base.isValid() && "The base element is set.");
@@ -7585,18 +7786,23 @@ class MappableExprsHandler {
             for (const OMPClauseMappableExprCommon::MappableComponent &MC :
                  Component) {
               if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
+                llvm::errs() << "DEBUG generateInfoForComponentList: Computing ComponentLB for overlapped element\n";
                 const auto *FD = dyn_cast<FieldDecl>(VD);
                 if (FD && FD->getType()->isLValueReferenceType()) {
+                  llvm::errs() << "  Reference field case\n";
                   const auto *ME =
                       cast<MemberExpr>(MC.getAssociatedExpression());
                   LValue BaseLVal = EmitMemberExprBase(CGF, ME);
                   ComponentLB =
                       CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
                           .getAddress();
+                  llvm::errs() << "  ComponentLB = "; ComponentLB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
                 } else {
+                  llvm::errs() << "  Standard field case\n";
                   ComponentLB =
                       CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
                           .getAddress();
+                  llvm::errs() << "  ComponentLB = "; ComponentLB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
                 }
                 llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF);
                 llvm::Value *LBPtr = LB.emitRawPointer(CGF);
@@ -7618,6 +7824,7 @@ class MappableExprsHandler {
             CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
                                                                       : 1);
             LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
+            llvm::errs() << "  Updated LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           }
           CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
           CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
@@ -7638,6 +7845,9 @@ class MappableExprsHandler {
         }
         llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
         
+        // DEBUG: Print size calculation result
+        llvm::errs() << "DEBUG generateInfoForComponentList: Size calculated for expression\n";
+
         // Lambda to handle BP loading for global pointers
 //         auto LoadGlobalPointerIfNeeded = [&]() {
 //           if (FirstPointerInComplexData) {
@@ -7656,15 +7866,24 @@ class MappableExprsHandler {
 //
 // //        if (IsAttachablePointeeExpr)
 //   //        LoadGlobalPointerIfNeeded();
+
         // Skip adding an entry in the CurInfo of this combined entry if the
         // whole struct is currently being mapped. The struct needs to be added
         // in the first position before any data internal to the struct is being
         // mapped.
         // Skip adding an entry in the CurInfo of this combined entry if the
         // PartialStruct.PreliminaryMapData.BasePointers has been mapped.
+        llvm::errs() << "DEBUG generateInfoForComponentList: Checking entry addition condition\n";
+        llvm::errs() << "  IsPartialMapped: " << IsPartialMapped << "\n";
+        llvm::errs() << "  MapType != OMPC_MAP_unknown: " << (MapType != OMPC_MAP_unknown) << "\n";
+        llvm::errs() << "  (!IsMemberPointerOrAddr && !IsPartialMapped): " << (!IsMemberPointerOrAddr && !IsPartialMapped) << "\n";
+        llvm::errs() << "  (Next == CE && MapType != OMPC_MAP_unknown): " << (Next == CE && MapType != OMPC_MAP_unknown) << "\n";
+
         if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
             (Next == CE && MapType != OMPC_MAP_unknown)) {
+          llvm::errs() << "  WILL ADD ENTRY\n";
           if (!IsMappingWholeStruct) {
+            llvm::errs() << "    Adding to CombinedInfo (not mapping whole struct)\n";
             CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
             CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
             CombinedInfo.DevicePtrDecls.push_back(nullptr);
@@ -7675,6 +7894,7 @@ class MappableExprsHandler {
             CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
                                                                       : 1);
           } else {
+            llvm::errs() << "    Adding to StructBaseCombinedInfo (mapping whole struct)\n";
             StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
             StructBaseCombinedInfo.BasePointers.push_back(
                 BP.emitRawPointer(CGF));
@@ -7700,25 +7920,37 @@ class MappableExprsHandler {
           // this map is the first one that relates with the current capture
           // (there is a set of entries for each capture).
           // Don't use PTR_AND_OBJ when we have array sections/subscripts on pointers
+          llvm::errs() << "DEBUG generateInfoForComponentList: Calculating flags\n";
+          llvm::errs() << "  IsExpressionFirstInfo: " << IsExpressionFirstInfo << "\n";
+          llvm::errs() << "  RequiresReference: " << RequiresReference << "\n";
+          llvm::errs() << "  FirstPointerInComplexData: " << FirstPointerInComplexData << "\n";
+          llvm::errs() << "  IsCaptureFirstInfo: " << IsCaptureFirstInfo << "\n";
+
           bool AddPtrFlag = (!IsExpressionFirstInfo || RequiresReference ||
                              FirstPointerInComplexData || IsMemberReference); //&&
                             // !IsAttachablePointeeExpr;
+          llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
+          
           OpenMPOffloadMappingFlags Flags =
               getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
                              AddPtrFlag, IsCaptureFirstInfo && !RequiresReference,
                              IsNonContiguous);
 
           if (!IsExpressionFirstInfo || IsMemberReference) {
+            llvm::errs() << "  Modifying flags for non-first expression or member reference\n";
             // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
             // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
-            if (IsPointer || (IsMemberReference && Next != CE))
+            if (IsPointer || (IsMemberReference && Next != CE)) {
+              llvm::errs() << "    Resetting TO/FROM/ALWAYS/DELETE/CLOSE flags for pointer\n";
               Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
                          OpenMPOffloadMappingFlags::OMP_MAP_FROM |
                          OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
                          OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
                          OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
+            }
 
             if (ShouldBeMemberOf) {
+              llvm::errs() << "    Adding MEMBER_OF flag and resetting ShouldBeMemberOf\n";
               // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
               // should be later updated with the correct value of MEMBER_OF.
               Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
@@ -7742,28 +7974,40 @@ class MappableExprsHandler {
           unsigned FieldIndex = FD->getFieldIndex();
 
           // Update info about the lowest and highest elements for this struct
+          llvm::errs() << "DEBUG generateInfoForComponentList: Updating PartialStruct for field " << FieldIndex << "\n";
           if (!PartialStruct.Base.isValid()) {
+            llvm::errs() << "  Initializing PartialStruct\n";
             PartialStruct.LowestElem = {FieldIndex, LowestElem};
+            llvm::errs() << "  PartialStruct.LowestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             if (IsFinalArraySection && OASE) {
               Address HB =
                   CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
                       .getAddress();
               PartialStruct.HighestElem = {FieldIndex, HB};
+              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; HB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "} (final array section)\n";
             } else {
               PartialStruct.HighestElem = {FieldIndex, LowestElem};
+              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             }
             PartialStruct.Base = BP;
+            llvm::errs() << "  PartialStruct.Base = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             PartialStruct.LB = BP;
+            llvm::errs() << "  PartialStruct.LB = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           } else if (FieldIndex < PartialStruct.LowestElem.first) {
+            llvm::errs() << "  Updating LowestElem (lower field index)\n";
             PartialStruct.LowestElem = {FieldIndex, LowestElem};
+            llvm::errs() << "  PartialStruct.LowestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
           } else if (FieldIndex > PartialStruct.HighestElem.first) {
+            llvm::errs() << "  Updating HighestElem (higher field index)\n";
             if (IsFinalArraySection && OASE) {
               Address HB =
                   CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
                       .getAddress();
               PartialStruct.HighestElem = {FieldIndex, HB};
+              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; HB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "} (final array section)\n";
             } else {
               PartialStruct.HighestElem = {FieldIndex, LowestElem};
+              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             }
           }
         }
@@ -7773,20 +8017,37 @@ class MappableExprsHandler {
           PartialStruct.IsArraySection = true;
 
         if (Next == CE) {
+          llvm::errs() << "DEBUG generateInfoForComponentList: Reached the end of components\n";
           // Generate ATTACH entry for array sections and subscripts on standalone
           // pointers Info was already collected during the main component loop
           // Check if we should use ATTACH-style mapping for this expression
           bool IsAttachablePointeeExpr = AttachInfo.IsValid && AttachInfo.BasePtrDecl && AttachInfo.BasePtrDecl == BaseDecl;
+          llvm::errs() << "DEBUG generateInfoForComponentList: AttachInfo.PteeExpr: "; if (AttachInfo.PteeExpr) AttachInfo.PteeExpr->dump(); else llvm::errs() << "nullptr\n";
+          llvm::errs() << "DEBUG generateInfoForComponentList: AttachInfo.BasePtrExpr: "; if (AttachInfo.BasePtrExpr) AttachInfo.BasePtrExpr->dump(); else llvm::errs() << "nullptr\n";
+          llvm::errs() << "DEBUG generateInfoForComponentList: PossibleBasePtr: "; if (PossibleBasePtr) PossibleBasePtr->dump(); else llvm::errs() << "nullptr\n";
+          llvm::errs() << "DEBUG generateInfoForComponentList: I: "; if (I->getAssociatedExpression()) I->getAssociatedExpression()->dump(); else llvm::errs() << "nullptr\n";
+
           if (IsAttachablePointeeExpr) {
+            llvm::errs() << "DEBUG generateInfoForComponentList: Computing ATTACH addresses\n";
+
             // Use BasePtrExpr for AttachBaseAddr
+            llvm::errs() << "  Using BasePtrExpr for AttachBaseAddr\n";
             AttachBaseAddr = CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
+            llvm::errs() << "  AttachBaseAddr = "; AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+
             if (OASE) {
+              llvm::errs() << "  ArraySectionExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+              llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             } else if (ASE) {
+              llvm::errs() << "  ArraySubscriptExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
+              llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             } else if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
+               llvm::errs() << "  MemberExpr case for AttachFirstElemAddr\n";
                AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
                llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+            }
           }
         }
 
@@ -7795,21 +8056,43 @@ class MappableExprsHandler {
           break;
 
         // The pointer becomes the base for the next element.
-        if (Next != CE)
+        if (Next != CE) {
+          llvm::errs() << "DEBUG generateInfoForComponentList: Updating BP for next element\n";
+          llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
+          llvm::errs() << "  Current BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           BP = IsMemberReference ? LowestElem : LB;
+          llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << " (using " << (IsMemberReference ? "LowestElem" : "LB") << ")\n";
+          // if (!EncounteredME && AttachInfo.IsValid && AttachInfo.PteeExpr &&
+          //     Next->getAssociatedExpression() == AttachInfo.PteeExpr) {
+          //   llvm::errs() << "  Doing an extra load from BP since next item is attachable: \n";
+          //   // Do an extra load from BP
+          //   BP = CGF.EmitLoadOfPointer(
+          //       BP, I->getAssociatedExpression()->getType()->castAs<PointerType>());
+          // }
+          // llvm::errs() << "  Updated BP with load = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+        }
         if (!IsPartialMapped)
           IsExpressionFirstInfo = false;
         IsCaptureFirstInfo = false;
         FirstPointerInComplexData = false;
         IsPrevMemberReference = IsMemberReference;
+
+        llvm::errs() << "DEBUG generateInfoForComponentList: End of component processing\n";
+        llvm::errs() << "  Updated IsExpressionFirstInfo: " << IsExpressionFirstInfo << "\n";
+        llvm::errs() << "  Updated IsCaptureFirstInfo: " << IsCaptureFirstInfo << "\n";
+        llvm::errs() << "  Updated IsPrevMemberReference: " << IsPrevMemberReference << "\n";
       } else if (FirstPointerInComplexData) {
+        llvm::errs() << "DEBUG generateInfoForComponentList: FirstPointerInComplexData case - final BP update\n";
+        llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         QualType Ty = Components.rbegin()
                           ->getAssociatedDeclaration()
                           ->getType()
                           .getNonReferenceType();
         BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
+        llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         FirstPointerInComplexData = false;
       }
+
     }
     // If ran into the whole component - allocate the space for the whole
     // record.
@@ -7829,18 +8112,30 @@ class MappableExprsHandler {
                   CGF.getContext().getPointerType(CGF.getContext().VoidTy)) /
                   8),
           CGF.Int64Ty, /*isSigned=*/true);
-      CombinedInfo.Sizes.push_back(PointerSize);
-      // ATTACH flag
-      CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
-      StructBaseCombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
-      StructBaseCombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
-      StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr);
-      StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
-      StructBaseCombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
-      StructBaseCombinedInfo.Sizes.push_back(PointerSize);
-      StructBaseCombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
-      StructBaseCombinedInfo.Mappers.push_back(nullptr);
-      StructBaseCombinedInfo.NonContigInfo.Dims.push_back(1);
+
+      if (IsMappingWholeStruct) {
+        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to StructBaseCombinedInfo\n";
+        StructBaseCombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
+        StructBaseCombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
+        StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr);
+        StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+        StructBaseCombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
+        StructBaseCombinedInfo.Sizes.push_back(PointerSize);
+        StructBaseCombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
+        StructBaseCombinedInfo.Mappers.push_back(nullptr);
+        StructBaseCombinedInfo.NonContigInfo.Dims.push_back(1);
+      } else {
+        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to CombinedInfo\n";
+        CombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
+        CombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
+        CombinedInfo.DevicePtrDecls.push_back(nullptr);
+        CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+        CombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
+        CombinedInfo.Sizes.push_back(PointerSize);
+        CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
+        CombinedInfo.Mappers.push_back(nullptr);
+        CombinedInfo.NonContigInfo.Dims.push_back(1);
+      }
     }
 
     if (!IsNonContiguous)
@@ -8018,6 +8313,11 @@ class MappableExprsHandler {
     CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
     CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
     CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
+    
+    // DEBUG: Print exit information
+    llvm::errs() << "DEBUG generateInfoForComponentList: EXIT\n";
+    llvm::errs() << "  CombinedInfo entries added: " << CombinedInfo.BasePointers.size() << "\n";
+    llvm::errs() << "  StructBaseCombinedInfo entries added: " << StructBaseCombinedInfo.BasePointers.size() << "\n";
   }
 
   /// Return the adjusted map modifiers if the declaration a capture refers to
@@ -8126,20 +8426,27 @@ struct AttachInfo {
 
 static AttachInfo findAttachComponent(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
+  // DEBUG: Print entry information
+  llvm::errs() << "DEBUG findAttachComponent: ENTRY\n";
 
   const auto *Begin = Components.begin();
   const auto *End = Components.end();
 
+  llvm::errs() << "DEBUG findAttachComponent: Starting reverse walk\n";
+
   for (const auto *I = Begin; I != End; ++I) {
     // Check if current component is an array section or subscript
     const Expr *CurrentExpr = I->getAssociatedExpression();
+    llvm::errs() << "DEBUG findAttachComponent: Current expr is: "; CurrentExpr->dump();
     if (!CurrentExpr) {
+      llvm::errs() << "DEBUG findAttachComponent: No current expression, continuing\n";
       break;
     }
 
     // Check if the next component (in forward direction) has a pointer type
     const auto *NextI = std::next(I);
     if (NextI == End) {
+      llvm::errs() << "DEBUG findAttachComponent: No next component available\n";
       break;
     }
 
@@ -8147,9 +8454,14 @@ static AttachInfo findAttachComponent(
    QualType NextType;
    if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
      NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
+     llvm::errs() << "DEBUG findAttachComponent: Next component declaration type: ";
+     NextType.dump();
    } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
      NextType = NextExpr->getType().getNonReferenceType().getCanonicalType();
+     llvm::errs() << "DEBUG findAttachComponent: Next component expression type: ";
+     NextType.dump();
    } else {
+     llvm::errs() << "DEBUG findAttachComponent: No next component type info, continuing\n";
      break;
    }
 
@@ -8157,14 +8469,28 @@ static AttachInfo findAttachComponent(
    if (!NextType->isPointerType())
      continue;
 
+   llvm::errs() << "DEBUG findAttachComponent: Found pointer type in next component, stopping here\n";
+
    // Get the pointer expression (NextRI) and use the candidate PteeExpr
    const Expr *BasePtrExpr = NextI->getAssociatedExpression();
    const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
    const Expr *PteeExpr = CurrentExpr;
 
+   llvm::errs() << "DEBUG findAttachComponent: Returning AttachInfo\n";
+   llvm::errs() << "  BasePtrExpr: ";
+   if (BasePtrExpr) BasePtrExpr->dump(); else llvm::errs() << "nullptr\n";
+   llvm::errs() << "  BasePtrDecl: ";
+   if (BasePtrDecl) BasePtrDecl->dump(); else llvm::errs() << "nullptr\n";
+   llvm::errs() << "  PteeExpr: ";
+   if (PteeExpr) PteeExpr->dump(); else llvm::errs() << "nullptr\n";
+   llvm::errs() << "  RbeginExpr: ";
+   const auto *BeginExpr = Begin->getAssociatedExpression();
+   if (BeginExpr) BeginExpr->dump(); else llvm::errs() << "nullptr\n";
    return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
+   llvm::errs() << "DEBUG findAttachComponent: Next component not pointer type, continuing\n";
  }
 
+  llvm::errs() << "DEBUG findAttachComponent: No suitable component found, returning invalid AttachInfo\n";
   return AttachInfo{};
 }
 
@@ -8361,8 +8687,7 @@ static AttachInfo findAttachComponent(
                   // For global pointers with ATTACH-style mapping, also allow
                   // ReturnDevicePointer to ensure consistent behavior between
                   // global and local pointers
-                  (VarD && !VarD->hasLocalStorage() &&
-                   ComponentListUsesAttachStyleMapping(CI->Components))) {
+                  (findAttachComponent(CI->Components).BasePtrDecl == VD)) {
                 CI->ForDeviceAddr = IsDevAddr;
                 CI->ReturnDevicePointer = true;
                 Found = true;
@@ -8537,20 +8862,36 @@ static AttachInfo findAttachComponent(
       // Unify entries in one list making sure the struct mapping precedes the
       // individual fields:
       MapCombinedInfoTy UnionCurInfo;
+      
+      // DEBUG: Print sizes before appending
+      llvm::errs() << "DEBUG CALLER: Before unifying entries:\n";
+      llvm::errs() << "  StructBaseCurInfo.BasePointers.size(): " << StructBaseCurInfo.BasePointers.size() << "\n";
+      llvm::errs() << "  CurInfo.BasePointers.size(): " << CurInfo.BasePointers.size() << "\n";
+      if (VD) {
+        llvm::errs() << "  VD: " << VD->getNameAsString() << "\n";
+      }
+      
       UnionCurInfo.append(StructBaseCurInfo);
       UnionCurInfo.append(CurInfo);
 
+      llvm::errs() << "DEBUG CALLER: After unifying:\n";
+      llvm::errs() << "  UnionCurInfo.BasePointers.size(): " << UnionCurInfo.BasePointers.size() << "\n";
+      llvm::errs() << "  PartialStruct.Base.isValid(): " << PartialStruct.Base.isValid() << "\n";
+
       // If there is an entry in PartialStruct it means we have a struct with
       // individual members mapped. Emit an extra combined entry.
       if (PartialStruct.Base.isValid()) {
         UnionCurInfo.NonContigInfo.Dims.push_back(0);
+        llvm::errs() << "DEBUG CALLER: Emitting combined entry for PartialStruct\n";
         // Emit a combined entry:
         emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
                           /*IsMapThis*/ !VD, OMPBuilder, VD);
       }
 
+      llvm::errs() << "DEBUG CALLER: Before final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
       // We need to append the results of this capture to what we already have.
       CombinedInfo.append(UnionCurInfo);
+      llvm::errs() << "DEBUG CALLER: After final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
     }
     // Append data for use_device_ptr clauses.
     CombinedInfo.append(UseDeviceDataCombinedInfo);

>From c23e01f94eb1d1783edfcc7aba0e023bb44c193d Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 8 Jul 2025 04:40:35 -0700
Subject: [PATCH 17/66] Fix handling of array-sections in findAttachComponent

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index a49efc310ec34..85de14dc3d80e 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8457,9 +8457,25 @@ static AttachInfo findAttachComponent(
      llvm::errs() << "DEBUG findAttachComponent: Next component declaration type: ";
      NextType.dump();
    } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
-     NextType = NextExpr->getType().getNonReferenceType().getCanonicalType();
-     llvm::errs() << "DEBUG findAttachComponent: Next component expression type: ";
-     NextType.dump();
+     // If NextExpr is an array-section, compute the result type using getBaseOriginalType
+     if (const auto *ArraySection = dyn_cast<ArraySectionExpr>(NextExpr)) {
+       // Get the original base type, handling chains of array sections properly
+       QualType BaseType = ArraySectionExpr::getBaseOriginalType(ArraySection->getBase());
+       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) {
+         NextType = ATy->getElementType();
+       } else {
+         NextType = BaseType->getPointeeType();
+       }
+       NextType = NextType.getNonReferenceType().getCanonicalType();
+       llvm::errs() << "DEBUG findAttachComponent: Next component array-section result type (base -> result): ";
+       BaseType.dump();
+       llvm::errs() << " -> ";
+       NextType.dump();
+     } else {
+       NextType = NextExpr->getType().getNonReferenceType().getCanonicalType();
+       llvm::errs() << "DEBUG findAttachComponent: Next component expression type: ";
+       NextType.dump();
+     }
    } else {
      llvm::errs() << "DEBUG findAttachComponent: No next component type info, continuing\n";
      break;

>From 9adf9a8863c5be1c395dab37475d51c9bbd533d0 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 8 Jul 2025 15:18:02 -0700
Subject: [PATCH 18/66] Fix one test.

---
 clang/test/OpenMP/reduction_implicit_map.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp
index 4c2c1a267c6bf..f0c2336a5e4a7 100644
--- a/clang/test/OpenMP/reduction_implicit_map.cpp
+++ b/clang/test/OpenMP/reduction_implicit_map.cpp
@@ -872,9 +872,9 @@ int main()
 // CHECK2-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP8]], i32 0
 // CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP10:%.*]] = mul nuw i32 [[TMP9]], 4
-// CHECK2-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP11]], i32 0
-// CHECK2-NEXT:    [[TMP12:%.*]] = sext i32 [[TMP10]] to i64
+// CHECK2-NEXT:    [[TMP11:%.*]] = sext i32 [[TMP10]] to i64
+// CHECK2-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP12]], i32 0
 // CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes, i32 40, i1 false)
 // CHECK2-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP13]], align 4
@@ -899,7 +899,7 @@ int main()
 // CHECK2-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
 // CHECK2-NEXT:    store ptr [[ARRAYIDX2]], ptr [[TMP23]], align 4
 // CHECK2-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
-// CHECK2-NEXT:    store i64 [[TMP12]], ptr [[TMP24]], align 4
+// CHECK2-NEXT:    store i64 [[TMP11]], ptr [[TMP24]], align 4
 // CHECK2-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 3
 // CHECK2-NEXT:    store ptr null, ptr [[TMP25]], align 4
 // CHECK2-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
@@ -969,9 +969,9 @@ int main()
 // CHECK2-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP59]], i32 0
 // CHECK2-NEXT:    [[TMP60:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP61:%.*]] = mul nuw i32 [[TMP60]], 4
-// CHECK2-NEXT:    [[TMP62:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP62]], i32 0
-// CHECK2-NEXT:    [[TMP63:%.*]] = sext i32 [[TMP61]] to i64
+// CHECK2-NEXT:    [[TMP62:%.*]] = sext i32 [[TMP61]] to i64
+// CHECK2-NEXT:    [[TMP63:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP63]], i32 0
 // CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES14]], ptr align 4 @.offload_sizes.1, i32 40, i1 false)
 // CHECK2-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
 // CHECK2-NEXT:    store i32 [[TMP52]], ptr [[TMP64]], align 4
@@ -996,7 +996,7 @@ int main()
 // CHECK2-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 3
 // CHECK2-NEXT:    store ptr [[ARRAYIDX9]], ptr [[TMP74]], align 4
 // CHECK2-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES14]], i32 0, i32 3
-// CHECK2-NEXT:    store i64 [[TMP63]], ptr [[TMP75]], align 4
+// CHECK2-NEXT:    store i64 [[TMP62]], ptr [[TMP75]], align 4
 // CHECK2-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 3
 // CHECK2-NEXT:    store ptr null, ptr [[TMP76]], align 4
 // CHECK2-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 4

>From 36f6d9be59738019565f2c00a00de90880d1777a Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 9 Jul 2025 14:34:34 -0700
Subject: [PATCH 19/66] Fix star case. Update some tests.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |   6 +
 clang/test/OpenMP/target_data_codegen.cpp     |  16 +-
 .../target_data_use_device_addr_codegen.cpp   |  20 +-
 .../target_data_use_device_ptr_codegen.cpp    |   1 -
 ...arget_map_both_pointer_pointee_codegen.cpp | 289 ++++++++++-------
 ...ap_both_pointer_pointee_codegen_global.cpp | 294 +++++++++++-------
 .../OpenMP/target_map_ptr_and_star_global.cpp | 125 +++++---
 .../OpenMP/target_map_ptr_and_star_local.cpp  | 116 ++++---
 8 files changed, 535 insertions(+), 332 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 85de14dc3d80e..5c054f5e31c34 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8047,6 +8047,12 @@ class MappableExprsHandler {
                llvm::errs() << "  MemberExpr case for AttachFirstElemAddr\n";
                AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
                llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+            } else if (auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression())) {
+              if (UO->getOpcode() == UO_Deref) {
+                llvm::errs() << "  UnaryOperator (dereference) case for AttachFirstElemAddr\n";
+                AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
+                llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+              }
             }
           }
         }
diff --git a/clang/test/OpenMP/target_data_codegen.cpp b/clang/test/OpenMP/target_data_codegen.cpp
index 926aa593f2ba1..7c272c24b28d5 100644
--- a/clang/test/OpenMP/target_data_codegen.cpp
+++ b/clang/test/OpenMP/target_data_codegen.cpp
@@ -625,8 +625,8 @@ void test_present_modifier(int arg) {
 
   // Make sure the struct picks up present even if another element of the struct
   // doesn't have present.
-  // CK8: private unnamed_addr constant [11 x i64] [i64 0, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 4, i64 4, i64 0, i64 4, i64 {{4|8}}, i64 {{4|8}}, i64 4]
-  // CK8: private unnamed_addr constant [11 x i64]
+  // CK8: private unnamed_addr constant [13 x i64] [i64 0, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 4, i64 {{4|8}}, i64 4, i64 0, i64 4, i64 {{4|8}}, i64 {{4|8}}, i64 {{4|8}}, i64 4]
+  // CK8: private unnamed_addr constant [13 x i64]
 
 // ps1
 //
@@ -635,9 +635,11 @@ void test_present_modifier(int arg) {
 // PRESENT=0x1000 | PTR_AND_OBJ=0x10 = 0x1010
 // PRESENT=0x1000 | PTR_AND_OBJ=0x10 | FROM=0x2 | TO=0x1 = 0x1013
 // MEMBER_OF_1=0x1000000000000 | FROM=0x2 | TO=0x1 = 0x1000000000003
+// ATTACH=0x4000
 //
 // CK8-SAME: {{^}} [i64 [[#0x1000]], i64 [[#0x1000000001010]],
 // CK8-SAME: {{^}} i64 [[#0x1010]], i64 [[#0x1013]], i64 [[#0x1000000000003]],
+// CK8-SAME: {{^}} i64 [[#0x4000]],
 
 // arg
 //
@@ -648,13 +650,15 @@ void test_present_modifier(int arg) {
 // ps2
 //
 // PRESENT=0x1000 = 0x1000
-// MEMBER_OF_7=0x7000000000000 | PRESENT=0x1000 | FROM=0x2 | TO=0x1 = 0x7000000001003
-// MEMBER_OF_7=0x7000000000000 | PTR_AND_OBJ=0x10 = 0x7000000000010
+// MEMBER_OF_8=0x8000000000000 | PRESENT=0x1000 | FROM=0x2 | TO=0x1 = 0x8000000001003
+// ATTACH=0x4000
+// MEMBER_OF_8=0x8000000000000 | PTR_AND_OBJ=0x10 = 0x8000000000010
 // PTR_AND_OBJ=0x10 = 0x10
 // PTR_AND_OBJ=0x10 | FROM=0x2 | TO=0x1 = 0x13
 //
-// CK8-SAME: {{^}} i64 [[#0x1000]], i64 [[#0x7000000001003]],
-// CK8-SAME: {{^}} i64 [[#0x7000000000010]], i64 [[#0x10]], i64 [[#0x13]]]
+// CK8-SAME: {{^}} i64 [[#0x1000]], i64 [[#0x8000000001003]],
+// CK8-SAME: {{^}} i64 [[#0x4000]],
+// CK8-SAME: {{^}} i64 [[#0x8000000000010]], i64 [[#0x10]], i64 [[#0x13]]]
 #pragma omp target data map(tofrom         \
                             : ps1->s)      \
     map(present, tofrom                    \
diff --git a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
index 48a4fa120468a..aaa680c795318 100644
--- a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
@@ -11,9 +11,9 @@
 #ifndef HEADER
 #define HEADER
 
-// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 4, i64 16, i64 4, i64 8, i64 8, i64 4, i64 0, i64 4]
+// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 4, i64 16, i64 8, i64 4, i64 8, i64 4, i64 0, i64 4]
 // 64 = 0x40 = OMP_MAP_RETURN_PARAM
-// CHECK-DAG: [[MAPTYPES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 67, i64 67, i64 3, i64 16384, i64 16384, i64 67, i64 67, i64 67]
+// CHECK-DAG: [[MAPTYPES1:@.+]] = private unnamed_addr constant [8 x i64] [i64 67, i64 67, i64 16384, i64 3, i64 16384, i64 67, i64 67, i64 67]
 // CHECK-DAG: [[SIZES2:@.+]] = private unnamed_addr constant [6 x i64] [i64 0, i64 4, i64 16, i64 4, i64 4, i64 0]
 // 0 = OMP_MAP_NONE
 // 281474976710720 = 0x1000000000040 = OMP_MAP_MEMBER_OF | OMP_MAP_RETURN_PARAM
@@ -46,10 +46,10 @@ int main() {
 // CHECK-LABEL: @main()
 //
 //  &a, &a, TO | FROM | RETURN_PARAM
-//  &p[0], &p[3], TO | FROM | RETURN_PARAM
-//  &p[0], &p[0], TO | FROM | RETURN_PARAM
-//  &p, &p[3], ATTACH
-//  &p, &p[0], ATTACH
+//  &ptr[0], &ptr[3], TO | FROM | RETURN_PARAM
+//  &ptr, &ptr[3], ATTACH
+//  &ptr[0], &ptr[0], TO | FROM | RETURN_PARAM
+//  &ptr, &ptr[0], ATTACH
 //  &ref_ptee(ref), &ref_ptee(ref), TO | FROM | RETURN_PARAM
 //  &arr, &arr[0], TO | FROM | ATTACH | RETURN_PARAM
 //
@@ -87,13 +87,13 @@ int main() {
 // CHECK: [[PTR1:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 1
 // CHECK: store ptr [[ARR_IDX]], ptr [[PTR1]],
 // CHECK: [[BPTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 2
-// CHECK: store ptr [[P3]], ptr [[BPTR2]],
+// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR2]],
 // CHECK: [[PTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 2
-// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR2]],
+// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR2]],
 // CHECK: [[BPTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 3
-// CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR3]],
+// CHECK: store ptr [[P3]], ptr [[BPTR3]],
 // CHECK: [[PTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 3
-// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR3]],
+// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR3]],
 // CHECK: [[BPTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 4
 // CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR4]], align
 // CHECK: [[PTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 4
diff --git a/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
index 906313a048deb..91bf97a6a5163 100644
--- a/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_ptr_codegen.cpp
@@ -45,7 +45,6 @@ void foo(float *&lr, T *&tr) {
   // &g, &g[/*lb=*/0], sizeof(g), ATTACH
   //
   // CK1:     [[T:%.+]] = load ptr, ptr [[DECL:@g]],
-  // CK1:     [[T:%.+]] = load ptr, ptr [[DECL]],
   // CK1:     [[BP:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
   // CK1:     store ptr [[T]], ptr [[BP]],
   // CK1:     call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
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 8a167a19ddbc9..f177b4bd2ae36 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -17,6 +17,7 @@ void f1() {
 void f2() {
   int *ptr;
   // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr[2])
     ptr[1] = 6;
 }
@@ -24,7 +25,8 @@ void f2() {
 void f3() {
   int *ptr;
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[0], 2 * sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[0], 2 * sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, ptr[0:2])
     ptr[1] = 7;
 }
@@ -32,7 +34,8 @@ void f3() {
 void f4() {
   int *ptr;
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, ptr[2])
     ptr[2] = 8;
 }
@@ -40,23 +43,26 @@ void f4() {
 void f5() {
   int *ptr;
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr[2], ptr)
     ptr[2] = 9;
 }
 
 void f6() {
   int *ptr;
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
-  // TODO: PARAM should not be needed here.
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target data map(ptr, ptr[2])
     ptr[2] = 10;
 }
 
 void f7() {
   int *ptr;
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
-  // TODO: PARAM should not be needed here.
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 11;
 }
@@ -64,18 +70,18 @@ void f7() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 8, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.9 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x3]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -109,18 +115,26 @@ void f7() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 2
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -134,25 +148,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 0
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l30
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -167,25 +190,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l39
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -200,25 +232,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l44
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l48
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -233,22 +274,37 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
-// CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP14:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX2]], align 4
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
@@ -256,21 +312,36 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
-// CHECK:    [[TMP6:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP0]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP14:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
+// CHECK:    store i32 11, ptr [[ARRAYIDX2]], align 4
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
index e39d602dca316..e346f4dc38f54 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -16,42 +16,48 @@ void f1() {
 }
 
 void f2() {
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr[2])
     ptr[1] = 6;
 }
 
 void f3() {
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[0], 2 * sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[0], 2 * sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, ptr[0:2])
     ptr[1] = 7;
 }
 
 void f4() {
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, ptr[2])
     ptr[2] = 8;
 }
 
 void f5() {
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target map(ptr[2], ptr)
     ptr[2] = 9;
 }
 
 void f6() {
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
-  // TODO: PARAM should not be needed here.
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
   #pragma omp target data map(ptr, ptr[2])
     ptr[2] = 10;
 }
 
 void f7() {
-  // &ptr, &ptr[2], sizeof(ptr[2]), TO | FROM | PARAM | PTR_AND_OBJ
-  // TODO: PARAM should not be needed here.
+  // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
+  // &ptr, &ptr[2], sizeof(ptr), ATTACH
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 11;
 }
@@ -59,18 +65,18 @@ void f7() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 8]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.9 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.11 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 8, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.9 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.10 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x3]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -102,19 +108,28 @@ void f7() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 2
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -128,25 +143,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 0
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l27
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l29
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -161,25 +185,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l34
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l37
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -194,25 +227,34 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l41
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l45
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -227,22 +269,37 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
-// CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP14:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX2]], align 4
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
@@ -250,21 +307,36 @@ void f7() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP4]], ptr [[TMP5]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
-// CHECK:    [[TMP6:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i64 2
-// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP7]], ptr [[TMP8]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP0]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP14:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
+// CHECK:    store i32 11, ptr [[ARRAYIDX2]], align 4
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
index 40d3cd24ac08f..e09f1a6f42fa9 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
@@ -15,21 +15,24 @@ void f1() {
 }
 
 void f2() {
-  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PARAM | PTR_AND_OBJ
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM | PARAM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(*ptr)
     ptr[1] = 6;
 }
 
 void f3() {
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, *ptr)
     ptr[1] = 6;
 }
 
 void f4() {
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
-  // &ptr, &ptr[0], sizeof(ptr[0]), TO | FROM | PTR_AND_OBJ
+  // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(*ptr, ptr)
     ptr[2] = 8;
 }
@@ -38,12 +41,12 @@ void f4() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x33]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x13]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -75,18 +78,26 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP3]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l19
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -100,24 +111,32 @@ void f4() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l26
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -132,24 +151,32 @@ void f4() {
 // CHECK-SAME: () #[[ATTR0]] {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP1]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l33
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
index 2eff1727e0e46..bd8bd4628ef35 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
@@ -17,6 +17,7 @@ void f1() {
 void f2() {
   int *ptr;
   // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM | PARAM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(*ptr)
     ptr[1] = 6;
 }
@@ -25,6 +26,7 @@ void f3() {
   int *ptr;
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(ptr, *ptr)
     ptr[1] = 6;
 }
@@ -33,6 +35,7 @@ void f4() {
   int *ptr;
   // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   // &ptr[0], &ptr[0], sizeof(ptr[0]), TO | FROM
+  // &ptr, &ptr[0], sizeof(ptr), ATTACH
   #pragma omp target map(*ptr, ptr)
     ptr[2] = 8;
 }
@@ -41,12 +44,12 @@ void f4() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x23]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x3]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -79,18 +82,25 @@ void f4() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP3]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
 // CHECK-SAME: (ptr noundef [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -105,24 +115,31 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l30
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8
@@ -138,24 +155,31 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
+// CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l39
 // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(8) [[PTR:%.*]]) #[[ATTR1]] {
 // CHECK:  entry:
 // CHECK:    store ptr [[PTR]], ptr [[PTR_ADDR:%.*]], align 8

>From 8349a496c67b4268abaf4db6f6538f552139f413 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 9 Jul 2025 14:56:29 -0700
Subject: [PATCH 20/66] Refactor AddAttachEntry

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 63 ++++++++++++++-------------
 1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 5c054f5e31c34..bf45b50aad166 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7118,6 +7118,37 @@ class MappableExprsHandler {
     return result;
   }
 
+  /// Utility function to add an ATTACH entry to the CombinedInfo structure.
+  /// Generates an ATTACH entry: &pointer, &pointer[idx], sizeof(pointer), ATTACH
+  void addAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
+                      Address AttachBaseAddr, Address AttachFirstElemAddr,
+                      const ValueDecl *BaseDecl, const Expr *MapExpr) const {
+    llvm::errs() << "DEBUG addAttachEntry: Adding ATTACH entry\n";
+    llvm::errs() << "  AttachBaseAddr = "; AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+    llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+    
+    // Size is the size of the pointer itself - use pointer size, not BaseDecl size
+    llvm::Value *PointerSize = CGF.Builder.CreateIntCast(
+        llvm::ConstantInt::get(
+            CGF.CGM.SizeTy,
+            CGF.getContext().getTypeSize(
+                CGF.getContext().getPointerType(CGF.getContext().VoidTy)) /
+                8),
+        CGF.Int64Ty, /*isSigned=*/true);
+
+    CombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
+    CombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
+    CombinedInfo.DevicePtrDecls.push_back(nullptr);
+    CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+    CombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
+    CombinedInfo.Sizes.push_back(PointerSize);
+    CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
+    CombinedInfo.Mappers.push_back(nullptr);
+    CombinedInfo.NonContigInfo.Dims.push_back(1);
+    
+    llvm::errs() << "DEBUG addAttachEntry: ATTACH entry added successfully\n";
+  }
+
   /// Generate the base pointers, section pointers, sizes, map type bits, and
   /// user-defined mappers (all included in \a CombinedInfo) for the provided
   /// map type, map or motion modifiers, and expression components.
@@ -8107,40 +8138,12 @@ class MappableExprsHandler {
 
     // Don't do this yet for member-exprs, like map(s.p[0:10])
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
-      // Generate ATTACH entry: &pointer, &pointer[idx], sizeof(pointer), ATTACH
-      // Use StructBaseCombinedInfo if mapping whole struct, otherwise use CombinedInfo
-      
-      // Size is the size of the pointer itself - use pointer size, not BaseDecl size
-      llvm::Value *PointerSize = CGF.Builder.CreateIntCast(
-          llvm::ConstantInt::get(
-              CGF.CGM.SizeTy,
-              CGF.getContext().getTypeSize(
-                  CGF.getContext().getPointerType(CGF.getContext().VoidTy)) /
-                  8),
-          CGF.Int64Ty, /*isSigned=*/true);
-
       if (IsMappingWholeStruct) {
         llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to StructBaseCombinedInfo\n";
-        StructBaseCombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
-        StructBaseCombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
-        StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr);
-        StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
-        StructBaseCombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
-        StructBaseCombinedInfo.Sizes.push_back(PointerSize);
-        StructBaseCombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
-        StructBaseCombinedInfo.Mappers.push_back(nullptr);
-        StructBaseCombinedInfo.NonContigInfo.Dims.push_back(1);
+        addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr, AttachFirstElemAddr, BaseDecl, MapExpr);
       } else {
         llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to CombinedInfo\n";
-        CombinedInfo.Exprs.emplace_back(BaseDecl, MapExpr);
-        CombinedInfo.BasePointers.push_back(AttachBaseAddr.emitRawPointer(CGF));
-        CombinedInfo.DevicePtrDecls.push_back(nullptr);
-        CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
-        CombinedInfo.Pointers.push_back(AttachFirstElemAddr.emitRawPointer(CGF));
-        CombinedInfo.Sizes.push_back(PointerSize);
-        CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
-        CombinedInfo.Mappers.push_back(nullptr);
-        CombinedInfo.NonContigInfo.Dims.push_back(1);
+        addAttachEntry(CGF, CombinedInfo, AttachBaseAddr, AttachFirstElemAddr, BaseDecl, MapExpr);
       }
     }
 

>From eaf332f3e2b4b6b415779d286a54478a5f6cc01b Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 9 Jul 2025 15:52:49 -0700
Subject: [PATCH 21/66] Delay addition of attach when we populate
 PartialStruct.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 56 ++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 13 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index bf45b50aad166..3d9acf513935a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6840,6 +6840,11 @@ class MappableExprsHandler {
     Address LB = Address::invalid();
     bool IsArraySection = false;
     bool HasCompleteRecord = false;
+    // ATTACH information for delayed processing
+    Address AttachBaseAddr = Address::invalid();
+    Address AttachFirstElemAddr = Address::invalid();
+    const ValueDecl *AttachBaseDecl = nullptr;
+    const Expr *AttachMapExpr = nullptr;
   };
 
 private:
@@ -8136,9 +8141,16 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
-    // Don't do this yet for member-exprs, like map(s.p[0:10])
+    // Handle ATTACH entries: delay if PartialStruct is being populated, otherwise add immediately
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
-      if (IsMappingWholeStruct) {
+      if (PartialStruct.Base.isValid()) {
+        // We're populating PartialStruct, delay ATTACH entry addition until after emitCombinedEntry
+        llvm::errs() << "DEBUG generateInfoForComponentList: Saving ATTACH info for delayed processing\n";
+        PartialStruct.AttachBaseAddr = AttachBaseAddr;
+        PartialStruct.AttachFirstElemAddr = AttachFirstElemAddr;
+        PartialStruct.AttachBaseDecl = BaseDecl;
+        PartialStruct.AttachMapExpr = MapExpr;
+      } else if (IsMappingWholeStruct) {
         llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to StructBaseCombinedInfo\n";
         addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr, AttachFirstElemAddr, BaseDecl, MapExpr);
       } else {
@@ -8905,18 +8917,21 @@ static AttachInfo findAttachComponent(
 
       // If there is an entry in PartialStruct it means we have a struct with
       // individual members mapped. Emit an extra combined entry.
+      MapCombinedInfoTy AttachCombinedInfo;
       if (PartialStruct.Base.isValid()) {
         UnionCurInfo.NonContigInfo.Dims.push_back(0);
         llvm::errs() << "DEBUG CALLER: Emitting combined entry for PartialStruct\n";
         // Emit a combined entry:
-        emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
-                          /*IsMapThis*/ !VD, OMPBuilder, VD);
+        emitCombinedEntry(CombinedInfo, AttachCombinedInfo, UnionCurInfo.Types, PartialStruct,
+                          /*IsMapThis*/ !VD, OMPBuilder, VD, 0, true);
       }
 
       llvm::errs() << "DEBUG CALLER: Before final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
       // We need to append the results of this capture to what we already have.
       CombinedInfo.append(UnionCurInfo);
       llvm::errs() << "DEBUG CALLER: After final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
+      // Append AttachCombinedInfo after UnionCurInfo
+      CombinedInfo.append(AttachCombinedInfo);
     }
     // Append data for use_device_ptr clauses.
     CombinedInfo.append(UseDeviceDataCombinedInfo);
@@ -8975,18 +8990,27 @@ static AttachInfo findAttachComponent(
   /// Generate code for the combined entry if we have a partially mapped struct
   /// and take care of the mapping flags of the arguments corresponding to
   /// individual struct members.
+  /// AttachCombinedInfo will be populated with ATTACH entries if needed.
   void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
+                         MapCombinedInfoTy &AttachCombinedInfo,
                          MapFlagsArrayTy &CurTypes,
                          const StructRangeInfoTy &PartialStruct, bool IsMapThis,
                          llvm::OpenMPIRBuilder &OMPBuilder,
-                         const ValueDecl *VD = nullptr,
-                         unsigned OffsetForMemberOfFlag = 0,
-                         bool NotTargetParams = true) const {
+                         const ValueDecl *VD,
+                         unsigned OffsetForMemberOfFlag,
+                         bool NotTargetParams) const {
     if (CurTypes.size() == 1 &&
         ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
          OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
-        !PartialStruct.IsArraySection)
+        !PartialStruct.IsArraySection) {
+      // Process delayed ATTACH entries if available - no combined entry case
+      if (PartialStruct.AttachBaseAddr.isValid() && PartialStruct.AttachFirstElemAddr.isValid()) {
+        llvm::errs() << "DEBUG emitCombinedEntry: Early return path - adding ATTACH with saved pointee\n";
+        addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr, PartialStruct.AttachFirstElemAddr,
+                       PartialStruct.AttachBaseDecl, PartialStruct.AttachMapExpr);
+      }
       return;
+    }
     Address LBAddr = PartialStruct.LowestElem.second;
     Address HBAddr = PartialStruct.HighestElem.second;
     if (PartialStruct.HasCompleteRecord) {
@@ -9072,6 +9096,13 @@ static AttachInfo findAttachComponent(
         OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
+    
+    // Process delayed ATTACH entries if available - combined entry case  
+    if (PartialStruct.AttachBaseAddr.isValid() && PartialStruct.AttachFirstElemAddr.isValid()) {
+      llvm::errs() << "DEBUG emitCombinedEntry: Combined entry path - using PartialStruct\n";
+      addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr, PartialStruct.Base,
+                     PartialStruct.AttachBaseDecl, PartialStruct.AttachMapExpr);
+    }
   }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and
@@ -9318,20 +9349,19 @@ static AttachInfo findAttachComponent(
           // If there is an entry in PartialStruct it means we have a
           // struct with individual members mapped. Emit an extra combined
           // entry.
+          MapCombinedInfoTy AttachCombinedInfo;
           if (PartialStruct.Base.isValid()) {
             CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
             emitCombinedEntry(
-                CurCaptureVarInfo, CurInfoForComponentLists.Types,
+                CurCaptureVarInfo, AttachCombinedInfo, CurInfoForComponentLists.Types,
                 PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
                 OffsetForMemberOfFlag,
                 /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
           }
 
-          // Return if we didn't add any entries.
-          if (CurInfoForComponentLists.BasePointers.empty())
-            return;
-
+          // Append in order: combined-entry -> curinfo (individual fields) -> attachinfo
           CurCaptureVarInfo.append(CurInfoForComponentLists);
+          CurCaptureVarInfo.append(AttachCombinedInfo);
         };
 
     // Next, we break-down the lists of components into lists that should be

>From da55bf866c36856ad909985614256f7050b9b597 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 15 Jul 2025 22:17:00 -0700
Subject: [PATCH 22/66] Update some more tests.

---
 ...target_map_structptr_and_member_global.cpp | 222 ++++++++++--------
 .../target_map_structptr_and_member_local.cpp | 222 ++++++++++--------
 offload/test/mapping/map_ptr_and_star_local.c |  12 +-
 .../mapping/map_structptr_and_member_global.c |  11 +-
 .../mapping/map_structptr_and_member_local.c  |  12 +-
 5 files changed, 272 insertions(+), 207 deletions(-)

diff --git a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
index dc2df3849f299..7a64310266024 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
@@ -23,6 +23,7 @@ void f1() {
 
 void f2() {
   // &ps[0], &ps->y, sizeof(ps->y), TO | PARAM
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y)
     ps->y = 6;
 }
@@ -30,6 +31,7 @@ void f2() {
 void f3() {
   // &ps, &ps, sizeof(ps), TO | PARAM
   // &ps[0], &ps->y, sizeof(ps->y), TO
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps, ps->y)
     ps->y = 7;
 }
@@ -37,6 +39,7 @@ void f3() {
 void f4() {
   // &ps, &ps, sizeof(ps), TO | PARAM
   // &ps[0], &ps->y, sizeof(ps->y), TO
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps)
     ps->y = 8;
 }
@@ -46,6 +49,7 @@ void f5() {
   // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
   // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
   // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
+  // &ps, &ps[0], sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -54,14 +58,14 @@ void f5() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 8, i64 0, i64 4, i64 2]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x21]], i64 [[#0x1]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x21]], i64 [[#0x1]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [5 x i64] [i64 8, i64 0, i64 4, i64 2, i64 8]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [5 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define dso_local void @_Z2f1v(
 // CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
@@ -95,18 +99,26 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 1
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ps, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l26(
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l27(
 // CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -122,24 +134,32 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ps, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l33(
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l35(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -156,24 +176,32 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ps, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l40(
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l43(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -191,47 +219,57 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
-// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
-// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
-// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
-// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l49(
+// CHECK:    [[TMP4:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = load ptr, ptr @ps, align 8
+// CHECK:    [[X2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP5]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64
+// CHECK:    [[TMP8:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP9:%.*]] = sub i64 [[TMP7]], [[TMP8]]
+// CHECK:    [[TMP10:%.*]] = sdiv exact i64 [[TMP9]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 40, i1 false)
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP10]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP3]], ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP23]], align 8
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK:    store ptr @ps, ptr [[TMP24]], align 8
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK:    store ptr [[TMP0]], ptr [[TMP25]], align 8
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK:    store ptr null, ptr [[TMP26]], align 8
+// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP29:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l53(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
index 44a982680bb8b..dfec813abc6a8 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
@@ -23,6 +23,7 @@ void f1() {
 void f2() {
   S s, *ps;
   // &ps[0], &ps->y, sizeof(ps->y), TO | PARAM
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y)
     ps->y = 6;
 }
@@ -31,6 +32,7 @@ void f3() {
   S s, *ps;
   // &ps, &ps, sizeof(ps), TO | PARAM
   // &ps[0], &ps->y, sizeof(ps->y), TO
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps, ps->y)
     ps->y = 7;
 }
@@ -39,6 +41,7 @@ void f4() {
   S s, *ps;
   // &ps, &ps, sizeof(ps), TO | PARAM
   // &ps[0], &ps->y, sizeof(ps->y), TO
+  // &ps, &ps->y, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps)
     ps->y = 8;
 }
@@ -49,6 +52,7 @@ void f5() {
   // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
   // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
   // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
+  // &ps, &ps[0], sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -57,14 +61,14 @@ void f5() {
 //.
 // CHECK: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 8]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x21]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [2 x i64] [i64 8, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x1]]]
-// CHECK: @.offload_sizes.7 = private unnamed_addr constant [4 x i64] [i64 8, i64 0, i64 4, i64 2]
-// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [4 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x21]], i64 [[#0x1]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x21]], i64 [[#0x1]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.7 = private unnamed_addr constant [5 x i64] [i64 8, i64 0, i64 4, i64 2, i64 8]
+// CHECK: @.offload_maptypes.8 = private unnamed_addr constant [5 x i64] [i64 [[#0x21]], i64 [[#0x0]], i64 [[#0x2000000000001]], i64 [[#0x2000000000001]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define dso_local void @_Z2f1v(
 // CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
@@ -98,18 +102,26 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 1
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PS]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y1]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l26(
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l27(
 // CHECK-SAME: ptr noundef [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -125,24 +137,32 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l34(
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l36(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -159,24 +179,32 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l42(
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l45(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
@@ -194,47 +222,57 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
-// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
-// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
-// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
-// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
-// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 32, i1 false)
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
-//
-//
-// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l52(
+// CHECK:    [[TMP4:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
+// CHECK:    [[TMP5:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK:    [[X2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP5]], i32 0, i32 0
+// CHECK:    [[TMP6:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64
+// CHECK:    [[TMP8:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP9:%.*]] = sub i64 [[TMP7]], [[TMP8]]
+// CHECK:    [[TMP10:%.*]] = sdiv exact i64 [[TMP9]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 40, i1 false)
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP10]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP3]], ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP23]], align 8
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK:    store ptr [[PS]], ptr [[TMP24]], align 8
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK:    store ptr [[TMP0]], ptr [[TMP25]], align 8
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK:    store ptr null, ptr [[TMP26]], align 8
+// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP29:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l56(
 // CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[PS:%.*]]) #[[ATTR1]] {
 // CHECK:  [[ENTRY:.*:]]
 // CHECK:    store ptr [[PS]], ptr [[PS_ADDR:%.*]], align 8
diff --git a/offload/test/mapping/map_ptr_and_star_local.c b/offload/test/mapping/map_ptr_and_star_local.c
index 0d2d689ec9912..ca7c4d0f98f7e 100644
--- a/offload/test/mapping/map_ptr_and_star_local.c
+++ b/offload/test/mapping/map_ptr_and_star_local.c
@@ -46,8 +46,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[0],
            x0_hostaddr == &p[0]);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 1 0 1
+    // CHECK:    111 1 1 0
     p++;
   }
 
@@ -56,8 +55,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-1],
            x0_hostaddr == &p[-1]);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    222 1 0 1
+    // CHECK:    222 1 1 0
     p++;
   }
 
@@ -66,8 +64,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", p[0], p_mappedptr == &p, x0_mappedptr == &p[-2],
            x0_hostaddr == &p[-2]);
-    // EXPECTED: 333 1 1 0
-    // CHECK:    333 1 0 1
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:p) should not bring back p, because p is an
@@ -75,8 +72,7 @@ void f1() {
   // location, &x[0], on host.
 #pragma omp target exit data map(always, from : p)
   printf("%d %d\n", p[0], p == &x[0]);
-  // EXPECTED:   111 1
-  // CHECK:      333 0
+  // CHECK:      111 1
 
 #pragma omp target exit data map(delete : p[0 : 5], p)
 }
diff --git a/offload/test/mapping/map_structptr_and_member_global.c b/offload/test/mapping/map_structptr_and_member_global.c
index f2fae005b79ab..9789a7f2f4882 100644
--- a/offload/test/mapping/map_structptr_and_member_global.c
+++ b/offload/test/mapping/map_structptr_and_member_global.c
@@ -51,8 +51,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
            s0_hostaddr == &ps->x);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 1 0 1
+    // CHECK:    111 1 1 0
     ps++;
   }
 
@@ -61,8 +60,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    222 1 0 1
+    // CHECK:    222 1 1 0
     ps++;
   }
 
@@ -72,7 +70,7 @@ void f1() {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
     // EXPECTED: 333 1 1 0
-    // CHECK:    333 1 0 1
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:ps) should not bring back ps, because ps is an
@@ -80,8 +78,7 @@ void f1() {
   // location, &s[0], on host.
 #pragma omp target exit data map(always, from : ps)
   printf("%d %d\n", ps->x, ps == &s[0]);
-  // EXPECTED:   111 1
-  // CHECK:      333 0
+  // CHECK:      111 1
 
 #pragma omp target exit data map(delete : ps, s)
 }
diff --git a/offload/test/mapping/map_structptr_and_member_local.c b/offload/test/mapping/map_structptr_and_member_local.c
index a9db3eefbc54f..850e04db81e62 100644
--- a/offload/test/mapping/map_structptr_and_member_local.c
+++ b/offload/test/mapping/map_structptr_and_member_local.c
@@ -50,8 +50,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps, s0_mappedptr == &ps->x,
            s0_hostaddr == &ps->x);
-    // EXPECTED: 111 1 1 0
-    // CHECK:    111 1 0 1
+    // CHECK:    111 1 1 0
     ps++;
   }
 
@@ -60,8 +59,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-1].x, s0_hostaddr == &ps[-1].x);
-    // EXPECTED: 222 1 1 0
-    // CHECK:    222 1 0 1
+    // CHECK:    222 1 1 0
     ps++;
   }
 
@@ -70,8 +68,7 @@ void f1() {
   {
     printf("%d %d %d %d\n", ps->x, ps_mappedptr == &ps,
            s0_mappedptr == &ps[-2].x, s0_hostaddr == &ps[-2].x);
-    // EXPECTED: 333 1 1 0
-    // CHECK:    333 1 0 1
+    // CHECK:    333 1 1 0
   }
 
   // The following map(from:ps) should not bring back ps, because ps is an
@@ -79,8 +76,7 @@ void f1() {
   // location, &s[0], on host.
 #pragma omp target exit data map(always, from : ps)
   printf("%d %d\n", ps->x, ps == &s[0]);
-  // EXPECTED:   111 1
-  // CHECK:      333 0
+  // CHECK:      111 1
 
 #pragma omp target exit data map(delete : ps, s)
 }

>From 5d72174220263f549c0d301ad9c4445a91bbde4a Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 00:53:09 -0700
Subject: [PATCH 23/66] [WIP][Offload] Introduce ATTACH map-type support for
 pointer attachment.

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!
---
 offload/include/OpenMP/Mapping.h   |  40 ++-
 offload/include/omptarget.h        |   3 +
 offload/libomptarget/interface.cpp |  22 +-
 offload/libomptarget/omptarget.cpp | 409 ++++++++++++++++++++++++++---
 4 files changed, 438 insertions(+), 36 deletions(-)

diff --git a/offload/include/OpenMP/Mapping.h b/offload/include/OpenMP/Mapping.h
index b9f5c16582931..93c1e56905ae4 100644
--- a/offload/include/OpenMP/Mapping.h
+++ b/offload/include/OpenMP/Mapping.h
@@ -417,12 +417,42 @@ struct MapperComponentsTy {
 typedef void (*MapperFuncPtrTy)(void *, void *, void *, int64_t, int64_t,
                                 void *);
 
+/// Structure to store information about a single ATTACH map entry.
+struct AttachMapInfo {
+  void *PointerBase;
+  void *PointeeBegin;
+  int64_t PointerSize;
+  int64_t MapType;
+  map_var_info_t Pointername;
+
+  AttachMapInfo(void *PointerBase, void *PointeeBegin, int64_t Size,
+                int64_t Type, map_var_info_t Name)
+      : PointerBase(PointerBase), PointeeBegin(PointeeBegin), PointerSize(Size),
+        MapType(Type), Pointername(Name) {}
+};
+
+/// Structure to track ATTACH entries and new allocations across recursive calls
+/// (for handling mappers) to targetDataBegin for a given construct.
+struct AttachInfoTy {
+  /// ATTACH map entries for deferred processing.
+  llvm::SmallVector<AttachMapInfo> AttachEntries;
+
+  /// Key: host pointer, Value: allocation size.
+  llvm::DenseMap<void *, int64_t> NewAllocations;
+
+  AttachInfoTy() = default;
+
+  // Delete copy constructor and copy assignment operator to prevent copying
+  AttachInfoTy(const AttachInfoTy &) = delete;
+  AttachInfoTy &operator=(const AttachInfoTy &) = delete;
+};
+
 // Function pointer type for targetData* functions (targetDataBegin,
 // targetDataEnd and targetDataUpdate).
 typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **,
                                    void **, int64_t *, int64_t *,
                                    map_var_info_t *, void **, AsyncInfoTy &,
-                                   bool);
+                                   AttachInfoTy *, bool);
 
 void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device,
                                bool toStdOut = false);
@@ -431,20 +461,26 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                     void **ArgsBase, void **Args, int64_t *ArgSizes,
                     int64_t *ArgTypes, map_var_info_t *ArgNames,
                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                    AttachInfoTy *AttachInfo = nullptr,
                     bool FromMapper = false);
 
 int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                   void **ArgBases, void **Args, int64_t *ArgSizes,
                   int64_t *ArgTypes, map_var_info_t *ArgNames,
                   void **ArgMappers, AsyncInfoTy &AsyncInfo,
-                  bool FromMapper = false);
+                  AttachInfoTy *AttachInfo = nullptr, bool FromMapper = false);
 
 int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                      void **ArgsBase, void **Args, int64_t *ArgSizes,
                      int64_t *ArgTypes, map_var_info_t *ArgNames,
                      void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                     AttachInfoTy *AttachInfo = nullptr,
                      bool FromMapper = false);
 
+// Process deferred ATTACH map entries collected during targetDataBegin.
+int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
+                         AsyncInfoTy &AsyncInfo);
+
 struct MappingInfoTy {
   MappingInfoTy(DeviceTy &Device) : Device(Device) {}
 
diff --git a/offload/include/omptarget.h b/offload/include/omptarget.h
index 6971780c7bdb5..9e4bfd2f9cfbe 100644
--- a/offload/include/omptarget.h
+++ b/offload/include/omptarget.h
@@ -80,6 +80,9 @@ enum tgt_map_type {
   // the structured region
   // This is an OpenMP extension for the sake of OpenACC support.
   OMP_TGT_MAPTYPE_OMPX_HOLD       = 0x2000,
+  // Attach pointer and pointee, after processing all other maps.
+  // Applicable to map-entering directives. Does not change ref-count.
+  OMP_TGT_MAPTYPE_ATTACH          = 0x4000,
   // descriptor for non-contiguous target-update
   OMP_TGT_MAPTYPE_NON_CONTIG      = 0x100000000000,
   // member of struct, member given by [16 MSBs] - 1
diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index ea354400f2e99..16e46e6d23872 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -165,12 +165,28 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
                                              OMPT_GET_RETURN_ADDRESS);)
 
   int Rc = OFFLOAD_SUCCESS;
+
+  // Only allocate AttachInfo for targetDataBegin
+  AttachInfoTy *AttachInfo = nullptr;
+  if (TargetDataFunction == targetDataBegin) {
+    AttachInfo = new AttachInfoTy();
+  }
+
   Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
                           ArgTypes, ArgNames, ArgMappers, AsyncInfo,
-                          false /*FromMapper=*/);
+                          AttachInfo, false /*FromMapper=*/);
 
-  if (Rc == OFFLOAD_SUCCESS)
-    Rc = AsyncInfo.synchronize();
+  if (Rc == OFFLOAD_SUCCESS) {
+    // Process deferred ATTACH entries BEFORE synchronization
+    if (AttachInfo && !AttachInfo->AttachEntries.empty())
+      Rc = processAttachEntries(*DeviceOrErr, *AttachInfo, AsyncInfo);
+
+    if (Rc == OFFLOAD_SUCCESS)
+      Rc = AsyncInfo.synchronize();
+  }
+
+  if (AttachInfo)
+    delete AttachInfo;
 
   handleTargetOutcome(Rc == OFFLOAD_SUCCESS, Loc);
 }
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 5b25d955dd320..aa142814e8384 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -293,7 +293,8 @@ void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name) {
 int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
                      int64_t ArgSize, int64_t ArgType, map_var_info_t ArgNames,
                      void *ArgMapper, AsyncInfoTy &AsyncInfo,
-                     TargetDataFuncPtrTy TargetDataFunction) {
+                     TargetDataFuncPtrTy TargetDataFunction,
+                     AttachInfoTy *AttachInfo = nullptr) {
   DP("Calling the mapper function " DPxMOD "\n", DPxPTR(ArgMapper));
 
   // The mapper function fills up Components.
@@ -324,17 +325,196 @@ int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
                               MapperArgsBase.data(), MapperArgs.data(),
                               MapperArgSizes.data(), MapperArgTypes.data(),
                               MapperArgNames.data(), /*arg_mappers*/ nullptr,
-                              AsyncInfo, /*FromMapper=*/true);
+                              AsyncInfo, AttachInfo, /*FromMapper=*/true);
 
   return Rc;
 }
 
+/// Utility function to perform a pointer attachment operation.
+///
+/// For something like:
+/// \code
+///  int *p;
+///  ...
+///  #pragma omp target enter data map(to:p[10:10])
+/// \endcode
+///
+/// for which the attachment operation gets represented using:
+/// \code
+///   &p, &p[10], sizeof(p), ATTACH
+/// \endcode
+///
+/// (Hst|Tgt)PtrAddr   represents &p
+/// (Hst|Tgt)PteeBase  represents &p[0]
+/// (Hst|Tgt)PteeBegin represents &p[10]
+///
+/// This function first computes the expected TgtPteeBase using:
+///   TgtPteeBase = TgtPteeBegin - (HstPteeBegin - HstPteeBase)
+///
+/// and then attaches TgtPteeBase to TgtPtrAddr.
+///
+/// \p HstPtrSize represents the size of the pointer p. For C/C++, this
+/// should be same as "sizeof(void*)" (say 8).
+///
+/// However, for Fortran, pointers/allocatables, which are also eligible for
+/// "pointer-attachment", may be implemented using descriptors that contain the
+/// address of the pointee in the first 8 bytes, but also contain other
+/// information such as lower-bound/upper-bound etc in their subsequent fields.
+///
+/// For example, for the following:
+/// \code
+///   integer, allocatable :: x(:)
+///   integer, pointer :: p(:)
+///   ...
+///   p => x(10: 19)
+///   ...
+///   !$omp target enter data map(to:p(:))
+/// \endcode
+///
+/// The map should trigger a pointer-attachment (assuming the pointer-attachment
+/// conditions as noted on processAttachEntries are met) between the descriptor
+/// for p, and its pointee data.
+///
+/// Since only the first 8 bytes of the descriptor contain the address of the
+/// pointee, an attachment operation on device descriptors involves:
+/// * Setting the first 8 bytes of the device descriptor to point the device
+/// address of the pointee.
+/// * Copying the remaining information about bounds/offset etc. from the host
+/// descriptor to the device descriptor.
+///
+/// The function also handles pointer-attachment portion of PTR_AND_OBJ maps,
+/// like:
+/// \code
+///   &p, &p[10], 10 * sizeof(p[10]), PTR_AND_OBJ
+/// \endcoe
+/// by using "sizeof(void*)" as \p HstPtrSize.
+static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
+                                    void **HstPtrAddr, void *HstPteeBase,
+                                    void *HstPteeBegin, void **TgtPtrAddr,
+                                    void *TgtPteeBegin, int64_t HstPtrSize,
+                                    TargetPointerResultTy &PtrTPR) {
+  assert(PtrTPR.getEntry() &&
+         "Need a valid pointer entry to perform pointer-attachment");
+
+  int64_t VoidPtrSize = sizeof(void *);
+  assert(HstPtrSize >= VoidPtrSize && "PointerSize is too small");
+
+  uint64_t Delta = (uint64_t)HstPteeBegin - (uint64_t)HstPteeBase;
+  void *TgtPteeBase = (void *)((uint64_t)TgtPteeBegin - Delta);
+
+  // Add shadow pointer tracking
+  // TODO: Support shadow-tracking of larger than VoidPtrSize pointers,
+  // to support restoration of Fortran descriptors. Currently, this check
+  // would return false, even if the host Fortran descriptor was, and we
+  // should have done an update of the device descriptor. e.g.
+  //
+  //   !$omp target enter data map(x(1:100)) !             (1)
+  //   p => x(10: 19)
+  //   !$omp target enter data map(p, p(:)) !              (2)
+  //   p => x(5: 9)
+  //   !$omp target enter data map(attach(always): p(:)) ! (3)
+  //
+  // While PtrAddr(&desc_p) and PteeBase(&p(1)) are same for (2) and (3), the
+  // pointer attachment for (3) needs to update the bounds information
+  // in the descriptor of p on device.
+  if (!PtrTPR.getEntry()->addShadowPointer(
+          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase}))
+    return OFFLOAD_SUCCESS;
+
+  DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n", DPxPTR(TgtPtrAddr),
+     DPxPTR(TgtPteeBase));
+
+  // Lambda to handle submitData result and perform final steps.
+  auto HandleSubmitResult = [&](int SubmitResult) -> int {
+    if (SubmitResult != OFFLOAD_SUCCESS) {
+      REPORT("Failed to update pointer on device.\n");
+      return OFFLOAD_FAIL;
+    }
+
+    if (PtrTPR.getEntry()->addEventIfNecessary(Device, AsyncInfo) !=
+        OFFLOAD_SUCCESS)
+      return OFFLOAD_FAIL;
+
+    return OFFLOAD_SUCCESS;
+  };
+
+  bool IsPtrAFortranDescriptor = HstPtrSize > VoidPtrSize;
+  if (!IsPtrAFortranDescriptor) {
+    // For "regular" pointers, we can use the VoidPtrLocation from AsyncInfo as
+    // the buffer space for the submission.
+    void *&BufferElement = AsyncInfo.getVoidPtrLocation();
+    BufferElement = TgtPteeBase;
+
+    // Submit the updated pointer value to device
+    return HandleSubmitResult(Device.submitData(
+        TgtPtrAddr, &BufferElement, VoidPtrSize, AsyncInfo, PtrTPR.getEntry()));
+  }
+
+  // For larger "pointers" (like Fortran's descriptors), we create a dynamic
+  // buffer, which will be eventually destroyed by AsyncInfo's post-processing
+  // callback.
+  char *DataBuffer = new char[HstPtrSize];
+
+  // For such descriptors, to the first VoidPtrSize bytes, we store the
+  // pointee's device address.
+  std::memcpy(DataBuffer, &TgtPteeBase, sizeof(void *));
+
+  // And to the remaining bytes, we copy the remaining contents of the host
+  // descriptor after the initial VoidPtrSize bytes.
+  uint64_t HstDescriptorFieldsSize = HstPtrSize - VoidPtrSize;
+  void *HstDescriptorFieldsAddr = (char *)HstPtrAddr + VoidPtrSize;
+  std::memcpy(DataBuffer + VoidPtrSize, HstDescriptorFieldsAddr,
+              HstDescriptorFieldsSize);
+
+  DP("Updating %" PRId64 " bytes of descriptor (" DPxMOD ") (pointer + %" PRId64
+     " additional bytes from host descriptor " DPxMOD ")\n",
+     HstPtrSize, DPxPTR(TgtPtrAddr), HstDescriptorFieldsSize,
+     DPxPTR(HstDescriptorFieldsAddr));
+
+  // Submit the entire buffer to device
+  // FIXME: When handling ATTACH map-type, pointer attachment needs to happen
+  // after the other mapping operations are done, to avoid possibility of
+  // pending transfers clobbering the attachment, for example:
+  //
+  //   int *p = ...;
+  //   int **pp = &p;
+  //   map(to: pp[0], p[0])
+  //
+  // Which would be represented by:
+  // &pp[0], &pp[0], sizeof(pp[0]), TO (1)
+  // &p[0], &p[0], sizeof(p[0]), TO    (2)
+  //
+  // &pp, &pp[0], sizeof(pp), ATTACH   (3)
+  // &p, &p[0], sizeof(p), ATTACH      (4)
+  //
+  // (4) and (1) are both trying to modify the device memory corresponding to
+  // &p. We need to ensure that (4) happens last.
+  //
+  // One possible solution to this could be to insert a "device barrier" before
+  // the first ATTACH submitData call, so that every subsequent submitData waits
+  // for any prior operations to finish. Like:
+  //   Device.submitData(..., /*InOrder=*/IsFirstAttachEntry)
+  // Where the boolean InOrder being true means that this submission should
+  // wait for prior memory submissions to finish.
+  int SubmitResult =
+      Device.submitData(TgtPtrAddr, DataBuffer, HstPtrSize, AsyncInfo,
+                        PtrTPR.getEntry());
+
+  AsyncInfo.addPostProcessingFunction([DataBuffer]() -> int {
+    delete[] DataBuffer;
+    return OFFLOAD_SUCCESS;
+  });
+  return HandleSubmitResult(SubmitResult);
+}
+
 /// Internal function to do the mapping and transfer the data to the device
 int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                     void **ArgsBase, void **Args, int64_t *ArgSizes,
                     int64_t *ArgTypes, map_var_info_t *ArgNames,
                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
-                    bool FromMapper) {
+                    AttachInfoTy *AttachInfo, bool FromMapper) {
+  assert(AttachInfo && "AttachInfo must be available for targetDataBegin for "
+                       "handling ATTACH map-types.");
   // process each input.
   for (int32_t I = 0; I < ArgNum; ++I) {
     // Ignore private variables and arrays - there is no mapping for them.
@@ -352,7 +532,7 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
       map_var_info_t ArgName = (!ArgNames) ? nullptr : ArgNames[I];
       int Rc = targetDataMapper(Loc, Device, ArgsBase[I], Args[I], ArgSizes[I],
                                 ArgTypes[I], ArgName, ArgMappers[I], AsyncInfo,
-                                targetDataBegin);
+                                targetDataBegin, AttachInfo);
 
       if (Rc != OFFLOAD_SUCCESS) {
         REPORT("Call to targetDataBegin via targetDataMapper for custom mapper"
@@ -369,6 +549,18 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
     int64_t DataSize = ArgSizes[I];
     map_var_info_t HstPtrName = (!ArgNames) ? nullptr : ArgNames[I];
 
+    // ATTACH map-types are supposed to be handled after all mapping for the
+    // construct is done. Defer their processing.
+    if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH) {
+      AttachInfo->AttachEntries.emplace_back(
+          /*PointerBase=*/HstPtrBase, /*PointeeBegin=*/HstPtrBegin,
+          /*PointerSize=*/DataSize, /*MapType=*/ArgTypes[I],
+          /*PointeeName=*/HstPtrName);
+
+      DP("Deferring ATTACH map-type processing for argument %d\n", I);
+      continue;
+    }
+
     // Adjust for proper alignment if this is a combined entry (for structs).
     // Look at the next argument - if that is MEMBER_OF this one, then this one
     // is a combined entry.
@@ -434,6 +626,11 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                                   : "device failure or illegal mapping");
         return OFFLOAD_FAIL;
       }
+
+      // Track new allocation, for eventual use in attachment decision-making.
+      if (PointerTpr.Flags.IsNewEntry && !IsHostPtr)
+        AttachInfo->NewAllocations[HstPtrBase] = sizeof(void *);
+
       DP("There are %zu bytes allocated at target address " DPxMOD " - is%s new"
          "\n",
          sizeof(void *), DPxPTR(PointerTgtPtrBegin),
@@ -464,6 +661,11 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                                 : "device failure or illegal mapping");
       return OFFLOAD_FAIL;
     }
+
+    // Track new allocation, for eventual use in attachment decision-making.
+    if (TPR.Flags.IsNewEntry && !IsHostPtr && TgtPtrBegin)
+      AttachInfo->NewAllocations[HstPtrBegin] = DataSize;
+
     DP("There are %" PRId64 " bytes allocated at target address " DPxMOD
        " - is%s new\n",
        DataSize, DPxPTR(TgtPtrBegin), (TPR.Flags.IsNewEntry ? "" : " not"));
@@ -476,30 +678,12 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
     }
 
     if (ArgTypes[I] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
-
-      uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase;
-      void *ExpectedTgtPtrBase = (void *)((uint64_t)TgtPtrBegin - Delta);
-
-      if (PointerTpr.getEntry()->addShadowPointer(ShadowPtrInfoTy{
-              (void **)PointerHstPtrBegin, HstPtrBase,
-              (void **)PointerTgtPtrBegin, ExpectedTgtPtrBase})) {
-        DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n",
-           DPxPTR(PointerTgtPtrBegin), DPxPTR(TgtPtrBegin));
-
-        void *&TgtPtrBase = AsyncInfo.getVoidPtrLocation();
-        TgtPtrBase = ExpectedTgtPtrBase;
-
-        int Ret =
-            Device.submitData(PointerTgtPtrBegin, &TgtPtrBase, sizeof(void *),
-                              AsyncInfo, PointerTpr.getEntry());
-        if (Ret != OFFLOAD_SUCCESS) {
-          REPORT("Copying data to device failed.\n");
-          return OFFLOAD_FAIL;
-        }
-        if (PointerTpr.getEntry()->addEventIfNecessary(Device, AsyncInfo) !=
-            OFFLOAD_SUCCESS)
-          return OFFLOAD_FAIL;
-      }
+      int Ret = performPointerAttachment(Device, AsyncInfo,
+                                         (void **)PointerHstPtrBegin, HstPtrBase, HstPtrBegin,
+                                         (void **)PointerTgtPtrBegin, TgtPtrBegin,
+                                         sizeof(void *), PointerTpr);
+      if (Ret != OFFLOAD_SUCCESS)
+        return OFFLOAD_FAIL;
     }
 
     // Check if variable can be used on the device:
@@ -515,6 +699,145 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
   return OFFLOAD_SUCCESS;
 }
 
+/// Process deferred ATTACH map entries collected during targetDataBegin.
+///
+/// From OpenMP's perspective, when mapping something that has a base pointer,
+/// such as:
+/// \code
+///   int *p;
+///   #pragma omp enter target data map(to: p[10:20])
+/// \endcode
+///
+/// a pointer-attachment between p and &p[10] should occur if both p and
+/// p[10] are present on the device after doing all allocations for all maps
+/// on the construct, and one of the following is true:
+///
+/// * The pointer p was newly allocated while handling the construct
+/// * The pointee p[10:20] was newly allocated while handling the construct
+/// * attach(always) map-type modifier was specified (OpenMP 6.1)
+///
+/// That's why we collect all attach entries and new memory allocations during
+/// targetDataBegin, and use that information to make the decision of whether
+/// to perform a pointer-attachment or not here, after maps have been handled.
+int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
+                         AsyncInfoTy &AsyncInfo) {
+  // Report all tracked allocations from both main loop and ATTACH processing
+  if (!AttachInfo.NewAllocations.empty()) {
+    DP("Tracked %u total new allocations:\n",
+       (unsigned)AttachInfo.NewAllocations.size());
+    for (const auto &Alloc : AttachInfo.NewAllocations) {
+      DP("  Host ptr: " DPxMOD ", Size: %" PRId64 " bytes\n",
+         DPxPTR(Alloc.first), Alloc.second);
+    }
+  }
+
+  if (AttachInfo.AttachEntries.empty())
+    return OFFLOAD_SUCCESS;
+
+  DP("Processing %zu deferred ATTACH map entries\n",
+     AttachInfo.AttachEntries.size());
+
+  for (size_t EntryIdx = 0; EntryIdx < AttachInfo.AttachEntries.size();
+       ++EntryIdx) {
+    const auto &AttachEntry = AttachInfo.AttachEntries[EntryIdx];
+
+    void **HstPtr = (void **)AttachEntry.PointerBase;
+
+    void *HstPteeBase = *HstPtr;
+    void *HstPteeBegin = AttachEntry.PointeeBegin;
+
+    int64_t PtrSize = AttachEntry.PointerSize;
+    int64_t MapType = AttachEntry.MapType;
+
+    DP("Processing ATTACH entry %zu: HstPtr=" DPxMOD ", HstPteeBegin=" DPxMOD
+       ", Size=%" PRId64 ", Type=0x%" PRIx64 "\n",
+       EntryIdx, DPxPTR(HstPtr), DPxPTR(HstPteeBegin), PtrSize, MapType);
+
+    const bool IsAttachAlways = MapType & OMP_TGT_MAPTYPE_ALWAYS;
+
+    // Lambda to check if a pointer was newly allocated
+    auto WasNewlyAllocated = [&](void *Ptr, const char *PtrName) {
+      bool IsNewlyAllocated =
+          llvm::any_of(AttachInfo.NewAllocations, [&](const auto &Alloc) {
+            void *AllocPtr = Alloc.first;
+            int64_t AllocSize = Alloc.second;
+            return Ptr >= AllocPtr &&
+                   Ptr < (void *)((char *)AllocPtr + AllocSize);
+          });
+      DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
+         EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
+      return IsNewlyAllocated;
+    };
+
+    // Only process ATTACH if base/begin was newly allocated OR ALWAYS flag is
+    // set
+    if (!IsAttachAlways && !WasNewlyAllocated(HstPtr, "pointer") &&
+        !WasNewlyAllocated(HstPteeBegin, "pointee")) {
+      DP("Skipping ATTACH entry %zu: neither pointer nor pointee was newly "
+         "allocated and no ALWAYS flag\n",
+         EntryIdx);
+      continue;
+    }
+
+    DP("Processing ATTACH entry %zu: Always=%s\n", EntryIdx,
+       IsAttachAlways ? "yes" : "no");
+
+    // Lambda to perform target pointer lookup and validation
+    auto LookupTargetPointer = [&](void *Ptr, int64_t Size, const char *PtrType)
+        -> std::optional<TargetPointerResultTy> {
+      // ATTACH map-type does not change ref-count, or do any allocation
+      // We just need to do a lookup for the pointer/pointee.
+      TargetPointerResultTy TPR = Device.getMappingInfo().getTgtPtrBegin(
+          Ptr, Size, /*UpdateRefCount=*/false,
+          /*UseHoldRefCount=*/false, /*MustContain=*/true);
+
+      DP("ATTACH entry %zu: %s lookup - HstPtr=" DPxMOD ", TgtPtr=" DPxMOD
+         ", IsPresent=%s, IsHostPtr=%s\n",
+         EntryIdx, PtrType, DPxPTR(Ptr), DPxPTR(TPR.TargetPointer),
+         TPR.isPresent() ? "yes" : "no",
+         TPR.Flags.IsHostPointer ? "yes" : "no");
+
+      if (!TPR.isPresent()) {
+        DP("Skipping ATTACH entry %zu: %s not present on device\n", EntryIdx,
+           PtrType);
+        return std::nullopt;
+      }
+      if (TPR.Flags.IsHostPointer) {
+        DP("Skipping ATTACH entry %zu: device version of the %s is a host "
+           "pointer.\n",
+           EntryIdx, PtrType);
+        return std::nullopt;
+      }
+
+      return TPR;
+    };
+
+    // Get device version of the pointer (e.g., &p)
+    auto PtrTPROpt = LookupTargetPointer(HstPtr, PtrSize, "pointer");
+    if (!PtrTPROpt)
+      continue;
+    TargetPointerResultTy &PtrTPR = *PtrTPROpt;
+    void **TgtPtrBase = (void **)PtrTPR.TargetPointer;
+
+    // Get device version of the pointee (e.g., &p[10])
+    auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");
+    if (!PteeTPROpt)
+      continue;
+    void *TgtPteeBegin = PteeTPROpt->TargetPointer;
+
+    // Update the device pointer to point to device pointee.
+    int Ret = performPointerAttachment(Device, AsyncInfo, HstPtr, HstPteeBase,
+                                       HstPteeBegin, TgtPtrBase, TgtPteeBegin,
+                                       PtrSize, PtrTPR);
+    if (Ret != OFFLOAD_SUCCESS)
+      return OFFLOAD_FAIL;
+
+    DP("ATTACH entry %zu processed successfully\n", EntryIdx);
+  }
+
+  return OFFLOAD_SUCCESS;
+}
+
 namespace {
 /// This structure contains information to deallocate a target pointer, aka.
 /// used to fix up the shadow map and potentially delete the entry from the
@@ -624,7 +947,8 @@ postProcessingTargetDataEnd(DeviceTy *Device,
 int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                   void **ArgBases, void **Args, int64_t *ArgSizes,
                   int64_t *ArgTypes, map_var_info_t *ArgNames,
-                  void **ArgMappers, AsyncInfoTy &AsyncInfo, bool FromMapper) {
+                  void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                  AttachInfoTy *AttachInfo, bool FromMapper) {
   int Ret = OFFLOAD_SUCCESS;
   auto *PostProcessingPtrs = new SmallVector<PostProcessingInfo>();
   // process each input.
@@ -635,6 +959,14 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
         (ArgTypes[I] & OMP_TGT_MAPTYPE_PRIVATE))
       continue;
 
+    // Ignore ATTACH entries - they should only be honored on map-entering
+    // directives. They may be encountered here while handling the "end" part of
+    // "#pragma omp target".
+    if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH) {
+      DP("Ignoring ATTACH entry %d in targetDataEnd\n", I);
+      continue;
+    }
+
     if (ArgMappers && ArgMappers[I]) {
       // Instead of executing the regular path of targetDataEnd, call the
       // targetDataMapper variant which will call targetDataEnd again
@@ -900,7 +1232,8 @@ static int getNonContigMergedDimension(__tgt_target_non_contig *NonContig,
 int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                      void **ArgsBase, void **Args, int64_t *ArgSizes,
                      int64_t *ArgTypes, map_var_info_t *ArgNames,
-                     void **ArgMappers, AsyncInfoTy &AsyncInfo, bool) {
+                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                     AttachInfoTy *AttachInfo, bool FromMapper) {
   // process each input.
   for (int32_t I = 0; I < ArgNum; ++I) {
     if ((ArgTypes[I] & OMP_TGT_MAPTYPE_LITERAL) ||
@@ -1213,13 +1546,27 @@ static int processDataBefore(ident_t *Loc, int64_t DeviceId, void *HostPtr,
   if (!DeviceOrErr)
     FATAL_MESSAGE(DeviceId, "%s", toString(DeviceOrErr.takeError()).c_str());
 
+  // Create AttachInfo for tracking any ATTACH entries, or new-allocations
+  // when handling the "begin" mapping for a target constructs.
+  AttachInfoTy AttachInfo;
+
   int Ret = targetDataBegin(Loc, *DeviceOrErr, ArgNum, ArgBases, Args, ArgSizes,
-                            ArgTypes, ArgNames, ArgMappers, AsyncInfo);
+                            ArgTypes, ArgNames, ArgMappers, AsyncInfo,
+                            &AttachInfo, false /*FromMapper=*/);
   if (Ret != OFFLOAD_SUCCESS) {
     REPORT("Call to targetDataBegin failed, abort target.\n");
     return OFFLOAD_FAIL;
   }
 
+  // Process collected ATTACH entries
+  if (!AttachInfo.AttachEntries.empty()) {
+    Ret = processAttachEntries(*DeviceOrErr, AttachInfo, AsyncInfo);
+    if (Ret != OFFLOAD_SUCCESS) {
+      REPORT("Failed to process ATTACH entries.\n");
+      return OFFLOAD_FAIL;
+    }
+  }
+
   // List of (first-)private arrays allocated for this target region
   SmallVector<int> TgtArgsPositions(ArgNum, -1);
 

>From fcdc13af98a0ad41206aa01fc2d76a60ff51a419 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 01:22:23 -0700
Subject: [PATCH 24/66] More test updates

---
 clang/test/OpenMP/target_data_codegen.cpp     |   8 +-
 .../OpenMP/target_data_map_codegen_hold.cpp   | 495 ++++++++++--------
 clang/test/OpenMP/target_map_codegen_23.cpp   | 108 +++-
 ...get_map_pointer_defalut_mapper_codegen.cpp |   4 +-
 4 files changed, 354 insertions(+), 261 deletions(-)

diff --git a/clang/test/OpenMP/target_data_codegen.cpp b/clang/test/OpenMP/target_data_codegen.cpp
index 7c272c24b28d5..b1da245110fb1 100644
--- a/clang/test/OpenMP/target_data_codegen.cpp
+++ b/clang/test/OpenMP/target_data_codegen.cpp
@@ -625,7 +625,7 @@ void test_present_modifier(int arg) {
 
   // Make sure the struct picks up present even if another element of the struct
   // doesn't have present.
-  // CK8: private unnamed_addr constant [13 x i64] [i64 0, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 4, i64 {{4|8}}, i64 4, i64 0, i64 4, i64 {{4|8}}, i64 {{4|8}}, i64 {{4|8}}, i64 4]
+  // CK8: private unnamed_addr constant [13 x i64] [i64 0, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 4, i64 {{4|8}}, i64 4, i64 0, i64 4, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 {{8|4}}]
   // CK8: private unnamed_addr constant [13 x i64]
 
 // ps1
@@ -651,14 +651,14 @@ void test_present_modifier(int arg) {
 //
 // PRESENT=0x1000 = 0x1000
 // MEMBER_OF_8=0x8000000000000 | PRESENT=0x1000 | FROM=0x2 | TO=0x1 = 0x8000000001003
-// ATTACH=0x4000
 // MEMBER_OF_8=0x8000000000000 | PTR_AND_OBJ=0x10 = 0x8000000000010
 // PTR_AND_OBJ=0x10 = 0x10
 // PTR_AND_OBJ=0x10 | FROM=0x2 | TO=0x1 = 0x13
+// ATTACH=0x4000
 //
 // CK8-SAME: {{^}} i64 [[#0x1000]], i64 [[#0x8000000001003]],
-// CK8-SAME: {{^}} i64 [[#0x4000]],
-// CK8-SAME: {{^}} i64 [[#0x8000000000010]], i64 [[#0x10]], i64 [[#0x13]]]
+// CK8-SAME: {{^}} i64 [[#0x8000000000010]], i64 [[#0x10]], i64 [[#0x13]],
+// CK8-SAME: {{^}} i64 [[#0x4000]]]
 #pragma omp target data map(tofrom         \
                             : ps1->s)      \
     map(present, tofrom                    \
diff --git a/clang/test/OpenMP/target_data_map_codegen_hold.cpp b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
index 3b115acaa2afb..d886e4edc3f2f 100644
--- a/clang/test/OpenMP/target_data_map_codegen_hold.cpp
+++ b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
@@ -49,8 +49,9 @@ struct S2 {
 //   PTR_AND_OBJ = 0x10
 //   CLOSE       = 0x400
 //   OMPX_HOLD   = 0x2000
+//   ATTACH      = 0x4000
 //   MEMBER_OF_1 = 0x1000000000000
-//   MEMBER_OF_7 = 0x7000000000000
+//   MEMBER_OF_8 = 0x8000000000000
 
 //.
 // CHECK-PPC64LE: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 20]
@@ -59,8 +60,8 @@ struct S2 {
 // CHECK-PPC64LE: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x2405]]]
 // CHECK-PPC64LE: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK-PPC64LE: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x2003]]]
-// CHECK-PPC64LE: @.offload_sizes.5 = private unnamed_addr constant [11 x i64] [i64 0, i64 4, i64 8, i64 8, i64 4, i64 4, i64 0, i64 4, i64 8, i64 8, i64 4]
-// CHECK-PPC64LE: @.offload_maptypes.6 = private unnamed_addr constant [11 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x7000000002003]], i64 [[#0x7000000002010]], i64 [[#0x2010]], i64 [[#0x2013]]]
+// CHECK-PPC64LE: @.offload_sizes.5 = private unnamed_addr constant [13 x i64] [i64 0, i64 4, i64 8, i64 8, i64 4, i64 8, i64 4, i64 0, i64 4, i64 8, i64 8, i64 4, i64 8]
+// CHECK-PPC64LE: @.offload_maptypes.6 = private unnamed_addr constant [13 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x8000000002003]], i64 [[#0x8000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]]]
 //.
 // CHECK-I386: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 20]
 // CHECK-I386: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x2001]]]
@@ -68,8 +69,8 @@ struct S2 {
 // CHECK-I386: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x2405]]]
 // CHECK-I386: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK-I386: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x2003]]]
-// CHECK-I386: @.offload_sizes.5 = private unnamed_addr constant [11 x i64] [i64 0, i64 4, i64 4, i64 4, i64 4, i64 4, i64 0, i64 4, i64 4, i64 4, i64 4]
-// CHECK-I386: @.offload_maptypes.6 = private unnamed_addr constant [11 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x7000000002003]], i64 [[#0x7000000002010]], i64 [[#0x2010]], i64 [[#0x2013]]]
+// CHECK-I386: @.offload_sizes.5 = private unnamed_addr constant [13 x i64] [i64 0, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 0, i64 4, i64 4, i64 4, i64 4, i64 4]
+// CHECK-I386: @.offload_maptypes.6 = private unnamed_addr constant [13 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x8000000002003]], i64 [[#0x8000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]]]
 //.
 // CHECK-PPC64LE-LABEL: @_Z3fooi(
 // CHECK-PPC64LE-NEXT:  entry:
@@ -86,10 +87,10 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [11 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [11 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [11 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [11 x i64], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 8
 // CHECK-PPC64LE-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-PPC64LE-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    store ptr [[LB]], ptr [[TMP0]], align 8
@@ -140,142 +141,158 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[S9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS10]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS13]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 8
-// CHECK-PPC64LE-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
-// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-PPC64LE-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS17]], align 8
+// CHECK-PPC64LE-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP38]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = ptrtoint ptr [[S]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = sub i64 [[TMP39]], [[TMP40]]
+// CHECK-PPC64LE-NEXT:    [[TMP42:%.*]] = sdiv exact i64 [[TMP41]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK-PPC64LE-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[S19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[S20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS24]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 8
-// CHECK-PPC64LE-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
-// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-PPC64LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.5, i64 88, i1 false)
-// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP61]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 0
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP63]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP65]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 1
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP66]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 2
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP69]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 3
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP72]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 4
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP75]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP76]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP77]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 5
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP78]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP79]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP80]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP59]], ptr [[TMP81]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 6
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP82]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP83]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP84]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 7
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP85]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[PS19]], ptr [[TMP86]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP87]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 8
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP88]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP89]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP90]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 9
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP91]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP92]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[S28]], ptr [[TMP93]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 10
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP94]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 11, ptr [[TMP95]], ptr [[TMP96]], ptr [[TMP97]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-PPC64LE-NEXT:    [[TMP98:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP98]], 1
-// CHECK-PPC64LE-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 11, ptr [[TMP99]], ptr [[TMP100]], ptr [[TMP101]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[PS28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[PS28]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS29:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP55]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[PS29]], align 8
+// CHECK-PPC64LE-NEXT:    [[S30:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP56]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = getelementptr ptr, ptr [[PS21]], i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = ptrtoint ptr [[TMP57]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = ptrtoint ptr [[S19]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = sub i64 [[TMP58]], [[TMP59]]
+// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = sdiv exact i64 [[TMP60]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-PPC64LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.5, i64 104, i1 false)
+// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP62]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP63]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store i64 [[TMP42]], ptr [[TMP64]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 0
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP65]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP66]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP67]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 1
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP68]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[PS]], ptr [[TMP69]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[PS11]], ptr [[TMP70]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 2
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP71]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[PS11]], ptr [[TMP72]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[PS14]], ptr [[TMP73]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 3
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP74]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[PS14]], ptr [[TMP75]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP76]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 4
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP77]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP79]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 5
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP80]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP81]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP82]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 6
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP83]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP84]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP85]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store i64 [[TMP61]], ptr [[TMP86]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 7
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP87]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP88]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP89]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 8
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP90]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 9
+// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP91]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 9
+// CHECK-PPC64LE-NEXT:    store ptr [[PS23]], ptr [[TMP92]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 9
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP93]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 10
+// CHECK-PPC64LE-NEXT:    store ptr [[PS23]], ptr [[TMP94]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 10
+// CHECK-PPC64LE-NEXT:    store ptr [[PS26]], ptr [[TMP95]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 10
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP96]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 11
+// CHECK-PPC64LE-NEXT:    store ptr [[PS26]], ptr [[TMP97]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 11
+// CHECK-PPC64LE-NEXT:    store ptr [[S30]], ptr [[TMP98]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 11
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP99]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
+// CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP101]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 12
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP102]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP103]], ptr [[TMP104]], ptr [[TMP105]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[TMP106:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[INC34:%.*]] = add nsw i32 [[TMP106]], 1
+// CHECK-PPC64LE-NEXT:    store i32 [[INC34]], ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP107]], ptr [[TMP108]], ptr [[TMP109]], ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-PPC64LE-NEXT:    ret void
 //
 // CHECK-I386-LABEL: @_Z3fooi(
@@ -293,10 +310,10 @@ struct S2 {
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [11 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [11 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [11 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [11 x i64], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 4
 // CHECK-I386-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-I386-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK-I386-NEXT:    store ptr [[LB]], ptr [[TMP0]], align 4
@@ -347,142 +364,158 @@ struct S2 {
 // CHECK-I386-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[S9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 4
+// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS10]], align 4
 // CHECK-I386-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 4
+// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 4
 // CHECK-I386-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS13]], align 4
 // CHECK-I386-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 4
+// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 4
 // CHECK-I386-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 4
-// CHECK-I386-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-I386-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
-// CHECK-I386-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-I386-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
-// CHECK-I386-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-I386-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS17]], align 4
+// CHECK-I386-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP38:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
+// CHECK-I386-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP38]] to i64
+// CHECK-I386-NEXT:    [[TMP40:%.*]] = ptrtoint ptr [[S]] to i64
+// CHECK-I386-NEXT:    [[TMP41:%.*]] = sub i64 [[TMP39]], [[TMP40]]
+// CHECK-I386-NEXT:    [[TMP42:%.*]] = sdiv exact i64 [[TMP41]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK-I386-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[S19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[S20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 4
+// CHECK-I386-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 4
 // CHECK-I386-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 4
+// CHECK-I386-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS24]], align 4
 // CHECK-I386-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 4
 // CHECK-I386-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 4
+// CHECK-I386-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 4
-// CHECK-I386-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
-// CHECK-I386-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
-// CHECK-I386-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
-// CHECK-I386-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
-// CHECK-I386-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-I386-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 88, i1 false)
-// CHECK-I386-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 4
-// CHECK-I386-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP61]], align 4
-// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 4
-// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP63]], align 4
-// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 4
-// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP65]], align 4
-// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP66]], align 4
-// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 4
-// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 4
-// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP69]], align 4
-// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 4
-// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 4
-// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP72]], align 4
-// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 4
-// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 4
-// CHECK-I386-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP75]], align 4
-// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP76]], align 4
-// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP77]], align 4
-// CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP78]], align 4
-// CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP79]], align 4
-// CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP80]], align 4
-// CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 6
-// CHECK-I386-NEXT:    store i64 [[TMP59]], ptr [[TMP81]], align 4
-// CHECK-I386-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP82]], align 4
-// CHECK-I386-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP83]], align 4
-// CHECK-I386-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP84]], align 4
-// CHECK-I386-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP85]], align 4
-// CHECK-I386-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[PS19]], ptr [[TMP86]], align 4
-// CHECK-I386-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP87]], align 4
-// CHECK-I386-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP88]], align 4
-// CHECK-I386-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP89]], align 4
-// CHECK-I386-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP90]], align 4
-// CHECK-I386-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP91]], align 4
-// CHECK-I386-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP92]], align 4
-// CHECK-I386-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[S28]], ptr [[TMP93]], align 4
-// CHECK-I386-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP94]], align 4
-// CHECK-I386-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 11, ptr [[TMP95]], ptr [[TMP96]], ptr [[TMP97]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-I386-NEXT:    [[TMP98:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP98]], 1
-// CHECK-I386-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [11 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 11, ptr [[TMP99]], ptr [[TMP100]], ptr [[TMP101]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[PS28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[PS28]], align 4
+// CHECK-I386-NEXT:    [[PS29:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP55]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[PS29]], align 4
+// CHECK-I386-NEXT:    [[S30:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP56]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP57:%.*]] = getelementptr ptr, ptr [[PS21]], i32 1
+// CHECK-I386-NEXT:    [[TMP58:%.*]] = ptrtoint ptr [[TMP57]] to i64
+// CHECK-I386-NEXT:    [[TMP59:%.*]] = ptrtoint ptr [[S19]] to i64
+// CHECK-I386-NEXT:    [[TMP60:%.*]] = sub i64 [[TMP58]], [[TMP59]]
+// CHECK-I386-NEXT:    [[TMP61:%.*]] = sdiv exact i64 [[TMP60]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-I386-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 104, i1 false)
+// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP62]], align 4
+// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP63]], align 4
+// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    store i64 [[TMP42]], ptr [[TMP64]], align 4
+// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP65]], align 4
+// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP66]], align 4
+// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP67]], align 4
+// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP68]], align 4
+// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[PS]], ptr [[TMP69]], align 4
+// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[PS11]], ptr [[TMP70]], align 4
+// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP71]], align 4
+// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[PS11]], ptr [[TMP72]], align 4
+// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[PS14]], ptr [[TMP73]], align 4
+// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP74]], align 4
+// CHECK-I386-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[PS14]], ptr [[TMP75]], align 4
+// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP76]], align 4
+// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP77]], align 4
+// CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 4
+// CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP79]], align 4
+// CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP80]], align 4
+// CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP81]], align 4
+// CHECK-I386-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP82]], align 4
+// CHECK-I386-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP83]], align 4
+// CHECK-I386-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP84]], align 4
+// CHECK-I386-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP85]], align 4
+// CHECK-I386-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
+// CHECK-I386-NEXT:    store i64 [[TMP61]], ptr [[TMP86]], align 4
+// CHECK-I386-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP87]], align 4
+// CHECK-I386-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP88]], align 4
+// CHECK-I386-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP89]], align 4
+// CHECK-I386-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP90]], align 4
+// CHECK-I386-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP91]], align 4
+// CHECK-I386-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr [[PS23]], ptr [[TMP92]], align 4
+// CHECK-I386-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP93]], align 4
+// CHECK-I386-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr [[PS23]], ptr [[TMP94]], align 4
+// CHECK-I386-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr [[PS26]], ptr [[TMP95]], align 4
+// CHECK-I386-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP96]], align 4
+// CHECK-I386-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr [[PS26]], ptr [[TMP97]], align 4
+// CHECK-I386-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr [[S30]], ptr [[TMP98]], align 4
+// CHECK-I386-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP99]], align 4
+// CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 4
+// CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP101]], align 4
+// CHECK-I386-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP102]], align 4
+// CHECK-I386-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP103]], ptr [[TMP104]], ptr [[TMP105]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[TMP106:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[INC34:%.*]] = add nsw i32 [[TMP106]], 1
+// CHECK-I386-NEXT:    store i32 [[INC34]], ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP107]], ptr [[TMP108]], ptr [[TMP109]], ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-I386-NEXT:    ret void
 //
 void foo(int arg) {
diff --git a/clang/test/OpenMP/target_map_codegen_23.cpp b/clang/test/OpenMP/target_map_codegen_23.cpp
index 7e9acdafad2f8..20ff8872f70fa 100644
--- a/clang/test/OpenMP/target_map_codegen_23.cpp
+++ b/clang/test/OpenMP/target_map_codegen_23.cpp
@@ -61,28 +61,28 @@ struct SC{
 // CK24: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE13:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
-// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24: [[SIZE13:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE13:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE14:@.+]] = private {{.*}}constant [1 x i64] [i64 {{48|56}}]
-// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24: [[SIZE14:@.+]] = private {{.*}}constant [2 x i64] [i64 {{48|56}}, i64 {{4|8}}]
+// CK24: [[MTYPE14:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE15:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
-// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24: [[SIZE15:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE15:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE16:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 20]
-// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
+// CK24: [[SIZE16:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 20, i64 {{4|8}}]
+// CK24: [[MTYPE16:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK24: [[SIZE17:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 {{3560|2880}}]
 // CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE18:@.+]] = private {{.*}}constant [1 x i64] [i64 4]
-// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
+// CK24: [[SIZE18:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK24: [[SIZE19:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{8|4}}, i64 4]
@@ -97,8 +97,8 @@ struct SC{
 // CK24: [[MTYPE21:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE22:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 8]
-// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710659]
+// CK24: [[SIZE22:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 8, i64 {{4|8}}]
+// CK24: [[MTYPE22:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK24: [[SIZE23:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{8|4}}, i64 8]
@@ -136,6 +136,8 @@ int explicit_maps_struct_fields(int a){
 // Same thing but starting from a pointer.
 //
 // Region 13
+//   &p[0], &p->a, sizeof(p->a), TO | FROM | PARAM
+//   &p, &p->a, sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -150,14 +152,24 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
 // CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 0
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR:[^,]+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 0
+
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR]]
+
 
 // CK24: call void [[CALL13:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->a)
   { p->a++; }
 
 // Region 14
+//   &p[0], &p->s.s, sizeof(p->s.s), TO | FROM | PARAM
+//   &p, &p->s.s, sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -173,14 +185,23 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[SEC11]] = getelementptr {{.*}}ptr [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 1
 
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR]]
 // CK24: call void [[CALL14:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.s)
   { p->a++; }
 
 // Region 15
+//   &p[0], &p->s.s.a, sizeof(p->s.s.a), TO | FROM | PARAM
+//   &p, &p->s.s.a, sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -197,14 +218,26 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: [[SEC00]] = getelementptr {{.*}}ptr [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[SEC11]] = getelementptr {{.*}}ptr [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 1
+
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL15:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.s.a)
   { p->a++; }
 
 // Region 16
+//   &p[0], &p->b[0], sizeof(p->b[0:5]), ALLOC | PARAM
+//   &p[0], &p->b[0], sizeof(p->b[0:5]), TO | FROM
+//   &p, &p[0], sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -230,8 +263,14 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: store ptr [[VAR0]], ptr [[BP1]]
 // CK24-DAG: store ptr [[SEC0]], ptr [[P1]]
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP2]]
+// CK24-DAG: store ptr [[VAR2:%[^,]+]], ptr [[P2]]
+
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR2]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL16:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->b[:5])
@@ -274,6 +313,8 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 18
+//   &p[0], &p->s.sa[3].a, sizeof(p->s.sa[3].a), TO | FROM | PARAM
+//   &p, &p->s.sa[3].a sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -291,8 +332,18 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: [[SEC000]] = getelementptr {{.*}}ptr [[SEC0000:%[^,]+]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[SEC0000]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
+// CK24-DAG: [[SEC11]] = getelementptr {{.*}}ptr [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}ptr [[VAR11:%.+]], i{{.+}} 0, i{{.+}} 1
+
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR11]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL18:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.sa[3].a)
@@ -423,6 +474,9 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 22
+//   &p[0], &p->s.s.b[0], sizeof(p->s.s.bb[0:2]), ALLOC | PARAM
+//   &p[0], &p->s.s.bb[0], sizeof(p->s.s.bb[0:2]), TO | FROM
+//   &p, &p[0], sizeof(p), ATTACH
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -450,8 +504,14 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: store ptr [[VAR0]], ptr [[BP1]]
 // CK24-DAG: store ptr [[SEC0]], ptr [[P1]]
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP2]]
+// CK24-DAG: store ptr [[VAR2:%[^,]+]], ptr [[P2]]
+
+// CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
+// CK24-DAG: [[VAR2]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL22:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.s.b[:2])
diff --git a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
index 6ab10c45beb25..db569bfa6cf44 100644
--- a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
+++ b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
@@ -44,7 +44,7 @@ void foo() {
 // CHECK-NOT: @.offload_sizes = private unnamed_addr constant [6 x i64] [i64 8, i64 0, i64 0, i64 0, i64 8, i64 4]
 // CHECK: @.offload_maptypes = private unnamed_addr constant [5 x i64] [i64 35, i64 16, i64 562949953421315, i64 562949953421315, i64 562949953421827]
 // CHECK-NOT: .offload_maptypes = private unnamed_addr constant  [6 x i64] [i64 35, i64 0, i64 562949953421315, i64 562949953421315, i64 562949953421827, i64 562949953421843]
-// CHECK: @.offload_sizes.1 = private unnamed_addr constant [4 x i64] [i64 0, i64 0, i64 0, i64 4]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976711171]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 4, i64 8]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976711171, i64 16384]
 // 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]

>From c35d7a0e987aa0ebf7c5ba234d40f9e6f0e4ad54 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 00:53:09 -0700
Subject: [PATCH 25/66] [WIP][Offload] Introduce ATTACH map-type support for
 pointer attachment.

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!
---
 offload/include/OpenMP/Mapping.h   |  40 ++-
 offload/include/omptarget.h        |   3 +
 offload/libomptarget/interface.cpp |  22 +-
 offload/libomptarget/omptarget.cpp | 409 ++++++++++++++++++++++++++---
 4 files changed, 438 insertions(+), 36 deletions(-)

diff --git a/offload/include/OpenMP/Mapping.h b/offload/include/OpenMP/Mapping.h
index b9f5c16582931..93c1e56905ae4 100644
--- a/offload/include/OpenMP/Mapping.h
+++ b/offload/include/OpenMP/Mapping.h
@@ -417,12 +417,42 @@ struct MapperComponentsTy {
 typedef void (*MapperFuncPtrTy)(void *, void *, void *, int64_t, int64_t,
                                 void *);
 
+/// Structure to store information about a single ATTACH map entry.
+struct AttachMapInfo {
+  void *PointerBase;
+  void *PointeeBegin;
+  int64_t PointerSize;
+  int64_t MapType;
+  map_var_info_t Pointername;
+
+  AttachMapInfo(void *PointerBase, void *PointeeBegin, int64_t Size,
+                int64_t Type, map_var_info_t Name)
+      : PointerBase(PointerBase), PointeeBegin(PointeeBegin), PointerSize(Size),
+        MapType(Type), Pointername(Name) {}
+};
+
+/// Structure to track ATTACH entries and new allocations across recursive calls
+/// (for handling mappers) to targetDataBegin for a given construct.
+struct AttachInfoTy {
+  /// ATTACH map entries for deferred processing.
+  llvm::SmallVector<AttachMapInfo> AttachEntries;
+
+  /// Key: host pointer, Value: allocation size.
+  llvm::DenseMap<void *, int64_t> NewAllocations;
+
+  AttachInfoTy() = default;
+
+  // Delete copy constructor and copy assignment operator to prevent copying
+  AttachInfoTy(const AttachInfoTy &) = delete;
+  AttachInfoTy &operator=(const AttachInfoTy &) = delete;
+};
+
 // Function pointer type for targetData* functions (targetDataBegin,
 // targetDataEnd and targetDataUpdate).
 typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **,
                                    void **, int64_t *, int64_t *,
                                    map_var_info_t *, void **, AsyncInfoTy &,
-                                   bool);
+                                   AttachInfoTy *, bool);
 
 void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device,
                                bool toStdOut = false);
@@ -431,20 +461,26 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                     void **ArgsBase, void **Args, int64_t *ArgSizes,
                     int64_t *ArgTypes, map_var_info_t *ArgNames,
                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                    AttachInfoTy *AttachInfo = nullptr,
                     bool FromMapper = false);
 
 int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                   void **ArgBases, void **Args, int64_t *ArgSizes,
                   int64_t *ArgTypes, map_var_info_t *ArgNames,
                   void **ArgMappers, AsyncInfoTy &AsyncInfo,
-                  bool FromMapper = false);
+                  AttachInfoTy *AttachInfo = nullptr, bool FromMapper = false);
 
 int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                      void **ArgsBase, void **Args, int64_t *ArgSizes,
                      int64_t *ArgTypes, map_var_info_t *ArgNames,
                      void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                     AttachInfoTy *AttachInfo = nullptr,
                      bool FromMapper = false);
 
+// Process deferred ATTACH map entries collected during targetDataBegin.
+int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
+                         AsyncInfoTy &AsyncInfo);
+
 struct MappingInfoTy {
   MappingInfoTy(DeviceTy &Device) : Device(Device) {}
 
diff --git a/offload/include/omptarget.h b/offload/include/omptarget.h
index 6971780c7bdb5..9e4bfd2f9cfbe 100644
--- a/offload/include/omptarget.h
+++ b/offload/include/omptarget.h
@@ -80,6 +80,9 @@ enum tgt_map_type {
   // the structured region
   // This is an OpenMP extension for the sake of OpenACC support.
   OMP_TGT_MAPTYPE_OMPX_HOLD       = 0x2000,
+  // Attach pointer and pointee, after processing all other maps.
+  // Applicable to map-entering directives. Does not change ref-count.
+  OMP_TGT_MAPTYPE_ATTACH          = 0x4000,
   // descriptor for non-contiguous target-update
   OMP_TGT_MAPTYPE_NON_CONTIG      = 0x100000000000,
   // member of struct, member given by [16 MSBs] - 1
diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index ea354400f2e99..16e46e6d23872 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -165,12 +165,28 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
                                              OMPT_GET_RETURN_ADDRESS);)
 
   int Rc = OFFLOAD_SUCCESS;
+
+  // Only allocate AttachInfo for targetDataBegin
+  AttachInfoTy *AttachInfo = nullptr;
+  if (TargetDataFunction == targetDataBegin) {
+    AttachInfo = new AttachInfoTy();
+  }
+
   Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
                           ArgTypes, ArgNames, ArgMappers, AsyncInfo,
-                          false /*FromMapper=*/);
+                          AttachInfo, false /*FromMapper=*/);
 
-  if (Rc == OFFLOAD_SUCCESS)
-    Rc = AsyncInfo.synchronize();
+  if (Rc == OFFLOAD_SUCCESS) {
+    // Process deferred ATTACH entries BEFORE synchronization
+    if (AttachInfo && !AttachInfo->AttachEntries.empty())
+      Rc = processAttachEntries(*DeviceOrErr, *AttachInfo, AsyncInfo);
+
+    if (Rc == OFFLOAD_SUCCESS)
+      Rc = AsyncInfo.synchronize();
+  }
+
+  if (AttachInfo)
+    delete AttachInfo;
 
   handleTargetOutcome(Rc == OFFLOAD_SUCCESS, Loc);
 }
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 5b25d955dd320..aa142814e8384 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -293,7 +293,8 @@ void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name) {
 int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
                      int64_t ArgSize, int64_t ArgType, map_var_info_t ArgNames,
                      void *ArgMapper, AsyncInfoTy &AsyncInfo,
-                     TargetDataFuncPtrTy TargetDataFunction) {
+                     TargetDataFuncPtrTy TargetDataFunction,
+                     AttachInfoTy *AttachInfo = nullptr) {
   DP("Calling the mapper function " DPxMOD "\n", DPxPTR(ArgMapper));
 
   // The mapper function fills up Components.
@@ -324,17 +325,196 @@ int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
                               MapperArgsBase.data(), MapperArgs.data(),
                               MapperArgSizes.data(), MapperArgTypes.data(),
                               MapperArgNames.data(), /*arg_mappers*/ nullptr,
-                              AsyncInfo, /*FromMapper=*/true);
+                              AsyncInfo, AttachInfo, /*FromMapper=*/true);
 
   return Rc;
 }
 
+/// Utility function to perform a pointer attachment operation.
+///
+/// For something like:
+/// \code
+///  int *p;
+///  ...
+///  #pragma omp target enter data map(to:p[10:10])
+/// \endcode
+///
+/// for which the attachment operation gets represented using:
+/// \code
+///   &p, &p[10], sizeof(p), ATTACH
+/// \endcode
+///
+/// (Hst|Tgt)PtrAddr   represents &p
+/// (Hst|Tgt)PteeBase  represents &p[0]
+/// (Hst|Tgt)PteeBegin represents &p[10]
+///
+/// This function first computes the expected TgtPteeBase using:
+///   TgtPteeBase = TgtPteeBegin - (HstPteeBegin - HstPteeBase)
+///
+/// and then attaches TgtPteeBase to TgtPtrAddr.
+///
+/// \p HstPtrSize represents the size of the pointer p. For C/C++, this
+/// should be same as "sizeof(void*)" (say 8).
+///
+/// However, for Fortran, pointers/allocatables, which are also eligible for
+/// "pointer-attachment", may be implemented using descriptors that contain the
+/// address of the pointee in the first 8 bytes, but also contain other
+/// information such as lower-bound/upper-bound etc in their subsequent fields.
+///
+/// For example, for the following:
+/// \code
+///   integer, allocatable :: x(:)
+///   integer, pointer :: p(:)
+///   ...
+///   p => x(10: 19)
+///   ...
+///   !$omp target enter data map(to:p(:))
+/// \endcode
+///
+/// The map should trigger a pointer-attachment (assuming the pointer-attachment
+/// conditions as noted on processAttachEntries are met) between the descriptor
+/// for p, and its pointee data.
+///
+/// Since only the first 8 bytes of the descriptor contain the address of the
+/// pointee, an attachment operation on device descriptors involves:
+/// * Setting the first 8 bytes of the device descriptor to point the device
+/// address of the pointee.
+/// * Copying the remaining information about bounds/offset etc. from the host
+/// descriptor to the device descriptor.
+///
+/// The function also handles pointer-attachment portion of PTR_AND_OBJ maps,
+/// like:
+/// \code
+///   &p, &p[10], 10 * sizeof(p[10]), PTR_AND_OBJ
+/// \endcoe
+/// by using "sizeof(void*)" as \p HstPtrSize.
+static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
+                                    void **HstPtrAddr, void *HstPteeBase,
+                                    void *HstPteeBegin, void **TgtPtrAddr,
+                                    void *TgtPteeBegin, int64_t HstPtrSize,
+                                    TargetPointerResultTy &PtrTPR) {
+  assert(PtrTPR.getEntry() &&
+         "Need a valid pointer entry to perform pointer-attachment");
+
+  int64_t VoidPtrSize = sizeof(void *);
+  assert(HstPtrSize >= VoidPtrSize && "PointerSize is too small");
+
+  uint64_t Delta = (uint64_t)HstPteeBegin - (uint64_t)HstPteeBase;
+  void *TgtPteeBase = (void *)((uint64_t)TgtPteeBegin - Delta);
+
+  // Add shadow pointer tracking
+  // TODO: Support shadow-tracking of larger than VoidPtrSize pointers,
+  // to support restoration of Fortran descriptors. Currently, this check
+  // would return false, even if the host Fortran descriptor was, and we
+  // should have done an update of the device descriptor. e.g.
+  //
+  //   !$omp target enter data map(x(1:100)) !             (1)
+  //   p => x(10: 19)
+  //   !$omp target enter data map(p, p(:)) !              (2)
+  //   p => x(5: 9)
+  //   !$omp target enter data map(attach(always): p(:)) ! (3)
+  //
+  // While PtrAddr(&desc_p) and PteeBase(&p(1)) are same for (2) and (3), the
+  // pointer attachment for (3) needs to update the bounds information
+  // in the descriptor of p on device.
+  if (!PtrTPR.getEntry()->addShadowPointer(
+          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase}))
+    return OFFLOAD_SUCCESS;
+
+  DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n", DPxPTR(TgtPtrAddr),
+     DPxPTR(TgtPteeBase));
+
+  // Lambda to handle submitData result and perform final steps.
+  auto HandleSubmitResult = [&](int SubmitResult) -> int {
+    if (SubmitResult != OFFLOAD_SUCCESS) {
+      REPORT("Failed to update pointer on device.\n");
+      return OFFLOAD_FAIL;
+    }
+
+    if (PtrTPR.getEntry()->addEventIfNecessary(Device, AsyncInfo) !=
+        OFFLOAD_SUCCESS)
+      return OFFLOAD_FAIL;
+
+    return OFFLOAD_SUCCESS;
+  };
+
+  bool IsPtrAFortranDescriptor = HstPtrSize > VoidPtrSize;
+  if (!IsPtrAFortranDescriptor) {
+    // For "regular" pointers, we can use the VoidPtrLocation from AsyncInfo as
+    // the buffer space for the submission.
+    void *&BufferElement = AsyncInfo.getVoidPtrLocation();
+    BufferElement = TgtPteeBase;
+
+    // Submit the updated pointer value to device
+    return HandleSubmitResult(Device.submitData(
+        TgtPtrAddr, &BufferElement, VoidPtrSize, AsyncInfo, PtrTPR.getEntry()));
+  }
+
+  // For larger "pointers" (like Fortran's descriptors), we create a dynamic
+  // buffer, which will be eventually destroyed by AsyncInfo's post-processing
+  // callback.
+  char *DataBuffer = new char[HstPtrSize];
+
+  // For such descriptors, to the first VoidPtrSize bytes, we store the
+  // pointee's device address.
+  std::memcpy(DataBuffer, &TgtPteeBase, sizeof(void *));
+
+  // And to the remaining bytes, we copy the remaining contents of the host
+  // descriptor after the initial VoidPtrSize bytes.
+  uint64_t HstDescriptorFieldsSize = HstPtrSize - VoidPtrSize;
+  void *HstDescriptorFieldsAddr = (char *)HstPtrAddr + VoidPtrSize;
+  std::memcpy(DataBuffer + VoidPtrSize, HstDescriptorFieldsAddr,
+              HstDescriptorFieldsSize);
+
+  DP("Updating %" PRId64 " bytes of descriptor (" DPxMOD ") (pointer + %" PRId64
+     " additional bytes from host descriptor " DPxMOD ")\n",
+     HstPtrSize, DPxPTR(TgtPtrAddr), HstDescriptorFieldsSize,
+     DPxPTR(HstDescriptorFieldsAddr));
+
+  // Submit the entire buffer to device
+  // FIXME: When handling ATTACH map-type, pointer attachment needs to happen
+  // after the other mapping operations are done, to avoid possibility of
+  // pending transfers clobbering the attachment, for example:
+  //
+  //   int *p = ...;
+  //   int **pp = &p;
+  //   map(to: pp[0], p[0])
+  //
+  // Which would be represented by:
+  // &pp[0], &pp[0], sizeof(pp[0]), TO (1)
+  // &p[0], &p[0], sizeof(p[0]), TO    (2)
+  //
+  // &pp, &pp[0], sizeof(pp), ATTACH   (3)
+  // &p, &p[0], sizeof(p), ATTACH      (4)
+  //
+  // (4) and (1) are both trying to modify the device memory corresponding to
+  // &p. We need to ensure that (4) happens last.
+  //
+  // One possible solution to this could be to insert a "device barrier" before
+  // the first ATTACH submitData call, so that every subsequent submitData waits
+  // for any prior operations to finish. Like:
+  //   Device.submitData(..., /*InOrder=*/IsFirstAttachEntry)
+  // Where the boolean InOrder being true means that this submission should
+  // wait for prior memory submissions to finish.
+  int SubmitResult =
+      Device.submitData(TgtPtrAddr, DataBuffer, HstPtrSize, AsyncInfo,
+                        PtrTPR.getEntry());
+
+  AsyncInfo.addPostProcessingFunction([DataBuffer]() -> int {
+    delete[] DataBuffer;
+    return OFFLOAD_SUCCESS;
+  });
+  return HandleSubmitResult(SubmitResult);
+}
+
 /// Internal function to do the mapping and transfer the data to the device
 int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                     void **ArgsBase, void **Args, int64_t *ArgSizes,
                     int64_t *ArgTypes, map_var_info_t *ArgNames,
                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
-                    bool FromMapper) {
+                    AttachInfoTy *AttachInfo, bool FromMapper) {
+  assert(AttachInfo && "AttachInfo must be available for targetDataBegin for "
+                       "handling ATTACH map-types.");
   // process each input.
   for (int32_t I = 0; I < ArgNum; ++I) {
     // Ignore private variables and arrays - there is no mapping for them.
@@ -352,7 +532,7 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
       map_var_info_t ArgName = (!ArgNames) ? nullptr : ArgNames[I];
       int Rc = targetDataMapper(Loc, Device, ArgsBase[I], Args[I], ArgSizes[I],
                                 ArgTypes[I], ArgName, ArgMappers[I], AsyncInfo,
-                                targetDataBegin);
+                                targetDataBegin, AttachInfo);
 
       if (Rc != OFFLOAD_SUCCESS) {
         REPORT("Call to targetDataBegin via targetDataMapper for custom mapper"
@@ -369,6 +549,18 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
     int64_t DataSize = ArgSizes[I];
     map_var_info_t HstPtrName = (!ArgNames) ? nullptr : ArgNames[I];
 
+    // ATTACH map-types are supposed to be handled after all mapping for the
+    // construct is done. Defer their processing.
+    if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH) {
+      AttachInfo->AttachEntries.emplace_back(
+          /*PointerBase=*/HstPtrBase, /*PointeeBegin=*/HstPtrBegin,
+          /*PointerSize=*/DataSize, /*MapType=*/ArgTypes[I],
+          /*PointeeName=*/HstPtrName);
+
+      DP("Deferring ATTACH map-type processing for argument %d\n", I);
+      continue;
+    }
+
     // Adjust for proper alignment if this is a combined entry (for structs).
     // Look at the next argument - if that is MEMBER_OF this one, then this one
     // is a combined entry.
@@ -434,6 +626,11 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                                   : "device failure or illegal mapping");
         return OFFLOAD_FAIL;
       }
+
+      // Track new allocation, for eventual use in attachment decision-making.
+      if (PointerTpr.Flags.IsNewEntry && !IsHostPtr)
+        AttachInfo->NewAllocations[HstPtrBase] = sizeof(void *);
+
       DP("There are %zu bytes allocated at target address " DPxMOD " - is%s new"
          "\n",
          sizeof(void *), DPxPTR(PointerTgtPtrBegin),
@@ -464,6 +661,11 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                                 : "device failure or illegal mapping");
       return OFFLOAD_FAIL;
     }
+
+    // Track new allocation, for eventual use in attachment decision-making.
+    if (TPR.Flags.IsNewEntry && !IsHostPtr && TgtPtrBegin)
+      AttachInfo->NewAllocations[HstPtrBegin] = DataSize;
+
     DP("There are %" PRId64 " bytes allocated at target address " DPxMOD
        " - is%s new\n",
        DataSize, DPxPTR(TgtPtrBegin), (TPR.Flags.IsNewEntry ? "" : " not"));
@@ -476,30 +678,12 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
     }
 
     if (ArgTypes[I] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
-
-      uint64_t Delta = (uint64_t)HstPtrBegin - (uint64_t)HstPtrBase;
-      void *ExpectedTgtPtrBase = (void *)((uint64_t)TgtPtrBegin - Delta);
-
-      if (PointerTpr.getEntry()->addShadowPointer(ShadowPtrInfoTy{
-              (void **)PointerHstPtrBegin, HstPtrBase,
-              (void **)PointerTgtPtrBegin, ExpectedTgtPtrBase})) {
-        DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n",
-           DPxPTR(PointerTgtPtrBegin), DPxPTR(TgtPtrBegin));
-
-        void *&TgtPtrBase = AsyncInfo.getVoidPtrLocation();
-        TgtPtrBase = ExpectedTgtPtrBase;
-
-        int Ret =
-            Device.submitData(PointerTgtPtrBegin, &TgtPtrBase, sizeof(void *),
-                              AsyncInfo, PointerTpr.getEntry());
-        if (Ret != OFFLOAD_SUCCESS) {
-          REPORT("Copying data to device failed.\n");
-          return OFFLOAD_FAIL;
-        }
-        if (PointerTpr.getEntry()->addEventIfNecessary(Device, AsyncInfo) !=
-            OFFLOAD_SUCCESS)
-          return OFFLOAD_FAIL;
-      }
+      int Ret = performPointerAttachment(Device, AsyncInfo,
+                                         (void **)PointerHstPtrBegin, HstPtrBase, HstPtrBegin,
+                                         (void **)PointerTgtPtrBegin, TgtPtrBegin,
+                                         sizeof(void *), PointerTpr);
+      if (Ret != OFFLOAD_SUCCESS)
+        return OFFLOAD_FAIL;
     }
 
     // Check if variable can be used on the device:
@@ -515,6 +699,145 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
   return OFFLOAD_SUCCESS;
 }
 
+/// Process deferred ATTACH map entries collected during targetDataBegin.
+///
+/// From OpenMP's perspective, when mapping something that has a base pointer,
+/// such as:
+/// \code
+///   int *p;
+///   #pragma omp enter target data map(to: p[10:20])
+/// \endcode
+///
+/// a pointer-attachment between p and &p[10] should occur if both p and
+/// p[10] are present on the device after doing all allocations for all maps
+/// on the construct, and one of the following is true:
+///
+/// * The pointer p was newly allocated while handling the construct
+/// * The pointee p[10:20] was newly allocated while handling the construct
+/// * attach(always) map-type modifier was specified (OpenMP 6.1)
+///
+/// That's why we collect all attach entries and new memory allocations during
+/// targetDataBegin, and use that information to make the decision of whether
+/// to perform a pointer-attachment or not here, after maps have been handled.
+int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
+                         AsyncInfoTy &AsyncInfo) {
+  // Report all tracked allocations from both main loop and ATTACH processing
+  if (!AttachInfo.NewAllocations.empty()) {
+    DP("Tracked %u total new allocations:\n",
+       (unsigned)AttachInfo.NewAllocations.size());
+    for (const auto &Alloc : AttachInfo.NewAllocations) {
+      DP("  Host ptr: " DPxMOD ", Size: %" PRId64 " bytes\n",
+         DPxPTR(Alloc.first), Alloc.second);
+    }
+  }
+
+  if (AttachInfo.AttachEntries.empty())
+    return OFFLOAD_SUCCESS;
+
+  DP("Processing %zu deferred ATTACH map entries\n",
+     AttachInfo.AttachEntries.size());
+
+  for (size_t EntryIdx = 0; EntryIdx < AttachInfo.AttachEntries.size();
+       ++EntryIdx) {
+    const auto &AttachEntry = AttachInfo.AttachEntries[EntryIdx];
+
+    void **HstPtr = (void **)AttachEntry.PointerBase;
+
+    void *HstPteeBase = *HstPtr;
+    void *HstPteeBegin = AttachEntry.PointeeBegin;
+
+    int64_t PtrSize = AttachEntry.PointerSize;
+    int64_t MapType = AttachEntry.MapType;
+
+    DP("Processing ATTACH entry %zu: HstPtr=" DPxMOD ", HstPteeBegin=" DPxMOD
+       ", Size=%" PRId64 ", Type=0x%" PRIx64 "\n",
+       EntryIdx, DPxPTR(HstPtr), DPxPTR(HstPteeBegin), PtrSize, MapType);
+
+    const bool IsAttachAlways = MapType & OMP_TGT_MAPTYPE_ALWAYS;
+
+    // Lambda to check if a pointer was newly allocated
+    auto WasNewlyAllocated = [&](void *Ptr, const char *PtrName) {
+      bool IsNewlyAllocated =
+          llvm::any_of(AttachInfo.NewAllocations, [&](const auto &Alloc) {
+            void *AllocPtr = Alloc.first;
+            int64_t AllocSize = Alloc.second;
+            return Ptr >= AllocPtr &&
+                   Ptr < (void *)((char *)AllocPtr + AllocSize);
+          });
+      DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
+         EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
+      return IsNewlyAllocated;
+    };
+
+    // Only process ATTACH if base/begin was newly allocated OR ALWAYS flag is
+    // set
+    if (!IsAttachAlways && !WasNewlyAllocated(HstPtr, "pointer") &&
+        !WasNewlyAllocated(HstPteeBegin, "pointee")) {
+      DP("Skipping ATTACH entry %zu: neither pointer nor pointee was newly "
+         "allocated and no ALWAYS flag\n",
+         EntryIdx);
+      continue;
+    }
+
+    DP("Processing ATTACH entry %zu: Always=%s\n", EntryIdx,
+       IsAttachAlways ? "yes" : "no");
+
+    // Lambda to perform target pointer lookup and validation
+    auto LookupTargetPointer = [&](void *Ptr, int64_t Size, const char *PtrType)
+        -> std::optional<TargetPointerResultTy> {
+      // ATTACH map-type does not change ref-count, or do any allocation
+      // We just need to do a lookup for the pointer/pointee.
+      TargetPointerResultTy TPR = Device.getMappingInfo().getTgtPtrBegin(
+          Ptr, Size, /*UpdateRefCount=*/false,
+          /*UseHoldRefCount=*/false, /*MustContain=*/true);
+
+      DP("ATTACH entry %zu: %s lookup - HstPtr=" DPxMOD ", TgtPtr=" DPxMOD
+         ", IsPresent=%s, IsHostPtr=%s\n",
+         EntryIdx, PtrType, DPxPTR(Ptr), DPxPTR(TPR.TargetPointer),
+         TPR.isPresent() ? "yes" : "no",
+         TPR.Flags.IsHostPointer ? "yes" : "no");
+
+      if (!TPR.isPresent()) {
+        DP("Skipping ATTACH entry %zu: %s not present on device\n", EntryIdx,
+           PtrType);
+        return std::nullopt;
+      }
+      if (TPR.Flags.IsHostPointer) {
+        DP("Skipping ATTACH entry %zu: device version of the %s is a host "
+           "pointer.\n",
+           EntryIdx, PtrType);
+        return std::nullopt;
+      }
+
+      return TPR;
+    };
+
+    // Get device version of the pointer (e.g., &p)
+    auto PtrTPROpt = LookupTargetPointer(HstPtr, PtrSize, "pointer");
+    if (!PtrTPROpt)
+      continue;
+    TargetPointerResultTy &PtrTPR = *PtrTPROpt;
+    void **TgtPtrBase = (void **)PtrTPR.TargetPointer;
+
+    // Get device version of the pointee (e.g., &p[10])
+    auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");
+    if (!PteeTPROpt)
+      continue;
+    void *TgtPteeBegin = PteeTPROpt->TargetPointer;
+
+    // Update the device pointer to point to device pointee.
+    int Ret = performPointerAttachment(Device, AsyncInfo, HstPtr, HstPteeBase,
+                                       HstPteeBegin, TgtPtrBase, TgtPteeBegin,
+                                       PtrSize, PtrTPR);
+    if (Ret != OFFLOAD_SUCCESS)
+      return OFFLOAD_FAIL;
+
+    DP("ATTACH entry %zu processed successfully\n", EntryIdx);
+  }
+
+  return OFFLOAD_SUCCESS;
+}
+
 namespace {
 /// This structure contains information to deallocate a target pointer, aka.
 /// used to fix up the shadow map and potentially delete the entry from the
@@ -624,7 +947,8 @@ postProcessingTargetDataEnd(DeviceTy *Device,
 int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                   void **ArgBases, void **Args, int64_t *ArgSizes,
                   int64_t *ArgTypes, map_var_info_t *ArgNames,
-                  void **ArgMappers, AsyncInfoTy &AsyncInfo, bool FromMapper) {
+                  void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                  AttachInfoTy *AttachInfo, bool FromMapper) {
   int Ret = OFFLOAD_SUCCESS;
   auto *PostProcessingPtrs = new SmallVector<PostProcessingInfo>();
   // process each input.
@@ -635,6 +959,14 @@ int targetDataEnd(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
         (ArgTypes[I] & OMP_TGT_MAPTYPE_PRIVATE))
       continue;
 
+    // Ignore ATTACH entries - they should only be honored on map-entering
+    // directives. They may be encountered here while handling the "end" part of
+    // "#pragma omp target".
+    if (ArgTypes[I] & OMP_TGT_MAPTYPE_ATTACH) {
+      DP("Ignoring ATTACH entry %d in targetDataEnd\n", I);
+      continue;
+    }
+
     if (ArgMappers && ArgMappers[I]) {
       // Instead of executing the regular path of targetDataEnd, call the
       // targetDataMapper variant which will call targetDataEnd again
@@ -900,7 +1232,8 @@ static int getNonContigMergedDimension(__tgt_target_non_contig *NonContig,
 int targetDataUpdate(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
                      void **ArgsBase, void **Args, int64_t *ArgSizes,
                      int64_t *ArgTypes, map_var_info_t *ArgNames,
-                     void **ArgMappers, AsyncInfoTy &AsyncInfo, bool) {
+                     void **ArgMappers, AsyncInfoTy &AsyncInfo,
+                     AttachInfoTy *AttachInfo, bool FromMapper) {
   // process each input.
   for (int32_t I = 0; I < ArgNum; ++I) {
     if ((ArgTypes[I] & OMP_TGT_MAPTYPE_LITERAL) ||
@@ -1213,13 +1546,27 @@ static int processDataBefore(ident_t *Loc, int64_t DeviceId, void *HostPtr,
   if (!DeviceOrErr)
     FATAL_MESSAGE(DeviceId, "%s", toString(DeviceOrErr.takeError()).c_str());
 
+  // Create AttachInfo for tracking any ATTACH entries, or new-allocations
+  // when handling the "begin" mapping for a target constructs.
+  AttachInfoTy AttachInfo;
+
   int Ret = targetDataBegin(Loc, *DeviceOrErr, ArgNum, ArgBases, Args, ArgSizes,
-                            ArgTypes, ArgNames, ArgMappers, AsyncInfo);
+                            ArgTypes, ArgNames, ArgMappers, AsyncInfo,
+                            &AttachInfo, false /*FromMapper=*/);
   if (Ret != OFFLOAD_SUCCESS) {
     REPORT("Call to targetDataBegin failed, abort target.\n");
     return OFFLOAD_FAIL;
   }
 
+  // Process collected ATTACH entries
+  if (!AttachInfo.AttachEntries.empty()) {
+    Ret = processAttachEntries(*DeviceOrErr, AttachInfo, AsyncInfo);
+    if (Ret != OFFLOAD_SUCCESS) {
+      REPORT("Failed to process ATTACH entries.\n");
+      return OFFLOAD_FAIL;
+    }
+  }
+
   // List of (first-)private arrays allocated for this target region
   SmallVector<int> TgtArgsPositions(ArgNum, -1);
 

>From b645d581e7add334bcdb11b5c845582c696d47cc Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 01:47:34 -0700
Subject: [PATCH 26/66] Minor format/stylistic changes.

---
 offload/libomptarget/interface.cpp |  7 +++----
 offload/libomptarget/omptarget.cpp | 18 +++++++++---------
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index 16e46e6d23872..1a65262f9dcda 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -168,13 +168,12 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
 
   // Only allocate AttachInfo for targetDataBegin
   AttachInfoTy *AttachInfo = nullptr;
-  if (TargetDataFunction == targetDataBegin) {
+  if (TargetDataFunction == targetDataBegin)
     AttachInfo = new AttachInfoTy();
-  }
 
   Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
-                          ArgTypes, ArgNames, ArgMappers, AsyncInfo,
-                          AttachInfo, false /*FromMapper=*/);
+                          ArgTypes, ArgNames, ArgMappers, AsyncInfo, AttachInfo,
+                          /*FromMapper=*/false);
 
   if (Rc == OFFLOAD_SUCCESS) {
     // Process deferred ATTACH entries BEFORE synchronization
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index aa142814e8384..b5bbc5a409e85 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -496,9 +496,8 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   //   Device.submitData(..., /*InOrder=*/IsFirstAttachEntry)
   // Where the boolean InOrder being true means that this submission should
   // wait for prior memory submissions to finish.
-  int SubmitResult =
-      Device.submitData(TgtPtrAddr, DataBuffer, HstPtrSize, AsyncInfo,
-                        PtrTPR.getEntry());
+  int SubmitResult = Device.submitData(TgtPtrAddr, DataBuffer, HstPtrSize,
+                                       AsyncInfo, PtrTPR.getEntry());
 
   AsyncInfo.addPostProcessingFunction([DataBuffer]() -> int {
     delete[] DataBuffer;
@@ -678,10 +677,10 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
     }
 
     if (ArgTypes[I] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
-      int Ret = performPointerAttachment(Device, AsyncInfo,
-                                         (void **)PointerHstPtrBegin, HstPtrBase, HstPtrBegin,
-                                         (void **)PointerTgtPtrBegin, TgtPtrBegin,
-                                         sizeof(void *), PointerTpr);
+      int Ret = performPointerAttachment(
+          Device, AsyncInfo, (void **)PointerHstPtrBegin, HstPtrBase,
+          HstPtrBegin, (void **)PointerTgtPtrBegin, TgtPtrBegin, sizeof(void *),
+          PointerTpr);
       if (Ret != OFFLOAD_SUCCESS)
         return OFFLOAD_FAIL;
     }
@@ -783,8 +782,9 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
        IsAttachAlways ? "yes" : "no");
 
     // Lambda to perform target pointer lookup and validation
-    auto LookupTargetPointer = [&](void *Ptr, int64_t Size, const char *PtrType)
-        -> std::optional<TargetPointerResultTy> {
+    auto LookupTargetPointer =
+        [&](void *Ptr, int64_t Size,
+            const char *PtrType) -> std::optional<TargetPointerResultTy> {
       // ATTACH map-type does not change ref-count, or do any allocation
       // We just need to do a lookup for the pointer/pointee.
       TargetPointerResultTy TPR = Device.getMappingInfo().getTgtPtrBegin(

>From 13faca11e08c6e58853e278494c86c2ba0f31fc2 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 02:14:54 -0700
Subject: [PATCH 27/66] Minor formatting changes.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 473 ++++++++++--------
 .../llvm/Frontend/OpenMP/OMPConstants.h       |   4 +-
 2 files changed, 268 insertions(+), 209 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 3d9acf513935a..d692caac9cf4a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6924,7 +6924,7 @@ class MappableExprsHandler {
     llvm::errs() << "DEBUG getExprTypeSize: ENTRY\n";
     llvm::errs() << "  Expression: ";
     E->dump();
-    
+
     QualType ExprTy = E->getType().getCanonicalType();
 
     // Calculate the size for array shaping expression.
@@ -6939,7 +6939,8 @@ class MappableExprsHandler {
                                       SE->getExprLoc());
         Size = CGF.Builder.CreateNUWMul(Size, Sz);
       }
-      llvm::errs() << "DEBUG getExprTypeSize: Returning size for ArrayShapingExpr\n";
+      llvm::errs()
+          << "DEBUG getExprTypeSize: Returning size for ArrayShapingExpr\n";
       return Size;
     }
 
@@ -6961,7 +6962,8 @@ class MappableExprsHandler {
       // base.
       if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
           !OAE->getLowerBound()) {
-        llvm::errs() << "DEBUG getExprTypeSize: Using whole length of base for ArraySection\n";
+        llvm::errs() << "DEBUG getExprTypeSize: Using whole length of base for "
+                        "ArraySection\n";
         return CGF.getTypeSize(BaseTy);
       }
 
@@ -7021,7 +7023,7 @@ class MappableExprsHandler {
     llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
     llvm::errs() << "  AddIsTargetParamFlag: " << AddIsTargetParamFlag << "\n";
     llvm::errs() << "  IsNonContiguous: " << IsNonContiguous << "\n";
-    
+
     OpenMPOffloadMappingFlags Bits =
         IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
                    : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
@@ -7064,9 +7066,10 @@ class MappableExprsHandler {
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
     if (IsNonContiguous)
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
-    
+
     // DEBUG: Print final flags
-    llvm::errs() << "DEBUG getMapTypeBits: Final bits = " << static_cast<unsigned>(Bits) << "\n";
+    llvm::errs() << "DEBUG getMapTypeBits: Final bits = "
+                 << static_cast<unsigned>(Bits) << "\n";
     return Bits;
   }
 
@@ -7077,18 +7080,20 @@ class MappableExprsHandler {
     llvm::errs() << "DEBUG isFinalArraySectionExpression: ENTRY\n";
     llvm::errs() << "  Expression: ";
     E->dump();
-    
+
     const auto *OASE = dyn_cast<ArraySectionExpr>(E);
 
     // It is not an array section and therefore not a unity-size one.
     if (!OASE) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: Not ArraySectionExpr, returning false\n";
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: Not "
+                      "ArraySectionExpr, returning false\n";
       return false;
     }
 
     // An array section with no colon always refer to a single element.
     if (OASE->getColonLocFirst().isInvalid()) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: No colon, single element, returning false\n";
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: No colon, single "
+                      "element, returning false\n";
       return false;
     }
 
@@ -7112,27 +7117,35 @@ class MappableExprsHandler {
     // Check if the length evaluates to 1.
     Expr::EvalResult Result;
     if (!Length->EvaluateAsInt(Result, CGF.getContext())) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: Cannot evaluate length as int, returning true\n";
+      llvm::errs() << "DEBUG isFinalArraySectionExpression: Cannot evaluate "
+                      "length as int, returning true\n";
       return true; // Can have more that size 1.
     }
 
     llvm::APSInt ConstLength = Result.Val.getInt();
     bool result = ConstLength.getSExtValue() != 1;
-    llvm::errs() << "DEBUG isFinalArraySectionExpression: Length = " << ConstLength.getSExtValue() 
-                 << ", returning " << result << "\n";
+    llvm::errs() << "DEBUG isFinalArraySectionExpression: Length = "
+                 << ConstLength.getSExtValue() << ", returning " << result
+                 << "\n";
     return result;
   }
 
   /// Utility function to add an ATTACH entry to the CombinedInfo structure.
-  /// Generates an ATTACH entry: &pointer, &pointer[idx], sizeof(pointer), ATTACH
+  /// Generates an ATTACH entry: &pointer, &pointer[idx], sizeof(pointer),
+  /// ATTACH
   void addAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
                       Address AttachBaseAddr, Address AttachFirstElemAddr,
                       const ValueDecl *BaseDecl, const Expr *MapExpr) const {
     llvm::errs() << "DEBUG addAttachEntry: Adding ATTACH entry\n";
-    llvm::errs() << "  AttachBaseAddr = "; AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-    llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-    
-    // Size is the size of the pointer itself - use pointer size, not BaseDecl size
+    llvm::errs() << "  AttachBaseAddr = ";
+    AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
+    llvm::errs() << "\n";
+    llvm::errs() << "  AttachFirstElemAddr = ";
+    AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
+    llvm::errs() << "\n";
+
+    // Size is the size of the pointer itself - use pointer size, not BaseDecl
+    // size
     llvm::Value *PointerSize = CGF.Builder.CreateIntCast(
         llvm::ConstantInt::get(
             CGF.CGM.SizeTy,
@@ -7150,7 +7163,7 @@ class MappableExprsHandler {
     CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
     CombinedInfo.Mappers.push_back(nullptr);
     CombinedInfo.NonContigInfo.Dims.push_back(1);
-    
+
     llvm::errs() << "DEBUG addAttachEntry: ATTACH entry added successfully\n";
   }
 
@@ -7171,13 +7184,14 @@ class MappableExprsHandler {
       const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr,
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
           OverlappedElements = {}) const {
-    
+
     // DEBUG: Print function entry information
     llvm::errs() << "DEBUG generateInfoForComponentList: ENTRY\n";
     llvm::errs() << "  MapType: " << MapType << "\n";
     llvm::errs() << "  IsFirstComponentList: " << IsFirstComponentList << "\n";
     llvm::errs() << "  IsImplicit: " << IsImplicit << "\n";
-    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses << "\n";
+    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses
+                 << "\n";
     llvm::errs() << "  ForDeviceAddr: " << ForDeviceAddr << "\n";
     llvm::errs() << "  Components.size(): " << Components.size() << "\n";
     if (BaseDecl) {
@@ -7187,9 +7201,7 @@ class MappableExprsHandler {
       llvm::errs() << "  MapExpr: ";
       MapExpr->dump();
     }
-    
 
-    Expr *PossibleBasePtr = nullptr;
     // The following summarizes what has to be generated for each map and the
     // types below. The generated information is expressed in this order:
     // base pointer, section pointer, size, flags
@@ -7418,7 +7430,7 @@ class MappableExprsHandler {
     Address AttachFirstElemAddr = Address::invalid();
 
     // Find the component that should use ATTACH-style mapping.
-    auto AttachInfo = findAttachComponent(Components);
+    auto AttachInfo = findAttachBasePointer(Components);
 
     llvm::errs() << "DEBUG generateInfoForComponentList: Computing initial BP\n";
     if (isa<MemberExpr>(AssocExpr)) {
@@ -7485,10 +7497,6 @@ class MappableExprsHandler {
           FirstPointerInComplexData = true;
         }
 
-        if (I->getAssociatedExpression()->getType()->isAnyPointerType() && std::next(I) != CE)
-          PossibleBasePtr = I->getAssociatedExpression();
-
-
         ++I;
         // DEBUG: Print what I now points to after increment
         if (I != CE) {
@@ -7553,7 +7561,7 @@ class MappableExprsHandler {
     bool IsMappingWholeStruct = true;
     llvm::errs() << "DEBUG generateInfoForComponentList: Checking IsMappingWholeStruct logic\n";
     llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses << "\n";
-    
+
     if (!GenerateAllInfoForClauses) {
       llvm::errs() << "  Setting IsMappingWholeStruct=false (GenerateAllInfoForClauses=false)\n";
       IsMappingWholeStruct = false;
@@ -7586,7 +7594,7 @@ class MappableExprsHandler {
         llvm::errs() << "  AssociatedExpression: ";
         I->getAssociatedExpression()->dump();
       }
-      
+
       // If the current component is member of a struct (parent struct) mark it.
       if (!EncounteredME) {
         EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
@@ -7628,7 +7636,7 @@ class MappableExprsHandler {
       bool IsFinalArraySection =
           !IsNonContiguous &&
           isFinalArraySectionExpression(I->getAssociatedExpression());
-      
+
       // DEBUG: Print array section information
       llvm::errs() << "DEBUG generateInfoForComponentList: IsFinalArraySection: " << IsFinalArraySection << "\n";
 
@@ -7639,7 +7647,7 @@ class MappableExprsHandler {
                                      : BaseDecl;
       MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
                                                : MapExpr;
-      
+
       // DEBUG: Print mapping declaration and expression
       llvm::errs() << "DEBUG generateInfoForComponentList: MapDecl: ";
       if (MapDecl) {
@@ -7652,7 +7660,7 @@ class MappableExprsHandler {
       // special treatment for array sections given that they are built-in
       // types.
       llvm::errs() << "DEBUG generateInfoForComponentList: Analyzing expression types\n";
-      
+
       const auto *OASE =
           dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
       const auto *ASE =
@@ -7661,13 +7669,13 @@ class MappableExprsHandler {
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
       const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
       const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
-      
+
       llvm::errs() << "  OASE (ArraySectionExpr): " << (OASE ? "yes" : "no") << "\n";
       llvm::errs() << "  ASE (ArraySubscriptExpr): " << (ASE ? "yes" : "no") << "\n";
       llvm::errs() << "  OAShE (OMPArrayShapingExpr): " << (OAShE ? "yes" : "no") << "\n";
       llvm::errs() << "  UO (UnaryOperator): " << (UO ? "yes" : "no") << "\n";
       llvm::errs() << "  BO (BinaryOperator): " << (BO ? "yes" : "no") << "\n";
-      
+
       bool IsPointer =
           OAShE ||
           (OASE && ArraySectionExpr::getBaseOriginalType(OASE)
@@ -7680,7 +7688,7 @@ class MappableExprsHandler {
       bool IsNonDerefPointer = IsPointer &&
                                !(UO && UO->getOpcode() != UO_Deref) && !BO &&
                                !IsNonContiguous;
-      
+
       llvm::errs() << "  IsPointer: " << IsPointer << "\n";
       llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
       llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
@@ -7695,9 +7703,6 @@ class MappableExprsHandler {
       llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
       llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
       llvm::errs() << "  IsFinalArraySection: " << IsFinalArraySection << "\n";
-      if (I->getAssociatedExpression()->getType()->isAnyPointerType() && std::next(I) != CE) {
-        PossibleBasePtr = I->getAssociatedExpression();
-      }
       if (Next == CE || IsMemberReference || IsNonDerefPointer ||
           IsFinalArraySection) {
         llvm::errs() << "  CONDITION MET: Generating address and size info\n";
@@ -7774,7 +7779,7 @@ class MappableExprsHandler {
         if (Next != CE) {
           llvm::errs() << "  Next->getAssociatedExpression()->getType()->isPointerType(): " << Next->getAssociatedExpression()->getType()->isPointerType() << "\n";
         }
-        
+
         bool IsMemberPointerOrAddr =
             EncounteredME &&
             (((IsPointer || ForDeviceAddr) &&
@@ -7782,7 +7787,7 @@ class MappableExprsHandler {
              (IsPrevMemberReference && !IsPointer) ||
              (IsMemberReference && Next != CE &&
               !Next->getAssociatedExpression()->getType()->isPointerType()));
-        
+
         llvm::errs() << "  IsMemberPointerOrAddr: " << IsMemberPointerOrAddr << "\n";
         if (!OverlappedElements.empty() && Next == CE) {
           // Handle base element with the info for overlapped elements.
@@ -7880,29 +7885,9 @@ class MappableExprsHandler {
           break;
         }
         llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
-        
+
         // DEBUG: Print size calculation result
         llvm::errs() << "DEBUG generateInfoForComponentList: Size calculated for expression\n";
-
-        // Lambda to handle BP loading for global pointers
-//         auto LoadGlobalPointerIfNeeded = [&]() {
-//           if (FirstPointerInComplexData) {
-//             llvm::errs() << "DEBUG generateInfoForComponentList: LoadGlobalPointerIfNeeded - updating BP\n";
-//             llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-//             QualType Ty = Components.rbegin()
-//                               ->getAssociatedDeclaration()
-//                               ->getType()
-//                               .getNonReferenceType();
-//             BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-//             llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-//             FirstPointerInComplexData = false;
-//           }
-//         };
-//         (void) LoadGlobalPointerIfNeeded;
-//
-// //        if (IsAttachablePointeeExpr)
-//   //        LoadGlobalPointerIfNeeded();
-
         // Skip adding an entry in the CurInfo of this combined entry if the
         // whole struct is currently being mapped. The struct needs to be added
         // in the first position before any data internal to the struct is being
@@ -7962,11 +7947,11 @@ class MappableExprsHandler {
           llvm::errs() << "  FirstPointerInComplexData: " << FirstPointerInComplexData << "\n";
           llvm::errs() << "  IsCaptureFirstInfo: " << IsCaptureFirstInfo << "\n";
 
-          bool AddPtrFlag = (!IsExpressionFirstInfo || RequiresReference ||
-                             FirstPointerInComplexData || IsMemberReference); //&&
-                            // !IsAttachablePointeeExpr;
+          bool AddPtrFlag =
+              (!IsExpressionFirstInfo || RequiresReference ||
+               FirstPointerInComplexData || IsMemberReference);
           llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
-          
+
           OpenMPOffloadMappingFlags Flags =
               getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
                              AddPtrFlag, IsCaptureFirstInfo && !RequiresReference,
@@ -8053,41 +8038,81 @@ class MappableExprsHandler {
           PartialStruct.IsArraySection = true;
 
         if (Next == CE) {
-          llvm::errs() << "DEBUG generateInfoForComponentList: Reached the end of components\n";
-          // Generate ATTACH entry for array sections and subscripts on standalone
-          // pointers Info was already collected during the main component loop
-          // Check if we should use ATTACH-style mapping for this expression
-          bool IsAttachablePointeeExpr = AttachInfo.IsValid && AttachInfo.BasePtrDecl && AttachInfo.BasePtrDecl == BaseDecl;
-          llvm::errs() << "DEBUG generateInfoForComponentList: AttachInfo.PteeExpr: "; if (AttachInfo.PteeExpr) AttachInfo.PteeExpr->dump(); else llvm::errs() << "nullptr\n";
-          llvm::errs() << "DEBUG generateInfoForComponentList: AttachInfo.BasePtrExpr: "; if (AttachInfo.BasePtrExpr) AttachInfo.BasePtrExpr->dump(); else llvm::errs() << "nullptr\n";
-          llvm::errs() << "DEBUG generateInfoForComponentList: PossibleBasePtr: "; if (PossibleBasePtr) PossibleBasePtr->dump(); else llvm::errs() << "nullptr\n";
-          llvm::errs() << "DEBUG generateInfoForComponentList: I: "; if (I->getAssociatedExpression()) I->getAssociatedExpression()->dump(); else llvm::errs() << "nullptr\n";
+          llvm::errs() << "DEBUG generateInfoForComponentList: Reached the end "
+                          "of components\n";
+          // Generate ATTACH entry for array sections and subscripts on
+          // standalone pointers Info was already collected during the main
+          // component loop Check if we should use ATTACH-style mapping for this
+          // expression
+          bool IsAttachablePointeeExpr = AttachInfo.IsValid &&
+                                         AttachInfo.BasePtrDecl &&
+                                         AttachInfo.BasePtrDecl == BaseDecl;
+          llvm::errs()
+              << "DEBUG generateInfoForComponentList: AttachInfo.PteeExpr: ";
+          if (AttachInfo.PteeExpr)
+            AttachInfo.PteeExpr->dump();
+          else
+            llvm::errs() << "nullptr\n";
+          llvm::errs()
+              << "DEBUG generateInfoForComponentList: AttachInfo.BasePtrExpr: ";
+          if (AttachInfo.BasePtrExpr)
+            AttachInfo.BasePtrExpr->dump();
+          else
+            llvm::errs() << "nullptr\n";
+          llvm::errs() << "DEBUG generateInfoForComponentList: I: ";
+          if (I->getAssociatedExpression())
+            I->getAssociatedExpression()->dump();
+          else
+            llvm::errs() << "nullptr\n";
 
           if (IsAttachablePointeeExpr) {
-            llvm::errs() << "DEBUG generateInfoForComponentList: Computing ATTACH addresses\n";
+            llvm::errs() << "DEBUG generateInfoForComponentList: Computing "
+                            "ATTACH addresses\n";
 
             // Use BasePtrExpr for AttachBaseAddr
             llvm::errs() << "  Using BasePtrExpr for AttachBaseAddr\n";
-            AttachBaseAddr = CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
-            llvm::errs() << "  AttachBaseAddr = "; AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+            AttachBaseAddr =
+                CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
+            llvm::errs() << "  AttachBaseAddr = ";
+            AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
+            llvm::errs() << "\n";
 
             if (OASE) {
-              llvm::errs() << "  ArraySectionExpr case for AttachFirstElemAddr\n";
-              AttachFirstElemAddr = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
-              llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+              llvm::errs()
+                  << "  ArraySectionExpr case for AttachFirstElemAddr\n";
+              AttachFirstElemAddr =
+                  CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true)
+                      .getAddress();
+              llvm::errs() << "  AttachFirstElemAddr = ";
+              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
+                  llvm::errs());
+              llvm::errs() << "\n";
             } else if (ASE) {
-              llvm::errs() << "  ArraySubscriptExpr case for AttachFirstElemAddr\n";
+              llvm::errs()
+                  << "  ArraySubscriptExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
-              llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-            } else if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
-               llvm::errs() << "  MemberExpr case for AttachFirstElemAddr\n";
-               AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
-               llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-            } else if (auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression())) {
+              llvm::errs() << "  AttachFirstElemAddr = ";
+              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
+                  llvm::errs());
+              llvm::errs() << "\n";
+            } else if (auto *ME =
+                           dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
+              llvm::errs() << "  MemberExpr case for AttachFirstElemAddr\n";
+              AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
+              llvm::errs() << "  AttachFirstElemAddr = ";
+              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
+                  llvm::errs());
+              llvm::errs() << "\n";
+            } else if (auto *UO = dyn_cast<UnaryOperator>(
+                           I->getAssociatedExpression())) {
               if (UO->getOpcode() == UO_Deref) {
-                llvm::errs() << "  UnaryOperator (dereference) case for AttachFirstElemAddr\n";
+                llvm::errs() << "  UnaryOperator (dereference) case for "
+                                "AttachFirstElemAddr\n";
                 AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
-                llvm::errs() << "  AttachFirstElemAddr = "; AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+                llvm::errs() << "  AttachFirstElemAddr = ";
+                AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
+                    llvm::errs());
+                llvm::errs() << "\n";
               }
             }
           }
@@ -8104,14 +8129,6 @@ class MappableExprsHandler {
           llvm::errs() << "  Current BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           BP = IsMemberReference ? LowestElem : LB;
           llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << " (using " << (IsMemberReference ? "LowestElem" : "LB") << ")\n";
-          // if (!EncounteredME && AttachInfo.IsValid && AttachInfo.PteeExpr &&
-          //     Next->getAssociatedExpression() == AttachInfo.PteeExpr) {
-          //   llvm::errs() << "  Doing an extra load from BP since next item is attachable: \n";
-          //   // Do an extra load from BP
-          //   BP = CGF.EmitLoadOfPointer(
-          //       BP, I->getAssociatedExpression()->getType()->castAs<PointerType>());
-          // }
-          // llvm::errs() << "  Updated BP with load = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         }
         if (!IsPartialMapped)
           IsExpressionFirstInfo = false;
@@ -8141,21 +8158,28 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
-    // Handle ATTACH entries: delay if PartialStruct is being populated, otherwise add immediately
+    // Handle ATTACH entries: delay if PartialStruct is being populated,
+    // otherwise add immediately
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
       if (PartialStruct.Base.isValid()) {
-        // We're populating PartialStruct, delay ATTACH entry addition until after emitCombinedEntry
-        llvm::errs() << "DEBUG generateInfoForComponentList: Saving ATTACH info for delayed processing\n";
+        // We're populating PartialStruct, delay ATTACH entry addition until
+        // after emitCombinedEntry
+        llvm::errs() << "DEBUG generateInfoForComponentList: Saving ATTACH "
+                        "info for delayed processing\n";
         PartialStruct.AttachBaseAddr = AttachBaseAddr;
         PartialStruct.AttachFirstElemAddr = AttachFirstElemAddr;
         PartialStruct.AttachBaseDecl = BaseDecl;
         PartialStruct.AttachMapExpr = MapExpr;
       } else if (IsMappingWholeStruct) {
-        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to StructBaseCombinedInfo\n";
-        addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr, AttachFirstElemAddr, BaseDecl, MapExpr);
+        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to "
+                        "StructBaseCombinedInfo\n";
+        addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr,
+                       AttachFirstElemAddr, BaseDecl, MapExpr);
       } else {
-        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to CombinedInfo\n";
-        addAttachEntry(CGF, CombinedInfo, AttachBaseAddr, AttachFirstElemAddr, BaseDecl, MapExpr);
+        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to "
+                        "CombinedInfo\n";
+        addAttachEntry(CGF, CombinedInfo, AttachBaseAddr, AttachFirstElemAddr,
+                       BaseDecl, MapExpr);
       }
     }
 
@@ -8334,7 +8358,7 @@ class MappableExprsHandler {
     CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
     CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
     CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
-    
+
     // DEBUG: Print exit information
     llvm::errs() << "DEBUG generateInfoForComponentList: EXIT\n";
     llvm::errs() << "  CombinedInfo entries added: " << CombinedInfo.BasePointers.size() << "\n";
@@ -8437,99 +8461,126 @@ class MappableExprsHandler {
     }
   }
 
-/// Result structure for findAttachComponent
-struct AttachInfo {
-  const Expr *BasePtrExpr = nullptr;  // The pointer expression
-  const ValueDecl *BasePtrDecl = nullptr;  // The pointer decl, if any
-  const Expr *PteeExpr = nullptr;     // The array section/subscript expression
-  bool IsValid = false;
-};
+  /// Result structure for findAttachBasePointer
+  struct AttachInfo {
+    const Expr *BasePtrExpr = nullptr;      // The pointer expression
+    const ValueDecl *BasePtrDecl = nullptr; // The pointer decl, if any
+    const Expr *PteeExpr = nullptr; // The array section/subscript expression
+    bool IsValid = false;
+  };
 
-static AttachInfo findAttachComponent(
+  static AttachInfo findAttachBasePointer(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
-  // DEBUG: Print entry information
-  llvm::errs() << "DEBUG findAttachComponent: ENTRY\n";
+    // DEBUG: Print entry information
+    llvm::errs() << "DEBUG findAttachBasePointer: ENTRY\n";
 
-  const auto *Begin = Components.begin();
-  const auto *End = Components.end();
+    const auto *Begin = Components.begin();
+    const auto *End = Components.end();
 
-  llvm::errs() << "DEBUG findAttachComponent: Starting reverse walk\n";
+    llvm::errs() << "DEBUG findAttachBasePointer: Starting reverse walk\n";
 
-  for (const auto *I = Begin; I != End; ++I) {
-    // Check if current component is an array section or subscript
-    const Expr *CurrentExpr = I->getAssociatedExpression();
-    llvm::errs() << "DEBUG findAttachComponent: Current expr is: "; CurrentExpr->dump();
-    if (!CurrentExpr) {
-      llvm::errs() << "DEBUG findAttachComponent: No current expression, continuing\n";
-      break;
-    }
+    for (const auto *I = Begin; I != End; ++I) {
+      // Check if current component is an array section or subscript
+      const Expr *CurrentExpr = I->getAssociatedExpression();
+      llvm::errs() << "DEBUG findAttachBasePointer: Current expr is: ";
+      CurrentExpr->dump();
+      if (!CurrentExpr) {
+        llvm::errs()
+            << "DEBUG findAttachBasePointer: No current expression, continuing\n";
+        break;
+      }
 
-    // Check if the next component (in forward direction) has a pointer type
-    const auto *NextI = std::next(I);
-    if (NextI == End) {
-      llvm::errs() << "DEBUG findAttachComponent: No next component available\n";
-      break;
+      // Check if the next component (in forward direction) has a pointer type
+      const auto *NextI = std::next(I);
+      if (NextI == End) {
+        llvm::errs()
+            << "DEBUG findAttachBasePointer: No next component available\n";
+        break;
+      }
+
+      // Get the type of the next component
+      QualType NextType;
+      if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
+        NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
+        llvm::errs()
+            << "DEBUG findAttachBasePointer: Next component declaration type: ";
+        NextType.dump();
+      } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
+        // If NextExpr is an array-section, compute the result type using
+        // getBaseOriginalType
+        if (const auto *ArraySection = dyn_cast<ArraySectionExpr>(NextExpr)) {
+          // Get the original base type, handling chains of array sections
+          // properly
+          QualType BaseType =
+              ArraySectionExpr::getBaseOriginalType(ArraySection->getBase());
+          if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) {
+            NextType = ATy->getElementType();
+          } else {
+            NextType = BaseType->getPointeeType();
+          }
+          NextType = NextType.getNonReferenceType().getCanonicalType();
+          llvm::errs() << "DEBUG findAttachBasePointer: Next component "
+                          "array-section result type (base -> result): ";
+          BaseType.dump();
+          llvm::errs() << " -> ";
+          NextType.dump();
+        } else {
+          NextType =
+              NextExpr->getType().getNonReferenceType().getCanonicalType();
+          llvm::errs()
+              << "DEBUG findAttachBasePointer: Next component expression type: ";
+          NextType.dump();
+        }
+      } else {
+        llvm::errs() << "DEBUG findAttachBasePointer: No next component type "
+                        "info, continuing\n";
+        break;
+      }
+
+      // Stop if the next component is a pointer type - this means we found our
+      // component
+      if (!NextType->isPointerType())
+        continue;
+
+      llvm::errs() << "DEBUG findAttachBasePointer: Found pointer type in next "
+                      "component, stopping here\n";
+
+      // Get the pointer expression (NextRI) and use the candidate PteeExpr
+      const Expr *BasePtrExpr = NextI->getAssociatedExpression();
+      const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
+      const Expr *PteeExpr = CurrentExpr;
+
+      llvm::errs() << "DEBUG findAttachBasePointer: Returning AttachInfo\n";
+      llvm::errs() << "  BasePtrExpr: ";
+      if (BasePtrExpr)
+        BasePtrExpr->dump();
+      else
+        llvm::errs() << "nullptr\n";
+      llvm::errs() << "  BasePtrDecl: ";
+      if (BasePtrDecl)
+        BasePtrDecl->dump();
+      else
+        llvm::errs() << "nullptr\n";
+      llvm::errs() << "  PteeExpr: ";
+      if (PteeExpr)
+        PteeExpr->dump();
+      else
+        llvm::errs() << "nullptr\n";
+      llvm::errs() << "  RbeginExpr: ";
+      const auto *BeginExpr = Begin->getAssociatedExpression();
+      if (BeginExpr)
+        BeginExpr->dump();
+      else
+        llvm::errs() << "nullptr\n";
+      return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
+      llvm::errs() << "DEBUG findAttachBasePointer: Next component not pointer "
+                      "type, continuing\n";
     }
 
-   // Get the type of the next component
-   QualType NextType;
-   if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
-     NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
-     llvm::errs() << "DEBUG findAttachComponent: Next component declaration type: ";
-     NextType.dump();
-   } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
-     // If NextExpr is an array-section, compute the result type using getBaseOriginalType
-     if (const auto *ArraySection = dyn_cast<ArraySectionExpr>(NextExpr)) {
-       // Get the original base type, handling chains of array sections properly
-       QualType BaseType = ArraySectionExpr::getBaseOriginalType(ArraySection->getBase());
-       if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) {
-         NextType = ATy->getElementType();
-       } else {
-         NextType = BaseType->getPointeeType();
-       }
-       NextType = NextType.getNonReferenceType().getCanonicalType();
-       llvm::errs() << "DEBUG findAttachComponent: Next component array-section result type (base -> result): ";
-       BaseType.dump();
-       llvm::errs() << " -> ";
-       NextType.dump();
-     } else {
-       NextType = NextExpr->getType().getNonReferenceType().getCanonicalType();
-       llvm::errs() << "DEBUG findAttachComponent: Next component expression type: ";
-       NextType.dump();
-     }
-   } else {
-     llvm::errs() << "DEBUG findAttachComponent: No next component type info, continuing\n";
-     break;
-   }
-
-   // Stop if the next component is a pointer type - this means we found our component
-   if (!NextType->isPointerType())
-     continue;
-
-   llvm::errs() << "DEBUG findAttachComponent: Found pointer type in next component, stopping here\n";
-
-   // Get the pointer expression (NextRI) and use the candidate PteeExpr
-   const Expr *BasePtrExpr = NextI->getAssociatedExpression();
-   const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
-   const Expr *PteeExpr = CurrentExpr;
-
-   llvm::errs() << "DEBUG findAttachComponent: Returning AttachInfo\n";
-   llvm::errs() << "  BasePtrExpr: ";
-   if (BasePtrExpr) BasePtrExpr->dump(); else llvm::errs() << "nullptr\n";
-   llvm::errs() << "  BasePtrDecl: ";
-   if (BasePtrDecl) BasePtrDecl->dump(); else llvm::errs() << "nullptr\n";
-   llvm::errs() << "  PteeExpr: ";
-   if (PteeExpr) PteeExpr->dump(); else llvm::errs() << "nullptr\n";
-   llvm::errs() << "  RbeginExpr: ";
-   const auto *BeginExpr = Begin->getAssociatedExpression();
-   if (BeginExpr) BeginExpr->dump(); else llvm::errs() << "nullptr\n";
-   return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
-   llvm::errs() << "DEBUG findAttachComponent: Next component not pointer type, continuing\n";
- }
-
-  llvm::errs() << "DEBUG findAttachComponent: No suitable component found, returning invalid AttachInfo\n";
-  return AttachInfo{};
-}
+    llvm::errs() << "DEBUG findAttachBasePointer: No suitable component found, "
+                    "returning invalid AttachInfo\n";
+    return AttachInfo{};
+  }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and
   /// mappers for the extracted mappable expressions (all included in \a
@@ -8724,7 +8775,7 @@ static AttachInfo findAttachComponent(
                   // For global pointers with ATTACH-style mapping, also allow
                   // ReturnDevicePointer to ensure consistent behavior between
                   // global and local pointers
-                  (findAttachComponent(CI->Components).BasePtrDecl == VD)) {
+                  (findAttachBasePointer(CI->Components).BasePtrDecl == VD)) {
                 CI->ForDeviceAddr = IsDevAddr;
                 CI->ReturnDevicePointer = true;
                 Found = true;
@@ -8899,7 +8950,7 @@ static AttachInfo findAttachComponent(
       // Unify entries in one list making sure the struct mapping precedes the
       // individual fields:
       MapCombinedInfoTy UnionCurInfo;
-      
+
       // DEBUG: Print sizes before appending
       llvm::errs() << "DEBUG CALLER: Before unifying entries:\n";
       llvm::errs() << "  StructBaseCurInfo.BasePointers.size(): " << StructBaseCurInfo.BasePointers.size() << "\n";
@@ -8907,7 +8958,7 @@ static AttachInfo findAttachComponent(
       if (VD) {
         llvm::errs() << "  VD: " << VD->getNameAsString() << "\n";
       }
-      
+
       UnionCurInfo.append(StructBaseCurInfo);
       UnionCurInfo.append(CurInfo);
 
@@ -8920,10 +8971,13 @@ static AttachInfo findAttachComponent(
       MapCombinedInfoTy AttachCombinedInfo;
       if (PartialStruct.Base.isValid()) {
         UnionCurInfo.NonContigInfo.Dims.push_back(0);
-        llvm::errs() << "DEBUG CALLER: Emitting combined entry for PartialStruct\n";
+        llvm::errs()
+            << "DEBUG CALLER: Emitting combined entry for PartialStruct\n";
         // Emit a combined entry:
-        emitCombinedEntry(CombinedInfo, AttachCombinedInfo, UnionCurInfo.Types, PartialStruct,
-                          /*IsMapThis*/ !VD, OMPBuilder, VD, 0, true);
+        emitCombinedEntry(CombinedInfo, AttachCombinedInfo, UnionCurInfo.Types,
+                          PartialStruct,
+                          /*IsMapThis*/ !VD, OMPBuilder, VD,
+                          /*OffsetForMemberOfFlag=*/0, /*NotTargetParam=*/true);
       }
 
       llvm::errs() << "DEBUG CALLER: Before final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
@@ -9091,17 +9145,21 @@ static AttachInfo findAttachComponent(
 
     // All other current entries will be MEMBER_OF the combined entry
     // (except for PTR_AND_OBJ entries which do not have a placeholder value
-    // 0xFFFF in the MEMBER_OF field).
+    // 0xFFFF in the MEMBER_OF field, or ATTACH entries since they are expected
+    // to be handled by themselves, after all other maps).
     OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
         OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
-    
-    // Process delayed ATTACH entries if available - combined entry case  
-    if (PartialStruct.AttachBaseAddr.isValid() && PartialStruct.AttachFirstElemAddr.isValid()) {
-      llvm::errs() << "DEBUG emitCombinedEntry: Combined entry path - using PartialStruct\n";
-      addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr, PartialStruct.Base,
-                     PartialStruct.AttachBaseDecl, PartialStruct.AttachMapExpr);
+
+    // Process delayed ATTACH entries if available - combined entry case
+    if (PartialStruct.AttachBaseAddr.isValid() &&
+        PartialStruct.AttachFirstElemAddr.isValid()) {
+      llvm::errs() << "DEBUG emitCombinedEntry: Combined entry path - using "
+                      "PartialStruct\n";
+      addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
+                     PartialStruct.Base, PartialStruct.AttachBaseDecl,
+                     PartialStruct.AttachMapExpr);
     }
   }
 
@@ -9353,13 +9411,14 @@ static AttachInfo findAttachComponent(
           if (PartialStruct.Base.isValid()) {
             CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
             emitCombinedEntry(
-                CurCaptureVarInfo, AttachCombinedInfo, CurInfoForComponentLists.Types,
-                PartialStruct, Cap->capturesThis(), OMPBuilder, nullptr,
-                OffsetForMemberOfFlag,
+                CurCaptureVarInfo, AttachCombinedInfo,
+                CurInfoForComponentLists.Types, PartialStruct,
+                Cap->capturesThis(), OMPBuilder, nullptr, OffsetForMemberOfFlag,
                 /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
           }
 
-          // Append in order: combined-entry -> curinfo (individual fields) -> attachinfo
+          // Append in order: combined-entry -> curinfo (individual fields) ->
+          // attachinfo
           CurCaptureVarInfo.append(CurInfoForComponentLists);
           CurCaptureVarInfo.append(AttachCombinedInfo);
         };
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
index 1702992368132..7bec7e0c6736d 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h
@@ -239,8 +239,8 @@ enum class OpenMPOffloadMappingFlags : uint64_t {
   // dynamic.
   // This is an OpenMP extension for the sake of OpenACC support.
   OMP_MAP_OMPX_HOLD = 0x2000,
-  /// Attach the pointer to the device address of the array section.
-  /// Used when mapping array sections on pointers.
+  // Attach pointer and pointee, after processing all other maps.
+  // Applicable to map-entering directives. Does not change ref-count.
   OMP_MAP_ATTACH = 0x4000,
   /// Signal that the runtime library should use args as an array of
   /// descriptor_dim pointers and use args_size as dims. Used when we have

>From 54b2ae411149000679caf4b3a14c4c0ae207ad67 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 04:01:21 -0700
Subject: [PATCH 28/66] Remove debug prints.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 479 +++-----------------------
 1 file changed, 40 insertions(+), 439 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index d692caac9cf4a..7650b320111f5 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6920,16 +6920,10 @@ class MappableExprsHandler {
   llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
 
   llvm::Value *getExprTypeSize(const Expr *E) const {
-    // DEBUG: Print entry information
-    llvm::errs() << "DEBUG getExprTypeSize: ENTRY\n";
-    llvm::errs() << "  Expression: ";
-    E->dump();
-
     QualType ExprTy = E->getType().getCanonicalType();
 
     // Calculate the size for array shaping expression.
     if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
-      llvm::errs() << "DEBUG getExprTypeSize: Handling OMPArrayShapingExpr\n";
       llvm::Value *Size =
           CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType());
       for (const Expr *SE : OAE->getDimensions()) {
@@ -6939,8 +6933,6 @@ class MappableExprsHandler {
                                       SE->getExprLoc());
         Size = CGF.Builder.CreateNUWMul(Size, Sz);
       }
-      llvm::errs()
-          << "DEBUG getExprTypeSize: Returning size for ArrayShapingExpr\n";
       return Size;
     }
 
@@ -6952,7 +6944,6 @@ class MappableExprsHandler {
     // do the calculation based on the length of the section instead of relying
     // on CGF.getTypeSize(E->getType()).
     if (const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
-      llvm::errs() << "DEBUG getExprTypeSize: Handling ArraySectionExpr\n";
       QualType BaseTy = ArraySectionExpr::getBaseOriginalType(
                             OAE->getBase()->IgnoreParenImpCasts())
                             .getCanonicalType();
@@ -6961,11 +6952,8 @@ class MappableExprsHandler {
       // not specified too, that means we are using the whole length of the
       // base.
       if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
-          !OAE->getLowerBound()) {
-        llvm::errs() << "DEBUG getExprTypeSize: Using whole length of base for "
-                        "ArraySection\n";
+          !OAE->getLowerBound())
         return CGF.getTypeSize(BaseTy);
-      }
 
       llvm::Value *ElemSize;
       if (const auto *PTy = BaseTy->getAs<PointerType>()) {
@@ -6978,10 +6966,8 @@ class MappableExprsHandler {
 
       // If we don't have a length at this point, that is because we have an
       // array section with a single element.
-      if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) {
-        llvm::errs() << "DEBUG getExprTypeSize: Single element ArraySection\n";
+      if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
         return ElemSize;
-      }
 
       if (const Expr *LenExpr = OAE->getLength()) {
         llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
@@ -7016,14 +7002,6 @@ class MappableExprsHandler {
       OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
       ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit,
       bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const {
-    // DEBUG: Print entry information
-    llvm::errs() << "DEBUG getMapTypeBits: ENTRY\n";
-    llvm::errs() << "  MapType: " << MapType << "\n";
-    llvm::errs() << "  IsImplicit: " << IsImplicit << "\n";
-    llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
-    llvm::errs() << "  AddIsTargetParamFlag: " << AddIsTargetParamFlag << "\n";
-    llvm::errs() << "  IsNonContiguous: " << IsNonContiguous << "\n";
-
     OpenMPOffloadMappingFlags Bits =
         IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
                    : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
@@ -7066,36 +7044,21 @@ class MappableExprsHandler {
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
     if (IsNonContiguous)
       Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
-
-    // DEBUG: Print final flags
-    llvm::errs() << "DEBUG getMapTypeBits: Final bits = "
-                 << static_cast<unsigned>(Bits) << "\n";
     return Bits;
   }
 
   /// Return true if the provided expression is a final array section. A
   /// final array section, is one whose length can't be proved to be one.
   bool isFinalArraySectionExpression(const Expr *E) const {
-    // DEBUG: Print entry information
-    llvm::errs() << "DEBUG isFinalArraySectionExpression: ENTRY\n";
-    llvm::errs() << "  Expression: ";
-    E->dump();
-
     const auto *OASE = dyn_cast<ArraySectionExpr>(E);
 
     // It is not an array section and therefore not a unity-size one.
-    if (!OASE) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: Not "
-                      "ArraySectionExpr, returning false\n";
+    if (!OASE)
       return false;
-    }
 
     // An array section with no colon always refer to a single element.
-    if (OASE->getColonLocFirst().isInvalid()) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: No colon, single "
-                      "element, returning false\n";
+    if (OASE->getColonLocFirst().isInvalid())
       return false;
-    }
 
     const Expr *Length = OASE->getLength();
 
@@ -7116,18 +7079,11 @@ class MappableExprsHandler {
 
     // Check if the length evaluates to 1.
     Expr::EvalResult Result;
-    if (!Length->EvaluateAsInt(Result, CGF.getContext())) {
-      llvm::errs() << "DEBUG isFinalArraySectionExpression: Cannot evaluate "
-                      "length as int, returning true\n";
+    if (!Length->EvaluateAsInt(Result, CGF.getContext()))
       return true; // Can have more that size 1.
-    }
 
     llvm::APSInt ConstLength = Result.Val.getInt();
-    bool result = ConstLength.getSExtValue() != 1;
-    llvm::errs() << "DEBUG isFinalArraySectionExpression: Length = "
-                 << ConstLength.getSExtValue() << ", returning " << result
-                 << "\n";
-    return result;
+    return ConstLength.getSExtValue() != 1;
   }
 
   /// Utility function to add an ATTACH entry to the CombinedInfo structure.
@@ -7136,13 +7092,6 @@ class MappableExprsHandler {
   void addAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
                       Address AttachBaseAddr, Address AttachFirstElemAddr,
                       const ValueDecl *BaseDecl, const Expr *MapExpr) const {
-    llvm::errs() << "DEBUG addAttachEntry: Adding ATTACH entry\n";
-    llvm::errs() << "  AttachBaseAddr = ";
-    AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
-    llvm::errs() << "\n";
-    llvm::errs() << "  AttachFirstElemAddr = ";
-    AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
-    llvm::errs() << "\n";
 
     // Size is the size of the pointer itself - use pointer size, not BaseDecl
     // size
@@ -7163,8 +7112,6 @@ class MappableExprsHandler {
     CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
     CombinedInfo.Mappers.push_back(nullptr);
     CombinedInfo.NonContigInfo.Dims.push_back(1);
-
-    llvm::errs() << "DEBUG addAttachEntry: ATTACH entry added successfully\n";
   }
 
   /// Generate the base pointers, section pointers, sizes, map type bits, and
@@ -7185,23 +7132,6 @@ class MappableExprsHandler {
       ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
           OverlappedElements = {}) const {
 
-    // DEBUG: Print function entry information
-    llvm::errs() << "DEBUG generateInfoForComponentList: ENTRY\n";
-    llvm::errs() << "  MapType: " << MapType << "\n";
-    llvm::errs() << "  IsFirstComponentList: " << IsFirstComponentList << "\n";
-    llvm::errs() << "  IsImplicit: " << IsImplicit << "\n";
-    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses
-                 << "\n";
-    llvm::errs() << "  ForDeviceAddr: " << ForDeviceAddr << "\n";
-    llvm::errs() << "  Components.size(): " << Components.size() << "\n";
-    if (BaseDecl) {
-      llvm::errs() << "  BaseDecl: " << BaseDecl->getNameAsString() << "\n";
-    }
-    if (MapExpr) {
-      llvm::errs() << "  MapExpr: ";
-      MapExpr->dump();
-    }
-
     // The following summarizes what has to be generated for each map and the
     // types below. The generated information is expressed in this order:
     // base pointer, section pointer, size, flags
@@ -7394,24 +7324,6 @@ class MappableExprsHandler {
     auto CI = Components.rbegin();
     auto CE = Components.rend();
     auto I = CI;
-    
-    // DEBUG: Print what I initially points to
-    llvm::errs() << "DEBUG generateInfoForComponentList: Initial iterator I points to:\n";
-    if (I != CE) {
-      if (I->getAssociatedDeclaration()) {
-        llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
-      } else {
-        llvm::errs() << "  AssociatedDeclaration: nullptr\n";
-      }
-      if (I->getAssociatedExpression()) {
-        llvm::errs() << "  AssociatedExpression: ";
-        I->getAssociatedExpression()->dump();
-      } else {
-        llvm::errs() << "  AssociatedExpression: nullptr\n";
-      }
-    } else {
-      llvm::errs() << "  I is already at end (CE)\n";
-    }
 
     // Track if the map information being generated is the first for a list of
     // components.
@@ -7432,33 +7344,24 @@ class MappableExprsHandler {
     // Find the component that should use ATTACH-style mapping.
     auto AttachInfo = findAttachBasePointer(Components);
 
-    llvm::errs() << "DEBUG generateInfoForComponentList: Computing initial BP\n";
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
-      llvm::errs() << "  Case: MemberExpr - using LoadCXXThisAddress\n";
       BP = CGF.LoadCXXThisAddress();
-      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
                (OASE &&
                 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
-      llvm::errs() << "  Case: ArrayExpr with CXXThisExpr base - using EmitOMPSharedLValue\n";
       BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
-      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else if (OAShE &&
                isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) {
-      llvm::errs() << "  Case: OMPArrayShapingExpr with CXXThisExpr base\n";
       BP = Address(
           CGF.EmitScalarExpr(OAShE->getBase()),
           CGF.ConvertTypeForMem(OAShE->getBase()->getType()->getPointeeType()),
           CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType()));
-      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
     } else {
       // The base is the reference to the variable.
       // BP = &Var.
-      llvm::errs() << "  Case: Standard variable reference - using EmitOMPSharedLValue\n";
       BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
-      llvm::errs() << "  BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
       if (const auto *VD =
               dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
         if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
@@ -7467,10 +7370,8 @@ class MappableExprsHandler {
               ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
                 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
                CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
-            llvm::errs() << "  Found declare target variable - updating BP\n";
             RequiresReference = true;
             BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
-            llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           }
         }
       }
@@ -7484,37 +7385,14 @@ class MappableExprsHandler {
         // No need to generate individual map information for the pointer, it
         // can be associated with the combined storage if shared memory mode is
         // active or the base declaration is not global variable.
-        llvm::errs() << "  Pointer dereferencing case - updating BP\n";
-        llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
         if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
-            !VD || VD->hasLocalStorage() || (AttachInfo.IsValid && VD == AttachInfo.BasePtrDecl)) {
-          llvm::errs() << "  Loading pointer value\n";
+            !VD || VD->hasLocalStorage() ||
+            (AttachInfo.IsValid && VD == AttachInfo.BasePtrDecl))
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-          llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
-        } else {
-          llvm::errs() << "  Setting FirstPointerInComplexData=true\n";
+        else
           FirstPointerInComplexData = true;
-        }
-
         ++I;
-        // DEBUG: Print what I now points to after increment
-        if (I != CE) {
-          llvm::errs() << "DEBUG generateInfoForComponentList: After increment, I now points to component with:\n";
-          if (I->getAssociatedDeclaration()) {
-            llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
-          } else {
-            llvm::errs() << "  AssociatedDeclaration: nullptr\n";
-          }
-          if (I->getAssociatedExpression()) {
-            llvm::errs() << "  AssociatedExpression: ";
-            I->getAssociatedExpression()->dump();
-          } else {
-            llvm::errs() << "  AssociatedExpression: nullptr\n";
-          }
-        } else {
-          llvm::errs() << "DEBUG generateInfoForComponentList: After increment, I reached end (CE)\n";
-        }
       }
     }
 
@@ -7559,65 +7437,35 @@ class MappableExprsHandler {
     // CombinedInfo list and instead add an entry to the StructBaseCombinedInfo
     // list only when generating all info for clauses.
     bool IsMappingWholeStruct = true;
-    llvm::errs() << "DEBUG generateInfoForComponentList: Checking IsMappingWholeStruct logic\n";
-    llvm::errs() << "  GenerateAllInfoForClauses: " << GenerateAllInfoForClauses << "\n";
-
     if (!GenerateAllInfoForClauses) {
-      llvm::errs() << "  Setting IsMappingWholeStruct=false (GenerateAllInfoForClauses=false)\n";
       IsMappingWholeStruct = false;
     } else {
-      llvm::errs() << "  Scanning components for MemberExpr...\n";
       for (auto TempI = I; TempI != CE; ++TempI) {
         const MemberExpr *PossibleME =
             dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
-        // Only consider non-arrow member expressions as whole struct mapping
-        // Arrow member expressions (like sp->x) are pointer-to-struct access, not struct mapping
-        // if (PossibleME && !PossibleME->isArrow()) {
         if (PossibleME) {
-          llvm::errs() << "  Found PossibleME (non-arrow) - setting IsMappingWholeStruct=false: "; 
-          PossibleME->dump();
           IsMappingWholeStruct = false;
           break;
         }
       }
     }
-    llvm::errs() << "  Final IsMappingWholeStruct: " << IsMappingWholeStruct << "\n";
 
     for (; I != CE; ++I) {
-      // DEBUG: Print component processing information
-      llvm::errs() << "DEBUG generateInfoForComponentList: Processing component " 
-                   << std::distance(Components.rbegin(), I) << "/" << Components.size() << "\n";
-      if (I->getAssociatedDeclaration()) {
-        llvm::errs() << "  AssociatedDeclaration: " << I->getAssociatedDeclaration()->getNameAsString() << "\n";
-      }
-      if (I->getAssociatedExpression()) {
-        llvm::errs() << "  AssociatedExpression: ";
-        I->getAssociatedExpression()->dump();
-      }
-
       // If the current component is member of a struct (parent struct) mark it.
       if (!EncounteredME) {
         EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
         // If we encounter a PTR_AND_OBJ entry from now on it should be marked
         // as MEMBER_OF the parent struct.
-        // However, for pointer-to-struct member access (like sp->x), we should NOT
-        // set ShouldBeMemberOf because this is not mapping a struct field but accessing
-        // through a pointer.
-        // if (EncounteredME && !EncounteredME->isArrow()) {
         if (EncounteredME) {
-          llvm::errs() << "DEBUG generateInfoForComponentList: Encountered MemberExpr (non-arrow), setting ShouldBeMemberOf=true\n";
           ShouldBeMemberOf = true;
           // Do not emit as complex pointer if this is actually not array-like
           // expression.
           if (FirstPointerInComplexData) {
-            llvm::errs() << "  FirstPointerInComplexData case - updating BP in MemberExpr\n";
-            llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             QualType Ty = std::prev(I)
                               ->getAssociatedDeclaration()
                               ->getType()
                               .getNonReferenceType();
             BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-            llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             FirstPointerInComplexData = false;
           }
         }
@@ -7637,9 +7485,6 @@ class MappableExprsHandler {
           !IsNonContiguous &&
           isFinalArraySectionExpression(I->getAssociatedExpression());
 
-      // DEBUG: Print array section information
-      llvm::errs() << "DEBUG generateInfoForComponentList: IsFinalArraySection: " << IsFinalArraySection << "\n";
-
       // If we have a declaration for the mapping use that, otherwise use
       // the base declaration of the map clause.
       const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
@@ -7648,19 +7493,9 @@ class MappableExprsHandler {
       MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
                                                : MapExpr;
 
-      // DEBUG: Print mapping declaration and expression
-      llvm::errs() << "DEBUG generateInfoForComponentList: MapDecl: ";
-      if (MapDecl) {
-        llvm::errs() << MapDecl->getNameAsString() << "\n";
-      } else {
-        llvm::errs() << "nullptr\n";
-      }
-
       // Get information on whether the element is a pointer. Have to do a
       // special treatment for array sections given that they are built-in
       // types.
-      llvm::errs() << "DEBUG generateInfoForComponentList: Analyzing expression types\n";
-
       const auto *OASE =
           dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
       const auto *ASE =
@@ -7669,13 +7504,6 @@ class MappableExprsHandler {
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
       const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
       const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
-
-      llvm::errs() << "  OASE (ArraySectionExpr): " << (OASE ? "yes" : "no") << "\n";
-      llvm::errs() << "  ASE (ArraySubscriptExpr): " << (ASE ? "yes" : "no") << "\n";
-      llvm::errs() << "  OAShE (OMPArrayShapingExpr): " << (OAShE ? "yes" : "no") << "\n";
-      llvm::errs() << "  UO (UnaryOperator): " << (UO ? "yes" : "no") << "\n";
-      llvm::errs() << "  BO (BinaryOperator): " << (BO ? "yes" : "no") << "\n";
-
       bool IsPointer =
           OAShE ||
           (OASE && ArraySectionExpr::getBaseOriginalType(OASE)
@@ -7689,23 +7517,11 @@ class MappableExprsHandler {
                                !(UO && UO->getOpcode() != UO_Deref) && !BO &&
                                !IsNonContiguous;
 
-      llvm::errs() << "  IsPointer: " << IsPointer << "\n";
-      llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
-      llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
-
-      if (OASE) {
+      if (OASE)
         ++DimSize;
-        llvm::errs() << "  Incremented DimSize to: " << DimSize << "\n";
-      }
 
-      llvm::errs() << "DEBUG generateInfoForComponentList: Checking entry generation condition\n";
-      llvm::errs() << "  Next == CE: " << (Next == CE) << "\n";
-      llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
-      llvm::errs() << "  IsNonDerefPointer: " << IsNonDerefPointer << "\n";
-      llvm::errs() << "  IsFinalArraySection: " << IsFinalArraySection << "\n";
       if (Next == CE || IsMemberReference || IsNonDerefPointer ||
           IsFinalArraySection) {
-        llvm::errs() << "  CONDITION MET: Generating address and size info\n";
         // If this is not the last component, we expect the pointer to be
         // associated with an array expression or member expression.
         assert((Next == CE ||
@@ -7737,49 +7553,30 @@ class MappableExprsHandler {
           }
           return BaseLV;
         };
-        llvm::errs() << "DEBUG generateInfoForComponentList: Emitting addresses\n";
         if (OAShE) {
-          llvm::errs() << "  Handling OMPArrayShapingExpr\n";
           LowestElem = LB =
               Address(CGF.EmitScalarExpr(OAShE->getBase()),
                       CGF.ConvertTypeForMem(
                           OAShE->getBase()->getType()->getPointeeType()),
                       CGF.getContext().getTypeAlignInChars(
                           OAShE->getBase()->getType()));
-          llvm::errs() << "  LowestElem = LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         } else if (IsMemberReference) {
-          llvm::errs() << "  Handling MemberReference\n";
           const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
           LValue BaseLVal = EmitMemberExprBase(CGF, ME);
           LowestElem = CGF.EmitLValueForFieldInitialization(
                               BaseLVal, cast<FieldDecl>(MapDecl))
                            .getAddress();
-          llvm::errs() << "  LowestElem = "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType())
                    .getAddress();
-          llvm::errs() << "  LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         } else {
-          llvm::errs() << "  Handling standard case - EmitOMPSharedLValue\n";
           LowestElem = LB =
               CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
                   .getAddress();
-          llvm::errs() << "  LowestElem = LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         }
 
         // If this component is a pointer inside the base struct then we don't
         // need to create any entry for it - it will be combined with the object
         // it is pointing to into a single PTR_AND_OBJ entry.
-        llvm::errs() << "DEBUG generateInfoForComponentList: Checking IsMemberPointerOrAddr\n";
-        llvm::errs() << "  EncounteredME: " << (EncounteredME ? "yes" : "no") << "\n";
-        llvm::errs() << "  ForDeviceAddr: " << ForDeviceAddr << "\n";
-        llvm::errs() << "  IsPrevMemberReference: " << IsPrevMemberReference << "\n";
-        if (EncounteredME) {
-          llvm::errs() << "  I->getAssociatedExpression() == EncounteredME: " << (I->getAssociatedExpression() == EncounteredME) << "\n";
-        }
-        if (Next != CE) {
-          llvm::errs() << "  Next->getAssociatedExpression()->getType()->isPointerType(): " << Next->getAssociatedExpression()->getType()->isPointerType() << "\n";
-        }
-
         bool IsMemberPointerOrAddr =
             EncounteredME &&
             (((IsPointer || ForDeviceAddr) &&
@@ -7787,8 +7584,6 @@ class MappableExprsHandler {
              (IsPrevMemberReference && !IsPointer) ||
              (IsMemberReference && Next != CE &&
               !Next->getAssociatedExpression()->getType()->isPointerType()));
-
-        llvm::errs() << "  IsMemberPointerOrAddr: " << IsMemberPointerOrAddr << "\n";
         if (!OverlappedElements.empty() && Next == CE) {
           // Handle base element with the info for overlapped elements.
           assert(!PartialStruct.Base.isValid() && "The base element is set.");
@@ -7804,8 +7599,8 @@ class MappableExprsHandler {
                   LowestElem, CGF.VoidPtrTy, CGF.Int8Ty),
               TypeSize.getQuantity() - 1);
           PartialStruct.HighestElem = {
-              std::numeric_limits<decltype(
-                  PartialStruct.HighestElem.first)>::max(),
+              std::numeric_limits<
+                  decltype(PartialStruct.HighestElem.first)>::max(),
               HB};
           PartialStruct.Base = BP;
           PartialStruct.LB = LB;
@@ -7827,23 +7622,18 @@ class MappableExprsHandler {
             for (const OMPClauseMappableExprCommon::MappableComponent &MC :
                  Component) {
               if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
-                llvm::errs() << "DEBUG generateInfoForComponentList: Computing ComponentLB for overlapped element\n";
                 const auto *FD = dyn_cast<FieldDecl>(VD);
                 if (FD && FD->getType()->isLValueReferenceType()) {
-                  llvm::errs() << "  Reference field case\n";
                   const auto *ME =
                       cast<MemberExpr>(MC.getAssociatedExpression());
                   LValue BaseLVal = EmitMemberExprBase(CGF, ME);
                   ComponentLB =
                       CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
                           .getAddress();
-                  llvm::errs() << "  ComponentLB = "; ComponentLB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
                 } else {
-                  llvm::errs() << "  Standard field case\n";
                   ComponentLB =
                       CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
                           .getAddress();
-                  llvm::errs() << "  ComponentLB = "; ComponentLB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
                 }
                 llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF);
                 llvm::Value *LBPtr = LB.emitRawPointer(CGF);
@@ -7865,7 +7655,6 @@ class MappableExprsHandler {
             CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
                                                                       : 1);
             LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
-            llvm::errs() << "  Updated LB = "; LB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           }
           CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
           CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
@@ -7885,26 +7674,15 @@ class MappableExprsHandler {
           break;
         }
         llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
-
-        // DEBUG: Print size calculation result
-        llvm::errs() << "DEBUG generateInfoForComponentList: Size calculated for expression\n";
         // Skip adding an entry in the CurInfo of this combined entry if the
         // whole struct is currently being mapped. The struct needs to be added
         // in the first position before any data internal to the struct is being
         // mapped.
         // Skip adding an entry in the CurInfo of this combined entry if the
         // PartialStruct.PreliminaryMapData.BasePointers has been mapped.
-        llvm::errs() << "DEBUG generateInfoForComponentList: Checking entry addition condition\n";
-        llvm::errs() << "  IsPartialMapped: " << IsPartialMapped << "\n";
-        llvm::errs() << "  MapType != OMPC_MAP_unknown: " << (MapType != OMPC_MAP_unknown) << "\n";
-        llvm::errs() << "  (!IsMemberPointerOrAddr && !IsPartialMapped): " << (!IsMemberPointerOrAddr && !IsPartialMapped) << "\n";
-        llvm::errs() << "  (Next == CE && MapType != OMPC_MAP_unknown): " << (Next == CE && MapType != OMPC_MAP_unknown) << "\n";
-
         if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
             (Next == CE && MapType != OMPC_MAP_unknown)) {
-          llvm::errs() << "  WILL ADD ENTRY\n";
           if (!IsMappingWholeStruct) {
-            llvm::errs() << "    Adding to CombinedInfo (not mapping whole struct)\n";
             CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
             CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
             CombinedInfo.DevicePtrDecls.push_back(nullptr);
@@ -7915,7 +7693,6 @@ class MappableExprsHandler {
             CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
                                                                       : 1);
           } else {
-            llvm::errs() << "    Adding to StructBaseCombinedInfo (mapping whole struct)\n";
             StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
             StructBaseCombinedInfo.BasePointers.push_back(
                 BP.emitRawPointer(CGF));
@@ -7940,38 +7717,23 @@ class MappableExprsHandler {
           // same expression except for the first one. We also need to signal
           // this map is the first one that relates with the current capture
           // (there is a set of entries for each capture).
-          // Don't use PTR_AND_OBJ when we have array sections/subscripts on pointers
-          llvm::errs() << "DEBUG generateInfoForComponentList: Calculating flags\n";
-          llvm::errs() << "  IsExpressionFirstInfo: " << IsExpressionFirstInfo << "\n";
-          llvm::errs() << "  RequiresReference: " << RequiresReference << "\n";
-          llvm::errs() << "  FirstPointerInComplexData: " << FirstPointerInComplexData << "\n";
-          llvm::errs() << "  IsCaptureFirstInfo: " << IsCaptureFirstInfo << "\n";
-
-          bool AddPtrFlag =
-              (!IsExpressionFirstInfo || RequiresReference ||
-               FirstPointerInComplexData || IsMemberReference);
-          llvm::errs() << "  AddPtrFlag: " << AddPtrFlag << "\n";
-
-          OpenMPOffloadMappingFlags Flags =
-              getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
-                             AddPtrFlag, IsCaptureFirstInfo && !RequiresReference,
-                             IsNonContiguous);
+          OpenMPOffloadMappingFlags Flags = getMapTypeBits(
+              MapType, MapModifiers, MotionModifiers, IsImplicit,
+              !IsExpressionFirstInfo || RequiresReference ||
+                  FirstPointerInComplexData || IsMemberReference,
+              IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
 
           if (!IsExpressionFirstInfo || IsMemberReference) {
-            llvm::errs() << "  Modifying flags for non-first expression or member reference\n";
             // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
             // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
-            if (IsPointer || (IsMemberReference && Next != CE)) {
-              llvm::errs() << "    Resetting TO/FROM/ALWAYS/DELETE/CLOSE flags for pointer\n";
+            if (IsPointer || (IsMemberReference && Next != CE))
               Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
                          OpenMPOffloadMappingFlags::OMP_MAP_FROM |
                          OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
                          OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
                          OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
-            }
 
             if (ShouldBeMemberOf) {
-              llvm::errs() << "    Adding MEMBER_OF flag and resetting ShouldBeMemberOf\n";
               // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
               // should be later updated with the correct value of MEMBER_OF.
               Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
@@ -7995,40 +7757,28 @@ class MappableExprsHandler {
           unsigned FieldIndex = FD->getFieldIndex();
 
           // Update info about the lowest and highest elements for this struct
-          llvm::errs() << "DEBUG generateInfoForComponentList: Updating PartialStruct for field " << FieldIndex << "\n";
           if (!PartialStruct.Base.isValid()) {
-            llvm::errs() << "  Initializing PartialStruct\n";
             PartialStruct.LowestElem = {FieldIndex, LowestElem};
-            llvm::errs() << "  PartialStruct.LowestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             if (IsFinalArraySection && OASE) {
               Address HB =
                   CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
                       .getAddress();
               PartialStruct.HighestElem = {FieldIndex, HB};
-              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; HB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "} (final array section)\n";
             } else {
               PartialStruct.HighestElem = {FieldIndex, LowestElem};
-              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             }
             PartialStruct.Base = BP;
-            llvm::errs() << "  PartialStruct.Base = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
             PartialStruct.LB = BP;
-            llvm::errs() << "  PartialStruct.LB = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
           } else if (FieldIndex < PartialStruct.LowestElem.first) {
-            llvm::errs() << "  Updating LowestElem (lower field index)\n";
             PartialStruct.LowestElem = {FieldIndex, LowestElem};
-            llvm::errs() << "  PartialStruct.LowestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
           } else if (FieldIndex > PartialStruct.HighestElem.first) {
-            llvm::errs() << "  Updating HighestElem (higher field index)\n";
             if (IsFinalArraySection && OASE) {
               Address HB =
                   CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
                       .getAddress();
               PartialStruct.HighestElem = {FieldIndex, HB};
-              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; HB.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "} (final array section)\n";
             } else {
               PartialStruct.HighestElem = {FieldIndex, LowestElem};
-              llvm::errs() << "  PartialStruct.HighestElem = {" << FieldIndex << ", "; LowestElem.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "}\n";
             }
           }
         }
@@ -8038,8 +7788,6 @@ class MappableExprsHandler {
           PartialStruct.IsArraySection = true;
 
         if (Next == CE) {
-          llvm::errs() << "DEBUG generateInfoForComponentList: Reached the end "
-                          "of components\n";
           // Generate ATTACH entry for array sections and subscripts on
           // standalone pointers Info was already collected during the main
           // component loop Check if we should use ATTACH-style mapping for this
@@ -8047,73 +7795,23 @@ class MappableExprsHandler {
           bool IsAttachablePointeeExpr = AttachInfo.IsValid &&
                                          AttachInfo.BasePtrDecl &&
                                          AttachInfo.BasePtrDecl == BaseDecl;
-          llvm::errs()
-              << "DEBUG generateInfoForComponentList: AttachInfo.PteeExpr: ";
-          if (AttachInfo.PteeExpr)
-            AttachInfo.PteeExpr->dump();
-          else
-            llvm::errs() << "nullptr\n";
-          llvm::errs()
-              << "DEBUG generateInfoForComponentList: AttachInfo.BasePtrExpr: ";
-          if (AttachInfo.BasePtrExpr)
-            AttachInfo.BasePtrExpr->dump();
-          else
-            llvm::errs() << "nullptr\n";
-          llvm::errs() << "DEBUG generateInfoForComponentList: I: ";
-          if (I->getAssociatedExpression())
-            I->getAssociatedExpression()->dump();
-          else
-            llvm::errs() << "nullptr\n";
-
           if (IsAttachablePointeeExpr) {
-            llvm::errs() << "DEBUG generateInfoForComponentList: Computing "
-                            "ATTACH addresses\n";
-
-            // Use BasePtrExpr for AttachBaseAddr
-            llvm::errs() << "  Using BasePtrExpr for AttachBaseAddr\n";
             AttachBaseAddr =
                 CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
-            llvm::errs() << "  AttachBaseAddr = ";
-            AttachBaseAddr.emitRawPointer(CGF)->printAsOperand(llvm::errs());
-            llvm::errs() << "\n";
 
             if (OASE) {
-              llvm::errs()
-                  << "  ArraySectionExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr =
                   CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true)
                       .getAddress();
-              llvm::errs() << "  AttachFirstElemAddr = ";
-              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
-                  llvm::errs());
-              llvm::errs() << "\n";
             } else if (ASE) {
-              llvm::errs()
-                  << "  ArraySubscriptExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
-              llvm::errs() << "  AttachFirstElemAddr = ";
-              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
-                  llvm::errs());
-              llvm::errs() << "\n";
             } else if (auto *ME =
                            dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
-              llvm::errs() << "  MemberExpr case for AttachFirstElemAddr\n";
               AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
-              llvm::errs() << "  AttachFirstElemAddr = ";
-              AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
-                  llvm::errs());
-              llvm::errs() << "\n";
             } else if (auto *UO = dyn_cast<UnaryOperator>(
                            I->getAssociatedExpression())) {
-              if (UO->getOpcode() == UO_Deref) {
-                llvm::errs() << "  UnaryOperator (dereference) case for "
-                                "AttachFirstElemAddr\n";
+              if (UO->getOpcode() == UO_Deref)
                 AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
-                llvm::errs() << "  AttachFirstElemAddr = ";
-                AttachFirstElemAddr.emitRawPointer(CGF)->printAsOperand(
-                    llvm::errs());
-                llvm::errs() << "\n";
-              }
             }
           }
         }
@@ -8123,35 +7821,21 @@ class MappableExprsHandler {
           break;
 
         // The pointer becomes the base for the next element.
-        if (Next != CE) {
-          llvm::errs() << "DEBUG generateInfoForComponentList: Updating BP for next element\n";
-          llvm::errs() << "  IsMemberReference: " << IsMemberReference << "\n";
-          llvm::errs() << "  Current BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
+        if (Next != CE)
           BP = IsMemberReference ? LowestElem : LB;
-          llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << " (using " << (IsMemberReference ? "LowestElem" : "LB") << ")\n";
-        }
         if (!IsPartialMapped)
           IsExpressionFirstInfo = false;
         IsCaptureFirstInfo = false;
         FirstPointerInComplexData = false;
         IsPrevMemberReference = IsMemberReference;
-
-        llvm::errs() << "DEBUG generateInfoForComponentList: End of component processing\n";
-        llvm::errs() << "  Updated IsExpressionFirstInfo: " << IsExpressionFirstInfo << "\n";
-        llvm::errs() << "  Updated IsCaptureFirstInfo: " << IsCaptureFirstInfo << "\n";
-        llvm::errs() << "  Updated IsPrevMemberReference: " << IsPrevMemberReference << "\n";
       } else if (FirstPointerInComplexData) {
-        llvm::errs() << "DEBUG generateInfoForComponentList: FirstPointerInComplexData case - final BP update\n";
-        llvm::errs() << "  Original BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         QualType Ty = Components.rbegin()
                           ->getAssociatedDeclaration()
                           ->getType()
                           .getNonReferenceType();
         BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
-        llvm::errs() << "  Updated BP = "; BP.emitRawPointer(CGF)->printAsOperand(llvm::errs()); llvm::errs() << "\n";
         FirstPointerInComplexData = false;
       }
-
     }
     // If ran into the whole component - allocate the space for the whole
     // record.
@@ -8164,20 +7848,14 @@ class MappableExprsHandler {
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
         // after emitCombinedEntry
-        llvm::errs() << "DEBUG generateInfoForComponentList: Saving ATTACH "
-                        "info for delayed processing\n";
         PartialStruct.AttachBaseAddr = AttachBaseAddr;
         PartialStruct.AttachFirstElemAddr = AttachFirstElemAddr;
         PartialStruct.AttachBaseDecl = BaseDecl;
         PartialStruct.AttachMapExpr = MapExpr;
       } else if (IsMappingWholeStruct) {
-        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to "
-                        "StructBaseCombinedInfo\n";
         addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr,
                        AttachFirstElemAddr, BaseDecl, MapExpr);
       } else {
-        llvm::errs() << "DEBUG generateInfoForComponentList: Adding ATTACH to "
-                        "CombinedInfo\n";
         addAttachEntry(CGF, CombinedInfo, AttachBaseAddr, AttachFirstElemAddr,
                        BaseDecl, MapExpr);
       }
@@ -8358,11 +8036,6 @@ class MappableExprsHandler {
     CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
     CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
     CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
-
-    // DEBUG: Print exit information
-    llvm::errs() << "DEBUG generateInfoForComponentList: EXIT\n";
-    llvm::errs() << "  CombinedInfo entries added: " << CombinedInfo.BasePointers.size() << "\n";
-    llvm::errs() << "  StructBaseCombinedInfo entries added: " << StructBaseCombinedInfo.BasePointers.size() << "\n";
   }
 
   /// Return the adjusted map modifiers if the declaration a capture refers to
@@ -8471,40 +8144,24 @@ class MappableExprsHandler {
 
   static AttachInfo findAttachBasePointer(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
-    // DEBUG: Print entry information
-    llvm::errs() << "DEBUG findAttachBasePointer: ENTRY\n";
 
     const auto *Begin = Components.begin();
     const auto *End = Components.end();
 
-    llvm::errs() << "DEBUG findAttachBasePointer: Starting reverse walk\n";
-
     for (const auto *I = Begin; I != End; ++I) {
-      // Check if current component is an array section or subscript
       const Expr *CurrentExpr = I->getAssociatedExpression();
-      llvm::errs() << "DEBUG findAttachBasePointer: Current expr is: ";
-      CurrentExpr->dump();
-      if (!CurrentExpr) {
-        llvm::errs()
-            << "DEBUG findAttachBasePointer: No current expression, continuing\n";
+      if (!CurrentExpr)
         break;
-      }
 
-      // Check if the next component (in forward direction) has a pointer type
       const auto *NextI = std::next(I);
-      if (NextI == End) {
-        llvm::errs()
-            << "DEBUG findAttachBasePointer: No next component available\n";
+      if (NextI == End)
         break;
-      }
 
-      // Get the type of the next component
+      // Check if the next component (in forward direction) has a pointer type
       QualType NextType;
+
       if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
         NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
-        llvm::errs()
-            << "DEBUG findAttachBasePointer: Next component declaration type: ";
-        NextType.dump();
       } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
         // If NextExpr is an array-section, compute the result type using
         // getBaseOriginalType
@@ -8513,72 +8170,33 @@ class MappableExprsHandler {
           // properly
           QualType BaseType =
               ArraySectionExpr::getBaseOriginalType(ArraySection->getBase());
-          if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) {
+          if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
             NextType = ATy->getElementType();
-          } else {
+          else
             NextType = BaseType->getPointeeType();
-          }
+
           NextType = NextType.getNonReferenceType().getCanonicalType();
-          llvm::errs() << "DEBUG findAttachBasePointer: Next component "
-                          "array-section result type (base -> result): ";
-          BaseType.dump();
-          llvm::errs() << " -> ";
-          NextType.dump();
         } else {
           NextType =
               NextExpr->getType().getNonReferenceType().getCanonicalType();
-          llvm::errs()
-              << "DEBUG findAttachBasePointer: Next component expression type: ";
-          NextType.dump();
         }
       } else {
-        llvm::errs() << "DEBUG findAttachBasePointer: No next component type "
-                        "info, continuing\n";
         break;
       }
 
-      // Stop if the next component is a pointer type - this means we found our
-      // component
+      // Stop if the next component is a pointer type - this means we found
+      // the base-pointer
       if (!NextType->isPointerType())
         continue;
 
-      llvm::errs() << "DEBUG findAttachBasePointer: Found pointer type in next "
-                      "component, stopping here\n";
-
       // Get the pointer expression (NextRI) and use the candidate PteeExpr
       const Expr *BasePtrExpr = NextI->getAssociatedExpression();
       const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
       const Expr *PteeExpr = CurrentExpr;
-
-      llvm::errs() << "DEBUG findAttachBasePointer: Returning AttachInfo\n";
-      llvm::errs() << "  BasePtrExpr: ";
-      if (BasePtrExpr)
-        BasePtrExpr->dump();
-      else
-        llvm::errs() << "nullptr\n";
-      llvm::errs() << "  BasePtrDecl: ";
-      if (BasePtrDecl)
-        BasePtrDecl->dump();
-      else
-        llvm::errs() << "nullptr\n";
-      llvm::errs() << "  PteeExpr: ";
-      if (PteeExpr)
-        PteeExpr->dump();
-      else
-        llvm::errs() << "nullptr\n";
-      llvm::errs() << "  RbeginExpr: ";
       const auto *BeginExpr = Begin->getAssociatedExpression();
-      if (BeginExpr)
-        BeginExpr->dump();
-      else
-        llvm::errs() << "nullptr\n";
       return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
-      llvm::errs() << "DEBUG findAttachBasePointer: Next component not pointer "
-                      "type, continuing\n";
     }
 
-    llvm::errs() << "DEBUG findAttachBasePointer: No suitable component found, "
-                    "returning invalid AttachInfo\n";
     return AttachInfo{};
   }
 
@@ -8950,29 +8568,14 @@ class MappableExprsHandler {
       // Unify entries in one list making sure the struct mapping precedes the
       // individual fields:
       MapCombinedInfoTy UnionCurInfo;
-
-      // DEBUG: Print sizes before appending
-      llvm::errs() << "DEBUG CALLER: Before unifying entries:\n";
-      llvm::errs() << "  StructBaseCurInfo.BasePointers.size(): " << StructBaseCurInfo.BasePointers.size() << "\n";
-      llvm::errs() << "  CurInfo.BasePointers.size(): " << CurInfo.BasePointers.size() << "\n";
-      if (VD) {
-        llvm::errs() << "  VD: " << VD->getNameAsString() << "\n";
-      }
-
       UnionCurInfo.append(StructBaseCurInfo);
       UnionCurInfo.append(CurInfo);
 
-      llvm::errs() << "DEBUG CALLER: After unifying:\n";
-      llvm::errs() << "  UnionCurInfo.BasePointers.size(): " << UnionCurInfo.BasePointers.size() << "\n";
-      llvm::errs() << "  PartialStruct.Base.isValid(): " << PartialStruct.Base.isValid() << "\n";
-
       // If there is an entry in PartialStruct it means we have a struct with
       // individual members mapped. Emit an extra combined entry.
       MapCombinedInfoTy AttachCombinedInfo;
       if (PartialStruct.Base.isValid()) {
         UnionCurInfo.NonContigInfo.Dims.push_back(0);
-        llvm::errs()
-            << "DEBUG CALLER: Emitting combined entry for PartialStruct\n";
         // Emit a combined entry:
         emitCombinedEntry(CombinedInfo, AttachCombinedInfo, UnionCurInfo.Types,
                           PartialStruct,
@@ -8980,10 +8583,8 @@ class MappableExprsHandler {
                           /*OffsetForMemberOfFlag=*/0, /*NotTargetParam=*/true);
       }
 
-      llvm::errs() << "DEBUG CALLER: Before final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
       // We need to append the results of this capture to what we already have.
       CombinedInfo.append(UnionCurInfo);
-      llvm::errs() << "DEBUG CALLER: After final append - CombinedInfo.BasePointers.size(): " << CombinedInfo.BasePointers.size() << "\n";
       // Append AttachCombinedInfo after UnionCurInfo
       CombinedInfo.append(AttachCombinedInfo);
     }
@@ -9057,12 +8658,14 @@ class MappableExprsHandler {
         ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
          OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
         !PartialStruct.IsArraySection) {
-      // Process delayed ATTACH entries if available - no combined entry case
-      if (PartialStruct.AttachBaseAddr.isValid() && PartialStruct.AttachFirstElemAddr.isValid()) {
-        llvm::errs() << "DEBUG emitCombinedEntry: Early return path - adding ATTACH with saved pointee\n";
-        addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr, PartialStruct.AttachFirstElemAddr,
-                       PartialStruct.AttachBaseDecl, PartialStruct.AttachMapExpr);
-      }
+      // Even if we are not creating a combined-entry, we need to process any
+      // previously delayed ATTACH entries.
+      if (PartialStruct.AttachBaseAddr.isValid() &&
+          PartialStruct.AttachFirstElemAddr.isValid())
+        addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
+                       PartialStruct.AttachFirstElemAddr,
+                       PartialStruct.AttachBaseDecl,
+                       PartialStruct.AttachMapExpr);
       return;
     }
     Address LBAddr = PartialStruct.LowestElem.second;
@@ -9152,15 +8755,13 @@ class MappableExprsHandler {
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
 
-    // Process delayed ATTACH entries if available - combined entry case
+    // When we are emitting a combined entry, we need to use the begin address
+    // of the combined entry for the pointee address of any ATTACH maps.
     if (PartialStruct.AttachBaseAddr.isValid() &&
-        PartialStruct.AttachFirstElemAddr.isValid()) {
-      llvm::errs() << "DEBUG emitCombinedEntry: Combined entry path - using "
-                      "PartialStruct\n";
+        PartialStruct.AttachFirstElemAddr.isValid())
       addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
                      PartialStruct.Base, PartialStruct.AttachBaseDecl,
                      PartialStruct.AttachMapExpr);
-    }
   }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and

>From 00b0767c48af678be87f144bfc22c68941054e70 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 04:44:44 -0700
Subject: [PATCH 29/66] Limit attach map-type generation to only map-entering
 constructs.

---
 clang/include/clang/Basic/OpenMPKinds.h |  8 ++++++++
 clang/lib/Basic/OpenMPKinds.cpp         |  5 +++++
 clang/lib/CodeGen/CGOpenMPRuntime.cpp   | 11 +++++++++--
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index f40db4c13c55a..e37887e8b86ba 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -301,6 +301,14 @@ bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind);
 /// otherwise - false.
 bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind);
 
+/// Checks if the specified directive is a map-entering target directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a map-entering target directive like
+/// 'omp target', 'omp target data', 'omp target enter data',
+/// 'omp target parallel', etc. (excludes 'omp target exit data', 'omp target
+/// update') otherwise - false.
+bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind);
+
 /// Checks if the specified composite/combined directive constitutes a teams
 /// directive in the outermost nest.  For example
 /// 'omp teams distribute' or 'omp teams distribute parallel for'.
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index d3d393bd09396..8a8ede203361b 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -650,6 +650,11 @@ bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
          DKind == OMPD_target_exit_data || DKind == OMPD_target_update;
 }
 
+bool clang::isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind) {
+  return DKind == OMPD_target_data || DKind == OMPD_target_enter_data ||
+         isOpenMPTargetExecutionDirective(DKind);
+}
+
 bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
   if (DKind == OMPD_teams)
     return true;
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 7650b320111f5..fa16f6a642a4d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7795,7 +7795,15 @@ class MappableExprsHandler {
           bool IsAttachablePointeeExpr = AttachInfo.IsValid &&
                                          AttachInfo.BasePtrDecl &&
                                          AttachInfo.BasePtrDecl == BaseDecl;
-          if (IsAttachablePointeeExpr) {
+          // Pointer attachment is needed at map-entering time or for declare
+          // mappers.
+          bool IsMapEnteringConstructOrMapper =
+              isa<const OMPDeclareMapperDecl *>(CurDir) ||
+              isOpenMPTargetMapEnteringDirective(
+                  cast<const OMPExecutableDirective *>(CurDir)
+                      ->getDirectiveKind());
+
+          if (IsAttachablePointeeExpr && IsMapEnteringConstructOrMapper) {
             AttachBaseAddr =
                 CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
 
@@ -8192,7 +8200,6 @@ class MappableExprsHandler {
       // Get the pointer expression (NextRI) and use the candidate PteeExpr
       const Expr *BasePtrExpr = NextI->getAssociatedExpression();
       const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
-      const Expr *PteeExpr = CurrentExpr;
       const auto *BeginExpr = Begin->getAssociatedExpression();
       return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
     }

>From baa9dbb2917f3ed13804f7eba80d135f2d32a6de Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 16 Jul 2025 05:36:13 -0700
Subject: [PATCH 30/66] Minor clean-up

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 40 ++++++++++++++++-----------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index fa16f6a642a4d..57e3a3b1b2229 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7388,7 +7388,7 @@ class MappableExprsHandler {
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
         if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
             !VD || VD->hasLocalStorage() ||
-            (AttachInfo.IsValid && VD == AttachInfo.BasePtrDecl))
+            (AttachInfo && VD == AttachInfo->BasePtrDecl))
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
         else
           FirstPointerInComplexData = true;
@@ -7792,9 +7792,9 @@ class MappableExprsHandler {
           // standalone pointers Info was already collected during the main
           // component loop Check if we should use ATTACH-style mapping for this
           // expression
-          bool IsAttachablePointeeExpr = AttachInfo.IsValid &&
-                                         AttachInfo.BasePtrDecl &&
-                                         AttachInfo.BasePtrDecl == BaseDecl;
+          bool IsAttachablePointeeExpr = AttachInfo &&
+                                         AttachInfo->BasePtrDecl &&
+                                         AttachInfo->BasePtrDecl == BaseDecl;
           // Pointer attachment is needed at map-entering time or for declare
           // mappers.
           bool IsMapEnteringConstructOrMapper =
@@ -7805,7 +7805,7 @@ class MappableExprsHandler {
 
           if (IsAttachablePointeeExpr && IsMapEnteringConstructOrMapper) {
             AttachBaseAddr =
-                CGF.EmitLValue(AttachInfo.BasePtrExpr).getAddress();
+                CGF.EmitLValue(AttachInfo->BasePtrExpr).getAddress();
 
             if (OASE) {
               AttachFirstElemAddr =
@@ -8147,10 +8147,18 @@ class MappableExprsHandler {
     const Expr *BasePtrExpr = nullptr;      // The pointer expression
     const ValueDecl *BasePtrDecl = nullptr; // The pointer decl, if any
     const Expr *PteeExpr = nullptr; // The array section/subscript expression
-    bool IsValid = false;
+
+    // Constructor with arguments
+    AttachInfo(const Expr *BasePtr, const ValueDecl *BaseDecl, const Expr *Ptee)
+        : BasePtrExpr(BasePtr), BasePtrDecl(BaseDecl), PteeExpr(Ptee) {}
   };
 
-  static AttachInfo findAttachBasePointer(
+  // Traverse the list of Components to find the first pointer expression, which
+  // should be the attachable-base-pointer for the current component-list.
+  // For example, for:
+  //  `map(pp->p->s.a[0])`, the base-pointer is `pp->p`, while the pointee is
+  //  `pp->p->s.a[0]`.
+  static std::optional<AttachInfo> findAttachBasePointer(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
@@ -8197,14 +8205,15 @@ class MappableExprsHandler {
       if (!NextType->isPointerType())
         continue;
 
-      // Get the pointer expression (NextRI) and use the candidate PteeExpr
+      // The Next component is the first pointer expression encountered, so
+      // that is the attachable-base-pointer for the current component-list.
       const Expr *BasePtrExpr = NextI->getAssociatedExpression();
       const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
       const auto *BeginExpr = Begin->getAssociatedExpression();
-      return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr, true};
+      return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr};
     }
 
-    return AttachInfo{};
+    return std::nullopt;
   }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and
@@ -8380,8 +8389,9 @@ class MappableExprsHandler {
           // returned and move on to the next declaration. Exclude cases where
           // the base pointer is mapped as array subscript, array section or
           // array shaping. The base address is passed as a pointer to base in
-          // this case and cannot be used as a base for use_device_ptr list
-          // item.
+          // this case (i.e. as a PTR_AND_OBJ) and cannot be used as a base
+          // for use_device_ptr list item. However, we don't use PTR_AND_OBJ
+          // mapping for any pointers when using ATTACH-style mapping.
           if (CI != Data.end()) {
             if (IsDevAddr) {
               CI->ForDeviceAddr = IsDevAddr;
@@ -8391,16 +8401,14 @@ class MappableExprsHandler {
             } else {
               auto PrevCI = std::next(CI->Components.rbegin());
               const auto *VarD = dyn_cast<VarDecl>(VD);
+              auto AttachInfo = findAttachBasePointer(CI->Components);
               if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
                   isa<MemberExpr>(IE) ||
                   !VD->getType().getNonReferenceType()->isPointerType() ||
                   PrevCI == CI->Components.rend() ||
                   isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
                   VarD->hasLocalStorage() ||
-                  // For global pointers with ATTACH-style mapping, also allow
-                  // ReturnDevicePointer to ensure consistent behavior between
-                  // global and local pointers
-                  (findAttachBasePointer(CI->Components).BasePtrDecl == VD)) {
+                  (AttachInfo && AttachInfo->BasePtrDecl == VD)) {
                 CI->ForDeviceAddr = IsDevAddr;
                 CI->ReturnDevicePointer = true;
                 Found = true;

>From c0d20e938f194bf0e174e4bb32ee602afaf6d804 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 20 Jul 2025 04:14:51 -0700
Subject: [PATCH 31/66] Minor NFC changes.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 52 +++++++++++--------
 ...ta_map_pointer_array_subscript_codegen.cpp |  4 +-
 .../target_data_use_device_addr_codegen.cpp   | 10 +++-
 clang/test/OpenMP/target_map_codegen_19.cpp   |  4 +-
 clang/test/OpenMP/target_map_codegen_20.cpp   |  8 +--
 clang/test/OpenMP/target_map_codegen_21.cpp   | 12 ++---
 clang/test/OpenMP/target_map_codegen_22.cpp   |  8 +--
 clang/test/OpenMP/target_map_codegen_23.cpp   | 42 +++++++++------
 clang/test/OpenMP/target_map_codegen_26.cpp   | 36 ++++++-------
 clang/test/OpenMP/target_map_codegen_27.cpp   |  8 +--
 .../OpenMP/target_task_affinity_codegen.cpp   |  2 -
 11 files changed, 105 insertions(+), 81 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 57e3a3b1b2229..0444540778154 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7335,14 +7335,13 @@ class MappableExprsHandler {
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-    // ATTACH entries are generated based solely on array section presence
 
     // Track info for ATTACH entry generation
     Address AttachBaseAddr = Address::invalid();
     Address AttachFirstElemAddr = Address::invalid();
 
-    // Find the component that should use ATTACH-style mapping.
-    auto AttachInfo = findAttachBasePointer(Components);
+    // Find the pointer-attachment base-pointer for the given list, if any.
+    std::optional<AttachInfoTy> AttachInfo = findAttachBasePointer(Components);
 
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
@@ -7788,13 +7787,12 @@ class MappableExprsHandler {
           PartialStruct.IsArraySection = true;
 
         if (Next == CE) {
-          // Generate ATTACH entry for array sections and subscripts on
-          // standalone pointers Info was already collected during the main
-          // component loop Check if we should use ATTACH-style mapping for this
-          // expression
-          bool IsAttachablePointeeExpr = AttachInfo &&
-                                         AttachInfo->BasePtrDecl &&
-                                         AttachInfo->BasePtrDecl == BaseDecl;
+          // For now, we are emitting ATTACH entries only when the
+          // "attach-base-pointer" is a vardecl itself, not an expression, or
+          // even a member of a struct.
+          bool IsEligibleForAttachMapping = AttachInfo &&
+                                            AttachInfo->BasePtrDecl &&
+                                            AttachInfo->BasePtrDecl == BaseDecl;
           // Pointer attachment is needed at map-entering time or for declare
           // mappers.
           bool IsMapEnteringConstructOrMapper =
@@ -7803,7 +7801,7 @@ class MappableExprsHandler {
                   cast<const OMPExecutableDirective *>(CurDir)
                       ->getDirectiveKind());
 
-          if (IsAttachablePointeeExpr && IsMapEnteringConstructOrMapper) {
+          if (IsEligibleForAttachMapping && IsMapEnteringConstructOrMapper) {
             AttachBaseAddr =
                 CGF.EmitLValue(AttachInfo->BasePtrExpr).getAddress();
 
@@ -7851,11 +7849,11 @@ class MappableExprsHandler {
       PartialStruct.HasCompleteRecord = true;
 
     // Handle ATTACH entries: delay if PartialStruct is being populated,
-    // otherwise add immediately
+    // otherwise add immediately.
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
-        // after emitCombinedEntry
+        // after emitCombinedEntry.
         PartialStruct.AttachBaseAddr = AttachBaseAddr;
         PartialStruct.AttachFirstElemAddr = AttachFirstElemAddr;
         PartialStruct.AttachBaseDecl = BaseDecl;
@@ -8143,13 +8141,14 @@ class MappableExprsHandler {
   }
 
   /// Result structure for findAttachBasePointer
-  struct AttachInfo {
+  struct AttachInfoTy {
     const Expr *BasePtrExpr = nullptr;      // The pointer expression
     const ValueDecl *BasePtrDecl = nullptr; // The pointer decl, if any
     const Expr *PteeExpr = nullptr; // The array section/subscript expression
 
     // Constructor with arguments
-    AttachInfo(const Expr *BasePtr, const ValueDecl *BaseDecl, const Expr *Ptee)
+    AttachInfoTy(const Expr *BasePtr, const ValueDecl *BaseDecl,
+                 const Expr *Ptee)
         : BasePtrExpr(BasePtr), BasePtrDecl(BaseDecl), PteeExpr(Ptee) {}
   };
 
@@ -8158,7 +8157,7 @@ class MappableExprsHandler {
   // For example, for:
   //  `map(pp->p->s.a[0])`, the base-pointer is `pp->p`, while the pointee is
   //  `pp->p->s.a[0]`.
-  static std::optional<AttachInfo> findAttachBasePointer(
+  static std::optional<AttachInfoTy> findAttachBasePointer(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
@@ -8210,7 +8209,7 @@ class MappableExprsHandler {
       const Expr *BasePtrExpr = NextI->getAssociatedExpression();
       const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
       const auto *BeginExpr = Begin->getAssociatedExpression();
-      return AttachInfo{BasePtrExpr, BasePtrDecl, BeginExpr};
+      return AttachInfoTy{BasePtrExpr, BasePtrDecl, BeginExpr};
     }
 
     return std::nullopt;
@@ -8401,7 +8400,8 @@ class MappableExprsHandler {
             } else {
               auto PrevCI = std::next(CI->Components.rbegin());
               const auto *VarD = dyn_cast<VarDecl>(VD);
-              auto AttachInfo = findAttachBasePointer(CI->Components);
+              std::optional<AttachInfoTy> AttachInfo =
+                  findAttachBasePointer(CI->Components);
               if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
                   isa<MemberExpr>(IE) ||
                   !VD->getType().getNonReferenceType()->isPointerType() ||
@@ -8660,7 +8660,8 @@ class MappableExprsHandler {
   /// Generate code for the combined entry if we have a partially mapped struct
   /// and take care of the mapping flags of the arguments corresponding to
   /// individual struct members.
-  /// AttachCombinedInfo will be populated with ATTACH entries if needed.
+  /// AttachCombinedInfo will be populated with ATTACH entries if
+  /// \p PartialStruct contains attach base-pointer information.
   void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
                          MapCombinedInfoTy &AttachCombinedInfo,
                          MapFlagsArrayTy &CurTypes,
@@ -8770,8 +8771,13 @@ class MappableExprsHandler {
     for (auto &M : CurTypes)
       OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
 
-    // When we are emitting a combined entry, we need to use the begin address
-    // of the combined entry for the pointee address of any ATTACH maps.
+    // When we are emitting a combined entry. If there were any pending
+    // attachments to be done, we do them to the begin address of the combined
+    // entry. Note that this means only one attachment per combined-entry will
+    // be done. So, for instance, if we have:
+    //   S *ps;
+    //   ... map(ps->a, ps->b)
+    // We won't emit separate ATTACH entries for the two list items, just one.
     if (PartialStruct.AttachBaseAddr.isValid() &&
         PartialStruct.AttachFirstElemAddr.isValid())
       addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
@@ -9033,8 +9039,8 @@ class MappableExprsHandler {
                 /*NotTargetParams*/ !IsEligibleForTargetParamFlag);
           }
 
-          // Append in order: combined-entry -> curinfo (individual fields) ->
-          // attachinfo
+          // We do the appends to get the entries in the following order:
+          // combined-entry -> individual-field-entries -> attach-entry
           CurCaptureVarInfo.append(CurInfoForComponentLists);
           CurCaptureVarInfo.append(AttachCombinedInfo);
         };
diff --git a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
index 652f8eff8454a..4366abb1d0887 100644
--- a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
+++ b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
@@ -39,10 +39,10 @@ MyObject *objects;
 // CHECK-DAG: [[MAPS1:@.+]] = private unnamed_addr constant [2 x i64] [i64 0, i64 281474976710673]
 // CHECK: @main
 int main(void) {
-//
+
 //  &objects[0], &objects[1], 1 * sizeof(objects[0]), TO
 //  &objects, &objects[1], sizeof(objects), ATTACH
-//
+
 // CHECK-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[BPGEP:%.+]], ptr [[PGEP:%.+]], ptr [[SIZES0]], ptr [[MAPS0]], ptr null, ptr null)
 // CHECK-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CHECK-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
diff --git a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
index aaa680c795318..fc048ab1caadd 100644
--- a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
@@ -51,7 +51,7 @@ int main() {
 //  &ptr[0], &ptr[0], TO | FROM | RETURN_PARAM
 //  &ptr, &ptr[0], ATTACH
 //  &ref_ptee(ref), &ref_ptee(ref), TO | FROM | RETURN_PARAM
-//  &arr, &arr[0], TO | FROM | ATTACH | RETURN_PARAM
+//  &arr, &arr[0], TO | FROM | RETURN_PARAM
 //
 // CHECK: [[A_ADDR:%.+]] = alloca float,
 // CHECK: [[PTR_ADDR:%.+]] = alloca ptr,
@@ -149,6 +149,14 @@ int main() {
 // CHECK: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 -1, i32 8, ptr [[BPTR]], ptr [[PTR]], ptr [[SIZE]], ptr [[MAPTYPES1]], ptr null, ptr null)
 
 // CHECK: foo
+//
+//  &this[0], &this->a, sizeof(this[0].(a-to-arr[a]) | ALLOC
+//  &this[0], &this->a, sizeof(a), TO | FROM | RETURN_PARAM | MEMBER_OF(1)
+//  &this->ptr, &this->ptr[3], 4 * sizeof(ptr[0], TO | FROM | PTR_AND_OBJ | RETURN_PARAM | MEMBER_OF(1)
+//  &this[0], &ref_ptee(this->ref), sizeof(this->ref[0]), TO | FROM | PTR_AND_OBJ | RETURN_PARAM | MEMBER_OF(1)
+//  &this->ptr, &this->ptr[0], sizeof(ptr[0], TO | FROM | PTR_AND_OBJ | MEMBER_OF(1)
+//  &this, &this->arr[0], 4 * sizeof(arr[0]), TO | FROM | RETURN_PARAM | MEMBER_OF(1)
+//
 // CHECK: [[BPTRS:%.+]] = alloca [6 x ptr],
 // CHECK: [[PTRS:%.+]] = alloca [6 x ptr],
 // CHECK: [[MAP_PTRS:%.+]] = alloca [6 x ptr],
diff --git a/clang/test/OpenMP/target_map_codegen_19.cpp b/clang/test/OpenMP/target_map_codegen_19.cpp
index 942545cb2e58e..1c4d47da93785 100644
--- a/clang/test/OpenMP/target_map_codegen_19.cpp
+++ b/clang/test/OpenMP/target_map_codegen_19.cpp
@@ -126,10 +126,10 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f
   }
 
 // Region 03
-//
+
 //  &d[0], &d[2], 3 * sizeof(d[0]), FROM | PARAM
 //  &d, &d[2], sizeof(d), ATTACH
-//
+
 // CK20-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK20-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK20-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_20.cpp b/clang/test/OpenMP/target_map_codegen_20.cpp
index 4514a7f65cf87..afaa35b79b889 100644
--- a/clang/test/OpenMP/target_map_codegen_20.cpp
+++ b/clang/test/OpenMP/target_map_codegen_20.cpp
@@ -130,10 +130,10 @@ struct CC {
     }
 
 // Region 01
-//
-//   &lb[0], &lb[/*lower_bound=*/0], X * sizeof(T), (TO | FROM) / (TO | FROM | PARAM)
-//   &lb, &lb[/*lower_bound=*/0], sizeof(T*), ATTACH
-//
+
+//  &lb[0], &lb[/*lower_bound=*/0], X * sizeof(T), (TO | FROM) / (TO | FROM | PARAM)
+//  &lb, &lb[/*lower_bound=*/0], sizeof(T*), ATTACH
+
 // CK21-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK21-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK21-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_21.cpp b/clang/test/OpenMP/target_map_codegen_21.cpp
index b3e94112624dd..1307da56874b7 100644
--- a/clang/test/OpenMP/target_map_codegen_21.cpp
+++ b/clang/test/OpenMP/target_map_codegen_21.cpp
@@ -192,10 +192,10 @@ int explicit_maps_globals(void){
   { c[3]+=1; }
 
 // Region 04
-//
+
 //  &d[0], &d[2], 5 * sizeof(d[0]), TO | FROM | PARAM
 //  &d, &d[2], sizeof(d), ATTACH
-//
+
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -296,10 +296,10 @@ int explicit_maps_globals(void){
   { sc[3].fa+=1; }
 
 // Region 09
-//
+
 //  &sd[0], &sd[2], 5 * sizeof(sd[0]), TO | FROM | ATTACH
 //  &sd, &sd[2], sizeof(sd), ATTACH
-//
+
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -400,10 +400,10 @@ int explicit_maps_globals(void){
   { stc[3].fa+=1; }
 
 // Region 14
-//
+
 //  &std[0], &std[2], 5 * sizeof(std[0]), TO | FROM | ATTACH
 //  &std, &std[2], sizeof(std), ATTACH
-//
+
 // CK22-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK22-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK22-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_22.cpp b/clang/test/OpenMP/target_map_codegen_22.cpp
index 6c17a847d47b4..5663fb0e8bc6a 100644
--- a/clang/test/OpenMP/target_map_codegen_22.cpp
+++ b/clang/test/OpenMP/target_map_codegen_22.cpp
@@ -175,10 +175,10 @@ int explicit_maps_inside_captured(int a){
       { c[3]+=1; }
 
 // Region 05
-//
-// &d[0], &d[2], 4 * sizeof(d[0]), TO | FROM
-// &d, &d[2], sizeof(d), ATTACH
-//
+
+//  &d[0], &d[2], 4 * sizeof(d[0]), TO | FROM
+//  &d, &d[2], sizeof(d), ATTACH
+
 // CK23-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK23-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK23-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_23.cpp b/clang/test/OpenMP/target_map_codegen_23.cpp
index 20ff8872f70fa..1068a85e7a342 100644
--- a/clang/test/OpenMP/target_map_codegen_23.cpp
+++ b/clang/test/OpenMP/target_map_codegen_23.cpp
@@ -134,10 +134,12 @@ int explicit_maps_struct_fields(int a){
 
 //
 // Same thing but starting from a pointer.
-//
+
 // Region 13
-//   &p[0], &p->a, sizeof(p->a), TO | FROM | PARAM
-//   &p, &p->a, sizeof(p), ATTACH
+
+//  &p[0], &p->a, sizeof(p->a), TO | FROM | PARAM
+//  &p, &p->a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -168,8 +170,10 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 14
-//   &p[0], &p->s.s, sizeof(p->s.s), TO | FROM | PARAM
-//   &p, &p->s.s, sizeof(p), ATTACH
+
+//  &p[0], &p->s.s, sizeof(p->s.s), TO | FROM | PARAM
+//  &p, &p->s.s, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -200,8 +204,10 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 15
-//   &p[0], &p->s.s.a, sizeof(p->s.s.a), TO | FROM | PARAM
-//   &p, &p->s.s.a, sizeof(p), ATTACH
+
+//  &p[0], &p->s.s.a, sizeof(p->s.s.a), TO | FROM | PARAM
+//  &p, &p->s.s.a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -235,9 +241,11 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 16
-//   &p[0], &p->b[0], sizeof(p->b[0:5]), ALLOC | PARAM
-//   &p[0], &p->b[0], sizeof(p->b[0:5]), TO | FROM
-//   &p, &p[0], sizeof(p), ATTACH
+
+//  &p[0], &p->b[0], sizeof(p->b[0:5]), ALLOC | PARAM
+//  &p[0], &p->b[0], sizeof(p->b[0:5]), TO | FROM
+//  &p, &p[0], sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -313,8 +321,10 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 18
-//   &p[0], &p->s.sa[3].a, sizeof(p->s.sa[3].a), TO | FROM | PARAM
-//   &p, &p->s.sa[3].a sizeof(p), ATTACH
+
+//  &p[0], &p->s.sa[3].a, sizeof(p->s.sa[3].a), TO | FROM | PARAM
+//  &p, &p->s.sa[3].a sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -474,9 +484,11 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 22
-//   &p[0], &p->s.s.b[0], sizeof(p->s.s.bb[0:2]), ALLOC | PARAM
-//   &p[0], &p->s.s.bb[0], sizeof(p->s.s.bb[0:2]), TO | FROM
-//   &p, &p[0], sizeof(p), ATTACH
+
+//  &p[0], &p->s.s.b[0], sizeof(p->s.s.bb[0:2]), ALLOC | PARAM
+//  &p[0], &p->s.s.bb[0], sizeof(p->s.s.bb[0:2]), TO | FROM
+//  &p, &p[0], sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_26.cpp b/clang/test/OpenMP/target_map_codegen_26.cpp
index b327a8f35ce7e..832f04674b40b 100644
--- a/clang/test/OpenMP/target_map_codegen_26.cpp
+++ b/clang/test/OpenMP/target_map_codegen_26.cpp
@@ -71,12 +71,12 @@ void zero_size_section_and_private_maps (int ii){
   int *pa;
 
 // Region 00
-//
-//   &pa, &pa, sizeof(pa), IMPLICIT | PARAM
+
+//  &pa, &pa, sizeof(pa), IMPLICIT | PARAM
 //
 // FIXME: This looks like a bug. The implicit map on a pointer
 // should be identical to pa[0:0]
-//
+
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -97,13 +97,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 01
-//
-//   &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
-//   &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+
+//  &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
+//  &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
 //
 // Can be optimized to:
-//   &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
-//
+//  &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
+
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -134,13 +134,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 02
-//
-//   &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
-//   &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
+
+//  &(pa[0]), &pa[/*lb=*/0], /*size=*/0, TO | FROM | PARAM
+//  &pa, &pa[/*lb=*/0], sizeof(pa), ATTACH
 //
 // Can be optimized to:
-//   &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
-//
+//  &pa[0], &pa[0], /*size=*/0, TO | FROM | PARAM
+
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -171,13 +171,13 @@ void zero_size_section_and_private_maps (int ii){
   }
 
 // Region 03
-//
-//   &pa[0], &pa[ii], /*size=*/0, TO | FROM | PARAM
-//   &pa, &pa[ii], sizeof(pa), ATTACH
+
+//  &pa[0], &pa[ii], /*size=*/0, TO | FROM | PARAM
+//  &pa, &pa[ii], sizeof(pa), ATTACH
 //
 // Can be optimized to:
-//   &pa[ii], &pa[ii], /*size=*/0, TO | FROM | PARAM
-//
+//  &pa[ii], &pa[ii], /*size=*/0, TO | FROM | PARAM
+
 // CK27-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK27-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK27-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_map_codegen_27.cpp b/clang/test/OpenMP/target_map_codegen_27.cpp
index 5f24ba97ba0a0..d0720fa6a4066 100644
--- a/clang/test/OpenMP/target_map_codegen_27.cpp
+++ b/clang/test/OpenMP/target_map_codegen_27.cpp
@@ -68,10 +68,10 @@ void explicit_maps_pointer_references (int *p){
   }
 
 // Region 01
-//
-// &(ref_ptee(a)[0]), &(ref_ptee(a)[2]), 100 * sizeof(int), TO | FROM | PARAM
-// &(ref_ptee(a)), &(ref_ptee(a)[2]), sizeof(ref_ptee(a)), ATTACH
-//
+
+//  &(ref_ptee(a)[0]), &(ref_ptee(a)[2]), 100 * sizeof(int), TO | FROM | PARAM
+//  &(ref_ptee(a)), &(ref_ptee(a)[2]), sizeof(ref_ptee(a)), ATTACH
+
 // CK28-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK28-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK28-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
diff --git a/clang/test/OpenMP/target_task_affinity_codegen.cpp b/clang/test/OpenMP/target_task_affinity_codegen.cpp
index f45d532c7b8d4..fb3df19c74eb4 100644
--- a/clang/test/OpenMP/target_task_affinity_codegen.cpp
+++ b/clang/test/OpenMP/target_task_affinity_codegen.cpp
@@ -69,8 +69,6 @@ int main() {
 //   &B, &B[/*lb=*/0], sizeof(B), ATTACH
 //   &A[0], &A[0], sizeof(A[0]), LITERAL | PARAM
 
-// TODO: Update the test to limit the checks to relevant lines only.
-
 //.
 // CHECK1: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4096, i64 8]
 // CHECK1: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 3, i64 16384]

>From a9b94d4c89ae6242afec237c89a0d86ba792b6f7 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 20 Jul 2025 04:44:07 -0700
Subject: [PATCH 32/66] Use lb instead of base when attaching to a
 partialstruct.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp                  |  3 +--
 clang/test/OpenMP/target_data_map_codegen_hold.cpp     |  8 ++++----
 clang/test/OpenMP/target_map_codegen_23.cpp            | 10 ++++------
 .../OpenMP/target_map_structptr_and_member_global.cpp  |  4 ++--
 .../OpenMP/target_map_structptr_and_member_local.cpp   |  4 ++--
 5 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 0444540778154..2c1f1112c8b8b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7335,7 +7335,6 @@ class MappableExprsHandler {
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-
     // Track info for ATTACH entry generation
     Address AttachBaseAddr = Address::invalid();
     Address AttachFirstElemAddr = Address::invalid();
@@ -8781,7 +8780,7 @@ class MappableExprsHandler {
     if (PartialStruct.AttachBaseAddr.isValid() &&
         PartialStruct.AttachFirstElemAddr.isValid())
       addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
-                     PartialStruct.Base, PartialStruct.AttachBaseDecl,
+                     LBAddr, PartialStruct.AttachBaseDecl,
                      PartialStruct.AttachMapExpr);
   }
 
diff --git a/clang/test/OpenMP/target_data_map_codegen_hold.cpp b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
index d886e4edc3f2f..0f5276ff8484a 100644
--- a/clang/test/OpenMP/target_data_map_codegen_hold.cpp
+++ b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
@@ -235,7 +235,7 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
 // CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP79]], align 8
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP79]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 5
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP80]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
@@ -279,7 +279,7 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
 // CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP101]], align 8
+// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP101]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 12
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP102]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
@@ -458,7 +458,7 @@ struct S2 {
 // CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
 // CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 4
 // CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP79]], align 4
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP79]], align 4
 // CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 5
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP80]], align 4
 // CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
@@ -502,7 +502,7 @@ struct S2 {
 // CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
 // CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 4
 // CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP101]], align 4
+// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP101]], align 4
 // CHECK-I386-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 12
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP102]], align 4
 // CHECK-I386-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
diff --git a/clang/test/OpenMP/target_map_codegen_23.cpp b/clang/test/OpenMP/target_map_codegen_23.cpp
index 1068a85e7a342..3801af995455a 100644
--- a/clang/test/OpenMP/target_map_codegen_23.cpp
+++ b/clang/test/OpenMP/target_map_codegen_23.cpp
@@ -244,7 +244,7 @@ int explicit_maps_struct_fields(int a){
 
 //  &p[0], &p->b[0], sizeof(p->b[0:5]), ALLOC | PARAM
 //  &p[0], &p->b[0], sizeof(p->b[0:5]), TO | FROM
-//  &p, &p[0], sizeof(p), ATTACH
+//  &p, &p->b[0], sizeof(p), ATTACH
 
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
@@ -274,11 +274,10 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP2]]
-// CK24-DAG: store ptr [[VAR2:%[^,]+]], ptr [[P2]]
+// CK24-DAG: store ptr [[SEC0]], ptr [[P2]]
 
 // CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
 // CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
-// CK24-DAG: [[VAR2]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL16:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->b[:5])
@@ -487,7 +486,7 @@ int explicit_maps_struct_fields(int a){
 
 //  &p[0], &p->s.s.b[0], sizeof(p->s.s.bb[0:2]), ALLOC | PARAM
 //  &p[0], &p->s.s.bb[0], sizeof(p->s.s.bb[0:2]), TO | FROM
-//  &p, &p[0], sizeof(p), ATTACH
+//  &p, &p->s.s.b[0], sizeof(p), ATTACH
 
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
@@ -519,11 +518,10 @@ int explicit_maps_struct_fields(int a){
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: store ptr [[VAR:%[^,]+]], ptr [[BP2]]
-// CK24-DAG: store ptr [[VAR2:%[^,]+]], ptr [[P2]]
+// CK24-DAG: store ptr [[SEC0]], ptr [[P2]]
 
 // CK24-DAG: [[VAR0]] = load ptr, ptr [[VAR]]
 // CK24-DAG: [[VAR00]] = load ptr, ptr [[VAR]]
-// CK24-DAG: [[VAR2]] = load ptr, ptr [[VAR]]
 
 // CK24: call void [[CALL22:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.s.b[:2])
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
index 7a64310266024..85f348de7ffe7 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
@@ -49,7 +49,7 @@ void f5() {
   // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
   // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
   // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
-  // &ps, &ps[0], sizeof(ps), ATTACH
+  // &ps, &ps[0].x, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -260,7 +260,7 @@ void f5() {
 // CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
 // CHECK:    store ptr @ps, ptr [[TMP24]], align 8
 // CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK:    store ptr [[TMP0]], ptr [[TMP25]], align 8
+// CHECK:    store ptr [[X]], ptr [[TMP25]], align 8
 // CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
 // CHECK:    store ptr null, ptr [[TMP26]], align 8
 // CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
index dfec813abc6a8..d9f2c200c0057 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
@@ -52,7 +52,7 @@ void f5() {
   // &ps[0], &ps[0].x, ((&ps[0].y + 1) - &ps[0].x)/8, ALLOC
   // &ps[0], &ps->y, sizeof(ps->y), TO | MEMBER_OF(2)
   // &ps[0], &ps->x, sizeof(ps->x), TO | MEMBER_OF(2)
-  // &ps, &ps[0], sizeof(ps), ATTACH
+  // &ps, &ps[0].x, sizeof(ps), ATTACH
   #pragma omp target map(to: ps->y, ps, ps->x)
     ps->y = 9;
 }
@@ -263,7 +263,7 @@ void f5() {
 // CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
 // CHECK:    store ptr [[PS]], ptr [[TMP24]], align 8
 // CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK:    store ptr [[TMP0]], ptr [[TMP25]], align 8
+// CHECK:    store ptr [[X]], ptr [[TMP25]], align 8
 // CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
 // CHECK:    store ptr null, ptr [[TMP26]], align 8
 // CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0

>From f1acc37466deeb14fcee1f0c588acd440e3b5612 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 21 Jul 2025 00:50:11 -0700
Subject: [PATCH 33/66] [NFC] Move computation of ptr/ptee addrs outside the
 loop.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 75 +++++++++++++--------------
 1 file changed, 35 insertions(+), 40 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 2c1f1112c8b8b..6f7dbdea79b88 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7335,10 +7335,6 @@ class MappableExprsHandler {
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-    // Track info for ATTACH entry generation
-    Address AttachBaseAddr = Address::invalid();
-    Address AttachFirstElemAddr = Address::invalid();
-
     // Find the pointer-attachment base-pointer for the given list, if any.
     std::optional<AttachInfoTy> AttachInfo = findAttachBasePointer(Components);
 
@@ -7785,42 +7781,6 @@ class MappableExprsHandler {
         if (IsFinalArraySection || IsNonContiguous)
           PartialStruct.IsArraySection = true;
 
-        if (Next == CE) {
-          // For now, we are emitting ATTACH entries only when the
-          // "attach-base-pointer" is a vardecl itself, not an expression, or
-          // even a member of a struct.
-          bool IsEligibleForAttachMapping = AttachInfo &&
-                                            AttachInfo->BasePtrDecl &&
-                                            AttachInfo->BasePtrDecl == BaseDecl;
-          // Pointer attachment is needed at map-entering time or for declare
-          // mappers.
-          bool IsMapEnteringConstructOrMapper =
-              isa<const OMPDeclareMapperDecl *>(CurDir) ||
-              isOpenMPTargetMapEnteringDirective(
-                  cast<const OMPExecutableDirective *>(CurDir)
-                      ->getDirectiveKind());
-
-          if (IsEligibleForAttachMapping && IsMapEnteringConstructOrMapper) {
-            AttachBaseAddr =
-                CGF.EmitLValue(AttachInfo->BasePtrExpr).getAddress();
-
-            if (OASE) {
-              AttachFirstElemAddr =
-                  CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true)
-                      .getAddress();
-            } else if (ASE) {
-              AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
-            } else if (auto *ME =
-                           dyn_cast<MemberExpr>(I->getAssociatedExpression())) {
-              AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
-            } else if (auto *UO = dyn_cast<UnaryOperator>(
-                           I->getAssociatedExpression())) {
-              if (UO->getOpcode() == UO_Deref)
-                AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
-            }
-          }
-        }
-
         // If we have a final array section, we are done with this expression.
         if (IsFinalArraySection)
           break;
@@ -7847,6 +7807,41 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
+    // Track info for ATTACH entry generation
+    Address AttachBaseAddr = Address::invalid();
+    Address AttachFirstElemAddr = Address::invalid();
+    // For now, we are emitting ATTACH entries only when the
+    // "attach-base-pointer" is a vardecl itself, not an expression, or
+    // even a member of a struct.
+    bool IsEligibleForAttachMapping = AttachInfo && AttachInfo->BasePtrDecl &&
+                                      AttachInfo->BasePtrDecl == BaseDecl;
+    // Pointer attachment is needed at map-entering time or for declare
+    // mappers.
+    bool IsMapEnteringConstructOrMapper =
+        isa<const OMPDeclareMapperDecl *>(CurDir) ||
+        isOpenMPTargetMapEnteringDirective(
+            cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind());
+
+    if (IsEligibleForAttachMapping && IsMapEnteringConstructOrMapper) {
+      AttachBaseAddr = CGF.EmitLValue(AttachInfo->BasePtrExpr).getAddress();
+
+      if (auto *OASE = dyn_cast<ArraySectionExpr>(
+              Components.rbegin()->getAssociatedExpression())) {
+        AttachFirstElemAddr =
+            CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+      } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(
+                     Components.rbegin()->getAssociatedExpression())) {
+        AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
+      } else if (auto *ME = dyn_cast<MemberExpr>(
+                     Components.rbegin()->getAssociatedExpression())) {
+        AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
+      } else if (auto *UO = dyn_cast<UnaryOperator>(
+                     Components.rbegin()->getAssociatedExpression())) {
+        if (UO->getOpcode() == UO_Deref)
+          AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
+      }
+    }
+
     // Handle ATTACH entries: delay if PartialStruct is being populated,
     // otherwise add immediately.
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {

>From 976470c7d5eb603d55be4d91dea595a9895e6c07 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 21 Jul 2025 02:31:38 -0700
Subject: [PATCH 34/66] [NFC] Return Expr* from findAttachBasePtr.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 127 +++++++++++++-------------
 1 file changed, 66 insertions(+), 61 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 6f7dbdea79b88..e939e0181ce9d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7336,7 +7336,7 @@ class MappableExprsHandler {
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
     // Find the pointer-attachment base-pointer for the given list, if any.
-    std::optional<AttachInfoTy> AttachInfo = findAttachBasePointer(Components);
+    const Expr *AttachPtrExpr = findAttachBasePointer(Components);
 
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
@@ -7382,7 +7382,8 @@ class MappableExprsHandler {
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
         if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
             !VD || VD->hasLocalStorage() ||
-            (AttachInfo && VD == AttachInfo->BasePtrDecl))
+            (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
+             VD == cast<DeclRefExpr>(AttachPtrExpr)->getDecl()))
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
         else
           FirstPointerInComplexData = true;
@@ -7807,43 +7808,12 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
-    // Track info for ATTACH entry generation
-    Address AttachBaseAddr = Address::invalid();
-    Address AttachFirstElemAddr = Address::invalid();
-    // For now, we are emitting ATTACH entries only when the
-    // "attach-base-pointer" is a vardecl itself, not an expression, or
-    // even a member of a struct.
-    bool IsEligibleForAttachMapping = AttachInfo && AttachInfo->BasePtrDecl &&
-                                      AttachInfo->BasePtrDecl == BaseDecl;
-    // Pointer attachment is needed at map-entering time or for declare
-    // mappers.
-    bool IsMapEnteringConstructOrMapper =
-        isa<const OMPDeclareMapperDecl *>(CurDir) ||
-        isOpenMPTargetMapEnteringDirective(
-            cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind());
-
-    if (IsEligibleForAttachMapping && IsMapEnteringConstructOrMapper) {
-      AttachBaseAddr = CGF.EmitLValue(AttachInfo->BasePtrExpr).getAddress();
-
-      if (auto *OASE = dyn_cast<ArraySectionExpr>(
-              Components.rbegin()->getAssociatedExpression())) {
-        AttachFirstElemAddr =
-            CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
-      } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(
-                     Components.rbegin()->getAssociatedExpression())) {
-        AttachFirstElemAddr = CGF.EmitLValue(ASE).getAddress();
-      } else if (auto *ME = dyn_cast<MemberExpr>(
-                     Components.rbegin()->getAssociatedExpression())) {
-        AttachFirstElemAddr = CGF.EmitMemberExpr(ME).getAddress();
-      } else if (auto *UO = dyn_cast<UnaryOperator>(
-                     Components.rbegin()->getAssociatedExpression())) {
-        if (UO->getOpcode() == UO_Deref)
-          AttachFirstElemAddr = CGF.EmitLValue(UO).getAddress();
-      }
-    }
-
     // Handle ATTACH entries: delay if PartialStruct is being populated,
     // otherwise add immediately.
+    const auto &[AttachBaseAddr, AttachFirstElemAddr] = getAttachPtrPteeAddrs(
+        AttachPtrExpr,
+        /*AttachPteeExpr=*/Components.rbegin()->getAssociatedExpression(),
+        /*MapBaseDecl=*/BaseDecl, CGF, CurDir);
     if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
@@ -8134,29 +8104,69 @@ class MappableExprsHandler {
     }
   }
 
-  /// Result structure for findAttachBasePointer
-  struct AttachInfoTy {
-    const Expr *BasePtrExpr = nullptr;      // The pointer expression
-    const ValueDecl *BasePtrDecl = nullptr; // The pointer decl, if any
-    const Expr *PteeExpr = nullptr; // The array section/subscript expression
+  /// Returns Pointer/Pointee Addresses for attach mapping between \p
+  /// PointerExpr and \p PointeeExpr. for \p CurDir, when handling a map
+  /// clause with base \p MapBaseDecl.
+  static std::pair<Address, Address>
+  getAttachPtrPteeAddrs(const Expr *PointerExpr, const Expr *PointeeExpr,
+                        const ValueDecl *MapBaseDecl, CodeGenFunction &CGF,
+                        llvm::PointerUnion<const OMPExecutableDirective *,
+                                           const OMPDeclareMapperDecl *>
+                            CurDir) {
 
-    // Constructor with arguments
-    AttachInfoTy(const Expr *BasePtr, const ValueDecl *BaseDecl,
-                 const Expr *Ptee)
-        : BasePtrExpr(BasePtr), BasePtrDecl(BaseDecl), PteeExpr(Ptee) {}
-  };
+    Address AttachPtrAddr = Address::invalid();
+    Address AttachPteeAddr = Address::invalid();
+    if (!PointerExpr || !PointeeExpr)
+      return {AttachPtrAddr, AttachPteeAddr};
+
+    // Pointer attachment is needed at map-entering time or for declare
+    // mappers.
+    if (!isa<const OMPDeclareMapperDecl *>(CurDir) &&
+        !isOpenMPTargetMapEnteringDirective(
+            cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind()))
+      return {AttachPtrAddr, AttachPteeAddr};
+
+    const auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr);
+    const VarDecl *PointerDecl =
+        !DRE ? nullptr : dyn_cast_if_present<VarDecl>(DRE->getDecl());
+
+    // For now, we are emitting ATTACH entries only when the
+    // "attach-base-pointer" is a vardecl itself, not an expression, or
+    // even a member of a struct.
+    if (!PointerDecl || PointerDecl != MapBaseDecl)
+      return {AttachPtrAddr, AttachPteeAddr};
+
+    AttachPtrAddr = CGF.EmitLValue(PointerExpr).getAddress();
+
+    if (auto *OASE = dyn_cast<ArraySectionExpr>(PointeeExpr)) {
+      AttachPteeAddr =
+          CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+    } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(PointeeExpr)) {
+      AttachPteeAddr = CGF.EmitLValue(ASE).getAddress();
+    } else if (auto *ME = dyn_cast<MemberExpr>(PointeeExpr)) {
+      AttachPteeAddr = CGF.EmitMemberExpr(ME).getAddress();
+    } else if (auto *UO = dyn_cast<UnaryOperator>(PointeeExpr)) {
+      if (UO->getOpcode() == UO_Deref)
+        AttachPteeAddr = CGF.EmitLValue(UO).getAddress();
+    }
+
+    return {AttachPtrAddr, AttachPteeAddr};
+  }
 
   // Traverse the list of Components to find the first pointer expression, which
   // should be the attachable-base-pointer for the current component-list.
   // For example, for:
   //  `map(pp->p->s.a[0])`, the base-pointer is `pp->p`, while the pointee is
   //  `pp->p->s.a[0]`.
-  static std::optional<AttachInfoTy> findAttachBasePointer(
+  static const Expr *findAttachBasePointer(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
     const auto *End = Components.end();
 
+    // Keep stripping away one component at a time, until we reach a pointer.
+    // The first pointer we encounter should be the base-pointer for
+    // pointer-attachment.
     for (const auto *I = Begin; I != End; ++I) {
       const Expr *CurrentExpr = I->getAssociatedExpression();
       if (!CurrentExpr)
@@ -8166,19 +8176,17 @@ class MappableExprsHandler {
       if (NextI == End)
         break;
 
-      // Check if the next component (in forward direction) has a pointer type
       QualType NextType;
-
       if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
         NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
       } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
         // If NextExpr is an array-section, compute the result type using
         // getBaseOriginalType
-        if (const auto *ArraySection = dyn_cast<ArraySectionExpr>(NextExpr)) {
+        if (const auto *OASE = dyn_cast<ArraySectionExpr>(NextExpr)) {
           // Get the original base type, handling chains of array sections
           // properly
           QualType BaseType =
-              ArraySectionExpr::getBaseOriginalType(ArraySection->getBase());
+              ArraySectionExpr::getBaseOriginalType(OASE->getBase());
           if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
             NextType = ATy->getElementType();
           else
@@ -8201,12 +8209,10 @@ class MappableExprsHandler {
       // The Next component is the first pointer expression encountered, so
       // that is the attachable-base-pointer for the current component-list.
       const Expr *BasePtrExpr = NextI->getAssociatedExpression();
-      const ValueDecl *BasePtrDecl = NextI->getAssociatedDeclaration();
-      const auto *BeginExpr = Begin->getAssociatedExpression();
-      return AttachInfoTy{BasePtrExpr, BasePtrDecl, BeginExpr};
+      return BasePtrExpr;
     }
 
-    return std::nullopt;
+    return nullptr;
   }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and
@@ -8394,15 +8400,15 @@ class MappableExprsHandler {
             } else {
               auto PrevCI = std::next(CI->Components.rbegin());
               const auto *VarD = dyn_cast<VarDecl>(VD);
-              std::optional<AttachInfoTy> AttachInfo =
-                  findAttachBasePointer(CI->Components);
+              const Expr *AttachPtrExpr = findAttachBasePointer(CI->Components);
               if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
                   isa<MemberExpr>(IE) ||
                   !VD->getType().getNonReferenceType()->isPointerType() ||
                   PrevCI == CI->Components.rend() ||
                   isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
                   VarD->hasLocalStorage() ||
-                  (AttachInfo && AttachInfo->BasePtrDecl == VD)) {
+                  (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
+                   VD == cast<DeclRefExpr>(AttachPtrExpr)->getDecl())) {
                 CI->ForDeviceAddr = IsDevAddr;
                 CI->ReturnDevicePointer = true;
                 Found = true;
@@ -8660,8 +8666,7 @@ class MappableExprsHandler {
                          MapCombinedInfoTy &AttachCombinedInfo,
                          MapFlagsArrayTy &CurTypes,
                          const StructRangeInfoTy &PartialStruct, bool IsMapThis,
-                         llvm::OpenMPIRBuilder &OMPBuilder,
-                         const ValueDecl *VD,
+                         llvm::OpenMPIRBuilder &OMPBuilder, const ValueDecl *VD,
                          unsigned OffsetForMemberOfFlag,
                          bool NotTargetParams) const {
     if (CurTypes.size() == 1 &&

>From fd2d0774f674047ee7990c89b2dcc8263263087a Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 21 Jul 2025 03:02:13 -0700
Subject: [PATCH 35/66] [NFC] Minor renaming/comment changes.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 65 ++++++++++++++-------------
 1 file changed, 33 insertions(+), 32 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index e939e0181ce9d..a5d9da5be359f 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6841,9 +6841,9 @@ class MappableExprsHandler {
     bool IsArraySection = false;
     bool HasCompleteRecord = false;
     // ATTACH information for delayed processing
-    Address AttachBaseAddr = Address::invalid();
-    Address AttachFirstElemAddr = Address::invalid();
-    const ValueDecl *AttachBaseDecl = nullptr;
+    Address AttachPtrAddr = Address::invalid();
+    Address AttachPteeAddr = Address::invalid();
+    const ValueDecl *AttachPtrDecl = nullptr;
     const Expr *AttachMapExpr = nullptr;
   };
 
@@ -7170,9 +7170,8 @@ class MappableExprsHandler {
     // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
     //
     // map(p[1:24])
-    // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ
-    // in unified shared memory mode or for local pointers
     // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
+    // &p, &p[1], sizeof(p), ATTACH
     //
     // map((*a)[0:3])
     // &(*a), &(*a), sizeof(pointer), TARGET_PARAM | TO | FROM
@@ -7242,12 +7241,15 @@ class MappableExprsHandler {
     //
     // map(ps->i)
     // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
+    // &ps, &(ps->i), sizeof(ps), ATTACH
     //
     // map(ps->s.f)
     // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
+    // &ps, &(ps->s.f[0]), sizeof(ps), ATTACH
     //
     // map(from: ps->p)
     // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
+    // &ps, &(ps->p), sizeof(ps), ATTACH
     //
     // map(to: ps->p[:22])
     // ps, &(ps->p), sizeof(double*), TARGET_PARAM
@@ -7256,6 +7258,7 @@ class MappableExprsHandler {
     //
     // map(ps->ps)
     // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
+    // &ps, &(ps->ps), sizeof(ps), ATTACH
     //
     // map(from: ps->ps->s.i)
     // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
@@ -7336,7 +7339,7 @@ class MappableExprsHandler {
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
     // Find the pointer-attachment base-pointer for the given list, if any.
-    const Expr *AttachPtrExpr = findAttachBasePointer(Components);
+    const Expr *AttachPtrExpr = findAttachPtrExpr(Components);
 
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
@@ -7493,8 +7496,6 @@ class MappableExprsHandler {
       // types.
       const auto *OASE =
           dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
-      const auto *ASE =
-          dyn_cast<ArraySubscriptExpr>(I->getAssociatedExpression());
       const auto *OAShE =
           dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
       const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
@@ -7808,25 +7809,25 @@ class MappableExprsHandler {
     if (!EncounteredME)
       PartialStruct.HasCompleteRecord = true;
 
-    // Handle ATTACH entries: delay if PartialStruct is being populated,
-    // otherwise add immediately.
-    const auto &[AttachBaseAddr, AttachFirstElemAddr] = getAttachPtrPteeAddrs(
+    // Add ATTACH entries for pointer-attachment: delay if PartialStruct is
+    // being populated, otherwise add immediately.
+    const auto &[AttachPtrAddr, AttachPteeAddr] = getAttachPtrPteeAddrs(
         AttachPtrExpr,
         /*AttachPteeExpr=*/Components.rbegin()->getAssociatedExpression(),
         /*MapBaseDecl=*/BaseDecl, CGF, CurDir);
-    if (AttachBaseAddr.isValid() && AttachFirstElemAddr.isValid()) {
+    if (AttachPtrAddr.isValid() && AttachPteeAddr.isValid()) {
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
         // after emitCombinedEntry.
-        PartialStruct.AttachBaseAddr = AttachBaseAddr;
-        PartialStruct.AttachFirstElemAddr = AttachFirstElemAddr;
-        PartialStruct.AttachBaseDecl = BaseDecl;
+        PartialStruct.AttachPtrAddr = AttachPtrAddr;
+        PartialStruct.AttachPteeAddr = AttachPteeAddr;
+        PartialStruct.AttachPtrDecl = BaseDecl;
         PartialStruct.AttachMapExpr = MapExpr;
       } else if (IsMappingWholeStruct) {
-        addAttachEntry(CGF, StructBaseCombinedInfo, AttachBaseAddr,
-                       AttachFirstElemAddr, BaseDecl, MapExpr);
+        addAttachEntry(CGF, StructBaseCombinedInfo, AttachPtrAddr,
+                       AttachPteeAddr, BaseDecl, MapExpr);
       } else {
-        addAttachEntry(CGF, CombinedInfo, AttachBaseAddr, AttachFirstElemAddr,
+        addAttachEntry(CGF, CombinedInfo, AttachPtrAddr, AttachPteeAddr,
                        BaseDecl, MapExpr);
       }
     }
@@ -8104,9 +8105,9 @@ class MappableExprsHandler {
     }
   }
 
-  /// Returns Pointer/Pointee Addresses for attach mapping between \p
-  /// PointerExpr and \p PointeeExpr. for \p CurDir, when handling a map
-  /// clause with base \p MapBaseDecl.
+  // Returns the Pointer/Pointee Addresses for attach mapping between \p
+  // PointerExpr and \p PointeeExpr. for \p CurDir, when handling a map
+  // clause with base \p MapBaseDecl.
   static std::pair<Address, Address>
   getAttachPtrPteeAddrs(const Expr *PointerExpr, const Expr *PointeeExpr,
                         const ValueDecl *MapBaseDecl, CodeGenFunction &CGF,
@@ -8158,7 +8159,7 @@ class MappableExprsHandler {
   // For example, for:
   //  `map(pp->p->s.a[0])`, the base-pointer is `pp->p`, while the pointee is
   //  `pp->p->s.a[0]`.
-  static const Expr *findAttachBasePointer(
+  static const Expr *findAttachPtrExpr(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
@@ -8400,7 +8401,7 @@ class MappableExprsHandler {
             } else {
               auto PrevCI = std::next(CI->Components.rbegin());
               const auto *VarD = dyn_cast<VarDecl>(VD);
-              const Expr *AttachPtrExpr = findAttachBasePointer(CI->Components);
+              const Expr *AttachPtrExpr = findAttachPtrExpr(CI->Components);
               if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
                   isa<MemberExpr>(IE) ||
                   !VD->getType().getNonReferenceType()->isPointerType() ||
@@ -8675,11 +8676,11 @@ class MappableExprsHandler {
         !PartialStruct.IsArraySection) {
       // Even if we are not creating a combined-entry, we need to process any
       // previously delayed ATTACH entries.
-      if (PartialStruct.AttachBaseAddr.isValid() &&
-          PartialStruct.AttachFirstElemAddr.isValid())
-        addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
-                       PartialStruct.AttachFirstElemAddr,
-                       PartialStruct.AttachBaseDecl,
+      if (PartialStruct.AttachPtrAddr.isValid() &&
+          PartialStruct.AttachPteeAddr.isValid())
+        addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachPtrAddr,
+                       PartialStruct.AttachPteeAddr,
+                       PartialStruct.AttachPtrDecl,
                        PartialStruct.AttachMapExpr);
       return;
     }
@@ -8777,10 +8778,10 @@ class MappableExprsHandler {
     //   S *ps;
     //   ... map(ps->a, ps->b)
     // We won't emit separate ATTACH entries for the two list items, just one.
-    if (PartialStruct.AttachBaseAddr.isValid() &&
-        PartialStruct.AttachFirstElemAddr.isValid())
-      addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachBaseAddr,
-                     LBAddr, PartialStruct.AttachBaseDecl,
+    if (PartialStruct.AttachPtrAddr.isValid() &&
+        PartialStruct.AttachPteeAddr.isValid())
+      addAttachEntry(CGF, AttachCombinedInfo, PartialStruct.AttachPtrAddr,
+                     LBAddr, PartialStruct.AttachPtrDecl,
                      PartialStruct.AttachMapExpr);
   }
 

>From fdced7dbfeef105ca3799930b647c0a9d67fcf1d Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 21 Jul 2025 03:28:47 -0700
Subject: [PATCH 36/66] Fix call to getAttachptrPteeAddrs.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index a5d9da5be359f..f91e3fb0e8d2b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7813,7 +7813,7 @@ class MappableExprsHandler {
     // being populated, otherwise add immediately.
     const auto &[AttachPtrAddr, AttachPteeAddr] = getAttachPtrPteeAddrs(
         AttachPtrExpr,
-        /*AttachPteeExpr=*/Components.rbegin()->getAssociatedExpression(),
+        /*AttachPteeExpr=*/Components.begin()->getAssociatedExpression(),
         /*MapBaseDecl=*/BaseDecl, CGF, CurDir);
     if (AttachPtrAddr.isValid() && AttachPteeAddr.isValid()) {
       if (PartialStruct.Base.isValid()) {

>From d791cb3c64912e350a7638eba2cd56bea62cca34 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 21 Jul 2025 03:42:50 -0700
Subject: [PATCH 37/66] Remove unnecessary include.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index f91e3fb0e8d2b..614b78b54915f 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -21,7 +21,6 @@
 #include "clang/AST/APValue.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/StmtOpenMP.h"
 #include "clang/AST/StmtVisitor.h"

>From df62d2e966e5529857782a0cd94573c518d9dde8 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 22 Jul 2025 01:48:37 -0700
Subject: [PATCH 38/66] No need to compute the pointee address from scratch.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 63 +++++++++++----------------
 1 file changed, 26 insertions(+), 37 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 614b78b54915f..e6f8541aacacd 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7332,6 +7332,7 @@ class MappableExprsHandler {
     bool IsExpressionFirstInfo = true;
     bool FirstPointerInComplexData = false;
     Address BP = Address::invalid();
+    Address FinalLowestElem = Address::invalid();
     const Expr *AssocExpr = I->getAssociatedExpression();
     const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
@@ -7594,8 +7595,8 @@ class MappableExprsHandler {
                   LowestElem, CGF.VoidPtrTy, CGF.Int8Ty),
               TypeSize.getQuantity() - 1);
           PartialStruct.HighestElem = {
-              std::numeric_limits<
-                  decltype(PartialStruct.HighestElem.first)>::max(),
+              std::numeric_limits<decltype(
+                  PartialStruct.HighestElem.first)>::max(),
               HB};
           PartialStruct.Base = BP;
           PartialStruct.LB = LB;
@@ -7782,6 +7783,11 @@ class MappableExprsHandler {
         if (IsFinalArraySection || IsNonContiguous)
           PartialStruct.IsArraySection = true;
 
+        // Save the final LowestElem, to use it as the pointee in attach maps,
+        // if emitted.
+        if (Next == CE)
+          FinalLowestElem = LowestElem;
+
         // If we have a final array section, we are done with this expression.
         if (IsFinalArraySection)
           break;
@@ -7810,11 +7816,13 @@ class MappableExprsHandler {
 
     // Add ATTACH entries for pointer-attachment: delay if PartialStruct is
     // being populated, otherwise add immediately.
-    const auto &[AttachPtrAddr, AttachPteeAddr] = getAttachPtrPteeAddrs(
-        AttachPtrExpr,
-        /*AttachPteeExpr=*/Components.begin()->getAssociatedExpression(),
-        /*MapBaseDecl=*/BaseDecl, CGF, CurDir);
-    if (AttachPtrAddr.isValid() && AttachPteeAddr.isValid()) {
+   if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
+      Address AttachPtrAddr = CGF.EmitLValue(AttachPtrExpr).getAddress();
+      Address AttachPteeAddr = FinalLowestElem;
+
+      assert(AttachPtrAddr.isValid() && "Attach ptr address is not valid.");
+      assert(AttachPteeAddr.isValid() && "Attach ptee address is not valid.");
+
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
         // after emitCombinedEntry.
@@ -8104,53 +8112,34 @@ class MappableExprsHandler {
     }
   }
 
-  // Returns the Pointer/Pointee Addresses for attach mapping between \p
-  // PointerExpr and \p PointeeExpr. for \p CurDir, when handling a map
-  // clause with base \p MapBaseDecl.
-  static std::pair<Address, Address>
-  getAttachPtrPteeAddrs(const Expr *PointerExpr, const Expr *PointeeExpr,
-                        const ValueDecl *MapBaseDecl, CodeGenFunction &CGF,
+  /// Returns whether an attach entry should be emitted for a map on
+  /// \p MapBaseDecl on the directive \p CurDir.
+  static bool
+  shouldEmitAttachEntry(const Expr *PointerExpr, const ValueDecl *MapBaseDecl,
+                        CodeGenFunction &CGF,
                         llvm::PointerUnion<const OMPExecutableDirective *,
                                            const OMPDeclareMapperDecl *>
                             CurDir) {
-
-    Address AttachPtrAddr = Address::invalid();
-    Address AttachPteeAddr = Address::invalid();
-    if (!PointerExpr || !PointeeExpr)
-      return {AttachPtrAddr, AttachPteeAddr};
+    if (!PointerExpr)
+      return false;
 
     // Pointer attachment is needed at map-entering time or for declare
     // mappers.
     if (!isa<const OMPDeclareMapperDecl *>(CurDir) &&
         !isOpenMPTargetMapEnteringDirective(
             cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind()))
-      return {AttachPtrAddr, AttachPteeAddr};
+      return false;
 
     const auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr);
     const VarDecl *PointerDecl =
         !DRE ? nullptr : dyn_cast_if_present<VarDecl>(DRE->getDecl());
 
     // For now, we are emitting ATTACH entries only when the
-    // "attach-base-pointer" is a vardecl itself, not an expression, or
-    // even a member of a struct.
+    // "attach-base-pointer" is a vardecl that matches the base var of the map.
     if (!PointerDecl || PointerDecl != MapBaseDecl)
-      return {AttachPtrAddr, AttachPteeAddr};
-
-    AttachPtrAddr = CGF.EmitLValue(PointerExpr).getAddress();
-
-    if (auto *OASE = dyn_cast<ArraySectionExpr>(PointeeExpr)) {
-      AttachPteeAddr =
-          CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
-    } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(PointeeExpr)) {
-      AttachPteeAddr = CGF.EmitLValue(ASE).getAddress();
-    } else if (auto *ME = dyn_cast<MemberExpr>(PointeeExpr)) {
-      AttachPteeAddr = CGF.EmitMemberExpr(ME).getAddress();
-    } else if (auto *UO = dyn_cast<UnaryOperator>(PointeeExpr)) {
-      if (UO->getOpcode() == UO_Deref)
-        AttachPteeAddr = CGF.EmitLValue(UO).getAddress();
-    }
+      return false;
 
-    return {AttachPtrAddr, AttachPteeAddr};
+    return true;
   }
 
   // Traverse the list of Components to find the first pointer expression, which

>From 63d2ca43fd66dc00f8d1cdb302fba4dbf51ea5ec Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 22 Jul 2025 03:07:30 -0700
Subject: [PATCH 39/66] Update tests after avoiding creating pointee addr, and
 a minor comment fix.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |   4 +
 clang/test/OpenMP/bug60602.cpp                | 368 ++++++-----
 clang/test/OpenMP/reduction_implicit_map.cpp  | 588 +++++++++---------
 .../OpenMP/target_data_map_codegen_hold.cpp   | 500 ++++++++-------
 ...ta_map_pointer_array_subscript_codegen.cpp |   4 +-
 .../target_data_use_device_addr_codegen.cpp   |  22 +-
 .../target_data_use_device_ptr_if_codegen.cpp |   4 +-
 ...arget_map_both_pointer_pointee_codegen.cpp | 266 ++++----
 ...ap_both_pointer_pointee_codegen_global.cpp | 266 ++++----
 clang/test/OpenMP/target_map_codegen_33.cpp   |  31 +-
 .../OpenMP/target_map_ptr_and_star_global.cpp | 113 ++--
 .../OpenMP/target_map_ptr_and_star_local.cpp  | 113 ++--
 ...target_map_structptr_and_member_global.cpp | 204 +++---
 .../target_map_structptr_and_member_local.cpp | 204 +++---
 .../OpenMP/target_task_affinity_codegen.cpp   | 381 ++++++------
 15 files changed, 1500 insertions(+), 1568 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index e6f8541aacacd..2e38add85bb5a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7172,6 +7172,10 @@ class MappableExprsHandler {
     // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
     // &p, &p[1], sizeof(p), ATTACH
     //
+    // map((22])p)
+    // p, p, 22*sizeof(float), TARGET_PARAM | TO | FROM
+    // &p, p, sizeof(float*), ATTACH
+    //
     // map((*a)[0:3])
     // &(*a), &(*a), sizeof(pointer), TARGET_PARAM | TO | FROM
     // &(*a), &(*a)[0], 3*sizeof(int), PTR_AND_OBJ | TO | FROM
diff --git a/clang/test/OpenMP/bug60602.cpp b/clang/test/OpenMP/bug60602.cpp
index 88af942cedb60..9b2dff791cccd 100644
--- a/clang/test/OpenMP/bug60602.cpp
+++ b/clang/test/OpenMP/bug60602.cpp
@@ -36,15 +36,15 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
 // CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [5 x ptr], align 8
 // CHECK-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [5 x i64], align 8
 // CHECK-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK-NEXT:    [[N_CASTED5:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS12:%.*]] = alloca [5 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS13:%.*]] = alloca [5 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS14:%.*]] = alloca [5 x ptr], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_SIZES15:%.*]] = alloca [5 x i64], align 8
+// CHECK-NEXT:    [[N_CASTED3:%.*]] = alloca i64, align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS8:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS9:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS10:%.*]] = alloca [5 x ptr], align 8
+// CHECK-NEXT:    [[DOTOFFLOAD_SIZES11:%.*]] = alloca [5 x i64], align 8
 // CHECK-NEXT:    [[TMP:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[DOTCAPTURE_EXPR_:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTCAPTURE_EXPR_16:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[KERNEL_ARGS18:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK-NEXT:    [[DOTCAPTURE_EXPR_12:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[KERNEL_ARGS14:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    store ptr [[A]], ptr [[A_ADDR]], align 8
 // CHECK-NEXT:    store ptr [[B]], ptr [[B_ADDR]], align 8
 // CHECK-NEXT:    store i32 [[N]], ptr [[N_ADDR]], align 4
@@ -68,203 +68,195 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
 // CHECK-NEXT:    [[TMP8:%.*]] = load i32, ptr [[N_ADDR]], align 4
 // CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP8]] to i64
 // CHECK-NEXT:    [[TMP9:%.*]] = mul nuw i64 [[CONV]], 4
-// CHECK-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP10]], i64 0
+// CHECK-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[B_ADDR]], align 8
 // CHECK-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP12]], i64 0
-// CHECK-NEXT:    [[TMP13:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV3:%.*]] = sext i32 [[TMP13]] to i64
-// CHECK-NEXT:    [[TMP14:%.*]] = mul nuw i64 [[CONV3]], 4
-// CHECK-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP15]], i64 0
+// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP11]], i64 0
+// CHECK-NEXT:    [[TMP12:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV2:%.*]] = sext i32 [[TMP12]] to i64
+// CHECK-NEXT:    [[TMP13:%.*]] = mul nuw i64 [[CONV2]], 4
 // CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes, i64 40, i1 false)
-// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP16]], align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP17]], align 8
-// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP18]], align 8
-// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP19]], align 8
-// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP20]], align 8
-// CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP9]], ptr [[TMP21]], align 8
-// CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP22]], align 8
-// CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP23]], align 8
-// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP24]], align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP25]], align 8
-// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP11]], ptr [[TMP26]], align 8
-// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[ARRAYIDX2]], ptr [[TMP27]], align 8
-// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
-// CHECK-NEXT:    store i64 [[TMP14]], ptr [[TMP28]], align 8
-// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK-NEXT:    store ptr null, ptr [[TMP29]], align 8
-// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP30]], align 8
-// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP31]], align 8
-// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
-// CHECK-NEXT:    store ptr null, ptr [[TMP32]], align 8
-// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP36]], align 4
-// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK-NEXT:    store i32 5, ptr [[TMP37]], align 4
-// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP14]], align 8
+// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP3]], ptr [[TMP15]], align 8
+// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP16]], align 8
+// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP17]], align 8
+// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP18]], align 8
+// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP9]], ptr [[TMP19]], align 8
+// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP20]], align 8
+// CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP21]], align 8
+// CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP22]], align 8
+// CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP23]], align 8
+// CHECK-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP10]], ptr [[TMP24]], align 8
+// CHECK-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP25]], align 8
+// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
+// CHECK-NEXT:    store i64 [[TMP13]], ptr [[TMP26]], align 8
+// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK-NEXT:    store ptr null, ptr [[TMP27]], align 8
+// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP28]], align 8
+// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP29]], align 8
+// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK-NEXT:    store ptr null, ptr [[TMP30]], align 8
+// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP34]], align 4
+// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK-NEXT:    store i32 5, ptr [[TMP35]], align 4
+// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP31]], ptr [[TMP36]], align 8
+// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP32]], ptr [[TMP37]], align 8
+// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
 // CHECK-NEXT:    store ptr [[TMP33]], ptr [[TMP38]], align 8
-// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP34]], ptr [[TMP39]], align 8
-// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP35]], ptr [[TMP40]], align 8
-// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP41]], align 8
-// CHECK-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP42]], align 8
-// CHECK-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP43]], align 8
-// CHECK-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP44]], align 8
-// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP45]], align 8
-// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP46]], align 4
-// CHECK-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP47]], align 4
-// CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP48]], align 4
-// CHECK-NEXT:    [[TMP49:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2:[0-9]+]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9.region_id, ptr [[KERNEL_ARGS]])
-// CHECK-NEXT:    [[TMP50:%.*]] = icmp ne i32 [[TMP49]], 0
-// CHECK-NEXT:    br i1 [[TMP50]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP39]], align 8
+// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP40]], align 8
+// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP41]], align 8
+// CHECK-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP42]], align 8
+// CHECK-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP43]], align 8
+// CHECK-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP44]], align 4
+// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP45]], align 4
+// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP46]], align 4
+// CHECK-NEXT:    [[TMP47:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2:[0-9]+]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9.region_id, ptr [[KERNEL_ARGS]])
+// CHECK-NEXT:    [[TMP48:%.*]] = icmp ne i32 [[TMP47]], 0
+// CHECK-NEXT:    br i1 [[TMP48]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK:       omp_offload.failed:
 // CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9(i64 [[TMP3]], ptr [[TMP4]], ptr [[TMP5]]) #[[ATTR2:[0-9]+]]
 // CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK:       omp_offload.cont:
-// CHECK-NEXT:    [[TMP51:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP51]], ptr [[N_CASTED5]], align 4
-// CHECK-NEXT:    [[TMP52:%.*]] = load i64, ptr [[N_CASTED5]], align 8
+// CHECK-NEXT:    [[TMP49:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP49]], ptr [[N_CASTED3]], align 4
+// CHECK-NEXT:    [[TMP50:%.*]] = load i64, ptr [[N_CASTED3]], align 8
+// CHECK-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[B_ADDR]], align 8
 // CHECK-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP56]], i64 0
-// CHECK-NEXT:    [[TMP57:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV7:%.*]] = sext i32 [[TMP57]] to i64
-// CHECK-NEXT:    [[TMP58:%.*]] = mul nuw i64 [[CONV7]], 4
-// CHECK-NEXT:    [[TMP59:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP59]], i64 0
-// CHECK-NEXT:    [[TMP60:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[TMP61:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP61]], i64 0
-// CHECK-NEXT:    [[TMP62:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[CONV10:%.*]] = sext i32 [[TMP62]] to i64
-// CHECK-NEXT:    [[TMP63:%.*]] = mul nuw i64 [[CONV10]], 4
-// CHECK-NEXT:    [[TMP64:%.*]] = load ptr, ptr [[B_ADDR]], align 8
-// CHECK-NEXT:    [[ARRAYIDX11:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP64]], i64 0
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES15]], ptr align 8 @.offload_sizes.1, i64 40, i1 false)
-// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP52]], ptr [[TMP65]], align 8
-// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 0
-// CHECK-NEXT:    store i64 [[TMP52]], ptr [[TMP66]], align 8
-// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 0
+// CHECK-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP54]], i64 0
+// CHECK-NEXT:    [[TMP55:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV5:%.*]] = sext i32 [[TMP55]] to i64
+// CHECK-NEXT:    [[TMP56:%.*]] = mul nuw i64 [[CONV5]], 4
+// CHECK-NEXT:    [[TMP57:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[TMP58:%.*]] = load ptr, ptr [[B_ADDR]], align 8
+// CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP58]], i64 0
+// CHECK-NEXT:    [[TMP59:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[CONV7:%.*]] = sext i32 [[TMP59]] to i64
+// CHECK-NEXT:    [[TMP60:%.*]] = mul nuw i64 [[CONV7]], 4
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES11]], ptr align 8 @.offload_sizes.1, i64 40, i1 false)
+// CHECK-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP50]], ptr [[TMP61]], align 8
+// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0
+// CHECK-NEXT:    store i64 [[TMP50]], ptr [[TMP62]], align 8
+// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP63]], align 8
+// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP53]], ptr [[TMP64]], align 8
+// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP65]], align 8
+// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP56]], ptr [[TMP66]], align 8
+// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 1
 // CHECK-NEXT:    store ptr null, ptr [[TMP67]], align 8
-// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[TMP55]], ptr [[TMP68]], align 8
-// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP69]], align 8
-// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP58]], ptr [[TMP70]], align 8
-// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP71]], align 8
-// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP72]], align 8
-// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP73]], align 8
-// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 2
+// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[A_ADDR]], ptr [[TMP68]], align 8
+// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP69]], align 8
+// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP70]], align 8
+// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP57]], ptr [[TMP71]], align 8
+// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP72]], align 8
+// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 3
+// CHECK-NEXT:    store i64 [[TMP60]], ptr [[TMP73]], align 8
+// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 3
 // CHECK-NEXT:    store ptr null, ptr [[TMP74]], align 8
-// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP60]], ptr [[TMP75]], align 8
-// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[ARRAYIDX9]], ptr [[TMP76]], align 8
-// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 3
-// CHECK-NEXT:    store i64 [[TMP63]], ptr [[TMP77]], align 8
-// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 3
-// CHECK-NEXT:    store ptr null, ptr [[TMP78]], align 8
-// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP79]], align 8
-// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[ARRAYIDX11]], ptr [[TMP80]], align 8
-// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS14]], i64 0, i64 4
-// CHECK-NEXT:    store ptr null, ptr [[TMP81]], align 8
-// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES15]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP85:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP85]], ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK-NEXT:    [[TMP86:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP86]], -2
+// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[B_ADDR]], ptr [[TMP75]], align 8
+// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP76]], align 8
+// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS10]], i64 0, i64 4
+// CHECK-NEXT:    store ptr null, ptr [[TMP77]], align 8
+// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES11]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP81:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP81]], ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK-NEXT:    [[TMP82:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[TMP82]], -2
 // CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[SUB]], 3
-// CHECK-NEXT:    [[SUB17:%.*]] = sub i32 [[DIV]], 1
-// CHECK-NEXT:    store i32 [[SUB17]], ptr [[DOTCAPTURE_EXPR_16]], align 4
-// CHECK-NEXT:    [[TMP87:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_16]], align 4
-// CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP87]], 1
-// CHECK-NEXT:    [[TMP88:%.*]] = zext i32 [[ADD]] to i64
-// CHECK-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP89]], align 4
-// CHECK-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1
-// CHECK-NEXT:    store i32 5, ptr [[TMP90]], align 4
-// CHECK-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP82]], ptr [[TMP91]], align 8
-// CHECK-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP83]], ptr [[TMP92]], align 8
-// CHECK-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP84]], ptr [[TMP93]], align 8
-// CHECK-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP94]], align 8
-// CHECK-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP95]], align 8
-// CHECK-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP96]], align 8
-// CHECK-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 8
-// CHECK-NEXT:    store i64 [[TMP88]], ptr [[TMP97]], align 8
-// CHECK-NEXT:    [[TMP98:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP98]], align 8
-// CHECK-NEXT:    [[TMP99:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP99]], align 4
-// CHECK-NEXT:    [[TMP100:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP100]], align 4
-// CHECK-NEXT:    [[TMP101:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP101]], align 4
-// CHECK-NEXT:    [[TMP102:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13.region_id, ptr [[KERNEL_ARGS18]])
-// CHECK-NEXT:    [[TMP103:%.*]] = icmp ne i32 [[TMP102]], 0
-// CHECK-NEXT:    br i1 [[TMP103]], label [[OMP_OFFLOAD_FAILED19:%.*]], label [[OMP_OFFLOAD_CONT20:%.*]]
-// CHECK:       omp_offload.failed19:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13(i64 [[TMP52]], ptr [[TMP53]], ptr [[TMP54]]) #[[ATTR2]]
-// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT20]]
-// CHECK:       omp_offload.cont20:
+// CHECK-NEXT:    [[SUB13:%.*]] = sub i32 [[DIV]], 1
+// CHECK-NEXT:    store i32 [[SUB13]], ptr [[DOTCAPTURE_EXPR_12]], align 4
+// CHECK-NEXT:    [[TMP83:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_12]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP83]], 1
+// CHECK-NEXT:    [[TMP84:%.*]] = zext i32 [[ADD]] to i64
+// CHECK-NEXT:    [[TMP85:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP85]], align 4
+// CHECK-NEXT:    [[TMP86:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
+// CHECK-NEXT:    store i32 5, ptr [[TMP86]], align 4
+// CHECK-NEXT:    [[TMP87:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP78]], ptr [[TMP87]], align 8
+// CHECK-NEXT:    [[TMP88:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP79]], ptr [[TMP88]], align 8
+// CHECK-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[TMP80]], ptr [[TMP89]], align 8
+// CHECK-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP90]], align 8
+// CHECK-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP91]], align 8
+// CHECK-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP92]], align 8
+// CHECK-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
+// CHECK-NEXT:    store i64 [[TMP84]], ptr [[TMP93]], align 8
+// CHECK-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP94]], align 8
+// CHECK-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP95]], align 4
+// CHECK-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP96]], align 4
+// CHECK-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP97]], align 4
+// CHECK-NEXT:    [[TMP98:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB2]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13.region_id, ptr [[KERNEL_ARGS14]])
+// CHECK-NEXT:    [[TMP99:%.*]] = icmp ne i32 [[TMP98]], 0
+// CHECK-NEXT:    br i1 [[TMP99]], label [[OMP_OFFLOAD_FAILED15:%.*]], label [[OMP_OFFLOAD_CONT16:%.*]]
+// CHECK:       omp_offload.failed15:
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l13(i64 [[TMP50]], ptr [[TMP51]], ptr [[TMP52]]) #[[ATTR2]]
+// CHECK-NEXT:    br label [[OMP_OFFLOAD_CONT16]]
+// CHECK:       omp_offload.cont16:
 // CHECK-NEXT:    br label [[FOR_INC:%.*]]
 // CHECK:       for.inc:
-// CHECK-NEXT:    [[TMP104:%.*]] = load i32, ptr [[I]], align 4
-// CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP104]], 1
+// CHECK-NEXT:    [[TMP100:%.*]] = load i32, ptr [[I]], align 4
+// CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP100]], 1
 // CHECK-NEXT:    store i32 [[INC]], ptr [[I]], align 4
 // CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP7:![0-9]+]]
 // CHECK:       for.end:
-// CHECK-NEXT:    [[TMP105:%.*]] = load ptr, ptr [[A_ADDR]], align 8
-// CHECK-NEXT:    [[TMP106:%.*]] = load i32, ptr [[N_ADDR]], align 4
-// CHECK-NEXT:    [[SUB21:%.*]] = sub nsw i32 [[TMP106]], 1
-// CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[SUB21]] to i64
-// CHECK-NEXT:    [[ARRAYIDX22:%.*]] = getelementptr inbounds i32, ptr [[TMP105]], i64 [[IDXPROM]]
-// CHECK-NEXT:    [[TMP107:%.*]] = load i32, ptr [[ARRAYIDX22]], align 4
-// CHECK-NEXT:    ret i32 [[TMP107]]
+// CHECK-NEXT:    [[TMP101:%.*]] = load ptr, ptr [[A_ADDR]], align 8
+// CHECK-NEXT:    [[TMP102:%.*]] = load i32, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[SUB17:%.*]] = sub nsw i32 [[TMP102]], 1
+// CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[SUB17]] to i64
+// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds i32, ptr [[TMP101]], i64 [[IDXPROM]]
+// CHECK-NEXT:    [[TMP103:%.*]] = load i32, ptr [[ARRAYIDX18]], align 4
+// CHECK-NEXT:    ret i32 [[TMP103]]
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z18kernel_within_loopPiS_ii_l9
diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp
index f0c2336a5e4a7..79c85447d7422 100644
--- a/clang/test/OpenMP/reduction_implicit_map.cpp
+++ b/clang/test/OpenMP/reduction_implicit_map.cpp
@@ -832,28 +832,28 @@ int main()
 // CHECK2-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [5 x i64], align 4
 // CHECK2-NEXT:    [[TMP:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    [[DOTCAPTURE_EXPR_:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_4:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_2:%.*]] = alloca i32, align 4
 // CHECK2-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK2-NEXT:    [[SIZE_CASTED6:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [5 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS12:%.*]] = alloca [5 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS13:%.*]] = alloca [5 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES14:%.*]] = alloca [5 x i64], align 4
-// CHECK2-NEXT:    [[_TMP15:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_16:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_17:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS22:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED4:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [5 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_SIZES10:%.*]] = alloca [5 x i64], align 4
+// CHECK2-NEXT:    [[_TMP11:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_12:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTCAPTURE_EXPR_13:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS18:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK2-NEXT:    [[A:%.*]] = alloca [10 x i32], align 4
-// CHECK2-NEXT:    [[SIZE_CASTED25:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS27:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS28:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS29:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS30:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
-// CHECK2-NEXT:    [[SIZE_CASTED33:%.*]] = alloca i32, align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS35:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS36:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS37:%.*]] = alloca [2 x ptr], align 4
-// CHECK2-NEXT:    [[KERNEL_ARGS38:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED21:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS23:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS24:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS25:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS26:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK2-NEXT:    [[SIZE_CASTED29:%.*]] = alloca i32, align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [2 x ptr], align 4
+// CHECK2-NEXT:    [[KERNEL_ARGS34:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK2-NEXT:    store ptr [[INPUT]], ptr [[INPUT_ADDR]], align 4
 // CHECK2-NEXT:    store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4
 // CHECK2-NEXT:    store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 4
@@ -865,294 +865,286 @@ int main()
 // CHECK2-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP5]], i32 0
-// CHECK2-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP6]], i32 0
+// CHECK2-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP8]], i32 0
-// CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP10:%.*]] = mul nuw i32 [[TMP9]], 4
-// CHECK2-NEXT:    [[TMP11:%.*]] = sext i32 [[TMP10]] to i64
-// CHECK2-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP12]], i32 0
+// CHECK2-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP7]], i32 0
+// CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP9:%.*]] = mul nuw i32 [[TMP8]], 4
+// CHECK2-NEXT:    [[TMP10:%.*]] = sext i32 [[TMP9]] to i64
 // CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes, i32 40, i1 false)
-// CHECK2-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP13]], align 4
-// CHECK2-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP14]], align 4
-// CHECK2-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP15]], align 4
-// CHECK2-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[TMP4]], ptr [[TMP16]], align 4
-// CHECK2-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP17]], align 4
-// CHECK2-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP18]], align 4
-// CHECK2-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP19]], align 4
-// CHECK2-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP20]], align 4
-// CHECK2-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr null, ptr [[TMP21]], align 4
-// CHECK2-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP7]], ptr [[TMP22]], align 4
-// CHECK2-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[ARRAYIDX2]], ptr [[TMP23]], align 4
-// CHECK2-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
-// CHECK2-NEXT:    store i64 [[TMP11]], ptr [[TMP24]], align 4
-// CHECK2-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr null, ptr [[TMP25]], align 4
-// CHECK2-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP26]], align 4
-// CHECK2-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[ARRAYIDX3]], ptr [[TMP27]], align 4
-// CHECK2-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr null, ptr [[TMP28]], align 4
-// CHECK2-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP32:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP32]], ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK2-NEXT:    [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
-// CHECK2-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP33]], 0
+// CHECK2-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP11]], align 4
+// CHECK2-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP1]], ptr [[TMP12]], align 4
+// CHECK2-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP13]], align 4
+// CHECK2-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[TMP4]], ptr [[TMP14]], align 4
+// CHECK2-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP15]], align 4
+// CHECK2-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP16]], align 4
+// CHECK2-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP17]], align 4
+// CHECK2-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP18]], align 4
+// CHECK2-NEXT:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr null, ptr [[TMP19]], align 4
+// CHECK2-NEXT:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP6]], ptr [[TMP20]], align 4
+// CHECK2-NEXT:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP21]], align 4
+// CHECK2-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 3
+// CHECK2-NEXT:    store i64 [[TMP10]], ptr [[TMP22]], align 4
+// CHECK2-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr null, ptr [[TMP23]], align 4
+// CHECK2-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP24]], align 4
+// CHECK2-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP25]], align 4
+// CHECK2-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr null, ptr [[TMP26]], align 4
+// CHECK2-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP30:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP30]], ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK2-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4
+// CHECK2-NEXT:    [[SUB:%.*]] = sub nsw i32 [[TMP31]], 0
 // CHECK2-NEXT:    [[DIV:%.*]] = sdiv i32 [[SUB]], 1
-// CHECK2-NEXT:    [[SUB5:%.*]] = sub nsw i32 [[DIV]], 1
-// CHECK2-NEXT:    store i32 [[SUB5]], ptr [[DOTCAPTURE_EXPR_4]], align 4
-// CHECK2-NEXT:    [[TMP34:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_4]], align 4
-// CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP34]], 1
-// CHECK2-NEXT:    [[TMP35:%.*]] = zext i32 [[ADD]] to i64
-// CHECK2-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP36]], align 4
-// CHECK2-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 5, ptr [[TMP37]], align 4
-// CHECK2-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK2-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[DIV]], 1
+// CHECK2-NEXT:    store i32 [[SUB3]], ptr [[DOTCAPTURE_EXPR_2]], align 4
+// CHECK2-NEXT:    [[TMP32:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_2]], align 4
+// CHECK2-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP32]], 1
+// CHECK2-NEXT:    [[TMP33:%.*]] = zext i32 [[ADD]] to i64
+// CHECK2-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP34]], align 4
+// CHECK2-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 5, ptr [[TMP35]], align 4
+// CHECK2-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP27]], ptr [[TMP36]], align 4
+// CHECK2-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP28]], ptr [[TMP37]], align 4
+// CHECK2-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
 // CHECK2-NEXT:    store ptr [[TMP29]], ptr [[TMP38]], align 4
-// CHECK2-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP30]], ptr [[TMP39]], align 4
-// CHECK2-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[TMP31]], ptr [[TMP40]], align 4
-// CHECK2-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes, ptr [[TMP41]], align 4
-// CHECK2-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP42]], align 4
-// CHECK2-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP43]], align 4
-// CHECK2-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 [[TMP35]], ptr [[TMP44]], align 8
-// CHECK2-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP45]], align 8
-// CHECK2-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
-// CHECK2-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP47]], align 4
-// CHECK2-NEXT:    [[TMP48:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP48]], align 4
-// CHECK2-NEXT:    [[TMP49:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4:[0-9]+]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69.region_id, ptr [[KERNEL_ARGS]])
-// CHECK2-NEXT:    [[TMP50:%.*]] = icmp ne i32 [[TMP49]], 0
-// CHECK2-NEXT:    br i1 [[TMP50]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK2-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes, ptr [[TMP39]], align 4
+// CHECK2-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP40]], align 4
+// CHECK2-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP41]], align 4
+// CHECK2-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 [[TMP33]], ptr [[TMP42]], align 8
+// CHECK2-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP43]], align 8
+// CHECK2-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP44]], align 4
+// CHECK2-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP45]], align 4
+// CHECK2-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP46]], align 4
+// CHECK2-NEXT:    [[TMP47:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4:[0-9]+]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69.region_id, ptr [[KERNEL_ARGS]])
+// CHECK2-NEXT:    [[TMP48:%.*]] = icmp ne i32 [[TMP47]], 0
+// CHECK2-NEXT:    br i1 [[TMP48]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK2:       omp_offload.failed:
 // CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l69(i32 [[TMP1]], ptr [[TMP2]], ptr [[TMP3]]) #[[ATTR2:[0-9]+]]
 // CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK2:       omp_offload.cont:
-// CHECK2-NEXT:    [[TMP51:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP51]], ptr [[SIZE_CASTED6]], align 4
-// CHECK2-NEXT:    [[TMP52:%.*]] = load i32, ptr [[SIZE_CASTED6]], align 4
+// CHECK2-NEXT:    [[TMP49:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP49]], ptr [[SIZE_CASTED4]], align 4
+// CHECK2-NEXT:    [[TMP50:%.*]] = load i32, ptr [[SIZE_CASTED4]], align 4
+// CHECK2-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
 // CHECK2-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP56]], i32 0
-// CHECK2-NEXT:    [[TMP57:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP57]], i32 0
-// CHECK2-NEXT:    [[TMP58:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP59:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP59]], i32 0
-// CHECK2-NEXT:    [[TMP60:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    [[TMP61:%.*]] = mul nuw i32 [[TMP60]], 4
-// CHECK2-NEXT:    [[TMP62:%.*]] = sext i32 [[TMP61]] to i64
-// CHECK2-NEXT:    [[TMP63:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP63]], i32 0
-// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES14]], ptr align 4 @.offload_sizes.1, i32 40, i1 false)
-// CHECK2-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP52]], ptr [[TMP64]], align 4
-// CHECK2-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP52]], ptr [[TMP65]], align 4
-// CHECK2-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP66]], align 4
-// CHECK2-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[TMP55]], ptr [[TMP67]], align 4
-// CHECK2-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX7]], ptr [[TMP68]], align 4
-// CHECK2-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP69]], align 4
-// CHECK2-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP70]], align 4
-// CHECK2-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP71]], align 4
-// CHECK2-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK2-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP54]], i32 0
+// CHECK2-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[INPUT_ADDR]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP56]], i32 0
+// CHECK2-NEXT:    [[TMP57:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    [[TMP58:%.*]] = mul nuw i32 [[TMP57]], 4
+// CHECK2-NEXT:    [[TMP59:%.*]] = sext i32 [[TMP58]] to i64
+// CHECK2-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES10]], ptr align 4 @.offload_sizes.1, i32 40, i1 false)
+// CHECK2-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP50]], ptr [[TMP60]], align 4
+// CHECK2-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP50]], ptr [[TMP61]], align 4
+// CHECK2-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP62]], align 4
+// CHECK2-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[TMP53]], ptr [[TMP63]], align 4
+// CHECK2-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP64]], align 4
+// CHECK2-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP65]], align 4
+// CHECK2-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[OUTPUT_ADDR]], ptr [[TMP66]], align 4
+// CHECK2-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP67]], align 4
+// CHECK2-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr null, ptr [[TMP68]], align 4
+// CHECK2-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP55]], ptr [[TMP69]], align 4
+// CHECK2-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP70]], align 4
+// CHECK2-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES10]], i32 0, i32 3
+// CHECK2-NEXT:    store i64 [[TMP59]], ptr [[TMP71]], align 4
+// CHECK2-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 3
 // CHECK2-NEXT:    store ptr null, ptr [[TMP72]], align 4
-// CHECK2-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP58]], ptr [[TMP73]], align 4
-// CHECK2-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[ARRAYIDX9]], ptr [[TMP74]], align 4
-// CHECK2-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES14]], i32 0, i32 3
-// CHECK2-NEXT:    store i64 [[TMP62]], ptr [[TMP75]], align 4
-// CHECK2-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr null, ptr [[TMP76]], align 4
-// CHECK2-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP77]], align 4
-// CHECK2-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP78]], align 4
-// CHECK2-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr null, ptr [[TMP79]], align 4
-// CHECK2-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES14]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP83:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP83]], ptr [[DOTCAPTURE_EXPR_16]], align 4
-// CHECK2-NEXT:    [[TMP84:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_16]], align 4
-// CHECK2-NEXT:    [[SUB18:%.*]] = sub nsw i32 [[TMP84]], 0
-// CHECK2-NEXT:    [[DIV19:%.*]] = sdiv i32 [[SUB18]], 1
-// CHECK2-NEXT:    [[SUB20:%.*]] = sub nsw i32 [[DIV19]], 1
-// CHECK2-NEXT:    store i32 [[SUB20]], ptr [[DOTCAPTURE_EXPR_17]], align 4
-// CHECK2-NEXT:    [[TMP85:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_17]], align 4
-// CHECK2-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP85]], 1
-// CHECK2-NEXT:    [[TMP86:%.*]] = zext i32 [[ADD21]] to i64
-// CHECK2-NEXT:    [[TMP87:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP87]], align 4
-// CHECK2-NEXT:    [[TMP88:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 5, ptr [[TMP88]], align 4
-// CHECK2-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP80]], ptr [[TMP89]], align 4
-// CHECK2-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP81]], ptr [[TMP90]], align 4
-// CHECK2-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr [[TMP82]], ptr [[TMP91]], align 4
-// CHECK2-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP92]], align 4
-// CHECK2-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP93]], align 4
-// CHECK2-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP94]], align 4
-// CHECK2-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 [[TMP86]], ptr [[TMP95]], align 8
-// CHECK2-NEXT:    [[TMP96:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP96]], align 8
-// CHECK2-NEXT:    [[TMP97:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP97]], align 4
-// CHECK2-NEXT:    [[TMP98:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP98]], align 4
-// CHECK2-NEXT:    [[TMP99:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP99]], align 4
-// CHECK2-NEXT:    [[TMP100:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73.region_id, ptr [[KERNEL_ARGS22]])
-// CHECK2-NEXT:    [[TMP101:%.*]] = icmp ne i32 [[TMP100]], 0
-// CHECK2-NEXT:    br i1 [[TMP101]], label [[OMP_OFFLOAD_FAILED23:%.*]], label [[OMP_OFFLOAD_CONT24:%.*]]
-// CHECK2:       omp_offload.failed23:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73(i32 [[TMP52]], ptr [[TMP53]], ptr [[TMP54]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT24]]
-// CHECK2:       omp_offload.cont24:
-// CHECK2-NEXT:    [[TMP102:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP102]], ptr [[SIZE_CASTED25]], align 4
-// CHECK2-NEXT:    [[TMP103:%.*]] = load i32, ptr [[SIZE_CASTED25]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX26:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[A]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP103]], ptr [[TMP104]], align 4
-// CHECK2-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP103]], ptr [[TMP105]], align 4
-// CHECK2-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP106]], align 4
-// CHECK2-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP107]], align 4
-// CHECK2-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX26]], ptr [[TMP108]], align 4
-// CHECK2-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS29]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP109]], align 4
-// CHECK2-NEXT:    [[TMP110:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP111:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP112:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP112]], align 4
-// CHECK2-NEXT:    [[TMP113:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 2, ptr [[TMP113]], align 4
-// CHECK2-NEXT:    [[TMP114:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP110]], ptr [[TMP114]], align 4
-// CHECK2-NEXT:    [[TMP115:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP111]], ptr [[TMP115]], align 4
-// CHECK2-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP116]], align 4
-// CHECK2-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP117]], align 4
-// CHECK2-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP118]], align 4
-// CHECK2-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP119]], align 4
-// CHECK2-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 0, ptr [[TMP120]], align 8
-// CHECK2-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP121]], align 8
-// CHECK2-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP122]], align 4
-// CHECK2-NEXT:    [[TMP123:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP123]], align 4
-// CHECK2-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP124]], align 4
-// CHECK2-NEXT:    [[TMP125:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78.region_id, ptr [[KERNEL_ARGS30]])
-// CHECK2-NEXT:    [[TMP126:%.*]] = icmp ne i32 [[TMP125]], 0
-// CHECK2-NEXT:    br i1 [[TMP126]], label [[OMP_OFFLOAD_FAILED31:%.*]], label [[OMP_OFFLOAD_CONT32:%.*]]
-// CHECK2:       omp_offload.failed31:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78(i32 [[TMP103]], ptr [[A]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT32]]
-// CHECK2:       omp_offload.cont32:
-// CHECK2-NEXT:    [[TMP127:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
-// CHECK2-NEXT:    store i32 [[TMP127]], ptr [[SIZE_CASTED33]], align 4
-// CHECK2-NEXT:    [[TMP128:%.*]] = load i32, ptr [[SIZE_CASTED33]], align 4
-// CHECK2-NEXT:    [[ARRAYIDX34:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i32 0, i32 3
-// CHECK2-NEXT:    [[TMP129:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP128]], ptr [[TMP129]], align 4
-// CHECK2-NEXT:    [[TMP130:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 [[TMP128]], ptr [[TMP130]], align 4
-// CHECK2-NEXT:    [[TMP131:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i32 0, i32 0
-// CHECK2-NEXT:    store ptr null, ptr [[TMP131]], align 4
-// CHECK2-NEXT:    [[TMP132:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP132]], align 4
-// CHECK2-NEXT:    [[TMP133:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr [[ARRAYIDX34]], ptr [[TMP133]], align 4
-// CHECK2-NEXT:    [[TMP134:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS37]], i32 0, i32 1
-// CHECK2-NEXT:    store ptr null, ptr [[TMP134]], align 4
-// CHECK2-NEXT:    [[TMP135:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP136:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0
-// CHECK2-NEXT:    [[TMP137:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0
-// CHECK2-NEXT:    store i32 3, ptr [[TMP137]], align 4
-// CHECK2-NEXT:    [[TMP138:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1
-// CHECK2-NEXT:    store i32 2, ptr [[TMP138]], align 4
-// CHECK2-NEXT:    [[TMP139:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2
-// CHECK2-NEXT:    store ptr [[TMP135]], ptr [[TMP139]], align 4
-// CHECK2-NEXT:    [[TMP140:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 3
-// CHECK2-NEXT:    store ptr [[TMP136]], ptr [[TMP140]], align 4
-// CHECK2-NEXT:    [[TMP141:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 4
-// CHECK2-NEXT:    store ptr @.offload_sizes.5, ptr [[TMP141]], align 4
-// CHECK2-NEXT:    [[TMP142:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 5
-// CHECK2-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP142]], align 4
-// CHECK2-NEXT:    [[TMP143:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 6
-// CHECK2-NEXT:    store ptr null, ptr [[TMP143]], align 4
-// CHECK2-NEXT:    [[TMP144:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 7
-// CHECK2-NEXT:    store ptr null, ptr [[TMP144]], align 4
-// CHECK2-NEXT:    [[TMP145:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 8
-// CHECK2-NEXT:    store i64 0, ptr [[TMP145]], align 8
-// CHECK2-NEXT:    [[TMP146:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 9
-// CHECK2-NEXT:    store i64 0, ptr [[TMP146]], align 8
-// CHECK2-NEXT:    [[TMP147:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 10
-// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP147]], align 4
-// CHECK2-NEXT:    [[TMP148:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 11
-// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP148]], align 4
-// CHECK2-NEXT:    [[TMP149:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 12
-// CHECK2-NEXT:    store i32 0, ptr [[TMP149]], align 4
-// CHECK2-NEXT:    [[TMP150:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81.region_id, ptr [[KERNEL_ARGS38]])
-// CHECK2-NEXT:    [[TMP151:%.*]] = icmp ne i32 [[TMP150]], 0
-// CHECK2-NEXT:    br i1 [[TMP151]], label [[OMP_OFFLOAD_FAILED39:%.*]], label [[OMP_OFFLOAD_CONT40:%.*]]
-// CHECK2:       omp_offload.failed39:
-// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81(i32 [[TMP128]], ptr [[A]]) #[[ATTR2]]
-// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT40]]
-// CHECK2:       omp_offload.cont40:
+// CHECK2-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[INPUT_ADDR]], ptr [[TMP73]], align 4
+// CHECK2-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP74]], align 4
+// CHECK2-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr null, ptr [[TMP75]], align 4
+// CHECK2-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES10]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP79:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP79]], ptr [[DOTCAPTURE_EXPR_12]], align 4
+// CHECK2-NEXT:    [[TMP80:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_12]], align 4
+// CHECK2-NEXT:    [[SUB14:%.*]] = sub nsw i32 [[TMP80]], 0
+// CHECK2-NEXT:    [[DIV15:%.*]] = sdiv i32 [[SUB14]], 1
+// CHECK2-NEXT:    [[SUB16:%.*]] = sub nsw i32 [[DIV15]], 1
+// CHECK2-NEXT:    store i32 [[SUB16]], ptr [[DOTCAPTURE_EXPR_13]], align 4
+// CHECK2-NEXT:    [[TMP81:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_13]], align 4
+// CHECK2-NEXT:    [[ADD17:%.*]] = add nsw i32 [[TMP81]], 1
+// CHECK2-NEXT:    [[TMP82:%.*]] = zext i32 [[ADD17]] to i64
+// CHECK2-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP83]], align 4
+// CHECK2-NEXT:    [[TMP84:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 5, ptr [[TMP84]], align 4
+// CHECK2-NEXT:    [[TMP85:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP76]], ptr [[TMP85]], align 4
+// CHECK2-NEXT:    [[TMP86:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP77]], ptr [[TMP86]], align 4
+// CHECK2-NEXT:    [[TMP87:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr [[TMP78]], ptr [[TMP87]], align 4
+// CHECK2-NEXT:    [[TMP88:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP88]], align 4
+// CHECK2-NEXT:    [[TMP89:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP89]], align 4
+// CHECK2-NEXT:    [[TMP90:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP90]], align 4
+// CHECK2-NEXT:    [[TMP91:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 [[TMP82]], ptr [[TMP91]], align 8
+// CHECK2-NEXT:    [[TMP92:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP92]], align 8
+// CHECK2-NEXT:    [[TMP93:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP93]], align 4
+// CHECK2-NEXT:    [[TMP94:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP94]], align 4
+// CHECK2-NEXT:    [[TMP95:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP95]], align 4
+// CHECK2-NEXT:    [[TMP96:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 0, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73.region_id, ptr [[KERNEL_ARGS18]])
+// CHECK2-NEXT:    [[TMP97:%.*]] = icmp ne i32 [[TMP96]], 0
+// CHECK2-NEXT:    br i1 [[TMP97]], label [[OMP_OFFLOAD_FAILED19:%.*]], label [[OMP_OFFLOAD_CONT20:%.*]]
+// CHECK2:       omp_offload.failed19:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l73(i32 [[TMP50]], ptr [[TMP51]], ptr [[TMP52]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT20]]
+// CHECK2:       omp_offload.cont20:
+// CHECK2-NEXT:    [[TMP98:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP98]], ptr [[SIZE_CASTED21]], align 4
+// CHECK2-NEXT:    [[TMP99:%.*]] = load i32, ptr [[SIZE_CASTED21]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX22:%.*]] = getelementptr inbounds nuw [10 x i32], ptr [[A]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP99]], ptr [[TMP100]], align 4
+// CHECK2-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP99]], ptr [[TMP101]], align 4
+// CHECK2-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP102]], align 4
+// CHECK2-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP103]], align 4
+// CHECK2-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX22]], ptr [[TMP104]], align 4
+// CHECK2-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP105]], align 4
+// CHECK2-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP108:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP108]], align 4
+// CHECK2-NEXT:    [[TMP109:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 2, ptr [[TMP109]], align 4
+// CHECK2-NEXT:    [[TMP110:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP106]], ptr [[TMP110]], align 4
+// CHECK2-NEXT:    [[TMP111:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP107]], ptr [[TMP111]], align 4
+// CHECK2-NEXT:    [[TMP112:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP112]], align 4
+// CHECK2-NEXT:    [[TMP113:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP113]], align 4
+// CHECK2-NEXT:    [[TMP114:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP114]], align 4
+// CHECK2-NEXT:    [[TMP115:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP115]], align 4
+// CHECK2-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 0, ptr [[TMP116]], align 8
+// CHECK2-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP117]], align 8
+// CHECK2-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP118]], align 4
+// CHECK2-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP119]], align 4
+// CHECK2-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP120]], align 4
+// CHECK2-NEXT:    [[TMP121:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78.region_id, ptr [[KERNEL_ARGS26]])
+// CHECK2-NEXT:    [[TMP122:%.*]] = icmp ne i32 [[TMP121]], 0
+// CHECK2-NEXT:    br i1 [[TMP122]], label [[OMP_OFFLOAD_FAILED27:%.*]], label [[OMP_OFFLOAD_CONT28:%.*]]
+// CHECK2:       omp_offload.failed27:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l78(i32 [[TMP99]], ptr [[A]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT28]]
+// CHECK2:       omp_offload.cont28:
+// CHECK2-NEXT:    [[TMP123:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4
+// CHECK2-NEXT:    store i32 [[TMP123]], ptr [[SIZE_CASTED29]], align 4
+// CHECK2-NEXT:    [[TMP124:%.*]] = load i32, ptr [[SIZE_CASTED29]], align 4
+// CHECK2-NEXT:    [[ARRAYIDX30:%.*]] = getelementptr inbounds [10 x i32], ptr [[A]], i32 0, i32 3
+// CHECK2-NEXT:    [[TMP125:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP124]], ptr [[TMP125]], align 4
+// CHECK2-NEXT:    [[TMP126:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 [[TMP124]], ptr [[TMP126]], align 4
+// CHECK2-NEXT:    [[TMP127:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 0
+// CHECK2-NEXT:    store ptr null, ptr [[TMP127]], align 4
+// CHECK2-NEXT:    [[TMP128:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[A]], ptr [[TMP128]], align 4
+// CHECK2-NEXT:    [[TMP129:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr [[ARRAYIDX30]], ptr [[TMP129]], align 4
+// CHECK2-NEXT:    [[TMP130:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 1
+// CHECK2-NEXT:    store ptr null, ptr [[TMP130]], align 4
+// CHECK2-NEXT:    [[TMP131:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP132:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
+// CHECK2-NEXT:    [[TMP133:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 0
+// CHECK2-NEXT:    store i32 3, ptr [[TMP133]], align 4
+// CHECK2-NEXT:    [[TMP134:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 1
+// CHECK2-NEXT:    store i32 2, ptr [[TMP134]], align 4
+// CHECK2-NEXT:    [[TMP135:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 2
+// CHECK2-NEXT:    store ptr [[TMP131]], ptr [[TMP135]], align 4
+// CHECK2-NEXT:    [[TMP136:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 3
+// CHECK2-NEXT:    store ptr [[TMP132]], ptr [[TMP136]], align 4
+// CHECK2-NEXT:    [[TMP137:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 4
+// CHECK2-NEXT:    store ptr @.offload_sizes.5, ptr [[TMP137]], align 4
+// CHECK2-NEXT:    [[TMP138:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 5
+// CHECK2-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP138]], align 4
+// CHECK2-NEXT:    [[TMP139:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 6
+// CHECK2-NEXT:    store ptr null, ptr [[TMP139]], align 4
+// CHECK2-NEXT:    [[TMP140:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 7
+// CHECK2-NEXT:    store ptr null, ptr [[TMP140]], align 4
+// CHECK2-NEXT:    [[TMP141:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 8
+// CHECK2-NEXT:    store i64 0, ptr [[TMP141]], align 8
+// CHECK2-NEXT:    [[TMP142:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 9
+// CHECK2-NEXT:    store i64 0, ptr [[TMP142]], align 8
+// CHECK2-NEXT:    [[TMP143:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 10
+// CHECK2-NEXT:    store [3 x i32] [i32 1, i32 0, i32 0], ptr [[TMP143]], align 4
+// CHECK2-NEXT:    [[TMP144:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 11
+// CHECK2-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP144]], align 4
+// CHECK2-NEXT:    [[TMP145:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 12
+// CHECK2-NEXT:    store i32 0, ptr [[TMP145]], align 4
+// CHECK2-NEXT:    [[TMP146:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB4]], i64 -1, i32 1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81.region_id, ptr [[KERNEL_ARGS34]])
+// CHECK2-NEXT:    [[TMP147:%.*]] = icmp ne i32 [[TMP146]], 0
+// CHECK2-NEXT:    br i1 [[TMP147]], label [[OMP_OFFLOAD_FAILED35:%.*]], label [[OMP_OFFLOAD_CONT36:%.*]]
+// CHECK2:       omp_offload.failed35:
+// CHECK2-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z3sumPiiS__l81(i32 [[TMP124]], ptr [[A]]) #[[ATTR2]]
+// CHECK2-NEXT:    br label [[OMP_OFFLOAD_CONT36]]
+// CHECK2:       omp_offload.cont36:
 // CHECK2-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/target_data_map_codegen_hold.cpp b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
index 0f5276ff8484a..4b8b2f0a059e6 100644
--- a/clang/test/OpenMP/target_data_map_codegen_hold.cpp
+++ b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
@@ -87,9 +87,9 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [13 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [13 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [13 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [13 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 8
 // CHECK-PPC64LE-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-PPC64LE-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
@@ -141,158 +141,154 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[S9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS10]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS13]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS17]], align 8
-// CHECK-PPC64LE-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP38]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = sub i64 [[TMP39]], [[TMP40]]
-// CHECK-PPC64LE-NEXT:    [[TMP42:%.*]] = sdiv exact i64 [[TMP41]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-PPC64LE-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
+// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-PPC64LE-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[S19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[S20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS24]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 8
 // CHECK-PPC64LE-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
 // CHECK-PPC64LE-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[PS28]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS29:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP55]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[PS29]], align 8
-// CHECK-PPC64LE-NEXT:    [[S30:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP56]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = getelementptr ptr, ptr [[PS21]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = ptrtoint ptr [[TMP57]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = ptrtoint ptr [[S19]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = sub i64 [[TMP58]], [[TMP59]]
-// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = sdiv exact i64 [[TMP60]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-PPC64LE-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
+// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
+// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK-PPC64LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.5, i64 104, i1 false)
-// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP62]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP63]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP42]], ptr [[TMP64]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 0
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP65]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP66]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP67]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 1
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP68]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS]], ptr [[TMP69]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS11]], ptr [[TMP70]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 2
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP71]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS11]], ptr [[TMP72]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS14]], ptr [[TMP73]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 3
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP74]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[PS14]], ptr [[TMP75]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP76]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 4
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP77]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP79]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 5
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP80]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP81]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP82]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 6
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP83]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP84]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP85]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP61]], ptr [[TMP86]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 7
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP87]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP43]], ptr [[TMP88]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP89]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 8
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP90]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP91]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS23]], ptr [[TMP92]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 9
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP93]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[PS23]], ptr [[TMP94]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[PS26]], ptr [[TMP95]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 10
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP96]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 11
-// CHECK-PPC64LE-NEXT:    store ptr [[PS26]], ptr [[TMP97]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 11
-// CHECK-PPC64LE-NEXT:    store ptr [[S30]], ptr [[TMP98]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 11
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP99]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
-// CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
-// CHECK-PPC64LE-NEXT:    store ptr [[S19]], ptr [[TMP101]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i64 0, i64 12
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP102]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP103]], ptr [[TMP104]], ptr [[TMP105]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-PPC64LE-NEXT:    [[TMP106:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[INC34:%.*]] = add nsw i32 [[TMP106]], 1
-// CHECK-PPC64LE-NEXT:    store i32 [[INC34]], ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP107]], ptr [[TMP108]], ptr [[TMP109]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP61]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 0
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP63]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP65]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 1
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP66]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 2
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP69]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 3
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP72]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 4
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP75]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP76]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP77]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 5
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP78]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP79]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP80]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 6
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP81]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP82]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP83]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store i64 [[TMP59]], ptr [[TMP84]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 7
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP85]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP86]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP87]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 8
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP88]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
+// CHECK-PPC64LE-NEXT:    store ptr [[PS19]], ptr [[TMP89]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
+// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP90]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 9
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP91]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
+// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP92]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
+// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP93]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 10
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP94]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 11
+// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP95]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 11
+// CHECK-PPC64LE-NEXT:    store ptr [[S28]], ptr [[TMP96]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 11
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP97]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 12
+// CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP98]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 12
+// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP99]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 12
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP100]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP101]], ptr [[TMP102]], ptr [[TMP103]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[TMP104:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP104]], 1
+// CHECK-PPC64LE-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP105]], ptr [[TMP106]], ptr [[TMP107]], ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-PPC64LE-NEXT:    ret void
 //
 // CHECK-I386-LABEL: @_Z3fooi(
@@ -310,9 +306,9 @@ struct S2 {
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS31:%.*]] = alloca [13 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS32:%.*]] = alloca [13 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS33:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [13 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [13 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 4
 // CHECK-I386-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-I386-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
@@ -364,158 +360,154 @@ struct S2 {
 // CHECK-I386-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[S9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 4
 // CHECK-I386-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS10]], align 4
+// CHECK-I386-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 4
 // CHECK-I386-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 4
 // CHECK-I386-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS13]], align 4
+// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 4
 // CHECK-I386-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 4
 // CHECK-I386-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 4
-// CHECK-I386-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS17]], align 4
-// CHECK-I386-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP38:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-I386-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP38]] to i64
-// CHECK-I386-NEXT:    [[TMP40:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-I386-NEXT:    [[TMP41:%.*]] = sub i64 [[TMP39]], [[TMP40]]
-// CHECK-I386-NEXT:    [[TMP42:%.*]] = sdiv exact i64 [[TMP41]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-I386-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
+// CHECK-I386-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
+// CHECK-I386-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
+// CHECK-I386-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
+// CHECK-I386-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-I386-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[S19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[S20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 4
 // CHECK-I386-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 4
 // CHECK-I386-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 4
 // CHECK-I386-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS24]], align 4
+// CHECK-I386-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 4
 // CHECK-I386-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 4
 // CHECK-I386-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
 // CHECK-I386-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 4
-// CHECK-I386-NEXT:    [[PS28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[PS28]], align 4
-// CHECK-I386-NEXT:    [[PS29:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP55]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[PS29]], align 4
-// CHECK-I386-NEXT:    [[S30:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP56]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP57:%.*]] = getelementptr ptr, ptr [[PS21]], i32 1
-// CHECK-I386-NEXT:    [[TMP58:%.*]] = ptrtoint ptr [[TMP57]] to i64
-// CHECK-I386-NEXT:    [[TMP59:%.*]] = ptrtoint ptr [[S19]] to i64
-// CHECK-I386-NEXT:    [[TMP60:%.*]] = sub i64 [[TMP58]], [[TMP59]]
-// CHECK-I386-NEXT:    [[TMP61:%.*]] = sdiv exact i64 [[TMP60]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-I386-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
+// CHECK-I386-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
+// CHECK-I386-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
+// CHECK-I386-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
+// CHECK-I386-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK-I386-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 104, i1 false)
-// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP62]], align 4
-// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP63]], align 4
-// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    store i64 [[TMP42]], ptr [[TMP64]], align 4
-// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP65]], align 4
-// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP66]], align 4
-// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP67]], align 4
-// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP68]], align 4
-// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS]], ptr [[TMP69]], align 4
-// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS11]], ptr [[TMP70]], align 4
-// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP71]], align 4
-// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS11]], ptr [[TMP72]], align 4
-// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS14]], ptr [[TMP73]], align 4
-// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP74]], align 4
-// CHECK-I386-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[PS14]], ptr [[TMP75]], align 4
-// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP76]], align 4
-// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP77]], align 4
-// CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP78]], align 4
-// CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP79]], align 4
-// CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP80]], align 4
-// CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP81]], align 4
-// CHECK-I386-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP82]], align 4
-// CHECK-I386-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP83]], align 4
-// CHECK-I386-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP84]], align 4
-// CHECK-I386-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP85]], align 4
-// CHECK-I386-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
-// CHECK-I386-NEXT:    store i64 [[TMP61]], ptr [[TMP86]], align 4
-// CHECK-I386-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP87]], align 4
-// CHECK-I386-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[TMP43]], ptr [[TMP88]], align 4
-// CHECK-I386-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP89]], align 4
-// CHECK-I386-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP90]], align 4
-// CHECK-I386-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP91]], align 4
-// CHECK-I386-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS23]], ptr [[TMP92]], align 4
-// CHECK-I386-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP93]], align 4
-// CHECK-I386-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[PS23]], ptr [[TMP94]], align 4
-// CHECK-I386-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[PS26]], ptr [[TMP95]], align 4
-// CHECK-I386-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP96]], align 4
-// CHECK-I386-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr [[PS26]], ptr [[TMP97]], align 4
-// CHECK-I386-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr [[S30]], ptr [[TMP98]], align 4
-// CHECK-I386-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP99]], align 4
-// CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP100]], align 4
-// CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr [[S19]], ptr [[TMP101]], align 4
-// CHECK-I386-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS33]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP102]], align 4
-// CHECK-I386-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP103]], ptr [[TMP104]], ptr [[TMP105]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-I386-NEXT:    [[TMP106:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[INC34:%.*]] = add nsw i32 [[TMP106]], 1
-// CHECK-I386-NEXT:    store i32 [[INC34]], ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP107]], ptr [[TMP108]], ptr [[TMP109]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 4
+// CHECK-I386-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP61]], align 4
+// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 4
+// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP63]], align 4
+// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 4
+// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP65]], align 4
+// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP66]], align 4
+// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 4
+// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 4
+// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP69]], align 4
+// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 4
+// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 4
+// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP72]], align 4
+// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 4
+// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 4
+// CHECK-I386-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP75]], align 4
+// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP76]], align 4
+// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP77]], align 4
+// CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP78]], align 4
+// CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP79]], align 4
+// CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP80]], align 4
+// CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP81]], align 4
+// CHECK-I386-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP82]], align 4
+// CHECK-I386-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP83]], align 4
+// CHECK-I386-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
+// CHECK-I386-NEXT:    store i64 [[TMP59]], ptr [[TMP84]], align 4
+// CHECK-I386-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP85]], align 4
+// CHECK-I386-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP86]], align 4
+// CHECK-I386-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP87]], align 4
+// CHECK-I386-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP88]], align 4
+// CHECK-I386-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr [[PS19]], ptr [[TMP89]], align 4
+// CHECK-I386-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP90]], align 4
+// CHECK-I386-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 9
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP91]], align 4
+// CHECK-I386-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP92]], align 4
+// CHECK-I386-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP93]], align 4
+// CHECK-I386-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 10
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP94]], align 4
+// CHECK-I386-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP95]], align 4
+// CHECK-I386-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr [[S28]], ptr [[TMP96]], align 4
+// CHECK-I386-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 11
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP97]], align 4
+// CHECK-I386-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP98]], align 4
+// CHECK-I386-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP99]], align 4
+// CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 12
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP100]], align 4
+// CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP101]], ptr [[TMP102]], ptr [[TMP103]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[TMP104:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP104]], 1
+// CHECK-I386-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP105]], ptr [[TMP106]], ptr [[TMP107]], ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-I386-NEXT:    ret void
 //
 void foo(int arg) {
diff --git a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
index 4366abb1d0887..60b65ba9a49da 100644
--- a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
+++ b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
@@ -58,9 +58,7 @@ int main(void) {
 // CHECK-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CHECK-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
 // CHECK-DAG: store ptr @objects, ptr [[BP1]]
-// CHECK-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CHECK-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%.+]], i{{.+}} 1
-// CHECK-DAG: [[RVAR1]] = load ptr, ptr @objects
+// CHECK-DAG: store ptr [[SEC0]], ptr [[P1]]
 
 #pragma omp target enter data map(to : objects [1:1])
 // CHECK: [[OBJ:%.+]] = load ptr, ptr @objects,
diff --git a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
index fc048ab1caadd..40f3e3b4bc9f7 100644
--- a/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_addr_codegen.cpp
@@ -65,16 +65,12 @@ int main() {
 // CHECK: [[P0:%.+]] = load ptr, ptr [[PTR_ADDR]],
 // CHECK: [[P1:%.+]] = load ptr, ptr [[PTR_ADDR]],
 // CHECK-NEXT: [[ARR_IDX:%.+]] = getelementptr inbounds nuw float, ptr [[P1]], i64 3
-// CHECK: [[P2:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT: [[ARR_IDX1:%.+]] = getelementptr inbounds nuw float, ptr [[P2]], i64 3
-// CHECK: [[P3:%.+]] = load ptr, ptr [[PTR_ADDR]],
-// CHECK: [[P4:%.+]] = load ptr, ptr [[PTR_ADDR]],
-// CHECK-NEXT: [[ARR_IDX2:%.+]] = getelementptr inbounds float, ptr [[P4]], i64 0
-// CHECK: [[P5:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8
-// CHECK-NEXT: [[ARR_IDX3:%.+]] = getelementptr inbounds float, ptr [[P5]], i64 0
+// CHECK: [[P2:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK: [[P5:%.+]] = load ptr, ptr [[PTR_ADDR]],
+// CHECK-NEXT: [[ARR_IDX1:%.+]] = getelementptr inbounds float, ptr [[P5]], i64 0
 // CHECK: [[P7:%.+]] = load ptr, ptr [[REF_ADDR]],
 // CHECK-NEXT: [[REF:%.+]] = load ptr, ptr [[REF_ADDR]],
-// CHECK-NEXT: [[ARR_IDX4:%.+]] = getelementptr inbounds nuw [4 x float], ptr [[ARR_ADDR]], i64 0, i64 0
+// CHECK-NEXT: [[ARR_IDX2:%.+]] = getelementptr inbounds nuw [4 x float], ptr [[ARR_ADDR]], i64 0, i64 0
 // CHECK: [[P10:%.+]] = mul nuw i64 {{.+}}, 4
 // CHECK-NEXT: [[ARR_IDX5:%.+]] = getelementptr inbounds float, ptr [[VLA_ADDR]], i64 0
 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[SIZES]], ptr align 8 [[SIZES1]], i64 64, i1 false)
@@ -89,15 +85,15 @@ int main() {
 // CHECK: [[BPTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 2
 // CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR2]],
 // CHECK: [[PTR2:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 2
-// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR2]],
+// CHECK: store ptr [[ARR_IDX]], ptr [[PTR2]],
 // CHECK: [[BPTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 3
-// CHECK: store ptr [[P3]], ptr [[BPTR3]],
+// CHECK: store ptr [[P2]], ptr [[BPTR3]],
 // CHECK: [[PTR3:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 3
-// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR3]],
+// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR3]],
 // CHECK: [[BPTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 4
 // CHECK: store ptr [[PTR_ADDR]], ptr [[BPTR4]], align
 // CHECK: [[PTR4:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 4
-// CHECK: store ptr [[ARR_IDX3]], ptr [[PTR4]], align 8
+// CHECK: store ptr [[ARR_IDX1]], ptr [[PTR4]], align 8
 // CHECK: [[BPTR5:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 5
 // CHECK: store ptr [[P7]], ptr [[BPTR5]], align
 // CHECK: [[PTR5:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 5
@@ -105,7 +101,7 @@ int main() {
 // CHECK: [[BPTR6:%.+]] = getelementptr inbounds [8 x ptr], ptr [[BPTRS]], i32 0, i32 6
 // CHECK: store ptr [[ARR_ADDR]], ptr [[BPTR6]],
 // CHECK: [[PTR6:%.+]] = getelementptr inbounds [8 x ptr], ptr [[PTRS]], i32 0, i32 6
-// CHECK: store ptr [[ARR_IDX4]], ptr [[PTR6]],
+// CHECK: store ptr [[ARR_IDX2]], ptr [[PTR6]],
 // CHECK: [[SIZE_PTR:%.+]] = getelementptr inbounds [8 x i64], ptr [[SIZES]], i32 0, i32 6
 // CHECK: store i64 [[P10:%.+]], ptr [[SIZE_PTR]], align 8
 // CHECK: [[MAP_PTR:%.+]] = getelementptr inbounds [8 x ptr], ptr [[MAP_PTRS]], i64 0, i64 6
diff --git a/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp b/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
index e6642a317caa6..fd0e3ee032c6f 100644
--- a/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
+++ b/clang/test/OpenMP/target_data_use_device_ptr_if_codegen.cpp
@@ -31,8 +31,6 @@ void add_one(float *b, int dm)
   // CK1:     [[RB_1:%.*]] = load ptr, ptr [[B:%b.addr]]
   // CK1:     [[RB_2:%.*]] = load ptr, ptr [[B]]
   // CK1:     [[RB0_1:%.*]] = getelementptr inbounds nuw float, ptr [[RB_2]], i{{.*}} 0
-  // CK1:     [[RB_3:%.*]] = load ptr, ptr [[B]]
-  // CK1:     [[RB0_2:%.*]] = getelementptr inbounds nuw float, ptr [[RB_3]], i{{.*}} 0
 
   // CK1:     [[BP0:%.+]] = getelementptr inbounds [2 x ptr], ptr [[BP:%.offload_baseptrs.*]], i32 0, i32 0
   // CK1:     store ptr [[RB_1]], ptr [[BP0]]
@@ -42,7 +40,7 @@ void add_one(float *b, int dm)
   // CK1:     [[BP1:%.+]] = getelementptr inbounds [2 x ptr], ptr [[BP]], i32 0, i32 1
   // CK1:     store ptr [[B]], ptr [[BP1]]
   // CK1:     [[P1:%.+]] = getelementptr inbounds [2 x ptr], ptr [[P]], i32 0, i32 1
-  // CK1:     store ptr [[RB0_2]], ptr [[P1]]
+  // CK1:     store ptr [[RB0_1]], ptr [[P1]]
 
   // CK1:     call void @__tgt_target_data_begin{{.+}}ptr [[MYSIZE00]], ptr [[MTYPE00]]
 
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 f177b4bd2ae36..737c855adc05b 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -115,23 +115,21 @@ void f7() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 2
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
@@ -150,29 +148,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l30
@@ -192,29 +188,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l39
@@ -234,29 +228,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l48
@@ -276,35 +268,33 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
-// CHECK:    [[TMP14:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX2]], align 4
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP11]], ptr [[TMP12]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP13:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP14]], ptr [[TMP15]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
@@ -314,34 +304,32 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP0]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP0]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
 // CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
-// CHECK:    [[TMP14:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
-// CHECK:    store i32 11, ptr [[ARRAYIDX2]], align 4
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP11]], ptr [[TMP12]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP13:%.*]] = load ptr, ptr [[PTR]], align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 2
+// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP14]], ptr [[TMP15]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
index e346f4dc38f54..701d09a4889fa 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -110,23 +110,21 @@ void f7() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP3]], i64 2
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
@@ -145,29 +143,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 0
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l29
@@ -187,29 +183,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l37
@@ -229,29 +223,27 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l45
@@ -271,35 +263,33 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
-// CHECK:    [[TMP14:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
-// CHECK:    store i32 10, ptr [[ARRAYIDX2]], align 4
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 3, ptr [[TMP11]], ptr [[TMP12]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
+// CHECK:    [[TMP13:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 2
+// CHECK:    store i32 10, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP14]], ptr [[TMP15]], ptr @.offload_sizes.9, ptr @.offload_maptypes.10, ptr null, ptr null)
 // CHECK:    ret void
 //
 //
@@ -309,34 +299,32 @@ void f7() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP2]], i64 2
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP0]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[ARRAYIDX1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP0]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
 // CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP12]], ptr [[TMP13]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
-// CHECK:    [[TMP14:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[TMP14]], i64 2
-// CHECK:    store i32 11, ptr [[ARRAYIDX2]], align 4
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP11]], ptr [[TMP12]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
+// CHECK:    [[TMP13:%.*]] = load ptr, ptr @ptr, align 8
+// CHECK:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[TMP13]], i64 2
+// CHECK:    store i32 11, ptr [[ARRAYIDX1]], align 4
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 3, ptr [[TMP14]], ptr [[TMP15]], ptr @.offload_sizes.11, ptr @.offload_maptypes.12, ptr null, ptr null)
 // CHECK:    ret void
 //
diff --git a/clang/test/OpenMP/target_map_codegen_33.cpp b/clang/test/OpenMP/target_map_codegen_33.cpp
index 7d4f7fa2e7483..5ac0da6b79b70 100644
--- a/clang/test/OpenMP/target_map_codegen_33.cpp
+++ b/clang/test/OpenMP/target_map_codegen_33.cpp
@@ -19,11 +19,15 @@
 // SIMD-ONLY32-NOT: {{__kmpc|__tgt}}
 #ifdef CK32
 
-// CK32-DAG: [[MTYPE_TO:@.+]] = {{.+}}constant [1 x i64] [i64 33]
-// CK32-DAG: [[MTYPE_FROM:@.+]] = {{.+}}constant [1 x i64] [i64 34]
+// CK32-DAG: [[MTYPE_TO:@.+]] = {{.+}}constant [2 x i64] [i64 33, i64 16384]
+// CK32-DAG: [[MTYPE_FROM:@.+]] = {{.+}}constant [2 x i64] [i64 34, i64 16384]
 
 void array_shaping(float *f, int sa) {
 
+// Region 01
+//  &f[0], &f[0], <size-of-shaping-array>, PARAM | TO
+//  &f, &f[0], sizeof(f), ATTACH
+//
 // CK32-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK32-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK32-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -39,12 +43,17 @@ void array_shaping(float *f, int sa) {
 // CK32-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
 // CK32-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 
-
 // CK32-DAG: store ptr [[F1:%.+]], ptr [[BP0]],
 // CK32-DAG: store ptr [[F2:%.+]], ptr [[P0]],
 // CK32-DAG: store i64 [[SIZE:%.+]], ptr [[S0]],
 
-// CK32-DAG: [[F1]] = load ptr, ptr [[F_ADDR:%.+]],
+// CK32-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK32-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+
+// CK32-DAG: store ptr [[F_ADDR:%.+]], ptr [[BP1]],
+// CK32-DAG: store ptr [[F2]], ptr [[P1]],
+
+// CK32-DAG: [[F1]] = load ptr, ptr [[F_ADDR]],
 // CK32-DAG: [[F2]] = load ptr, ptr [[F_ADDR]],
 // CK32-64-DAG: [[SIZE]] = mul nuw i64 [[SZ1:%.+]], 4
 // CK32-64-DAG: [[SZ1]] = mul nuw i64 12, %{{.+}}
@@ -55,6 +64,11 @@ void array_shaping(float *f, int sa) {
                        : ([3][sa][4])f)
   f[0] = 1;
   sa = 1;
+
+// Region 02
+//  &f[0], &f[0], <size-of-shaping-array>, PARAM | FROM
+//  &f, &f[0], sizeof(f), ATTACH
+//
 // CK32-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK32-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK32-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -70,12 +84,17 @@ void array_shaping(float *f, int sa) {
 // CK32-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
 // CK32-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 
-
 // CK32-DAG: store ptr [[F1:%.+]], ptr [[BP0]],
 // CK32-DAG: store ptr [[F2:%.+]], ptr [[P0]],
 // CK32-DAG: store i64 [[SIZE:%.+]], ptr [[S0]],
 
-// CK32-DAG: [[F1]] = load ptr, ptr [[F_ADDR:%.+]],
+// CK32-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CK32-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+
+// CK32-DAG: store ptr [[F_ADDR:%.+]], ptr [[BP1]],
+// CK32-DAG: store ptr [[F2]], ptr [[P1]],
+
+// CK32-DAG: [[F1]] = load ptr, ptr [[F_ADDR]],
 // CK32-DAG: [[F2]] = load ptr, ptr [[F_ADDR]],
 // CK32-64-DAG: [[SIZE]] = mul nuw i64 [[SZ1:%.+]], 5
 // CK32-64-DAG: [[SZ1]] = mul nuw i64 4, %{{.+}}
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
index e09f1a6f42fa9..910c9f00d72e9 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_global.cpp
@@ -79,22 +79,21 @@ void f4() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP2]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP3]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ptr, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP2]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l20
@@ -112,28 +111,27 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l28
@@ -152,28 +150,27 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ptr, align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ptr, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l36
diff --git a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
index bd8bd4628ef35..c70a7c8d8adf1 100644
--- a/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
+++ b/clang/test/OpenMP/target_map_ptr_and_star_local.cpp
@@ -82,22 +82,21 @@ void f4() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP2]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP3]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP2]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PTR]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP2]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l21
@@ -115,28 +114,27 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l30
@@ -155,28 +153,27 @@ void f4() {
 // CHECK:  entry:
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PTR:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PTR]], align 8
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PTR]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP1]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP2]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP1]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP1]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l39
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
index 85f348de7ffe7..4c15b0259aeeb 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_global.cpp
@@ -99,23 +99,21 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 1
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[Y]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ps, ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr @ps, ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l27(
@@ -134,29 +132,27 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ps, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l35(
@@ -176,29 +172,27 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr @ps, ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr @ps, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l43(
@@ -219,54 +213,50 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ps, align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[TMP4:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = load ptr, ptr @ps, align 8
-// CHECK:    [[X2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP5]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr i32, ptr [[Y]], i32 1
-// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64
-// CHECK:    [[TMP8:%.*]] = ptrtoint ptr [[X]] to i64
-// CHECK:    [[TMP9:%.*]] = sub i64 [[TMP7]], [[TMP8]]
-// CHECK:    [[TMP10:%.*]] = sdiv exact i64 [[TMP9]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
+// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 40, i1 false)
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr @ps, ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[X]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK:    store i64 [[TMP10]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP0]], ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP3]], ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP22]], align 8
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP23]], align 8
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
-// CHECK:    store ptr @ps, ptr [[TMP24]], align 8
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK:    store ptr [[X]], ptr [[TMP25]], align 8
-// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
-// CHECK:    store ptr null, ptr [[TMP26]], align 8
-// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP29:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr @ps, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK:    store ptr @ps, ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK:    store ptr [[X]], ptr [[TMP23]], align 8
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK:    store ptr null, ptr [[TMP24]], align 8
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l53(
diff --git a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
index d9f2c200c0057..1adc069f407c0 100644
--- a/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
+++ b/clang/test/OpenMP/target_map_structptr_and_member_local.cpp
@@ -102,23 +102,21 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 1
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[Y]], ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PS]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y1]], ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[Y]], ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[PS]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f2v_l27(
@@ -137,29 +135,27 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f3v_l36(
@@ -179,29 +175,27 @@ void f5() {
 // CHECK:    [[TMP0:%.*]] = load ptr, ptr [[PS:%.*]], align 8
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
-// CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
-// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP2]], align 8
+// CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
 // CHECK:    store ptr [[PS]], ptr [[TMP3]], align 8
-// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP4]], align 8
-// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP5]], align 8
-// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP6]], align 8
-// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[Y]], ptr [[TMP7]], align 8
-// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP8]], align 8
-// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
-// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y1]], ptr [[TMP10]], align 8
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP4]], align 8
+// CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
+// CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[Y]], ptr [[TMP6]], align 8
+// CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP7]], align 8
+// CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[PS]], ptr [[TMP8]], align 8
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f4v_l45(
@@ -222,54 +216,50 @@ void f5() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PS]], align 8
 // CHECK:    [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S:%.*]], ptr [[TMP1]], i32 0, i32 1
 // CHECK:    [[TMP2:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP2]], i32 0, i32 1
 // CHECK:    [[TMP3:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[TMP4:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP4]], i32 0, i32 0
-// CHECK:    [[TMP5:%.*]] = load ptr, ptr [[PS]], align 8
-// CHECK:    [[X2:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP5]], i32 0, i32 0
-// CHECK:    [[TMP6:%.*]] = getelementptr i32, ptr [[Y]], i32 1
-// CHECK:    [[TMP7:%.*]] = ptrtoint ptr [[TMP6]] to i64
-// CHECK:    [[TMP8:%.*]] = ptrtoint ptr [[X]] to i64
-// CHECK:    [[TMP9:%.*]] = sub i64 [[TMP7]], [[TMP8]]
-// CHECK:    [[TMP10:%.*]] = sdiv exact i64 [[TMP9]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK:    [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S]], ptr [[TMP3]], i32 0, i32 0
+// CHECK:    [[TMP4:%.*]] = getelementptr i32, ptr [[Y]], i32 1
+// CHECK:    [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
+// CHECK:    [[TMP6:%.*]] = ptrtoint ptr [[X]] to i64
+// CHECK:    [[TMP7:%.*]] = sub i64 [[TMP5]], [[TMP6]]
+// CHECK:    [[TMP8:%.*]] = sdiv exact i64 [[TMP7]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
 // CHECK:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES:%.*]], ptr align 8 @.offload_sizes.7, i64 40, i1 false)
-// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP11]], align 8
-// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[PS]], ptr [[TMP12]], align 8
-// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
-// CHECK:    store ptr null, ptr [[TMP13]], align 8
-// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[TMP0]], ptr [[TMP14]], align 8
-// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK:    store ptr [[X]], ptr [[TMP15]], align 8
-// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK:    store i64 [[TMP10]], ptr [[TMP16]], align 8
-// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK:    store ptr null, ptr [[TMP17]], align 8
-// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
-// CHECK:    store ptr [[TMP0]], ptr [[TMP18]], align 8
-// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[Y]], ptr [[TMP19]], align 8
-// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
-// CHECK:    store ptr null, ptr [[TMP20]], align 8
-// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
-// CHECK:    store ptr [[TMP3]], ptr [[TMP21]], align 8
-// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
-// CHECK:    store ptr [[X]], ptr [[TMP22]], align 8
-// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
-// CHECK:    store ptr null, ptr [[TMP23]], align 8
-// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
-// CHECK:    store ptr [[PS]], ptr [[TMP24]], align 8
-// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
-// CHECK:    store ptr [[X]], ptr [[TMP25]], align 8
-// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
-// CHECK:    store ptr null, ptr [[TMP26]], align 8
-// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK:    [[TMP28:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK:    [[TMP29:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK:    [[TMP30:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
+// CHECK:    [[TMP9:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP9]], align 8
+// CHECK:    [[TMP10:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
+// CHECK:    store ptr [[PS]], ptr [[TMP10]], align 8
+// CHECK:    [[TMP11:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
+// CHECK:    store ptr null, ptr [[TMP11]], align 8
+// CHECK:    [[TMP12:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK:    store ptr [[TMP0]], ptr [[TMP12]], align 8
+// CHECK:    [[TMP13:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK:    store ptr [[X]], ptr [[TMP13]], align 8
+// CHECK:    [[TMP14:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK:    store i64 [[TMP8]], ptr [[TMP14]], align 8
+// CHECK:    [[TMP15:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK:    store ptr null, ptr [[TMP15]], align 8
+// CHECK:    [[TMP16:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
+// CHECK:    store ptr [[TMP0]], ptr [[TMP16]], align 8
+// CHECK:    [[TMP17:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
+// CHECK:    store ptr [[Y]], ptr [[TMP17]], align 8
+// CHECK:    [[TMP18:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
+// CHECK:    store ptr null, ptr [[TMP18]], align 8
+// CHECK:    [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 3
+// CHECK:    store ptr [[TMP2]], ptr [[TMP19]], align 8
+// CHECK:    [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 3
+// CHECK:    store ptr [[X]], ptr [[TMP20]], align 8
+// CHECK:    [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 3
+// CHECK:    store ptr null, ptr [[TMP21]], align 8
+// CHECK:    [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 4
+// CHECK:    store ptr [[PS]], ptr [[TMP22]], align 8
+// CHECK:    [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 4
+// CHECK:    store ptr [[X]], ptr [[TMP23]], align 8
+// CHECK:    [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 4
+// CHECK:    store ptr null, ptr [[TMP24]], align 8
+// CHECK:    [[TMP25:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK:    [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK:    [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK:    [[TMP28:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], ptr [[KERNEL_ARGS:%.*]], i32 0, i32 0
 //
 //
 // CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z2f5v_l56(
diff --git a/clang/test/OpenMP/target_task_affinity_codegen.cpp b/clang/test/OpenMP/target_task_affinity_codegen.cpp
index fb3df19c74eb4..48e2c5e403880 100644
--- a/clang/test/OpenMP/target_task_affinity_codegen.cpp
+++ b/clang/test/OpenMP/target_task_affinity_codegen.cpp
@@ -62,7 +62,6 @@ int main() {
 //   &A[0], &A[/*lb=*/0], 1024 * sizeof(A[0]), TO | FROM
 //   &A, &A[/*lb=*/0], sizeof(A), ATTACH
 // (2):
-//
 //   &A[0], &A[0], sizeof(A), RETURN_PARAM
 // (3):
 //   &B[0], &B[/*lb=*/0], 1024 * sizeof(B[0]), TO | FROM | PARAM
@@ -93,113 +92,109 @@ int main() {
 // CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 8
 // CHECK1-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 8
 // CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS1:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS2:%.*]] = alloca [1 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS3:%.*]] = alloca [1 x ptr], align 8
 // CHECK1-NEXT:    [[TMP0:%.*]] = alloca ptr, align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [3 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [3 x ptr], align 8
-// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [3 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [3 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [3 x ptr], align 8
+// CHECK1-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [3 x ptr], align 8
 // CHECK1-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
 // CHECK1-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK1-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[A]], align 8
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[A]], align 8
 // CHECK1-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i64 0
-// CHECK1-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[A]], align 8
-// CHECK1-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP3]], i64 0
-// CHECK1-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP1]], ptr [[TMP4]], align 8
-// CHECK1-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 8
-// CHECK1-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP6]], align 8
-// CHECK1-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[A]], ptr [[TMP7]], align 8
-// CHECK1-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 8
-// CHECK1-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
-// CHECK1-NEXT:    store ptr null, ptr [[TMP9]], align 8
-// CHECK1-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP10]], ptr [[TMP11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[A]], align 8
-// CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP12]], ptr [[TMP13]], align 8
-// CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP12]], ptr [[TMP14]], align 8
-// CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP15]], align 8
-// CHECK1-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP16]], ptr [[TMP17]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP13]], align 8
-// CHECK1-NEXT:    store ptr [[TMP18]], ptr [[TMP0]], align 8
-// CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK1-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP1]], ptr [[TMP3]], align 8
+// CHECK1-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 8
+// CHECK1-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP5]], align 8
+// CHECK1-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[A]], ptr [[TMP6]], align 8
+// CHECK1-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 8
+// CHECK1-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
+// CHECK1-NEXT:    store ptr null, ptr [[TMP8]], align 8
+// CHECK1-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP9]], ptr [[TMP10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[A]], align 8
+// CHECK1-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP11]], ptr [[TMP12]], align 8
+// CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP11]], ptr [[TMP13]], align 8
+// CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS3]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP14]], align 8
+// CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP12]], align 8
+// CHECK1-NEXT:    store ptr [[TMP17]], ptr [[TMP0]], align 8
+// CHECK1-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[B]], align 8
+// CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[TMP0]], align 8
+// CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[B]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP22]], i64 0
-// CHECK1-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[B]], align 8
-// CHECK1-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP23]], i64 0
-// CHECK1-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[TMP21]], ptr [[TMP24]], align 8
-// CHECK1-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK1-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP25]], align 8
-// CHECK1-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 0
-// CHECK1-NEXT:    store ptr null, ptr [[TMP26]], align 8
-// CHECK1-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[B]], ptr [[TMP27]], align 8
-// CHECK1-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
-// CHECK1-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP28]], align 8
-// CHECK1-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 1
-// CHECK1-NEXT:    store ptr null, ptr [[TMP29]], align 8
-// CHECK1-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
-// CHECK1-NEXT:    store ptr [[TMP20]], ptr [[TMP30]], align 8
-// CHECK1-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
-// CHECK1-NEXT:    store ptr [[TMP20]], ptr [[TMP31]], align 8
-// CHECK1-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i64 0, i64 2
-// CHECK1-NEXT:    store ptr null, ptr [[TMP32]], align 8
-// CHECK1-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK1-NEXT:    store i32 3, ptr [[TMP35]], align 4
-// CHECK1-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK1-NEXT:    store i32 3, ptr [[TMP36]], align 4
-// CHECK1-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK1-NEXT:    store ptr [[TMP33]], ptr [[TMP37]], align 8
-// CHECK1-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK1-NEXT:    store ptr [[TMP34]], ptr [[TMP38]], align 8
-// CHECK1-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK1-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP39]], align 8
-// CHECK1-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK1-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP40]], align 8
-// CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK1-NEXT:    store ptr null, ptr [[TMP41]], align 8
-// CHECK1-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK1-NEXT:    store ptr null, ptr [[TMP42]], align 8
-// CHECK1-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK1-NEXT:    store i64 0, ptr [[TMP43]], align 8
-// CHECK1-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK1-NEXT:    store i64 0, ptr [[TMP44]], align 8
-// CHECK1-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK1-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP45]], align 4
-// CHECK1-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK1-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
-// CHECK1-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK1-NEXT:    store i32 0, ptr [[TMP47]], align 4
-// CHECK1-NEXT:    [[TMP48:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
-// CHECK1-NEXT:    [[TMP49:%.*]] = icmp ne i32 [[TMP48]], 0
-// CHECK1-NEXT:    br i1 [[TMP49]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK1-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP21]], i64 0
+// CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[TMP20]], ptr [[TMP22]], align 8
+// CHECK1-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
+// CHECK1-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP23]], align 8
+// CHECK1-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i64 0, i64 0
+// CHECK1-NEXT:    store ptr null, ptr [[TMP24]], align 8
+// CHECK1-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[B]], ptr [[TMP25]], align 8
+// CHECK1-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 1
+// CHECK1-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP26]], align 8
+// CHECK1-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i64 0, i64 1
+// CHECK1-NEXT:    store ptr null, ptr [[TMP27]], align 8
+// CHECK1-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP19]], ptr [[TMP28]], align 8
+// CHECK1-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP19]], ptr [[TMP29]], align 8
+// CHECK1-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i64 0, i64 2
+// CHECK1-NEXT:    store ptr null, ptr [[TMP30]], align 8
+// CHECK1-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK1-NEXT:    store i32 3, ptr [[TMP33]], align 4
+// CHECK1-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK1-NEXT:    store i32 3, ptr [[TMP34]], align 4
+// CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK1-NEXT:    store ptr [[TMP31]], ptr [[TMP35]], align 8
+// CHECK1-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK1-NEXT:    store ptr [[TMP32]], ptr [[TMP36]], align 8
+// CHECK1-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK1-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP37]], align 8
+// CHECK1-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK1-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP38]], align 8
+// CHECK1-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK1-NEXT:    store ptr null, ptr [[TMP39]], align 8
+// CHECK1-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK1-NEXT:    store ptr null, ptr [[TMP40]], align 8
+// CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK1-NEXT:    store i64 0, ptr [[TMP41]], align 8
+// CHECK1-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK1-NEXT:    store i64 0, ptr [[TMP42]], align 8
+// CHECK1-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK1-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP43]], align 4
+// CHECK1-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK1-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP44]], align 4
+// CHECK1-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK1-NEXT:    store i32 0, ptr [[TMP45]], align 4
+// CHECK1-NEXT:    [[TMP46:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
+// CHECK1-NEXT:    [[TMP47:%.*]] = icmp ne i32 [[TMP46]], 0
+// CHECK1-NEXT:    br i1 [[TMP47]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK1:       omp_offload.failed:
-// CHECK1-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP19]], ptr [[TMP20]]) #[[ATTR1:[0-9]+]]
+// CHECK1-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP18]], ptr [[TMP19]]) #[[ATTR1:[0-9]+]]
 // CHECK1-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK1:       omp_offload.cont:
-// CHECK1-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK1-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK1-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP52]], ptr [[TMP53]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP48]], ptr [[TMP49]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK1-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK1-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK1-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
 // CHECK1-NEXT:    ret i32 0
 //
 //
@@ -332,113 +327,109 @@ int main() {
 // CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 4
 // CHECK3-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 4
 // CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS1:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS2:%.*]] = alloca [1 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS3:%.*]] = alloca [1 x ptr], align 4
 // CHECK3-NEXT:    [[TMP0:%.*]] = alloca ptr, align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS7:%.*]] = alloca [3 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS8:%.*]] = alloca [3 x ptr], align 4
-// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS9:%.*]] = alloca [3 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [3 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [3 x ptr], align 4
+// CHECK3-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [3 x ptr], align 4
 // CHECK3-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
 // CHECK3-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK3-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[A]], align 4
 // CHECK3-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[A]], align 4
 // CHECK3-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP2]], i32 0
-// CHECK3-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[A]], align 4
-// CHECK3-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP3]], i32 0
-// CHECK3-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP1]], ptr [[TMP4]], align 4
-// CHECK3-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP5]], align 4
-// CHECK3-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP6]], align 4
-// CHECK3-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[A]], ptr [[TMP7]], align 4
-// CHECK3-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP8]], align 4
-// CHECK3-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr null, ptr [[TMP9]], align 4
-// CHECK3-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP10]], ptr [[TMP11]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[A]], align 4
-// CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP12]], ptr [[TMP13]], align 4
-// CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP12]], ptr [[TMP14]], align 4
-// CHECK3-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP15]], align 4
-// CHECK3-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP16]], ptr [[TMP17]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[TMP13]], align 4
-// CHECK3-NEXT:    store ptr [[TMP18]], ptr [[TMP0]], align 4
-// CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[TMP0]], align 4
+// CHECK3-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP1]], ptr [[TMP3]], align 4
+// CHECK3-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 4
+// CHECK3-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP5]], align 4
+// CHECK3-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[A]], ptr [[TMP6]], align 4
+// CHECK3-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 4
+// CHECK3-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr null, ptr [[TMP8]], align 4
+// CHECK3-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 2, ptr [[TMP9]], ptr [[TMP10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[A]], align 4
+// CHECK3-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP11]], ptr [[TMP12]], align 4
+// CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP11]], ptr [[TMP13]], align 4
+// CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS3]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP14]], align 4
+// CHECK3-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP15]], ptr [[TMP16]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[TMP12]], align 4
+// CHECK3-NEXT:    store ptr [[TMP17]], ptr [[TMP0]], align 4
+// CHECK3-NEXT:    [[TMP18:%.*]] = load ptr, ptr [[B]], align 4
+// CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[TMP0]], align 4
+// CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[B]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP22]], i32 0
-// CHECK3-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[B]], align 4
-// CHECK3-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP23]], i32 0
-// CHECK3-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[TMP21]], ptr [[TMP24]], align 4
-// CHECK3-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr [[ARRAYIDX5]], ptr [[TMP25]], align 4
-// CHECK3-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 0
-// CHECK3-NEXT:    store ptr null, ptr [[TMP26]], align 4
-// CHECK3-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[B]], ptr [[TMP27]], align 4
-// CHECK3-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr [[ARRAYIDX6]], ptr [[TMP28]], align 4
-// CHECK3-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 1
-// CHECK3-NEXT:    store ptr null, ptr [[TMP29]], align 4
-// CHECK3-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 2
-// CHECK3-NEXT:    store ptr [[TMP20]], ptr [[TMP30]], align 4
-// CHECK3-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 2
-// CHECK3-NEXT:    store ptr [[TMP20]], ptr [[TMP31]], align 4
-// CHECK3-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS9]], i32 0, i32 2
-// CHECK3-NEXT:    store ptr null, ptr [[TMP32]], align 4
-// CHECK3-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK3-NEXT:    store i32 3, ptr [[TMP35]], align 4
-// CHECK3-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK3-NEXT:    store i32 3, ptr [[TMP36]], align 4
-// CHECK3-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK3-NEXT:    store ptr [[TMP33]], ptr [[TMP37]], align 4
-// CHECK3-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK3-NEXT:    store ptr [[TMP34]], ptr [[TMP38]], align 4
-// CHECK3-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK3-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP39]], align 4
-// CHECK3-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK3-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP40]], align 4
-// CHECK3-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK3-NEXT:    store ptr null, ptr [[TMP41]], align 4
-// CHECK3-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK3-NEXT:    store ptr null, ptr [[TMP42]], align 4
-// CHECK3-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK3-NEXT:    store i64 0, ptr [[TMP43]], align 8
-// CHECK3-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK3-NEXT:    store i64 0, ptr [[TMP44]], align 8
-// CHECK3-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK3-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP45]], align 4
-// CHECK3-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK3-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP46]], align 4
-// CHECK3-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK3-NEXT:    store i32 0, ptr [[TMP47]], align 4
-// CHECK3-NEXT:    [[TMP48:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
-// CHECK3-NEXT:    [[TMP49:%.*]] = icmp ne i32 [[TMP48]], 0
-// CHECK3-NEXT:    br i1 [[TMP49]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
+// CHECK3-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP21]], i32 0
+// CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[TMP20]], ptr [[TMP22]], align 4
+// CHECK3-NEXT:    [[TMP23:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP23]], align 4
+// CHECK3-NEXT:    [[TMP24:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i32 0, i32 0
+// CHECK3-NEXT:    store ptr null, ptr [[TMP24]], align 4
+// CHECK3-NEXT:    [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[B]], ptr [[TMP25]], align 4
+// CHECK3-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr [[ARRAYIDX4]], ptr [[TMP26]], align 4
+// CHECK3-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i32 0, i32 1
+// CHECK3-NEXT:    store ptr null, ptr [[TMP27]], align 4
+// CHECK3-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP19]], ptr [[TMP28]], align 4
+// CHECK3-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP19]], ptr [[TMP29]], align 4
+// CHECK3-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS7]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr null, ptr [[TMP30]], align 4
+// CHECK3-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK3-NEXT:    store i32 3, ptr [[TMP33]], align 4
+// CHECK3-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK3-NEXT:    store i32 3, ptr [[TMP34]], align 4
+// CHECK3-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK3-NEXT:    store ptr [[TMP31]], ptr [[TMP35]], align 4
+// CHECK3-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK3-NEXT:    store ptr [[TMP32]], ptr [[TMP36]], align 4
+// CHECK3-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK3-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP37]], align 4
+// CHECK3-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK3-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP38]], align 4
+// CHECK3-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK3-NEXT:    store ptr null, ptr [[TMP39]], align 4
+// CHECK3-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK3-NEXT:    store ptr null, ptr [[TMP40]], align 4
+// CHECK3-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK3-NEXT:    store i64 0, ptr [[TMP41]], align 8
+// CHECK3-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK3-NEXT:    store i64 0, ptr [[TMP42]], align 8
+// CHECK3-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK3-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP43]], align 4
+// CHECK3-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK3-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP44]], align 4
+// CHECK3-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK3-NEXT:    store i32 0, ptr [[TMP45]], align 4
+// CHECK3-NEXT:    [[TMP46:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.region_id, ptr [[KERNEL_ARGS]])
+// CHECK3-NEXT:    [[TMP47:%.*]] = icmp ne i32 [[TMP46]], 0
+// CHECK3-NEXT:    br i1 [[TMP47]], label [[OMP_OFFLOAD_FAILED:%.*]], label [[OMP_OFFLOAD_CONT:%.*]]
 // CHECK3:       omp_offload.failed:
-// CHECK3-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP19]], ptr [[TMP20]]) #[[ATTR1:[0-9]+]]
+// CHECK3-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44(ptr [[TMP18]], ptr [[TMP19]]) #[[ATTR1:[0-9]+]]
 // CHECK3-NEXT:    br label [[OMP_OFFLOAD_CONT]]
 // CHECK3:       omp_offload.cont:
-// CHECK3-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
-// CHECK3-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK3-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP52]], ptr [[TMP53]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 1, ptr [[TMP48]], ptr [[TMP49]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr null, ptr null)
+// CHECK3-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK3-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK3-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 2, ptr [[TMP50]], ptr [[TMP51]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr null, ptr null)
 // CHECK3-NEXT:    ret i32 0
 //
 //

>From c9f8c0a66bf344c8981fb81b19474e364909b44e Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 22 Jul 2025 04:05:38 -0700
Subject: [PATCH 40/66] Move initialization of FinalLowestElem earlier.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 2e38add85bb5a..245a48d1ec6c0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7574,6 +7574,11 @@ class MappableExprsHandler {
                   .getAddress();
         }
 
+        // Save the final LowestElem, to use it as the pointee in attach maps,
+        // if emitted.
+        if (Next == CE)
+          FinalLowestElem = LowestElem;
+
         // If this component is a pointer inside the base struct then we don't
         // need to create any entry for it - it will be combined with the object
         // it is pointing to into a single PTR_AND_OBJ entry.
@@ -7787,11 +7792,6 @@ class MappableExprsHandler {
         if (IsFinalArraySection || IsNonContiguous)
           PartialStruct.IsArraySection = true;
 
-        // Save the final LowestElem, to use it as the pointee in attach maps,
-        // if emitted.
-        if (Next == CE)
-          FinalLowestElem = LowestElem;
-
         // If we have a final array section, we are done with this expression.
         if (IsFinalArraySection)
           break;

>From f044a565034b6a8a28ef00e0cc80e6fc3abfe6f8 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 23 Jul 2025 06:21:58 -0700
Subject: [PATCH 41/66] Improve readability, add some more comments.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 143 +++++++++++++++++---------
 1 file changed, 97 insertions(+), 46 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 245a48d1ec6c0..d5a56b9fb8cc7 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7820,7 +7820,7 @@ class MappableExprsHandler {
 
     // Add ATTACH entries for pointer-attachment: delay if PartialStruct is
     // being populated, otherwise add immediately.
-   if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
+    if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
       Address AttachPtrAddr = CGF.EmitLValue(AttachPtrExpr).getAddress();
       Address AttachPteeAddr = FinalLowestElem;
 
@@ -8146,63 +8146,114 @@ class MappableExprsHandler {
     return true;
   }
 
-  // Traverse the list of Components to find the first pointer expression, which
-  // should be the attachable-base-pointer for the current component-list.
-  // For example, for:
-  //  `map(pp->p->s.a[0])`, the base-pointer is `pp->p`, while the pointee is
-  //  `pp->p->s.a[0]`.
+  /// Get the type of an element of a ComponentList Expr \p Exp.
+  ///
+  /// For something like the following:
+  /// ```c
+  ///  int *p, **p;
+  /// ```
+  /// The types for the following Exprs would be:
+  ///   Expr     | Type
+  ///   ---------|-----------
+  ///   p        | int *
+  ///   *p       | int
+  ///   p[0]     | int
+  ///   p[0:1]   | int
+  ///   pp       | int **
+  ///   pp[0]    | int *
+  ///   pp[0:1]  | int *
+  static QualType getComponentExprElementType(const Expr *Exp) {
+    assert(!isa<OMPArrayShapingExpr>(Exp) &&
+           "Cannot get element-type from array-shaping expr.");
+
+    // Unless we are handling array-section expressions, including
+    // array-subscripts, derefs, we can rely on getType.
+    if (!isa<ArraySectionExpr>(Exp))
+      return Exp->getType().getNonReferenceType().getCanonicalType();
+
+    // For array-sections, we need to find the type of one element of
+    // the section.
+    const auto *OASE = cast<ArraySectionExpr>(Exp);
+
+    QualType BaseType = ArraySectionExpr::getBaseOriginalType(OASE->getBase());
+
+    QualType ElemTy;
+    if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
+      ElemTy = ATy->getElementType();
+    else
+      ElemTy = BaseType->getPointeeType();
+
+    ElemTy = ElemTy.getNonReferenceType().getCanonicalType();
+    return ElemTy;
+  }
+
+  /// Traverse the list of Components to find the first pointer expression,
+  /// which should be the attachable-base-pointer for the current
+  /// component-list.
+  ///
+  /// For example, given the following:
+  /// ```c
+  /// struct S {
+  ///   int a;
+  ///   int b[10];
+  ///   int *p;
+  /// }
+  /// S s, *ps, **pps, *(pas[10]);
+  /// ```
+  /// The base-pointers for the following map operands would be:
+  ///   map list-item   | attach base-pointer
+  ///   ----------------|---------------------
+  ///   s               | N/A
+  ///   s.a             | N/A
+  ///   s.p             | N/A
+  ///   ps              | N/A
+  ///   ps->p           | ps
+  ///   ps[1]           | ps
+  ///   *(ps + 1)       | ps
+  ///   (ps + 1)[1]     | ps
+  ///   ps[1:10]        | ps
+  ///   ps->b[10]       | ps
+  ///   ps->p[10]       | ps->p
+  ///   pps[1][2]       | pps[1]
+  ///   pps[1:1][2]     | pps[1:1]
+  ///   pps[1]->p       | pps[1]
+  ///   pps[1]->p[10]   | pps[1]
+  ///   pas[1]          | N/A
+  ///   pas[1][2]       | pas[1]
+  /// TODO: This may need to be updated to handle ref_ptr/ptee cases for byref
+  /// map operands.
   static const Expr *findAttachPtrExpr(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
     const auto *End = Components.end();
 
-    // Keep stripping away one component at a time, until we reach a pointer.
-    // The first pointer we encounter should be the base-pointer for
-    // pointer-attachment.
-    for (const auto *I = Begin; I != End; ++I) {
-      const Expr *CurrentExpr = I->getAssociatedExpression();
-      if (!CurrentExpr)
-        break;
+    // If we only have a single component, we have a map like "map(p)", which
+    // cannot have a base-pointer.
+    if (Components.size() < 2)
+      return nullptr;
 
-      const auto *NextI = std::next(I);
-      if (NextI == End)
+    // To find the attach base-pointer, we start with the second component,
+    // stripping away one component at a time, until we reach a pointer Expr
+    // (that is not a binary operator). The first such pointer should be the
+    // attach base-pointer for the component list.
+    for (const auto *I = std::next(Begin); I != End; ++I) {
+      const Expr *CurExpr = I->getAssociatedExpression();
+      if (!CurExpr)
         break;
 
-      QualType NextType;
-      if (const auto *NextDecl = NextI->getAssociatedDeclaration()) {
-        NextType = NextDecl->getType().getNonReferenceType().getCanonicalType();
-      } else if (const auto *NextExpr = NextI->getAssociatedExpression()) {
-        // If NextExpr is an array-section, compute the result type using
-        // getBaseOriginalType
-        if (const auto *OASE = dyn_cast<ArraySectionExpr>(NextExpr)) {
-          // Get the original base type, handling chains of array sections
-          // properly
-          QualType BaseType =
-              ArraySectionExpr::getBaseOriginalType(OASE->getBase());
-          if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
-            NextType = ATy->getElementType();
-          else
-            NextType = BaseType->getPointeeType();
-
-          NextType = NextType.getNonReferenceType().getCanonicalType();
-        } else {
-          NextType =
-              NextExpr->getType().getNonReferenceType().getCanonicalType();
-        }
-      } else {
-        break;
-      }
+      // If CurExpr is something like `p + 10`, we need to ignore it, since
+      // we are looking for `p`.
+      if (isa<BinaryOperator>(CurExpr))
+        continue;
 
-      // Stop if the next component is a pointer type - this means we found
-      // the base-pointer
-      if (!NextType->isPointerType())
+      // Keep going until we reach an Expr of pointer type.
+      QualType CurType = getComponentExprElementType(CurExpr);
+      if (!CurType->isPointerType())
         continue;
 
-      // The Next component is the first pointer expression encountered, so
-      // that is the attachable-base-pointer for the current component-list.
-      const Expr *BasePtrExpr = NextI->getAssociatedExpression();
-      return BasePtrExpr;
+      // We have found a pointer Expr. This must be the attach pointer.
+      return CurExpr;
     }
 
     return nullptr;

>From 168a2b89a67ec161eb2adac1abbf671c3037a5da Mon Sep 17 00:00:00 2001
From: Alex Duran <alejandro.duran at intel.com>
Date: Fri, 25 Jul 2025 08:02:53 +0200
Subject: [PATCH 42/66] add dataFence to plugin interface

---
 offload/include/device.h                              |  5 +++++
 offload/libomptarget/device.cpp                       |  4 ++++
 offload/plugins-nextgen/amdgpu/src/rtl.cpp            |  4 ++++
 .../plugins-nextgen/common/include/PluginInterface.h  |  8 ++++++++
 .../plugins-nextgen/common/src/PluginInterface.cpp    | 11 +++++++++++
 offload/plugins-nextgen/cuda/src/rtl.cpp              |  4 ++++
 offload/plugins-nextgen/host/src/rtl.cpp              |  4 ++++
 7 files changed, 40 insertions(+)

diff --git a/offload/include/device.h b/offload/include/device.h
index f4b10abbaa3fd..226a9c8902354 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -98,6 +98,11 @@ struct DeviceTy {
   int32_t dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
                        int64_t Size, AsyncInfoTy &AsyncInfo);
 
+  // Insert a data fence between previous data operations and the following
+  // operations if necessary for the device.
+  int32_t dataFence(AsyncInfoTy &AsyncInfo);
+
+
   /// Notify the plugin about a new mapping starting at the host address
   /// \p HstPtr and \p Size bytes.
   int32_t notifyDataMapped(void *HstPtr, int64_t Size);
diff --git a/offload/libomptarget/device.cpp b/offload/libomptarget/device.cpp
index f88e30ae9e76b..6585286bf4285 100644
--- a/offload/libomptarget/device.cpp
+++ b/offload/libomptarget/device.cpp
@@ -191,6 +191,10 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
                                   DstPtr, Size, AsyncInfo);
 }
 
+int32_t DeviceTy::dataFence(AsyncInfoTy &AsyncInfo) {
+  return RTL->data_fence(RTLDeviceID, AsyncInfo);
+}
+
 int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) {
   DP("Notifying about new mapping: HstPtr=" DPxMOD ", Size=%" PRId64 "\n",
      DPxPTR(HstPtr), Size);
diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
index f8db9bf0ae739..d436fa8cc685b 100644
--- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp
+++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
@@ -2538,6 +2538,10 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy {
                                           getAgent(), (uint64_t)Size);
   }
 
+  Error dataFence(__tgt_async_info *Async) override {
+    return Plugin::success();
+  }
+
   /// Initialize the async info for interoperability purposes.
   Error initAsyncInfoImpl(AsyncInfoWrapperTy &AsyncInfoWrapper) override {
     // TODO: Implement this function.
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 8c17a2ee07047..e4ea79542609d 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -891,6 +891,10 @@ struct GenericDeviceTy : public DeviceAllocatorTy {
   virtual Error dataRetrieveImpl(void *HstPtr, const void *TgtPtr, int64_t Size,
                                  AsyncInfoWrapperTy &AsyncInfoWrapper) = 0;
 
+  /// Instert a data fence between previous data operations and the following 
+  /// operations if necessary for the device
+  virtual Error dataFence(__tgt_async_info *AsyncInfo) = 0;
+
   /// Exchange data between devices (device to device transfer). Calling this
   /// function is only valid if GenericPlugin::isDataExchangable() passing the
   /// two devices returns true.
@@ -1355,6 +1359,10 @@ struct GenericPluginTy {
                               int DstDeviceId, void *DstPtr, int64_t Size,
                               __tgt_async_info *AsyncInfo);
 
+  /// Places a fence between previous data movements and following data movements
+  /// if necessary on the device
+  int32_t data_fence(int32_t DeviceId, __tgt_async_info *AsyncInfo);
+
   /// Begin executing a kernel on the given device.
   int32_t launch_kernel(int32_t DeviceId, void *TgtEntryPtr, void **TgtArgs,
                         ptrdiff_t *TgtOffsets, KernelArgsTy *KernelArgs,
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 94a050b559efe..5425e1ec3e21e 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -2231,3 +2231,14 @@ int32_t GenericPluginTy::get_function(__tgt_device_binary Binary,
   *KernelPtr = &Kernel;
   return OFFLOAD_SUCCESS;
 }
+
+int32_t GenericPluginTy::data_fence(int32_t DeviceId, __tgt_async_info *AsyncInfo ) {
+  auto Err = getDevice(DeviceId).dataFence(AsyncInfo);
+  if (Err) {
+    REPORT("Failure to place data fence on device %d: %s\n",
+           DeviceId, toString(std::move(Err)).data());
+    return OFFLOAD_FAIL;
+  }
+
+  return OFFLOAD_SUCCESS;
+}
\ No newline at end of file
diff --git a/offload/plugins-nextgen/cuda/src/rtl.cpp b/offload/plugins-nextgen/cuda/src/rtl.cpp
index 5a391a4d36006..e396ee8117d0a 100644
--- a/offload/plugins-nextgen/cuda/src/rtl.cpp
+++ b/offload/plugins-nextgen/cuda/src/rtl.cpp
@@ -858,6 +858,10 @@ struct CUDADeviceTy : public GenericDeviceTy {
     return Plugin::success();
   }
 
+  Error dataFence(__tgt_async_info *Async) override {
+    return Plugin::success();
+  }
+
   /// Initialize the device info for interoperability purposes.
   Error initDeviceInfoImpl(__tgt_device_info *DeviceInfo) override {
     assert(Context && "Context is null");
diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index d950572265b4c..58b1e69206722 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -295,6 +295,10 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
                          "dataExchangeImpl not supported");
   }
 
+  Error dataFence(__tgt_async_info *Async) override {
+    return Plugin::success();
+  }
+
   /// All functions are already synchronous. No need to do anything on this
   /// synchronization function.
   Error synchronizeImpl(__tgt_async_info &AsyncInfo) override {

>From 23702158609886016e01a4f3a1f3edb94d085660 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 27 Jul 2025 03:26:11 -0700
Subject: [PATCH 43/66] Clang-format fixes.

---
 offload/include/device.h                                 | 1 -
 offload/plugins-nextgen/common/include/PluginInterface.h | 6 +++---
 offload/plugins-nextgen/common/src/PluginInterface.cpp   | 7 ++++---
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/offload/include/device.h b/offload/include/device.h
index 226a9c8902354..1e85bb1876c83 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -102,7 +102,6 @@ struct DeviceTy {
   // operations if necessary for the device.
   int32_t dataFence(AsyncInfoTy &AsyncInfo);
 
-
   /// Notify the plugin about a new mapping starting at the host address
   /// \p HstPtr and \p Size bytes.
   int32_t notifyDataMapped(void *HstPtr, int64_t Size);
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index e4ea79542609d..c9f40d2994a0b 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -891,7 +891,7 @@ struct GenericDeviceTy : public DeviceAllocatorTy {
   virtual Error dataRetrieveImpl(void *HstPtr, const void *TgtPtr, int64_t Size,
                                  AsyncInfoWrapperTy &AsyncInfoWrapper) = 0;
 
-  /// Instert a data fence between previous data operations and the following 
+  /// Instert a data fence between previous data operations and the following
   /// operations if necessary for the device
   virtual Error dataFence(__tgt_async_info *AsyncInfo) = 0;
 
@@ -1359,8 +1359,8 @@ struct GenericPluginTy {
                               int DstDeviceId, void *DstPtr, int64_t Size,
                               __tgt_async_info *AsyncInfo);
 
-  /// Places a fence between previous data movements and following data movements
-  /// if necessary on the device
+  /// Places a fence between previous data movements and following data
+  /// movements if necessary on the device
   int32_t data_fence(int32_t DeviceId, __tgt_async_info *AsyncInfo);
 
   /// Begin executing a kernel on the given device.
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 5425e1ec3e21e..ae4433b05571b 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -2232,11 +2232,12 @@ int32_t GenericPluginTy::get_function(__tgt_device_binary Binary,
   return OFFLOAD_SUCCESS;
 }
 
-int32_t GenericPluginTy::data_fence(int32_t DeviceId, __tgt_async_info *AsyncInfo ) {
+int32_t GenericPluginTy::data_fence(int32_t DeviceId,
+                                    __tgt_async_info *AsyncInfo) {
   auto Err = getDevice(DeviceId).dataFence(AsyncInfo);
   if (Err) {
-    REPORT("Failure to place data fence on device %d: %s\n",
-           DeviceId, toString(std::move(Err)).data());
+    REPORT("Failure to place data fence on device %d: %s\n", DeviceId,
+           toString(std::move(Err)).data());
     return OFFLOAD_FAIL;
   }
 

>From 280638949165611c293e23792c2481a8df7a45bc Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 27 Jul 2025 04:37:36 -0700
Subject: [PATCH 44/66] Insert a data-fence before the first
 pointer-attachment.

---
 offload/libomptarget/omptarget.cpp | 102 +++++++++++++++++------------
 1 file changed, 60 insertions(+), 42 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index b5bbc5a409e85..eebfa340c8472 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -333,23 +333,23 @@ int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
 /// Utility function to perform a pointer attachment operation.
 ///
 /// For something like:
-/// \code
+/// ```cpp
 ///  int *p;
 ///  ...
 ///  #pragma omp target enter data map(to:p[10:10])
-/// \endcode
+/// ```
 ///
 /// for which the attachment operation gets represented using:
-/// \code
+/// ```
 ///   &p, &p[10], sizeof(p), ATTACH
-/// \endcode
+/// ```
 ///
 /// (Hst|Tgt)PtrAddr   represents &p
 /// (Hst|Tgt)PteeBase  represents &p[0]
 /// (Hst|Tgt)PteeBegin represents &p[10]
 ///
 /// This function first computes the expected TgtPteeBase using:
-///   TgtPteeBase = TgtPteeBegin - (HstPteeBegin - HstPteeBase)
+///   `<Select>TgtPteeBase = TgtPteeBegin - (HstPteeBegin - HstPteeBase)`
 ///
 /// and then attaches TgtPteeBase to TgtPtrAddr.
 ///
@@ -362,14 +362,14 @@ int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
 /// information such as lower-bound/upper-bound etc in their subsequent fields.
 ///
 /// For example, for the following:
-/// \code
+/// ```fortran
 ///   integer, allocatable :: x(:)
 ///   integer, pointer :: p(:)
 ///   ...
 ///   p => x(10: 19)
 ///   ...
 ///   !$omp target enter data map(to:p(:))
-/// \endcode
+/// ```
 ///
 /// The map should trigger a pointer-attachment (assuming the pointer-attachment
 /// conditions as noted on processAttachEntries are met) between the descriptor
@@ -384,10 +384,10 @@ int targetDataMapper(ident_t *Loc, DeviceTy &Device, void *ArgBase, void *Arg,
 ///
 /// The function also handles pointer-attachment portion of PTR_AND_OBJ maps,
 /// like:
-/// \code
+/// ```
 ///   &p, &p[10], 10 * sizeof(p[10]), PTR_AND_OBJ
-/// \endcoe
-/// by using "sizeof(void*)" as \p HstPtrSize.
+/// ```
+/// by using `sizeof(void*)` as \p HstPtrSize.
 static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
                                     void **HstPtrAddr, void *HstPteeBase,
                                     void *HstPteeBegin, void **TgtPtrAddr,
@@ -405,8 +405,9 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   // Add shadow pointer tracking
   // TODO: Support shadow-tracking of larger than VoidPtrSize pointers,
   // to support restoration of Fortran descriptors. Currently, this check
-  // would return false, even if the host Fortran descriptor was, and we
-  // should have done an update of the device descriptor. e.g.
+  // would return false, even if the host Fortran descriptor had been
+  // updated since its previous map, and we should have updated its
+  // device counterpart. e.g.
   //
   //   !$omp target enter data map(x(1:100)) !             (1)
   //   p => x(10: 19)
@@ -472,30 +473,6 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
      DPxPTR(HstDescriptorFieldsAddr));
 
   // Submit the entire buffer to device
-  // FIXME: When handling ATTACH map-type, pointer attachment needs to happen
-  // after the other mapping operations are done, to avoid possibility of
-  // pending transfers clobbering the attachment, for example:
-  //
-  //   int *p = ...;
-  //   int **pp = &p;
-  //   map(to: pp[0], p[0])
-  //
-  // Which would be represented by:
-  // &pp[0], &pp[0], sizeof(pp[0]), TO (1)
-  // &p[0], &p[0], sizeof(p[0]), TO    (2)
-  //
-  // &pp, &pp[0], sizeof(pp), ATTACH   (3)
-  // &p, &p[0], sizeof(p), ATTACH      (4)
-  //
-  // (4) and (1) are both trying to modify the device memory corresponding to
-  // &p. We need to ensure that (4) happens last.
-  //
-  // One possible solution to this could be to insert a "device barrier" before
-  // the first ATTACH submitData call, so that every subsequent submitData waits
-  // for any prior operations to finish. Like:
-  //   Device.submitData(..., /*InOrder=*/IsFirstAttachEntry)
-  // Where the boolean InOrder being true means that this submission should
-  // wait for prior memory submissions to finish.
   int SubmitResult = Device.submitData(TgtPtrAddr, DataBuffer, HstPtrSize,
                                        AsyncInfo, PtrTPR.getEntry());
 
@@ -702,10 +679,10 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
 ///
 /// From OpenMP's perspective, when mapping something that has a base pointer,
 /// such as:
-/// \code
+/// ```cpp
 ///   int *p;
 ///   #pragma omp enter target data map(to: p[10:20])
-/// \endcode
+/// ```
 ///
 /// a pointer-attachment between p and &p[10] should occur if both p and
 /// p[10] are present on the device after doing all allocations for all maps
@@ -718,6 +695,33 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
 /// That's why we collect all attach entries and new memory allocations during
 /// targetDataBegin, and use that information to make the decision of whether
 /// to perform a pointer-attachment or not here, after maps have been handled.
+///
+/// Additionally, once we decide that a pointer-attachment should be performed,
+/// we need to make sure that it happens after any previously submitted data
+/// transfers have completed, to avoid the possibility of the pending transfers
+/// clobbering the attachment. For example:
+///
+/// ```cpp
+///   int *p = ...;
+///   int **pp = &p;
+///   map(to: pp[0], p[0])
+/// ```
+///
+/// Which would be represented by:
+/// ```
+/// &pp[0], &pp[0], sizeof(pp[0]), TO (1)
+/// &p[0], &p[0], sizeof(p[0]), TO    (2)
+///
+/// &pp, &pp[0], sizeof(pp), ATTACH   (3)
+/// &p, &p[0], sizeof(p), ATTACH      (4)
+/// ```
+///
+/// (4) and (1) are both trying to modify the device memory corresponding to
+/// `&p`. So, if we decide that (4) should do an attachment, we also need to
+/// ensure that (4) happens after (1) is complete.
+///
+/// For this purpose, we insert a data_fence before the first
+/// pointer-attachment, (3), to ensure that all pending transfers finish first.
 int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
                          AsyncInfoTy &AsyncInfo) {
   // Report all tracked allocations from both main loop and ATTACH processing
@@ -736,6 +740,8 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
   DP("Processing %zu deferred ATTACH map entries\n",
      AttachInfo.AttachEntries.size());
 
+  int Ret = OFFLOAD_SUCCESS;
+  bool IsFirstPointerAttachment = true;
   for (size_t EntryIdx = 0; EntryIdx < AttachInfo.AttachEntries.size();
        ++EntryIdx) {
     const auto &AttachEntry = AttachInfo.AttachEntries[EntryIdx];
@@ -825,10 +831,22 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       continue;
     void *TgtPteeBegin = PteeTPROpt->TargetPointer;
 
-    // Update the device pointer to point to device pointee.
-    int Ret = performPointerAttachment(Device, AsyncInfo, HstPtr, HstPteeBase,
-                                       HstPteeBegin, TgtPtrBase, TgtPteeBegin,
-                                       PtrSize, PtrTPR);
+    // Insert a data-fence before the first pointer-attachment.
+    if (IsFirstPointerAttachment) {
+      IsFirstPointerAttachment = false;
+      DP("Inserting a data fence before the first pointer attachment.\n");
+      Ret = Device.dataFence(AsyncInfo);
+      if (Ret != OFFLOAD_SUCCESS) {
+        REPORT("Failed to insert data fence.\n");
+        return OFFLOAD_FAIL;
+      }
+    }
+
+    // Do the pointer-attachment, i.e. update the device pointer to point to
+    // device pointee.
+    Ret = performPointerAttachment(Device, AsyncInfo, HstPtr, HstPteeBase,
+                                   HstPteeBegin, TgtPtrBase, TgtPteeBegin,
+                                   PtrSize, PtrTPR);
     if (Ret != OFFLOAD_SUCCESS)
       return OFFLOAD_FAIL;
 

>From e411f29e6631b78d06a71cf16e67ede0d1b7bac0 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 27 Jul 2025 05:28:13 -0700
Subject: [PATCH 45/66] Update new upstream test.

---
 ...et_map_array_section_no_length_codegen.cpp | 458 +++++++++---------
 1 file changed, 240 insertions(+), 218 deletions(-)

diff --git a/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
index 43fd509be8bcb..9030fff2108c6 100644
--- a/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
+++ b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
@@ -1,4 +1,4 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 5
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --global-value-regex "\.offload_.*" --global-hex-value-regex ".offload_maptypes.*" --version 5
 // RUN: %clang_cc1 -verify -triple i386-unknown-unknown -fopenmp -fopenmp-version=60 -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s
 
 // RUN: %clang_cc1 -verify -triple i386-unknown-unknown -fopenmp -fopenmp-version=60 -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
@@ -32,19 +32,29 @@ void array_section_no_length_map_clause(float *d, int index) {
   }
 }
 #endif
+//.
+// CHECK: @.offload_sizes = private unnamed_addr constant [2 x i64] [i64 4, i64 4]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 0, i64 4]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x4000]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 4, i64 4, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x10]], i64 [[#0x320]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 4, i64 0, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x13]], i64 [[#0x320]]]
+//.
 // CHECK-LABEL: define dso_local void @_Z34array_section_no_length_map_clausePfi(
 // CHECK-SAME: ptr noundef [[D:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[D_ADDR:%.*]] = alloca ptr, align 4
 // CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[F:%.*]] = alloca ptr, align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [2 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS:%.*]] = alloca [2 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [2 x ptr], align 4
 // CHECK-NEXT:    [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [2 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS3:%.*]] = alloca [2 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [2 x ptr], align 4
 // CHECK-NEXT:    [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    [[INDEX_CASTED:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [3 x ptr], align 4
@@ -63,235 +73,247 @@ void array_section_no_length_map_clause(float *d, int index) {
 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[D_ADDR]], align 4
 // CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[D_ADDR]], align 4
 // CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds nuw float, ptr [[TMP2]], i32 0
-// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK-NEXT:    store ptr [[TMP1]], ptr [[TMP3]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
 // CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP4]], align 4
-// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
 // CHECK-NEXT:    store ptr null, ptr [[TMP5]], align 4
-// CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP8]], align 4
-// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP9]], align 4
-// CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP6]], ptr [[TMP10]], align 4
-// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP7]], ptr [[TMP11]], align 4
-// CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes, ptr [[TMP12]], align 4
-// CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP13]], align 4
-// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP14]], align 4
-// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP15]], align 4
-// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP16]], align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP17]], align 8
-// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP18]], align 4
-// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP19]], align 4
-// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP20]], align 4
-// CHECK-NEXT:    [[TMP21:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14.region_id, ptr [[KERNEL_ARGS]])
-// CHECK-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
-// CHECK-NEXT:    br i1 [[TMP22]], label %[[OMP_OFFLOAD_FAILED:.*]], label %[[OMP_OFFLOAD_CONT:.*]]
+// CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[D_ADDR]], ptr [[TMP6]], align 4
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX]], ptr [[TMP7]], align 4
+// CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP8]], align 4
+// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP11]], align 4
+// CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK-NEXT:    store i32 2, ptr [[TMP12]], align 4
+// CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP9]], ptr [[TMP13]], align 4
+// CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP10]], ptr [[TMP14]], align 4
+// CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK-NEXT:    store ptr @.offload_sizes, ptr [[TMP15]], align 4
+// CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes, ptr [[TMP16]], align 4
+// CHECK-NEXT:    [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP17]], align 4
+// CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP18]], align 4
+// CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP19]], align 8
+// CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP20]], align 8
+// CHECK-NEXT:    [[TMP21:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP21]], align 4
+// CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP22]], align 4
+// CHECK-NEXT:    [[TMP23:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP23]], align 4
+// CHECK-NEXT:    [[TMP24:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14.region_id, ptr [[KERNEL_ARGS]])
+// CHECK-NEXT:    [[TMP25:%.*]] = icmp ne i32 [[TMP24]], 0
+// CHECK-NEXT:    br i1 [[TMP25]], label %[[OMP_OFFLOAD_FAILED:.*]], label %[[OMP_OFFLOAD_CONT:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED]]:
 // CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14(ptr [[TMP0]]) #[[ATTR2:[0-9]+]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT]]
 // CHECK:       [[OMP_OFFLOAD_CONT]]:
-// CHECK-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[D_ADDR]], align 4
-// CHECK-NEXT:    [[TMP24:%.*]] = load ptr, ptr [[D_ADDR]], align 4
-// CHECK-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[D_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw float, ptr [[TMP25]], i32 2
-// CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[TMP24]], ptr [[TMP26]], align 4
-// CHECK-NEXT:    [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP27]], align 4
-// CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP28]], align 4
-// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP31]], align 4
-// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1
-// CHECK-NEXT:    store i32 1, ptr [[TMP32]], align 4
-// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP29]], ptr [[TMP33]], align 4
-// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP30]], ptr [[TMP34]], align 4
-// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes.1, ptr [[TMP35]], align 4
-// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP36]], align 4
-// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP37]], align 4
-// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP38]], align 4
-// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP39]], align 8
-// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP40]], align 8
-// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP41]], align 4
-// CHECK-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP42]], align 4
-// CHECK-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP43]], align 4
-// CHECK-NEXT:    [[TMP44:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19.region_id, ptr [[KERNEL_ARGS5]])
-// CHECK-NEXT:    [[TMP45:%.*]] = icmp ne i32 [[TMP44]], 0
-// CHECK-NEXT:    br i1 [[TMP45]], label %[[OMP_OFFLOAD_FAILED6:.*]], label %[[OMP_OFFLOAD_CONT7:.*]]
+// CHECK-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw float, ptr [[TMP28]], i32 2
+// CHECK-NEXT:    [[TMP29:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP27]], ptr [[TMP29]], align 4
+// CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP30]], align 4
+// CHECK-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP31]], align 4
+// CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[D_ADDR]], ptr [[TMP32]], align 4
+// CHECK-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX1]], ptr [[TMP33]], align 4
+// CHECK-NEXT:    [[TMP34:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP34]], align 4
+// CHECK-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP36:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP37]], align 4
+// CHECK-NEXT:    [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1
+// CHECK-NEXT:    store i32 2, ptr [[TMP38]], align 4
+// CHECK-NEXT:    [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP35]], ptr [[TMP39]], align 4
+// CHECK-NEXT:    [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP36]], ptr [[TMP40]], align 4
+// CHECK-NEXT:    [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4
+// CHECK-NEXT:    store ptr @.offload_sizes.1, ptr [[TMP41]], align 4
+// CHECK-NEXT:    [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.2, ptr [[TMP42]], align 4
+// CHECK-NEXT:    [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP43]], align 4
+// CHECK-NEXT:    [[TMP44:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP44]], align 4
+// CHECK-NEXT:    [[TMP45:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP45]], align 8
+// CHECK-NEXT:    [[TMP46:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP46]], align 8
+// CHECK-NEXT:    [[TMP47:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP47]], align 4
+// CHECK-NEXT:    [[TMP48:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP48]], align 4
+// CHECK-NEXT:    [[TMP49:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP49]], align 4
+// CHECK-NEXT:    [[TMP50:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19.region_id, ptr [[KERNEL_ARGS5]])
+// CHECK-NEXT:    [[TMP51:%.*]] = icmp ne i32 [[TMP50]], 0
+// CHECK-NEXT:    br i1 [[TMP51]], label %[[OMP_OFFLOAD_FAILED6:.*]], label %[[OMP_OFFLOAD_CONT7:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED6]]:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19(ptr [[TMP23]]) #[[ATTR2]]
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19(ptr [[TMP26]]) #[[ATTR2]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT7]]
 // CHECK:       [[OMP_OFFLOAD_CONT7]]:
-// CHECK-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP47:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP47]], ptr [[INDEX_CASTED]], align 4
-// CHECK-NEXT:    [[TMP48:%.*]] = load i32, ptr [[INDEX_CASTED]], align 4
-// CHECK-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP51:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds ptr, ptr [[TMP50]], i32 [[TMP51]]
 // CHECK-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[F]], align 4
 // CHECK-NEXT:    [[TMP53:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds ptr, ptr [[TMP52]], i32 [[TMP53]]
-// CHECK-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[ARRAYIDX9]], align 4
-// CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw float, ptr [[TMP54]], i32 0
-// CHECK-NEXT:    [[TMP55:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[TMP49]], ptr [[TMP55]], align 4
-// CHECK-NEXT:    [[TMP56:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP56]], align 4
-// CHECK-NEXT:    [[TMP57:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP57]], align 4
-// CHECK-NEXT:    [[TMP58:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP58]], align 4
-// CHECK-NEXT:    [[TMP59:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP59]], align 4
-// CHECK-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP60]], align 4
-// CHECK-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP48]], ptr [[TMP61]], align 4
-// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP48]], ptr [[TMP62]], align 4
-// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK-NEXT:    store i32 [[TMP53]], ptr [[INDEX_CASTED]], align 4
+// CHECK-NEXT:    [[TMP54:%.*]] = load i32, ptr [[INDEX_CASTED]], align 4
+// CHECK-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP57:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds ptr, ptr [[TMP56]], i32 [[TMP57]]
+// CHECK-NEXT:    [[TMP58:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP59:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds ptr, ptr [[TMP58]], i32 [[TMP59]]
+// CHECK-NEXT:    [[TMP60:%.*]] = load ptr, ptr [[ARRAYIDX9]], align 4
+// CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw float, ptr [[TMP60]], i32 0
+// CHECK-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP55]], ptr [[TMP61]], align 4
+// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP62]], align 4
+// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
 // CHECK-NEXT:    store ptr null, ptr [[TMP63]], align 4
-// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP66]], align 4
-// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP67]], align 4
-// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP64]], ptr [[TMP68]], align 4
-// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP65]], ptr [[TMP69]], align 4
-// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP70]], align 4
-// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP71]], align 4
-// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP72]], align 4
-// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP73]], align 4
-// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP74]], align 8
-// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP75]], align 8
-// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP76]], align 4
-// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP77]], align 4
-// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP78]], align 4
-// CHECK-NEXT:    [[TMP79:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24.region_id, ptr [[KERNEL_ARGS14]])
-// CHECK-NEXT:    [[TMP80:%.*]] = icmp ne i32 [[TMP79]], 0
-// CHECK-NEXT:    br i1 [[TMP80]], label %[[OMP_OFFLOAD_FAILED15:.*]], label %[[OMP_OFFLOAD_CONT16:.*]]
+// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP64]], align 4
+// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP65]], align 4
+// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP66]], align 4
+// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
+// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP67]], align 4
+// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
+// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP68]], align 4
+// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP69]], align 4
+// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP72]], align 4
+// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
+// CHECK-NEXT:    store i32 3, ptr [[TMP73]], align 4
+// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP70]], ptr [[TMP74]], align 4
+// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP71]], ptr [[TMP75]], align 4
+// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
+// CHECK-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP76]], align 4
+// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP77]], align 4
+// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP78]], align 4
+// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP79]], align 4
+// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP80]], align 8
+// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP81]], align 8
+// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP82]], align 4
+// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP83]], align 4
+// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP84]], align 4
+// CHECK-NEXT:    [[TMP85:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24.region_id, ptr [[KERNEL_ARGS14]])
+// CHECK-NEXT:    [[TMP86:%.*]] = icmp ne i32 [[TMP85]], 0
+// CHECK-NEXT:    br i1 [[TMP86]], label %[[OMP_OFFLOAD_FAILED15:.*]], label %[[OMP_OFFLOAD_CONT16:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED15]]:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24(ptr [[TMP46]], i32 [[TMP48]]) #[[ATTR2]]
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24(ptr [[TMP52]], i32 [[TMP54]]) #[[ATTR2]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT16]]
 // CHECK:       [[OMP_OFFLOAD_CONT16]]:
-// CHECK-NEXT:    [[TMP81:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP82:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP82]], ptr [[INDEX_CASTED17]], align 4
-// CHECK-NEXT:    [[TMP83:%.*]] = load i32, ptr [[INDEX_CASTED17]], align 4
-// CHECK-NEXT:    [[TMP84:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP85:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP86:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds ptr, ptr [[TMP85]], i32 [[TMP86]]
-// CHECK-NEXT:    [[TMP87:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP87]], 1
-// CHECK-NEXT:    [[TMP88:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP89:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds ptr, ptr [[TMP88]], i32 [[TMP89]]
-// CHECK-NEXT:    [[TMP90:%.*]] = load ptr, ptr [[ARRAYIDX19]], align 4
-// CHECK-NEXT:    [[ARRAYIDX20:%.*]] = getelementptr inbounds nuw float, ptr [[TMP90]], i32 [[ADD]]
-// CHECK-NEXT:    [[TMP91:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP91]], 1
-// CHECK-NEXT:    [[TMP92:%.*]] = mul nuw i32 [[ADD21]], 4
-// CHECK-NEXT:    [[TMP93:%.*]] = icmp ugt i32 4, [[TMP92]]
-// CHECK-NEXT:    [[TMP94:%.*]] = sub nuw i32 4, [[TMP92]]
-// CHECK-NEXT:    [[TMP95:%.*]] = select i1 [[TMP93]], i32 [[TMP94]], i32 0
-// CHECK-NEXT:    [[TMP96:%.*]] = sext i32 [[TMP95]] to i64
+// CHECK-NEXT:    [[TMP87:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP88:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP88]], ptr [[INDEX_CASTED17]], align 4
+// CHECK-NEXT:    [[TMP89:%.*]] = load i32, ptr [[INDEX_CASTED17]], align 4
+// CHECK-NEXT:    [[TMP90:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP91:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP92:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds ptr, ptr [[TMP91]], i32 [[TMP92]]
+// CHECK-NEXT:    [[TMP93:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP93]], 1
+// CHECK-NEXT:    [[TMP94:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP95:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds ptr, ptr [[TMP94]], i32 [[TMP95]]
+// CHECK-NEXT:    [[TMP96:%.*]] = load ptr, ptr [[ARRAYIDX19]], align 4
+// CHECK-NEXT:    [[ARRAYIDX20:%.*]] = getelementptr inbounds nuw float, ptr [[TMP96]], i32 [[ADD]]
+// CHECK-NEXT:    [[TMP97:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP97]], 1
+// CHECK-NEXT:    [[TMP98:%.*]] = mul nuw i32 [[ADD21]], 4
+// CHECK-NEXT:    [[TMP99:%.*]] = icmp ugt i32 4, [[TMP98]]
+// CHECK-NEXT:    [[TMP100:%.*]] = sub nuw i32 4, [[TMP98]]
+// CHECK-NEXT:    [[TMP101:%.*]] = select i1 [[TMP99]], i32 [[TMP100]], i32 0
+// CHECK-NEXT:    [[TMP102:%.*]] = sext i32 [[TMP101]] to i64
 // CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 24, i1 false)
-// CHECK-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[TMP84]], ptr [[TMP97]], align 4
-// CHECK-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP98]], align 4
-// CHECK-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP99]], align 4
-// CHECK-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP100]], align 4
-// CHECK-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX20]], ptr [[TMP101]], align 4
-// CHECK-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP96]], ptr [[TMP102]], align 4
-// CHECK-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP103]], align 4
-// CHECK-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP83]], ptr [[TMP104]], align 4
-// CHECK-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP83]], ptr [[TMP105]], align 4
-// CHECK-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP106]], align 4
-// CHECK-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP110:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP110]], align 4
-// CHECK-NEXT:    [[TMP111:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP111]], align 4
-// CHECK-NEXT:    [[TMP112:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP107]], ptr [[TMP112]], align 4
-// CHECK-NEXT:    [[TMP113:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP108]], ptr [[TMP113]], align 4
-// CHECK-NEXT:    [[TMP114:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP109]], ptr [[TMP114]], align 4
-// CHECK-NEXT:    [[TMP115:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP115]], align 4
-// CHECK-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP116]], align 4
-// CHECK-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP117]], align 4
-// CHECK-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP118]], align 8
-// CHECK-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP119]], align 8
-// CHECK-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP120]], align 4
-// CHECK-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP121]], align 4
-// CHECK-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP122]], align 4
-// CHECK-NEXT:    [[TMP123:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29.region_id, ptr [[KERNEL_ARGS25]])
-// CHECK-NEXT:    [[TMP124:%.*]] = icmp ne i32 [[TMP123]], 0
-// CHECK-NEXT:    br i1 [[TMP124]], label %[[OMP_OFFLOAD_FAILED26:.*]], label %[[OMP_OFFLOAD_CONT27:.*]]
+// CHECK-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP90]], ptr [[TMP103]], align 4
+// CHECK-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP104]], align 4
+// CHECK-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP105]], align 4
+// CHECK-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP106]], align 4
+// CHECK-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX20]], ptr [[TMP107]], align 4
+// CHECK-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP102]], ptr [[TMP108]], align 4
+// CHECK-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP109]], align 4
+// CHECK-NEXT:    [[TMP110:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 2
+// CHECK-NEXT:    store i32 [[TMP89]], ptr [[TMP110]], align 4
+// CHECK-NEXT:    [[TMP111:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 2
+// CHECK-NEXT:    store i32 [[TMP89]], ptr [[TMP111]], align 4
+// CHECK-NEXT:    [[TMP112:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP112]], align 4
+// CHECK-NEXT:    [[TMP113:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP114:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP115:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP116]], align 4
+// CHECK-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 1
+// CHECK-NEXT:    store i32 3, ptr [[TMP117]], align 4
+// CHECK-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP113]], ptr [[TMP118]], align 4
+// CHECK-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP114]], ptr [[TMP119]], align 4
+// CHECK-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[TMP115]], ptr [[TMP120]], align 4
+// CHECK-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP121]], align 4
+// CHECK-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP122]], align 4
+// CHECK-NEXT:    [[TMP123:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP123]], align 4
+// CHECK-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP124]], align 8
+// CHECK-NEXT:    [[TMP125:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP125]], align 8
+// CHECK-NEXT:    [[TMP126:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP126]], align 4
+// CHECK-NEXT:    [[TMP127:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP127]], align 4
+// CHECK-NEXT:    [[TMP128:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP128]], align 4
+// CHECK-NEXT:    [[TMP129:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29.region_id, ptr [[KERNEL_ARGS25]])
+// CHECK-NEXT:    [[TMP130:%.*]] = icmp ne i32 [[TMP129]], 0
+// CHECK-NEXT:    br i1 [[TMP130]], label %[[OMP_OFFLOAD_FAILED26:.*]], label %[[OMP_OFFLOAD_CONT27:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED26]]:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(ptr [[TMP81]], i32 [[TMP83]]) #[[ATTR2]]
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(ptr [[TMP87]], i32 [[TMP89]]) #[[ATTR2]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT27]]
 // CHECK:       [[OMP_OFFLOAD_CONT27]]:
 // CHECK-NEXT:    ret void

>From 40320d2adca0e293bc64fd66eb70e94515594920 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 30 Jul 2025 11:34:28 -0700
Subject: [PATCH 46/66] Use unique_ptr, avoid c-style casts.

---
 offload/libomptarget/interface.cpp | 12 +++++-------
 offload/libomptarget/omptarget.cpp | 25 +++++++++++++++----------
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index 1a65262f9dcda..661b14dd80f8e 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -30,6 +30,7 @@
 #include <cstdint>
 #include <cstdio>
 #include <cstdlib>
+#include <memory>
 
 #ifdef OMPT_SUPPORT
 using namespace llvm::omp::target::ompt;
@@ -167,13 +168,13 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
   int Rc = OFFLOAD_SUCCESS;
 
   // Only allocate AttachInfo for targetDataBegin
-  AttachInfoTy *AttachInfo = nullptr;
+  std::unique_ptr<AttachInfoTy> AttachInfo;
   if (TargetDataFunction == targetDataBegin)
-    AttachInfo = new AttachInfoTy();
+    AttachInfo = std::make_unique<AttachInfoTy>();
 
   Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
-                          ArgTypes, ArgNames, ArgMappers, AsyncInfo, AttachInfo,
-                          /*FromMapper=*/false);
+                          ArgTypes, ArgNames, ArgMappers, AsyncInfo,
+                          AttachInfo.get(), /*FromMapper=*/false);
 
   if (Rc == OFFLOAD_SUCCESS) {
     // Process deferred ATTACH entries BEFORE synchronization
@@ -184,9 +185,6 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
       Rc = AsyncInfo.synchronize();
   }
 
-  if (AttachInfo)
-    delete AttachInfo;
-
   handleTargetOutcome(Rc == OFFLOAD_SUCCESS, Loc);
 }
 
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index eebfa340c8472..eec34a4f9eb3f 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -399,8 +399,10 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   int64_t VoidPtrSize = sizeof(void *);
   assert(HstPtrSize >= VoidPtrSize && "PointerSize is too small");
 
-  uint64_t Delta = (uint64_t)HstPteeBegin - (uint64_t)HstPteeBase;
-  void *TgtPteeBase = (void *)((uint64_t)TgtPteeBegin - Delta);
+  uint64_t Delta = reinterpret_cast<uint64_t>(HstPteeBegin) -
+                   reinterpret_cast<uint64_t>(HstPteeBase);
+  void *TgtPteeBase = reinterpret_cast<void *>(
+      reinterpret_cast<uint64_t>(TgtPteeBegin) - Delta);
 
   // Add shadow pointer tracking
   // TODO: Support shadow-tracking of larger than VoidPtrSize pointers,
@@ -463,7 +465,8 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   // And to the remaining bytes, we copy the remaining contents of the host
   // descriptor after the initial VoidPtrSize bytes.
   uint64_t HstDescriptorFieldsSize = HstPtrSize - VoidPtrSize;
-  void *HstDescriptorFieldsAddr = (char *)HstPtrAddr + VoidPtrSize;
+  void *HstDescriptorFieldsAddr =
+      reinterpret_cast<char *>(HstPtrAddr) + VoidPtrSize;
   std::memcpy(DataBuffer + VoidPtrSize, HstDescriptorFieldsAddr,
               HstDescriptorFieldsSize);
 
@@ -613,7 +616,7 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
          (PointerTpr.Flags.IsNewEntry ? "" : " not"));
       PointerHstPtrBegin = HstPtrBase;
       // modify current entry.
-      HstPtrBase = *(void **)HstPtrBase;
+      HstPtrBase = *reinterpret_cast<void **>(HstPtrBase);
       // No need to update pointee ref count for the first element of the
       // subelement that comes from mapper.
       UpdateRef =
@@ -655,9 +658,10 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
 
     if (ArgTypes[I] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
       int Ret = performPointerAttachment(
-          Device, AsyncInfo, (void **)PointerHstPtrBegin, HstPtrBase,
-          HstPtrBegin, (void **)PointerTgtPtrBegin, TgtPtrBegin, sizeof(void *),
-          PointerTpr);
+          Device, AsyncInfo, reinterpret_cast<void **>(PointerHstPtrBegin),
+          HstPtrBase, HstPtrBegin,
+          reinterpret_cast<void **>(PointerTgtPtrBegin), TgtPtrBegin,
+          sizeof(void *), PointerTpr);
       if (Ret != OFFLOAD_SUCCESS)
         return OFFLOAD_FAIL;
     }
@@ -746,7 +750,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
        ++EntryIdx) {
     const auto &AttachEntry = AttachInfo.AttachEntries[EntryIdx];
 
-    void **HstPtr = (void **)AttachEntry.PointerBase;
+    void **HstPtr = reinterpret_cast<void **>(AttachEntry.PointerBase);
 
     void *HstPteeBase = *HstPtr;
     void *HstPteeBegin = AttachEntry.PointeeBegin;
@@ -767,7 +771,8 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
             void *AllocPtr = Alloc.first;
             int64_t AllocSize = Alloc.second;
             return Ptr >= AllocPtr &&
-                   Ptr < (void *)((char *)AllocPtr + AllocSize);
+                   Ptr < reinterpret_cast<void *>(
+                             reinterpret_cast<char *>(AllocPtr) + AllocSize);
           });
       DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
          EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
@@ -823,7 +828,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
     if (!PtrTPROpt)
       continue;
     TargetPointerResultTy &PtrTPR = *PtrTPROpt;
-    void **TgtPtrBase = (void **)PtrTPR.TargetPointer;
+    void **TgtPtrBase = reinterpret_cast<void **>(PtrTPR.TargetPointer);
 
     // Get device version of the pointee (e.g., &p[10])
     auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");

>From fcdb2f599254b0fee664de9e3e624b759f2640a8 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 30 Jul 2025 11:34:28 -0700
Subject: [PATCH 47/66] Use unique_ptr, avoid c-style casts.

---
 offload/libomptarget/interface.cpp | 12 +++++-------
 offload/libomptarget/omptarget.cpp | 25 +++++++++++++++----------
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index 1a65262f9dcda..661b14dd80f8e 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -30,6 +30,7 @@
 #include <cstdint>
 #include <cstdio>
 #include <cstdlib>
+#include <memory>
 
 #ifdef OMPT_SUPPORT
 using namespace llvm::omp::target::ompt;
@@ -167,13 +168,13 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
   int Rc = OFFLOAD_SUCCESS;
 
   // Only allocate AttachInfo for targetDataBegin
-  AttachInfoTy *AttachInfo = nullptr;
+  std::unique_ptr<AttachInfoTy> AttachInfo;
   if (TargetDataFunction == targetDataBegin)
-    AttachInfo = new AttachInfoTy();
+    AttachInfo = std::make_unique<AttachInfoTy>();
 
   Rc = TargetDataFunction(Loc, *DeviceOrErr, ArgNum, ArgsBase, Args, ArgSizes,
-                          ArgTypes, ArgNames, ArgMappers, AsyncInfo, AttachInfo,
-                          /*FromMapper=*/false);
+                          ArgTypes, ArgNames, ArgMappers, AsyncInfo,
+                          AttachInfo.get(), /*FromMapper=*/false);
 
   if (Rc == OFFLOAD_SUCCESS) {
     // Process deferred ATTACH entries BEFORE synchronization
@@ -184,9 +185,6 @@ targetData(ident_t *Loc, int64_t DeviceId, int32_t ArgNum, void **ArgsBase,
       Rc = AsyncInfo.synchronize();
   }
 
-  if (AttachInfo)
-    delete AttachInfo;
-
   handleTargetOutcome(Rc == OFFLOAD_SUCCESS, Loc);
 }
 
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index eebfa340c8472..eec34a4f9eb3f 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -399,8 +399,10 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   int64_t VoidPtrSize = sizeof(void *);
   assert(HstPtrSize >= VoidPtrSize && "PointerSize is too small");
 
-  uint64_t Delta = (uint64_t)HstPteeBegin - (uint64_t)HstPteeBase;
-  void *TgtPteeBase = (void *)((uint64_t)TgtPteeBegin - Delta);
+  uint64_t Delta = reinterpret_cast<uint64_t>(HstPteeBegin) -
+                   reinterpret_cast<uint64_t>(HstPteeBase);
+  void *TgtPteeBase = reinterpret_cast<void *>(
+      reinterpret_cast<uint64_t>(TgtPteeBegin) - Delta);
 
   // Add shadow pointer tracking
   // TODO: Support shadow-tracking of larger than VoidPtrSize pointers,
@@ -463,7 +465,8 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   // And to the remaining bytes, we copy the remaining contents of the host
   // descriptor after the initial VoidPtrSize bytes.
   uint64_t HstDescriptorFieldsSize = HstPtrSize - VoidPtrSize;
-  void *HstDescriptorFieldsAddr = (char *)HstPtrAddr + VoidPtrSize;
+  void *HstDescriptorFieldsAddr =
+      reinterpret_cast<char *>(HstPtrAddr) + VoidPtrSize;
   std::memcpy(DataBuffer + VoidPtrSize, HstDescriptorFieldsAddr,
               HstDescriptorFieldsSize);
 
@@ -613,7 +616,7 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
          (PointerTpr.Flags.IsNewEntry ? "" : " not"));
       PointerHstPtrBegin = HstPtrBase;
       // modify current entry.
-      HstPtrBase = *(void **)HstPtrBase;
+      HstPtrBase = *reinterpret_cast<void **>(HstPtrBase);
       // No need to update pointee ref count for the first element of the
       // subelement that comes from mapper.
       UpdateRef =
@@ -655,9 +658,10 @@ int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum,
 
     if (ArgTypes[I] & OMP_TGT_MAPTYPE_PTR_AND_OBJ && !IsHostPtr) {
       int Ret = performPointerAttachment(
-          Device, AsyncInfo, (void **)PointerHstPtrBegin, HstPtrBase,
-          HstPtrBegin, (void **)PointerTgtPtrBegin, TgtPtrBegin, sizeof(void *),
-          PointerTpr);
+          Device, AsyncInfo, reinterpret_cast<void **>(PointerHstPtrBegin),
+          HstPtrBase, HstPtrBegin,
+          reinterpret_cast<void **>(PointerTgtPtrBegin), TgtPtrBegin,
+          sizeof(void *), PointerTpr);
       if (Ret != OFFLOAD_SUCCESS)
         return OFFLOAD_FAIL;
     }
@@ -746,7 +750,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
        ++EntryIdx) {
     const auto &AttachEntry = AttachInfo.AttachEntries[EntryIdx];
 
-    void **HstPtr = (void **)AttachEntry.PointerBase;
+    void **HstPtr = reinterpret_cast<void **>(AttachEntry.PointerBase);
 
     void *HstPteeBase = *HstPtr;
     void *HstPteeBegin = AttachEntry.PointeeBegin;
@@ -767,7 +771,8 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
             void *AllocPtr = Alloc.first;
             int64_t AllocSize = Alloc.second;
             return Ptr >= AllocPtr &&
-                   Ptr < (void *)((char *)AllocPtr + AllocSize);
+                   Ptr < reinterpret_cast<void *>(
+                             reinterpret_cast<char *>(AllocPtr) + AllocSize);
           });
       DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
          EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
@@ -823,7 +828,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
     if (!PtrTPROpt)
       continue;
     TargetPointerResultTy &PtrTPR = *PtrTPROpt;
-    void **TgtPtrBase = (void **)PtrTPR.TargetPointer;
+    void **TgtPtrBase = reinterpret_cast<void **>(PtrTPR.TargetPointer);
 
     // Get device version of the pointee (e.g., &p[10])
     auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");

>From 39e4ab1c667e09e85d3eb6906ce4ec2fb1a9b6d1 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Fri, 1 Aug 2025 04:57:00 -0700
Subject: [PATCH 48/66] Add newline at end of file.

---
 offload/plugins-nextgen/common/src/PluginInterface.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index ae4433b05571b..1b034d26df28f 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -2242,4 +2242,4 @@ int32_t GenericPluginTy::data_fence(int32_t DeviceId,
   }
 
   return OFFLOAD_SUCCESS;
-}
\ No newline at end of file
+}

>From 946295326ab66873798ac5d7f4b257495a460380 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Fri, 1 Aug 2025 05:22:25 -0700
Subject: [PATCH 49/66] Cache the attach-ptr-expr computation result, and reuse
 it if needed.

---
 clang/include/clang/AST/OpenMPClause.h | 13 +++++++
 clang/lib/CodeGen/CGOpenMPRuntime.cpp  | 53 ++++++++++++++++++++++++--
 2 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 1118d3e062e68..c27c858864525 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -5815,6 +5815,12 @@ class OMPClauseMappableExprCommon {
     ValueDecl *getAssociatedDeclaration() const {
       return AssociatedDeclaration;
     }
+
+    bool operator==(const MappableComponent &Other) const {
+      return AssociatedExpressionNonContiguousPr ==
+                 Other.AssociatedExpressionNonContiguousPr &&
+             AssociatedDeclaration == Other.AssociatedDeclaration;
+    }
   };
 
   // List of components of an expression. This first one is the whole
@@ -5828,6 +5834,13 @@ class OMPClauseMappableExprCommon {
   using MappableExprComponentLists = SmallVector<MappableExprComponentList, 8>;
   using MappableExprComponentListsRef = ArrayRef<MappableExprComponentList>;
 
+  // Hash function to allow usage as DenseMap keys.
+  friend llvm::hash_code hash_value(const MappableComponent &MC) {
+    return llvm::hash_combine(MC.getAssociatedExpression(),
+                              MC.getAssociatedDeclaration(),
+                              MC.isNonContiguous());
+  }
+
 protected:
   // Return the total number of elements in a list of component lists.
   static unsigned
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 381c8390b1965..1ff5240506d93 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6918,6 +6918,11 @@ class MappableExprsHandler {
   /// Map between lambda declarations and their map type.
   llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
 
+  /// Map from component lists to their attach pointer expressions.
+  mutable llvm::DenseMap<
+      OMPClauseMappableExprCommon::MappableExprComponentListRef, const Expr *>
+      AttachPtrExprMap;
+
   llvm::Value *getExprTypeSize(const Expr *E) const {
     QualType ExprTy = E->getType().getCanonicalType();
 
@@ -6993,6 +6998,18 @@ class MappableExprsHandler {
     return CGF.getTypeSize(ExprTy);
   }
 
+  /// Get the previously-cached attach pointer for a component list, if-any.
+  const Expr *getAttachPtrExpr(
+      OMPClauseMappableExprCommon::MappableExprComponentListRef Components)
+      const {
+    auto It = AttachPtrExprMap.find(Components);
+    if (It != AttachPtrExprMap.end()) {
+      return It->second;
+    }
+
+    return nullptr;
+  }
+
   /// Return the corresponding bits for a given map clause modifier. Add
   /// a flag marking the map as a pointer if requested. Add a flag marking the
   /// map as the first one of a series of maps that relate to the same map
@@ -7446,8 +7463,8 @@ class MappableExprsHandler {
     const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
     const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
 
-    // Find the pointer-attachment base-pointer for the given list, if any.
-    const Expr *AttachPtrExpr = findAttachPtrExpr(Components);
+    // Get the pointer-attachment base-pointer for the given list, if any.
+    const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
 
     if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
@@ -8476,7 +8493,7 @@ class MappableExprsHandler {
           }
         };
 
-    auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF, const ValueDecl *VD,
+    auto &&IsMapInfoExist = [&Info, this](CodeGenFunction &CGF, const ValueDecl *VD,
                                     const Expr *IE, bool IsDevAddr) -> bool {
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
@@ -8507,7 +8524,7 @@ class MappableExprsHandler {
             } else {
               auto PrevCI = std::next(CI->Components.rbegin());
               const auto *VarD = dyn_cast<VarDecl>(VD);
-              const Expr *AttachPtrExpr = findAttachPtrExpr(CI->Components);
+              const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
               if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
                   isa<MemberExpr>(IE) ||
                   !VD->getType().getNonReferenceType()->isPointerType() ||
@@ -8758,6 +8775,34 @@ class MappableExprsHandler {
           LambdasMap.try_emplace(std::get<0>(L), C);
       }
     }
+
+    auto cacheAttachPtrExprsForClauseComponents = [this](const auto *C) {
+      for (auto L : C->component_lists()) {
+        OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+            std::get<1>(L);
+        if (!Components.empty()) {
+          const Expr *AttachPtrExpr = findAttachPtrExpr(Components);
+          AttachPtrExprMap[Components] = AttachPtrExpr;
+        }
+      }
+    };
+
+    // Populate the AttachPtrExprMap for all component lists from map-related
+    // clauses.
+    for (const auto *C : Dir.getClausesOfKind<OMPMapClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPToClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPFromClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
+    for (const auto *C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
+      cacheAttachPtrExprsForClauseComponents(C);
   }
 
   /// Constructor for the declare mapper directive.

>From 371918ef2d919786ea3cc04e9d92f93fdd4205e5 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 5 Aug 2025 01:14:53 -0700
Subject: [PATCH 50/66] Clean-up some debug prints.

---
 offload/libomptarget/omptarget.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index eec34a4f9eb3f..4dbb45e686a85 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -421,8 +421,11 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   // pointer attachment for (3) needs to update the bounds information
   // in the descriptor of p on device.
   if (!PtrTPR.getEntry()->addShadowPointer(
-          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase}))
+          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase})) {
+    DP("Pointer " DPxMOD " is already attached to " DPxMOD "\n",
+       DPxPTR(TgtPtrAddr), DPxPTR(TgtPteeBase));
     return OFFLOAD_SUCCESS;
+  }
 
   DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n", DPxPTR(TgtPtrAddr),
      DPxPTR(TgtPteeBase));
@@ -774,8 +777,8 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
                    Ptr < reinterpret_cast<void *>(
                              reinterpret_cast<char *>(AllocPtr) + AllocSize);
           });
-      DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
-         EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
+      DP("Attach %s " DPxMOD " was newly allocated: %s\n", PtrName, DPxPTR(Ptr),
+         IsNewlyAllocated ? "yes" : "no");
       return IsNewlyAllocated;
     };
 
@@ -789,9 +792,6 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       continue;
     }
 
-    DP("Processing ATTACH entry %zu: Always=%s\n", EntryIdx,
-       IsAttachAlways ? "yes" : "no");
-
     // Lambda to perform target pointer lookup and validation
     auto LookupTargetPointer =
         [&](void *Ptr, int64_t Size,
@@ -802,9 +802,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
           Ptr, Size, /*UpdateRefCount=*/false,
           /*UseHoldRefCount=*/false, /*MustContain=*/true);
 
-      DP("ATTACH entry %zu: %s lookup - HstPtr=" DPxMOD ", TgtPtr=" DPxMOD
-         ", IsPresent=%s, IsHostPtr=%s\n",
-         EntryIdx, PtrType, DPxPTR(Ptr), DPxPTR(TPR.TargetPointer),
+      DP("Attach %s lookup - IsPresent=%s, IsHostPtr=%s\n", PtrType,
          TPR.isPresent() ? "yes" : "no",
          TPR.Flags.IsHostPointer ? "yes" : "no");
 

>From eb35a3ef9962d3773e513daf8179fe5d8ffdfdb9 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Tue, 5 Aug 2025 01:14:53 -0700
Subject: [PATCH 51/66] Clean-up some debug prints.

---
 offload/libomptarget/omptarget.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index eec34a4f9eb3f..4dbb45e686a85 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -421,8 +421,11 @@ static int performPointerAttachment(DeviceTy &Device, AsyncInfoTy &AsyncInfo,
   // pointer attachment for (3) needs to update the bounds information
   // in the descriptor of p on device.
   if (!PtrTPR.getEntry()->addShadowPointer(
-          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase}))
+          ShadowPtrInfoTy{HstPtrAddr, HstPteeBase, TgtPtrAddr, TgtPteeBase})) {
+    DP("Pointer " DPxMOD " is already attached to " DPxMOD "\n",
+       DPxPTR(TgtPtrAddr), DPxPTR(TgtPteeBase));
     return OFFLOAD_SUCCESS;
+  }
 
   DP("Update pointer (" DPxMOD ") -> [" DPxMOD "]\n", DPxPTR(TgtPtrAddr),
      DPxPTR(TgtPteeBase));
@@ -774,8 +777,8 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
                    Ptr < reinterpret_cast<void *>(
                              reinterpret_cast<char *>(AllocPtr) + AllocSize);
           });
-      DP("ATTACH entry %zu: %s pointer " DPxMOD " was newly allocated: %s\n",
-         EntryIdx, PtrName, DPxPTR(Ptr), IsNewlyAllocated ? "yes" : "no");
+      DP("Attach %s " DPxMOD " was newly allocated: %s\n", PtrName, DPxPTR(Ptr),
+         IsNewlyAllocated ? "yes" : "no");
       return IsNewlyAllocated;
     };
 
@@ -789,9 +792,6 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       continue;
     }
 
-    DP("Processing ATTACH entry %zu: Always=%s\n", EntryIdx,
-       IsAttachAlways ? "yes" : "no");
-
     // Lambda to perform target pointer lookup and validation
     auto LookupTargetPointer =
         [&](void *Ptr, int64_t Size,
@@ -802,9 +802,7 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
           Ptr, Size, /*UpdateRefCount=*/false,
           /*UseHoldRefCount=*/false, /*MustContain=*/true);
 
-      DP("ATTACH entry %zu: %s lookup - HstPtr=" DPxMOD ", TgtPtr=" DPxMOD
-         ", IsPresent=%s, IsHostPtr=%s\n",
-         EntryIdx, PtrType, DPxPTR(Ptr), DPxPTR(TPR.TargetPointer),
+      DP("Attach %s lookup - IsPresent=%s, IsHostPtr=%s\n", PtrType,
          TPR.isPresent() ? "yes" : "no",
          TPR.Flags.IsHostPointer ? "yes" : "no");
 

>From f1a4e805d0769656ff8a6aebb450da3cc6debf9e Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 6 Aug 2025 06:27:20 -0700
Subject: [PATCH 52/66] [NFC][Offload] Add missing maps to OpenMP offloading
 tests.

---
 offload/test/mapping/data_member_ref.cpp  | 3 ++-
 offload/test/mapping/ptr_and_obj_motion.c | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/offload/test/mapping/data_member_ref.cpp b/offload/test/mapping/data_member_ref.cpp
index fdb8abcaa6506..7947a62c169f4 100644
--- a/offload/test/mapping/data_member_ref.cpp
+++ b/offload/test/mapping/data_member_ref.cpp
@@ -60,7 +60,8 @@ int main() {
   printf("Host %d %d.\n", Bar.VRef.Data, V.Data);
   // CHECK: Host 123456.
   printf("Host %d.\n", *Baz.VRef.Data);
-#pragma omp target map(*Baz.VRef.Data) map(from : D1, D2)
+#pragma omp target map(Baz.VRef.Data) map(*Baz.VRef.Data) map(V1.Data[0 : 0])  \
+    map(from : D1, D2)
   {
     // CHECK: Device 123456.
     D1 = *Baz.VRef.Data;
diff --git a/offload/test/mapping/ptr_and_obj_motion.c b/offload/test/mapping/ptr_and_obj_motion.c
index 8fa2c9865b4ac..224b59654ab9a 100644
--- a/offload/test/mapping/ptr_and_obj_motion.c
+++ b/offload/test/mapping/ptr_and_obj_motion.c
@@ -17,7 +17,7 @@ void init(double vertexx[]) {
 }
 
 void change(DV *dvptr) {
-#pragma omp target map(dvptr->dataptr[0 : 100])
+#pragma omp target map(dvptr->dataptr[0 : 100]) map(alloc: dvptr->dataptr)
   {
     printf("In change: %lf, expected 77.0\n", dvptr->dataptr[77]);
     dvptr->dataptr[77] += 1.0;

>From c15b2b9ccf5d4cfa75733130e4f47d4c81b08be4 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 6 Aug 2025 06:44:28 -0700
Subject: [PATCH 53/66] [NFC][Clang][OpenMP] Extract collection of
 component-lists out of generateInfoForCaptureFromClauseInfo.

This will be useful for future changes where we use the information
outside this function.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 101 +++++++++++++++-----------
 1 file changed, 58 insertions(+), 43 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 1ff5240506d93..80cc7b8b2844d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9074,46 +9074,13 @@ class MappableExprsHandler {
     }
   }
 
-  /// For a capture that has an associated clause, generate the base pointers,
-  /// section pointers, sizes, map types, and mappers (all included in
-  /// \a CurCaptureVarInfo).
-  void generateInfoForCaptureFromClauseInfo(
-      const CapturedStmt::Capture *Cap, llvm::Value *Arg,
-      MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
-      unsigned OffsetForMemberOfFlag) const {
-    assert(!Cap->capturesVariableArrayType() &&
-           "Not expecting to generate map info for a variable array type!");
-
-    // We need to know when we generating information for the first component
-    const ValueDecl *VD = Cap->capturesThis()
-                              ? nullptr
-                              : Cap->getCapturedVar()->getCanonicalDecl();
-
-    // for map(to: lambda): skip here, processing it in
-    // generateDefaultMapInfo
-    if (LambdasMap.count(VD))
+  /// Populate component lists for non-lambda captured variables from map,
+  /// is_device_ptr and has_device_addr clause info.
+  void populateComponentListsForNonLambdaCaptureFromClauses(
+      const ValueDecl *VD, MapDataArrayTy &DeclComponentLists) const {
+    if (VD && LambdasMap.count(VD))
       return;
 
-    // If this declaration appears in a is_device_ptr clause we just have to
-    // pass the pointer by value. If it is a reference to a declaration, we just
-    // pass its value.
-    if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
-      CurCaptureVarInfo.Exprs.push_back(VD);
-      CurCaptureVarInfo.BasePointers.emplace_back(Arg);
-      CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
-      CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
-      CurCaptureVarInfo.Pointers.push_back(Arg);
-      CurCaptureVarInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
-          CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
-          /*isSigned=*/true));
-      CurCaptureVarInfo.Types.push_back(
-          OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
-          OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
-      CurCaptureVarInfo.Mappers.push_back(nullptr);
-      return;
-    }
-
-    MapDataArrayTy DeclComponentLists;
     // For member fields list in is_device_ptr, store it in
     // DeclComponentLists for generating components info.
     static const OpenMPMapModifierKind Unknown = OMPC_MAP_MODIFIER_unknown;
@@ -9163,19 +9130,60 @@ class MappableExprsHandler {
       bool HasAllocsR = MapType == OMPC_MAP_alloc;
       return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
     });
+  }
+
+  /// For a capture that has an associated clause, generate the base pointers,
+  /// section pointers, sizes, map types, and mappers (all included in
+  /// \a CurCaptureVarInfo).
+  void generateInfoForCaptureFromClauseInfo(
+      const MapDataArrayTy &DeclComponentListsFromClauses,
+      const CapturedStmt::Capture *Cap, llvm::Value *Arg,
+      MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
+      unsigned OffsetForMemberOfFlag) const {
+    assert(!Cap->capturesVariableArrayType() &&
+           "Not expecting to generate map info for a variable array type!");
+
+    // We need to know when we generating information for the first component
+    const ValueDecl *VD = Cap->capturesThis()
+                              ? nullptr
+                              : Cap->getCapturedVar()->getCanonicalDecl();
+
+    // for map(to: lambda): skip here, processing it in
+    // generateDefaultMapInfo
+    if (LambdasMap.count(VD))
+      return;
+
+    // If this declaration appears in a is_device_ptr clause we just have to
+    // pass the pointer by value. If it is a reference to a declaration, we just
+    // pass its value.
+    if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
+      CurCaptureVarInfo.Exprs.push_back(VD);
+      CurCaptureVarInfo.BasePointers.emplace_back(Arg);
+      CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
+      CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
+      CurCaptureVarInfo.Pointers.push_back(Arg);
+      CurCaptureVarInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
+          CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty,
+          /*isSigned=*/true));
+      CurCaptureVarInfo.Types.push_back(
+          OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
+          OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
+      CurCaptureVarInfo.Mappers.push_back(nullptr);
+      return;
+    }
 
     auto GenerateInfoForComponentLists =
-        [&](ArrayRef<MapData> DeclComponentLists,
+        [&](ArrayRef<MapData> DeclComponentListsFromClauses,
             bool IsEligibleForTargetParamFlag) {
           MapCombinedInfoTy CurInfoForComponentLists;
           StructRangeInfoTy PartialStruct;
 
-          if (DeclComponentLists.empty())
+          if (DeclComponentListsFromClauses.empty())
             return;
 
           generateInfoForCaptureFromComponentLists(
-              VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
-              IsEligibleForTargetParamFlag);
+              VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
+              PartialStruct, IsEligibleForTargetParamFlag);
 
           // If there is an entry in PartialStruct it means we have a
           // struct with individual members mapped. Emit an extra combined
@@ -9914,10 +9922,17 @@ static void genMapInfoForCaptures(
                               OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
       CurInfo.Mappers.push_back(nullptr);
     } else {
+      const ValueDecl *CapturedVD =
+          CI->capturesThis() ? nullptr
+                             : CI->getCapturedVar()->getCanonicalDecl();
+      // Populate component lists for the captured variable from clauses.
+      MappableExprsHandler::MapDataArrayTy DeclComponentLists;
+      MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
+          CapturedVD, DeclComponentLists);
       // If we have any information in the map clause, we use it, otherwise we
       // just do a default mapping.
       MEHandler.generateInfoForCaptureFromClauseInfo(
-          CI, *CV, CurInfo, OMPBuilder,
+          DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
           /*OffsetForMemberOfFlag=*/CombinedInfo.BasePointers.size());
 
       if (!CI->capturesThis())

>From 4517cd2bcd140a870c3846a52750ed8a1874bd3d Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Fri, 8 Aug 2025 04:31:49 -0700
Subject: [PATCH 54/66] Do pointee lookup and release its TPR before pointer
 lookup.

---
 offload/libomptarget/omptarget.cpp | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 4dbb45e686a85..4b2200b6ebaa5 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -782,10 +782,10 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       return IsNewlyAllocated;
     };
 
-    // Only process ATTACH if base/begin was newly allocated OR ALWAYS flag is
-    // set
-    if (!IsAttachAlways && !WasNewlyAllocated(HstPtr, "pointer") &&
-        !WasNewlyAllocated(HstPteeBegin, "pointee")) {
+    // Only process ATTACH if either the pointee or the pointer was newly
+    // allocated, or the ALWAYS flag is set.
+    if (!IsAttachAlways && !WasNewlyAllocated(HstPteeBegin, "pointee") &&
+        !WasNewlyAllocated(HstPtr, "pointer")) {
       DP("Skipping ATTACH entry %zu: neither pointer nor pointee was newly "
          "allocated and no ALWAYS flag\n",
          EntryIdx);
@@ -821,19 +821,22 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       return TPR;
     };
 
-    // Get device version of the pointer (e.g., &p)
+    // Get device version of the pointee (e.g., &p[10]) first, as we can
+    // release its TPR after extracting the pointer value.
+    void *TgtPteeBegin;
+    if (auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee"))
+      TgtPteeBegin = PteeTPROpt->TargetPointer;
+    else
+      continue;
+
+    // Get device version of the pointer (e.g., &p) next. We need to keep its
+    // TPR for use in shadow-pointer handling during pointer-attachment.
     auto PtrTPROpt = LookupTargetPointer(HstPtr, PtrSize, "pointer");
     if (!PtrTPROpt)
       continue;
     TargetPointerResultTy &PtrTPR = *PtrTPROpt;
     void **TgtPtrBase = reinterpret_cast<void **>(PtrTPR.TargetPointer);
 
-    // Get device version of the pointee (e.g., &p[10])
-    auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");
-    if (!PteeTPROpt)
-      continue;
-    void *TgtPteeBegin = PteeTPROpt->TargetPointer;
-
     // Insert a data-fence before the first pointer-attachment.
     if (IsFirstPointerAttachment) {
       IsFirstPointerAttachment = false;

>From d2e6a7cfaaf8d5ba3cc4bbc1d6b4dd81918d2b49 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 6 Aug 2025 07:12:31 -0700
Subject: [PATCH 55/66] Expand to remove the restriction to only support simple
 vars as attach-poitners.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 304 +++++++++++++++++++-------
 1 file changed, 222 insertions(+), 82 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 80cc7b8b2844d..49bd8264ba729 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -28,6 +28,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Bitcode/BitcodeReader.h"
@@ -6846,6 +6847,35 @@ class MappableExprsHandler {
     const Expr *AttachMapExpr = nullptr;
   };
 
+  /// Check if there's any component list where the attach pointer expression
+  /// matches the given captured variable.
+  bool hasAttachEntryForCapturedVar(const ValueDecl *VD) const {
+    for (const auto &AttachEntry : AttachPtrExprMap) {
+      if (AttachEntry.second) {
+        // Check if the attach pointer expression is a DeclRefExpr that
+        // references the captured variable
+        if (const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second)) {
+          if (DRE->getDecl() == VD) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  /// Get the previously-cached attach pointer for a component list, if-any.
+  const Expr *getAttachPtrExpr(
+      OMPClauseMappableExprCommon::MappableExprComponentListRef Components)
+      const {
+    auto It = AttachPtrExprMap.find(Components);
+    if (It != AttachPtrExprMap.end()) {
+      return It->second;
+    }
+
+    return nullptr;
+  }
+
 private:
   /// Kind that defines how a device pointer has to be returned.
   struct MapInfo {
@@ -6923,6 +6953,19 @@ class MappableExprsHandler {
       OMPClauseMappableExprCommon::MappableExprComponentListRef, const Expr *>
       AttachPtrExprMap;
 
+  /// Map from attach pointer expressions to their component lists.
+  /// nullptr key represents component lists with no attach pointer expression.
+  mutable llvm::DenseMap<
+      const Expr *,
+      SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
+      AttachPtrToComponentListsMap;
+
+  /// Map from attach pointer expressions to their component depth.
+  /// nullptr key has std::nullopt depth. This can be used to order attach-ptr
+  /// expressions with increasing/decreasing depth.
+  mutable llvm::DenseMap<const Expr *, std::optional<size_t>>
+      AttachPtrComponentDepthMap;
+
   llvm::Value *getExprTypeSize(const Expr *E) const {
     QualType ExprTy = E->getType().getCanonicalType();
 
@@ -6998,18 +7041,6 @@ class MappableExprsHandler {
     return CGF.getTypeSize(ExprTy);
   }
 
-  /// Get the previously-cached attach pointer for a component list, if-any.
-  const Expr *getAttachPtrExpr(
-      OMPClauseMappableExprCommon::MappableExprComponentListRef Components)
-      const {
-    auto It = AttachPtrExprMap.find(Components);
-    if (It != AttachPtrExprMap.end()) {
-      return It->second;
-    }
-
-    return nullptr;
-  }
-
   /// Return the corresponding bits for a given map clause modifier. Add
   /// a flag marking the map as a pointer if requested. Add a flag marking the
   /// map as the first one of a series of maps that relate to the same map
@@ -7465,8 +7496,23 @@ class MappableExprsHandler {
 
     // Get the pointer-attachment base-pointer for the given list, if any.
     const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
-
-    if (isa<MemberExpr>(AssocExpr)) {
+    Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
+    Address AttachPteeBaseAddr =
+        !AttachPtrAddr.isValid()
+            ? Address::invalid()
+            : CGF.EmitLoadOfPointer(
+                  AttachPtrAddr,
+                  CGF.getContext().VoidPtrTy.castAs<PointerType>());
+
+    bool HasAttachPtr = AttachPtrExpr != nullptr;
+    bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
+    bool SeenAttachPtr = FirstComponentIsForAttachPtr;
+
+    if (FirstComponentIsForAttachPtr) {
+      // No need to process AttachPtr here. It will be processed at the end
+      // after we have computed the pointee's address.
+      ++I;
+    } else if (isa<MemberExpr>(AssocExpr)) {
       // The base is the 'this' pointer. The content of the pointer is going
       // to be the base of the field being mapped.
       BP = CGF.LoadCXXThisAddress();
@@ -7509,9 +7555,7 @@ class MappableExprsHandler {
         // active or the base declaration is not global variable.
         const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
         if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
-            !VD || VD->hasLocalStorage() ||
-            (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
-             VD == cast<DeclRefExpr>(AttachPtrExpr)->getDecl()))
+            !VD || VD->hasLocalStorage() || HasAttachPtr)
           BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
         else
           FirstPointerInComplexData = true;
@@ -7574,6 +7618,19 @@ class MappableExprsHandler {
     }
 
     for (; I != CE; ++I) {
+      // If we have a valid attach-ptr, we skip processing all components until
+      // after the attach-ptr.
+      if (HasAttachPtr && !SeenAttachPtr) {
+        SeenAttachPtr |= I->getAssociatedExpression() == AttachPtrExpr;
+        continue;
+      }
+
+      bool IsFirstComponentAfterAttach =
+          HasAttachPtr &&
+          std::prev(I)->getAssociatedExpression() == AttachPtrExpr;
+      if (IsFirstComponentAfterAttach)
+        BP = AttachPteeBaseAddr;
+
       // If the current component is member of a struct (parent struct) mark it.
       if (!EncounteredME) {
         EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
@@ -7901,24 +7958,24 @@ class MappableExprsHandler {
     // Add ATTACH entries for pointer-attachment: delay if PartialStruct is
     // being populated, otherwise add immediately.
     if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
-      Address AttachPtrAddr = CGF.EmitLValue(AttachPtrExpr).getAddress();
-      Address AttachPteeAddr = FinalLowestElem;
+      Address AttachPteeBeginAddr = FinalLowestElem;
 
       assert(AttachPtrAddr.isValid() && "Attach ptr address is not valid.");
-      assert(AttachPteeAddr.isValid() && "Attach ptee address is not valid.");
+      assert(AttachPteeBeginAddr.isValid() &&
+             "Attach ptee begin address is not valid.");
 
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
         // after emitCombinedEntry.
         PartialStruct.AttachPtrAddr = AttachPtrAddr;
-        PartialStruct.AttachPteeAddr = AttachPteeAddr;
+        PartialStruct.AttachPteeAddr = AttachPteeBeginAddr;
         PartialStruct.AttachPtrDecl = BaseDecl;
         PartialStruct.AttachMapExpr = MapExpr;
       } else if (IsMappingWholeStruct) {
         addAttachEntry(CGF, StructBaseCombinedInfo, AttachPtrAddr,
-                       AttachPteeAddr, BaseDecl, MapExpr);
+                       AttachPteeBeginAddr, BaseDecl, MapExpr);
       } else {
-        addAttachEntry(CGF, CombinedInfo, AttachPtrAddr, AttachPteeAddr,
+        addAttachEntry(CGF, CombinedInfo, AttachPtrAddr, AttachPteeBeginAddr,
                        BaseDecl, MapExpr);
       }
     }
@@ -8196,6 +8253,32 @@ class MappableExprsHandler {
     }
   }
 
+  /// Returns the address corresponding to \p PointerExpr.
+  static Address getAttachPtrAddr(const Expr *PointerExpr,
+                                  CodeGenFunction &CGF) {
+    Address AttachPtrAddr = Address::invalid();
+    if (!PointerExpr)
+      return AttachPtrAddr;
+
+    if (auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
+      // If the pointer is a variable, we can use its address directly.
+      AttachPtrAddr = CGF.EmitLValue(DRE).getAddress();
+    } else if (auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
+      AttachPtrAddr =
+          CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/true).getAddress();
+    } else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
+      AttachPtrAddr = CGF.EmitLValue(ASE).getAddress();
+    } else if (auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
+      AttachPtrAddr = CGF.EmitMemberExpr(ME).getAddress();
+    } else if (auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
+      if (UO->getOpcode() == UO_Deref)
+        AttachPtrAddr = CGF.EmitLValue(UO).getAddress();
+    }
+    assert(AttachPtrAddr.isValid() &&
+           "Failed to get address for attach pointer expression");
+    return AttachPtrAddr;
+  }
+
   /// Returns whether an attach entry should be emitted for a map on
   /// \p MapBaseDecl on the directive \p CurDir.
   static bool
@@ -8214,15 +8297,6 @@ class MappableExprsHandler {
             cast<const OMPExecutableDirective *>(CurDir)->getDirectiveKind()))
       return false;
 
-    const auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr);
-    const VarDecl *PointerDecl =
-        !DRE ? nullptr : dyn_cast_if_present<VarDecl>(DRE->getDecl());
-
-    // For now, we are emitting ATTACH entries only when the
-    // "attach-base-pointer" is a vardecl that matches the base var of the map.
-    if (!PointerDecl || PointerDecl != MapBaseDecl)
-      return false;
-
     return true;
   }
 
@@ -8300,25 +8374,26 @@ class MappableExprsHandler {
   ///   pps[1]->p[10]   | pps[1]
   ///   pas[1]          | N/A
   ///   pas[1][2]       | pas[1]
+  /// Returns a pair of the attach pointer expression and its depth in the
+  /// component list.
   /// TODO: This may need to be updated to handle ref_ptr/ptee cases for byref
   /// map operands.
-  static const Expr *findAttachPtrExpr(
+  static std::pair<const Expr *, std::optional<size_t>> findAttachPtrExpr(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
     const auto *Begin = Components.begin();
-    const auto *End = Components.end();
 
     // If we only have a single component, we have a map like "map(p)", which
     // cannot have a base-pointer.
     if (Components.size() < 2)
-      return nullptr;
+      return {nullptr, std::nullopt};
 
     // To find the attach base-pointer, we start with the second component,
     // stripping away one component at a time, until we reach a pointer Expr
     // (that is not a binary operator). The first such pointer should be the
     // attach base-pointer for the component list.
-    for (const auto *I = std::next(Begin); I != End; ++I) {
-      const Expr *CurExpr = I->getAssociatedExpression();
+    for (size_t I = 1; I < Components.size(); ++I) {
+      const Expr *CurExpr = Components[I].getAssociatedExpression();
       if (!CurExpr)
         break;
 
@@ -8333,10 +8408,52 @@ class MappableExprsHandler {
         continue;
 
       // We have found a pointer Expr. This must be the attach pointer.
-      return CurExpr;
+      return {CurExpr, Components.size() - I};
     }
 
-    return nullptr;
+    return {nullptr, std::nullopt};
+  }
+
+  /// Group component lists by their AttachPtrExpr and return them sorted by
+  /// complexity. Complexity is determined by the depth of the AttachPtrExpr in
+  /// the component list. Lower depth = lower complexity. nullptr (no attach
+  /// pointer) has lowest complexity.
+  SmallVector<const Expr *, 8> getAttachPtrExprsSortedByComplexity() const {
+    SmallVector<const Expr *, 8> SortedAttachPtrs;
+
+    // Collect all unique AttachPtrExprs from the map
+    for (const auto &Entry : AttachPtrComponentDepthMap)
+      SortedAttachPtrs.push_back(Entry.first);
+
+    // Sort by complexity (nullptr first, then by increasing complexity) using
+    // stable_sort
+    llvm::stable_sort(SortedAttachPtrs, [this](const Expr *A, const Expr *B) {
+      // Use cached component depth values
+      auto ItA = AttachPtrComponentDepthMap.find(A);
+      auto ItB = AttachPtrComponentDepthMap.find(B);
+
+      // std::nullopt (no attach pointer) has lowest complexity
+      std::optional<size_t> DepthA = (ItA != AttachPtrComponentDepthMap.end())
+                                         ? ItA->second
+                                         : std::nullopt;
+      std::optional<size_t> DepthB = (ItB != AttachPtrComponentDepthMap.end())
+                                         ? ItB->second
+                                         : std::nullopt;
+
+      // If both are nullopt, they're equal
+      if (!DepthA.has_value() && !DepthB.has_value())
+        return false;
+      // If only A is nullopt, A comes first (lower complexity)
+      if (!DepthA.has_value())
+        return true;
+      // If only B is nullopt, B comes first (lower complexity)
+      if (!DepthB.has_value())
+        return false;
+      // Both have values, compare by depth (lower depth = lower complexity)
+      return DepthA.value() < DepthB.value();
+    });
+
+    return SortedAttachPtrs;
   }
 
   /// Generate all the base pointers, section pointers, sizes, map types, and
@@ -8781,8 +8898,10 @@ class MappableExprsHandler {
         OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
             std::get<1>(L);
         if (!Components.empty()) {
-          const Expr *AttachPtrExpr = findAttachPtrExpr(Components);
+          auto [AttachPtrExpr, Depth] = findAttachPtrExpr(Components);
           AttachPtrExprMap[Components] = AttachPtrExpr;
+          AttachPtrToComponentListsMap[AttachPtrExpr].push_back(Components);
+          AttachPtrComponentDepthMap[AttachPtrExpr] = Depth;
         }
       }
     };
@@ -9204,56 +9323,53 @@ class MappableExprsHandler {
           CurCaptureVarInfo.append(AttachCombinedInfo);
         };
 
-    // Next, we break-down the lists of components into lists that should be
-    // handled together.
-    //
-    // For now, we handle maps on pointers by themselves, and everything else
-    // together.
+    // Group component lists by their AttachPtrExpr and process them in order
+    // of increasing complexity (nullptr first, then simple expressions like p,
+    // then more complex ones like p[0], etc.)
     //
-    // TODO: Do this based on which lists have the same attachable-base-pointer
-    // e.g. The map clauses below, which are present on the same construct,
-    // should be handled grouped together based on their
-    // attachable-base-pointers:
+    // Example: The map clauses below should be handled grouped together based
+    // on their attachable-base-pointers:
     //   map-clause                | attachable-base-pointer
     //   --------------------------+------------------------
-    //   map(p, ps)                | none
+    //   map(p, ps)                | nullptr
     //   map(p[0])                 | p
     //   map(p[0]->b, p[0]->c)     | p[0]
     //   map(ps->d, ps->e, ps->pt) | ps
     //   map(ps->pt->d, ps->pt->e) | ps->pt
 
-    MapDataArrayTy ListsThatMapPointerVDItself;
-    MapDataArrayTy RemainingLists;
-    bool IsVDPointerType = VD && VD->getType()->isPointerType();
+    // Group component lists by their AttachPtrExpr
+    llvm::MapVector<const Expr *, MapDataArrayTy> AttachPtrGroups;
 
-    for (const MapData &L : DeclComponentLists) {
-      if (IsVDPointerType) {
-        OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
-            std::get<0>(L);
-        bool IsMapOfPointerVD =
-            Components.size() == 1 &&
-            Components[0].getAssociatedDeclaration() &&
-            Components[0].getAssociatedDeclaration()->getCanonicalDecl() == VD;
-        if (IsMapOfPointerVD) {
-          ListsThatMapPointerVDItself.push_back(L);
-          continue;
-        }
-      }
-      RemainingLists.push_back(L);
+    for (const MapData &L : DeclComponentListsFromClauses) {
+      OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+          std::get<0>(L);
+      const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
+      AttachPtrGroups[AttachPtrExpr].push_back(L);
     }
 
-    // If VD is a pointer, and there are component-lists mapping VD itself,
-    // like: `int *p; ... map(p)`, we handle them first, and
-    // the first one from the should get the TARGET_PARAM flag.
-    GenerateInfoForComponentLists(ListsThatMapPointerVDItself,
-                                  /*IsEligibleForTargetParamFlag=*/true);
-    // Then we handle all the other lists together. Note that since we already
-    // added TARGET_PARAM for the pointer case, we shouldn't add it again if
-    // if there are other lists that get handled here, for example, the list
-    // for `map(p[0:10]` in `int *p; ... map(p, p[0:10])`.
-    GenerateInfoForComponentLists(
-        RemainingLists,
-        /*IsEligibleForTargetParamFlag=*/ListsThatMapPointerVDItself.empty());
+    // Sort AttachPtrExprs by complexity and process each group
+    bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
+    bool FirstGroupProcessed = false;
+
+    // Get AttachPtrExprs sorted by complexity
+    SmallVector<const Expr *, 8> SortedAttachPtrs =
+        getAttachPtrExprsSortedByComplexity();
+
+    // Process each group in order
+    for (const Expr *AttachPtr : SortedAttachPtrs) {
+      const MapDataArrayTy &GroupLists = AttachPtrGroups[AttachPtr];
+      if (GroupLists.empty())
+        continue;
+
+      // Determine if this group of component-lists is eligible for TARGET_PARAM
+      // flag. Only the first group processed should be eligible, and only if no
+      // default mapping was done.
+      bool IsEligibleForTargetParamFlag =
+          !FirstGroupProcessed && NoDefaultMappingDoneForVD;
+
+      GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
+      FirstGroupProcessed = true;
+    }
   }
 
   /// Generate the base pointers, section pointers, sizes, map types, and
@@ -9925,10 +10041,37 @@ static void genMapInfoForCaptures(
       const ValueDecl *CapturedVD =
           CI->capturesThis() ? nullptr
                              : CI->getCapturedVar()->getCanonicalDecl();
+      bool HasEntryWithCVAsAttachPtr = false;
+      if (CapturedVD)
+        HasEntryWithCVAsAttachPtr =
+            MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
+
       // Populate component lists for the captured variable from clauses.
       MappableExprsHandler::MapDataArrayTy DeclComponentLists;
       MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
           CapturedVD, DeclComponentLists);
+
+      // Map clauses on a target construct must either have a base pointer, or a
+      // base-variable. So, if we don't have a base-pointer, that means that it
+      // must have a base-variable, like map(s), map(s.x) etc. In such cases, we
+      // do not need to handle default map generation for s.
+      bool HasEntryWithoutAttachPtr = false;
+      for (const auto &MapData : DeclComponentLists) {
+        OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+            std::get<0>(MapData);
+        const Expr *AttachPtr = MEHandler.getAttachPtrExpr(Components);
+        if (!AttachPtr) {
+          HasEntryWithoutAttachPtr = true;
+          break;
+        }
+      }
+
+      // Generate default map info first if there's no direct map with CV as
+      // the base-variable, or attach pointer.
+      if (DeclComponentLists.empty() ||
+          (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
+        MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
+
       // If we have any information in the map clause, we use it, otherwise we
       // just do a default mapping.
       MEHandler.generateInfoForCaptureFromClauseInfo(
@@ -9940,9 +10083,6 @@ static void genMapInfoForCaptures(
       else
         MappedVarSet.insert(nullptr);
 
-      if (CurInfo.BasePointers.empty())
-        MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
-
       // Generate correct mapping for variables captured by reference in
       // lambdas.
       if (CI->capturesVariable())

>From a78e9b00d097991ff157ec0f502b2e2aef095eb8 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Fri, 8 Aug 2025 04:31:49 -0700
Subject: [PATCH 56/66] Do pointee lookup and release its TPR before pointer
 lookup.

---
 offload/libomptarget/omptarget.cpp | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 4dbb45e686a85..4b2200b6ebaa5 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -782,10 +782,10 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       return IsNewlyAllocated;
     };
 
-    // Only process ATTACH if base/begin was newly allocated OR ALWAYS flag is
-    // set
-    if (!IsAttachAlways && !WasNewlyAllocated(HstPtr, "pointer") &&
-        !WasNewlyAllocated(HstPteeBegin, "pointee")) {
+    // Only process ATTACH if either the pointee or the pointer was newly
+    // allocated, or the ALWAYS flag is set.
+    if (!IsAttachAlways && !WasNewlyAllocated(HstPteeBegin, "pointee") &&
+        !WasNewlyAllocated(HstPtr, "pointer")) {
       DP("Skipping ATTACH entry %zu: neither pointer nor pointee was newly "
          "allocated and no ALWAYS flag\n",
          EntryIdx);
@@ -821,19 +821,22 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
       return TPR;
     };
 
-    // Get device version of the pointer (e.g., &p)
+    // Get device version of the pointee (e.g., &p[10]) first, as we can
+    // release its TPR after extracting the pointer value.
+    void *TgtPteeBegin;
+    if (auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee"))
+      TgtPteeBegin = PteeTPROpt->TargetPointer;
+    else
+      continue;
+
+    // Get device version of the pointer (e.g., &p) next. We need to keep its
+    // TPR for use in shadow-pointer handling during pointer-attachment.
     auto PtrTPROpt = LookupTargetPointer(HstPtr, PtrSize, "pointer");
     if (!PtrTPROpt)
       continue;
     TargetPointerResultTy &PtrTPR = *PtrTPROpt;
     void **TgtPtrBase = reinterpret_cast<void **>(PtrTPR.TargetPointer);
 
-    // Get device version of the pointee (e.g., &p[10])
-    auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee");
-    if (!PteeTPROpt)
-      continue;
-    void *TgtPteeBegin = PteeTPROpt->TargetPointer;
-
     // Insert a data-fence before the first pointer-attachment.
     if (IsFirstPointerAttachment) {
       IsFirstPointerAttachment = false;

>From 4e3956ca2af4a64c13f66a1b2d60520dd42aea12 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Fri, 8 Aug 2025 23:10:04 -0700
Subject: [PATCH 57/66] Add an attach-ptr-expr comparator and use it to group
 components-lists by attach-ptrs.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 96 ++++++++++++++++++++++-----
 1 file changed, 78 insertions(+), 18 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 49bd8264ba729..ffdeb5647a470 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6765,6 +6765,68 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
 // code for that information.
 class MappableExprsHandler {
 public:
+  // Custom comparator for attach-ptr expessions that compares them by
+  // complexity (i.e. their component-depth) first, then semantically.
+  struct AttachPtrExprComparator {
+    const MappableExprsHandler *Handler;
+
+    AttachPtrExprComparator(const MappableExprsHandler *H) : Handler(H) {}
+
+    bool operator()(const Expr *LHS, const Expr *RHS) const {
+      if (LHS == RHS)
+        return false;
+
+      // First, compare by complexity (depth)
+      auto ItLHS = Handler->AttachPtrComponentDepthMap.find(LHS);
+      auto ItRHS = Handler->AttachPtrComponentDepthMap.find(RHS);
+
+      std::optional<size_t> DepthLHS =
+          (ItLHS != Handler->AttachPtrComponentDepthMap.end()) ? ItLHS->second
+                                                               : std::nullopt;
+      std::optional<size_t> DepthRHS =
+          (ItRHS != Handler->AttachPtrComponentDepthMap.end()) ? ItRHS->second
+                                                               : std::nullopt;
+
+      // std::nullopt (no attach pointer) has lowest complexity
+      if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
+        // Both have same complexity, now check semantic equality
+        if (areSemanticallyEqual(LHS, RHS))
+          return false;   // They are semantically equal
+        return LHS < RHS; // Use pointer comparison for consistent ordering
+      }
+      if (!DepthLHS.has_value())
+        return true; // LHS has lower complexity
+      if (!DepthRHS.has_value())
+        return false; // RHS has lower complexity
+
+      // Both have values, compare by depth (lower depth = lower complexity)
+      if (DepthLHS.value() != DepthRHS.value())
+        return DepthLHS.value() < DepthRHS.value();
+
+      // Same complexity, now check semantic equality
+      if (areSemanticallyEqual(LHS, RHS))
+        return false; // They are semantically equal
+
+      // Same complexity but semantically different exprs. Use pointer
+      // comparison as a fallback to break the tie.
+      return LHS < RHS;
+    }
+
+  private:
+    bool areSemanticallyEqual(const Expr *LHS, const Expr *RHS) const {
+      // For DeclRefExpr, compare by the referenced declaration directly
+      if (const auto *LHSDeclRef = dyn_cast<DeclRefExpr>(LHS)) {
+        if (const auto *RHSDeclRef = dyn_cast<DeclRefExpr>(RHS)) {
+          if (LHSDeclRef->getDecl() == RHSDeclRef->getDecl())
+            return true; // They reference the same declaration
+        }
+      }
+
+      // Use Expr::isSameComparisonOperand for other semantic comparisons
+      return Expr::isSameComparisonOperand(LHS, RHS);
+    }
+  };
+
   /// Get the offset of the OMP_MAP_MEMBER_OF field.
   static unsigned getFlagMemberOffset() {
     unsigned Offset = 0;
@@ -6953,13 +7015,6 @@ class MappableExprsHandler {
       OMPClauseMappableExprCommon::MappableExprComponentListRef, const Expr *>
       AttachPtrExprMap;
 
-  /// Map from attach pointer expressions to their component lists.
-  /// nullptr key represents component lists with no attach pointer expression.
-  mutable llvm::DenseMap<
-      const Expr *,
-      SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
-      AttachPtrToComponentListsMap;
-
   /// Map from attach pointer expressions to their component depth.
   /// nullptr key has std::nullopt depth. This can be used to order attach-ptr
   /// expressions with increasing/decreasing depth.
@@ -7617,6 +7672,7 @@ class MappableExprsHandler {
       }
     }
 
+    bool SeemFirstNonBinOpExprAfterAttachPtr = false;
     for (; I != CE; ++I) {
       // If we have a valid attach-ptr, we skip processing all components until
       // after the attach-ptr.
@@ -7625,11 +7681,18 @@ class MappableExprsHandler {
         continue;
       }
 
-      bool IsFirstComponentAfterAttach =
-          HasAttachPtr &&
-          std::prev(I)->getAssociatedExpression() == AttachPtrExpr;
-      if (IsFirstComponentAfterAttach)
+      // After finding the attach pointer, skip binary-ops, to skip past
+      // expressions like (p + 10), for a map like map(*(p + 10)), where p is
+      // the attach-ptr.
+      if (HasAttachPtr && !SeemFirstNonBinOpExprAfterAttachPtr) {
+        const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
+        if (BO)
+          continue;
+
+        // Found the first non-binary-operator component after attach
+        SeemFirstNonBinOpExprAfterAttachPtr = true;
         BP = AttachPteeBaseAddr;
+      }
 
       // If the current component is member of a struct (parent struct) mark it.
       if (!EncounteredME) {
@@ -8900,7 +8963,6 @@ class MappableExprsHandler {
         if (!Components.empty()) {
           auto [AttachPtrExpr, Depth] = findAttachPtrExpr(Components);
           AttachPtrExprMap[Components] = AttachPtrExpr;
-          AttachPtrToComponentListsMap[AttachPtrExpr].push_back(Components);
           AttachPtrComponentDepthMap[AttachPtrExpr] = Depth;
         }
       }
@@ -9351,12 +9413,10 @@ class MappableExprsHandler {
     bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
     bool FirstGroupProcessed = false;
 
-    // Get AttachPtrExprs sorted by complexity
-    SmallVector<const Expr *, 8> SortedAttachPtrs =
-        getAttachPtrExprsSortedByComplexity();
-
-    // Process each group in order
-    for (const Expr *AttachPtr : SortedAttachPtrs) {
+    // Process each group in order of their attach-pointers increasing
+    // complexity.
+    for (const auto &Entry : AttachPtrGroups) {
+      const Expr *AttachPtr = Entry.first;
       const MapDataArrayTy &GroupLists = AttachPtrGroups[AttachPtr];
       if (GroupLists.empty())
         continue;

>From 3022b9a247e2f2eeb89ff04a8b6c3a9c24d0aba7 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Sun, 10 Aug 2025 05:19:36 -0700
Subject: [PATCH 58/66] Fix comparison of attach-ptrs, group component-lists by
 attach-ptr for target-data, fix matching of use-device-ptr/addr.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 417 +++++++++++++++++++++-----
 1 file changed, 338 insertions(+), 79 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index ffdeb5647a470..1594b77a6889c 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6759,16 +6759,39 @@ llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective(
 namespace {
 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
 
+// Utility to safely compare expression locations for deterministic ordering.
+// This function asserts that both expressions have valid source locations.
+static bool compareExprLocs(const Expr *LHS, const Expr *RHS) {
+  // Assert that neither LHS nor RHS can be null
+  assert(LHS && "LHS expression cannot be null");
+  assert(RHS && "RHS expression cannot be null");
+
+  // Get source locations
+  SourceLocation LocLHS = LHS->getExprLoc();
+  SourceLocation LocRHS = RHS->getExprLoc();
+
+  // Assert that we have valid source locations
+  assert(LocLHS.isValid() && "LHS expression must have valid source location");
+  assert(LocRHS.isValid() && "RHS expression must have valid source location");
+
+  // Compare source locations for deterministic ordering
+  bool result = LocLHS < LocRHS;
+  return result;
+}
+
 // Utility to handle information from clauses associated with a given
 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
 // It provides a convenient interface to obtain the information and generate
 // code for that information.
 class MappableExprsHandler {
 public:
-  // Custom comparator for attach-ptr expessions that compares them by
+  // Custom comparator for attach-pointer expressions that compares them by
   // complexity (i.e. their component-depth) first, then semantically.
   struct AttachPtrExprComparator {
     const MappableExprsHandler *Handler;
+    // Cache of previous comparison results.
+    mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>, bool>
+        CachedComparisonResults;
 
     AttachPtrExprComparator(const MappableExprsHandler *H) : Handler(H) {}
 
@@ -6790,9 +6813,10 @@ class MappableExprsHandler {
       // std::nullopt (no attach pointer) has lowest complexity
       if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
         // Both have same complexity, now check semantic equality
-        if (areSemanticallyEqual(LHS, RHS))
-          return false;   // They are semantically equal
-        return LHS < RHS; // Use pointer comparison for consistent ordering
+        if (areEqual(LHS, RHS))
+          return false;
+        // Different semantically, compare by location
+        return compareExprLocs(LHS, RHS);
       }
       if (!DepthLHS.has_value())
         return true; // LHS has lower complexity
@@ -6804,25 +6828,176 @@ class MappableExprsHandler {
         return DepthLHS.value() < DepthRHS.value();
 
       // Same complexity, now check semantic equality
-      if (areSemanticallyEqual(LHS, RHS))
-        return false; // They are semantically equal
+      if (areEqual(LHS, RHS))
+        return false;
+      // Different semantically, compare by location
+      return compareExprLocs(LHS, RHS);
+    }
+
+  public:
+    bool areEqual(const Expr *LHS, const Expr *RHS) const {
+      // Check cache first for faster lookup
+      auto CachedResultIt = CachedComparisonResults.find({LHS, RHS});
+      if (CachedResultIt != CachedComparisonResults.end())
+        return CachedResultIt->second;
 
-      // Same complexity but semantically different exprs. Use pointer
-      // comparison as a fallback to break the tie.
-      return LHS < RHS;
+      bool ComparisonResult = areSemanticallyEqual(LHS, RHS);
+
+      // Cache the result for future lookups (both orders since semantic
+      // equality is commutative)
+      CachedComparisonResults[{LHS, RHS}] = ComparisonResult;
+      CachedComparisonResults[{RHS, LHS}] = ComparisonResult;
+      return ComparisonResult;
     }
 
   private:
+    // Helper function to compare attach-pointer expressions semantically.
+    // This function handles various expression types that can be part of an
+    // attach-pointer.
     bool areSemanticallyEqual(const Expr *LHS, const Expr *RHS) const {
-      // For DeclRefExpr, compare by the referenced declaration directly
-      if (const auto *LHSDeclRef = dyn_cast<DeclRefExpr>(LHS)) {
-        if (const auto *RHSDeclRef = dyn_cast<DeclRefExpr>(RHS)) {
-          if (LHSDeclRef->getDecl() == RHSDeclRef->getDecl())
-            return true; // They reference the same declaration
-        }
+      if (LHS == RHS)
+        return true;
+
+      // If only one is null, they aren't equal
+      if (!LHS || !RHS)
+        return false;
+
+      ASTContext &Ctx = Handler->CGF.getContext();
+      // Strip away parentheses and no-op casts to get to the core expression
+      LHS = LHS->IgnoreParenNoopCasts(Ctx);
+      RHS = RHS->IgnoreParenNoopCasts(Ctx);
+
+      // Direct pointer comparison of the underlying expressions
+      if (LHS == RHS)
+        return true;
+
+      // Check if the expression classes match
+      if (LHS->getStmtClass() != RHS->getStmtClass())
+        return false;
+
+      // Handle DeclRefExpr (variable references)
+      if (const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
+        const auto *RD = dyn_cast<DeclRefExpr>(RHS);
+        if (!RD)
+          return false;
+        return LD->getDecl()->getCanonicalDecl() ==
+               RD->getDecl()->getCanonicalDecl();
+      }
+
+      // Handle ArraySubscriptExpr (array indexing like a[i])
+      if (const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
+        const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
+        if (!RA)
+          return false;
+        return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
+               areSemanticallyEqual(LA->getIdx(), RA->getIdx());
+      }
+
+      // Handle MemberExpr (member access like s.m or p->m)
+      if (const auto *LM = dyn_cast<MemberExpr>(LHS)) {
+        const auto *RM = dyn_cast<MemberExpr>(RHS);
+        if (!RM)
+          return false;
+        if (LM->getMemberDecl()->getCanonicalDecl() !=
+            RM->getMemberDecl()->getCanonicalDecl())
+          return false;
+        return areSemanticallyEqual(LM->getBase(), RM->getBase());
+      }
+
+      // Handle UnaryOperator (unary operations like *p, &x, etc.)
+      if (const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
+        const auto *RU = dyn_cast<UnaryOperator>(RHS);
+        if (!RU)
+          return false;
+        if (LU->getOpcode() != RU->getOpcode())
+          return false;
+        return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
+      }
+
+      // Handle BinaryOperator (binary operations like p + offset)
+      if (const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
+        const auto *RB = dyn_cast<BinaryOperator>(RHS);
+        if (!RB)
+          return false;
+        if (LB->getOpcode() != RB->getOpcode())
+          return false;
+        return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
+               areSemanticallyEqual(LB->getRHS(), RB->getRHS());
+      }
+
+      // Handle ArraySectionExpr (array sections like a[0:1])
+      // Attach pointers should not contain array-sections, but currently we
+      // don't emit an error.
+      if (const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
+        const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
+        if (!RAS)
+          return false;
+        return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
+               areSemanticallyEqual(LAS->getLowerBound(),
+                                    RAS->getLowerBound()) &&
+               areSemanticallyEqual(LAS->getLength(), RAS->getLength());
       }
 
-      // Use Expr::isSameComparisonOperand for other semantic comparisons
+      // Handle CastExpr (explicit casts)
+      if (const auto *LC = dyn_cast<CastExpr>(LHS)) {
+        const auto *RC = dyn_cast<CastExpr>(RHS);
+        if (!RC)
+          return false;
+        if (LC->getCastKind() != RC->getCastKind())
+          return false;
+        return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
+      }
+
+      // Handle CXXThisExpr (this pointer)
+      if (isa<CXXThisExpr>(LHS) && isa<CXXThisExpr>(RHS))
+        return true;
+
+      // Handle IntegerLiteral (integer constants)
+      if (const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
+        const auto *RI = dyn_cast<IntegerLiteral>(RHS);
+        if (!RI)
+          return false;
+        return LI->getValue() == RI->getValue();
+      }
+
+      // Handle CharacterLiteral (character constants)
+      if (const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
+        const auto *RC = dyn_cast<CharacterLiteral>(RHS);
+        if (!RC)
+          return false;
+        return LC->getValue() == RC->getValue();
+      }
+
+      // Handle FloatingLiteral (floating point constants)
+      if (const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
+        const auto *RF = dyn_cast<FloatingLiteral>(RHS);
+        if (!RF)
+          return false;
+        // Use bitwise comparison for floating point literals
+        return LF->getValue().bitwiseIsEqual(RF->getValue());
+      }
+
+      // Handle StringLiteral (string constants)
+      if (const auto *LS = dyn_cast<StringLiteral>(LHS)) {
+        const auto *RS = dyn_cast<StringLiteral>(RHS);
+        if (!RS)
+          return false;
+        return LS->getString() == RS->getString();
+      }
+
+      // Handle CXXNullPtrLiteralExpr (nullptr)
+      if (isa<CXXNullPtrLiteralExpr>(LHS) && isa<CXXNullPtrLiteralExpr>(RHS))
+        return true;
+
+      // Handle CXXBoolLiteralExpr (true/false)
+      if (const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
+        const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
+        if (!RB)
+          return false;
+        return LB->getValue() == RB->getValue();
+      }
+
+      // Fallback for other forms - use the existing comparison method
       return Expr::isSameComparisonOperand(LHS, RHS);
     }
   };
@@ -8673,8 +8848,11 @@ class MappableExprsHandler {
           }
         };
 
-    auto &&IsMapInfoExist = [&Info, this](CodeGenFunction &CGF, const ValueDecl *VD,
-                                    const Expr *IE, bool IsDevAddr) -> bool {
+    auto &&IsMapInfoExist = [&Info, this](CodeGenFunction &CGF,
+                                          const ValueDecl *VD, const Expr *IE,
+                                          const Expr *DesiredAttachPtrExpr,
+                                          const Expr *DesiredFirstComponentExpr,
+                                          bool IsDevAddr) -> bool {
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
       // return true.
@@ -8685,19 +8863,55 @@ class MappableExprsHandler {
       if (It != Info.end()) {
         bool Found = false;
         for (auto &Data : It->second) {
-          auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
-            return MI.Components.back().getAssociatedDeclaration() == VD;
-          });
-          // If we found a map entry, signal that the pointer has to be
-          // returned and move on to the next declaration. Exclude cases where
-          // the base pointer is mapped as array subscript, array section or
-          // array shaping. The base address is passed as a pointer to base in
-          // this case (i.e. as a PTR_AND_OBJ) and cannot be used as a base
-          // for use_device_ptr list item. However, we don't use PTR_AND_OBJ
-          // mapping for any pointers when using ATTACH-style mapping.
-          if (CI != Data.end()) {
+          // Select the best candidate among all matches in this bucket, rather
+          // than stopping at the first one. This avoids accidentally picking a
+          // more complex component list (e.g., xpp[1][1]) when a simpler one
+          // (e.g., xpp[1]) exists and is the intended attach target for
+          // use_device_addr/use_device_ptr.
+          MapInfo *CI = nullptr;
+          MapInfo *ChosenFirst = nullptr;
+          MapInfo *ChosenAttach = nullptr;
+          MapInfo *ChosenFallback = nullptr;
+          for (auto &MI : Data) {
+            bool Match = MI.Components.back().getAssociatedDeclaration() == VD;
+            if (!Match)
+              continue;
+            // 1) Prefer exact match on first component (e.g., xpp[1]).
+            if (DesiredFirstComponentExpr && !MI.Components.empty() &&
+                AttachPtrExprComparator(this).areEqual(
+                    MI.Components.front().getAssociatedExpression(),
+                    DesiredFirstComponentExpr)) {
+              if (!ChosenFirst ||
+                  MI.Components.size() < ChosenFirst->Components.size())
+                ChosenFirst = &MI;
+            }
+            // 2) Next preference: exact match on attach-pointer (e.g., xpp).
+            const Expr *MIAP = getAttachPtrExpr(MI.Components);
+            if (DesiredAttachPtrExpr && AttachPtrExprComparator(this).areEqual(
+                                            MIAP, DesiredAttachPtrExpr)) {
+              if (!ChosenAttach ||
+                  MI.Components.size() < ChosenAttach->Components.size())
+                ChosenAttach = &MI;
+            }
+            // 3) Fallback: least complex among all matches.
+            if (!ChosenFallback ||
+                MI.Components.size() < ChosenFallback->Components.size())
+              ChosenFallback = &MI;
+          }
+
+          if (!CI) {
+            if (ChosenFirst) {
+              CI = ChosenFirst;
+            } else if (ChosenAttach) {
+              CI = ChosenAttach;
+            } else if (ChosenFallback) {
+              CI = ChosenFallback;
+            }
+          }
+
+          if (CI) {
             if (IsDevAddr) {
-              CI->ForDeviceAddr = IsDevAddr;
+              CI->ForDeviceAddr = true;
               CI->ReturnDevicePointer = true;
               Found = true;
               break;
@@ -8744,7 +8958,12 @@ class MappableExprsHandler {
         const ValueDecl *VD = Components.back().getAssociatedDeclaration();
         VD = cast<ValueDecl>(VD->getCanonicalDecl());
         const Expr *IE = Components.back().getAssociatedExpression();
-        if (IsMapInfoExist(CGF, VD, IE, /*IsDevAddr=*/false))
+        const Expr *DesiredAttach = getAttachPtrExpr(Components);
+        const Expr *DesiredFirst =
+            Components.empty() ? nullptr
+                               : Components.front().getAssociatedExpression();
+        if (IsMapInfoExist(CGF, VD, IE, DesiredAttach, DesiredFirst,
+                           /*IsDevAddr=*/false))
           continue;
         MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),
                    /*IsDevAddr=*/false);
@@ -8766,7 +8985,23 @@ class MappableExprsHandler {
           continue;
         VD = cast<ValueDecl>(VD->getCanonicalDecl());
         const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
-        if (IsMapInfoExist(CGF, VD, IE, /*IsDevAddr=*/true))
+        const Expr *DesiredAttach = getAttachPtrExpr(Components);
+        if (const auto *ASE_IE = dyn_cast_or_null<ArraySubscriptExpr>(
+                IE->IgnoreParenImpCasts())) {
+          const Expr *BaseIE = ASE_IE->getBase()->IgnoreParenImpCasts();
+          if (!isa<DeclRefExpr>(BaseIE)) {
+            llvm::errs() << "error: use_device_addr expects base-pointer to be "
+                            "an identifier (e.g., xpp or xpp[1]); got: ";
+            IE->dump();
+            // Continue without marking; fall back to generating a zero-size
+            // entry if needed.
+          }
+        }
+        const Expr *DesiredFirst =
+            Components.empty() ? nullptr
+                               : Components.front().getAssociatedExpression();
+        if (IsMapInfoExist(CGF, VD, IE, DesiredAttach, DesiredFirst,
+                           /*IsDevAddr=*/true))
           continue;
         MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),
                    /*IsDevAddr=*/true);
@@ -8774,27 +9009,51 @@ class MappableExprsHandler {
     }
 
     for (const auto &Data : Info) {
-      StructRangeInfoTy PartialStruct;
-      // Current struct information:
       MapCombinedInfoTy CurInfo;
-      // Current struct base information:
-      MapCombinedInfoTy StructBaseCurInfo;
       const Decl *D = Data.first;
       const ValueDecl *VD = cast_or_null<ValueDecl>(D);
+      // Group component lists by their AttachPtrExpr and process them in order
+      // of increasing complexity (nullptr first, then simple expressions like
+      // p, then more complex ones like p[0], etc.)
+      //
+      // This is similar to how generateInfoForCaptureFromClauseInfo handles
+      // grouping for target constructs.
+      std::map<const Expr *, SmallVector<MapInfo, 8>, AttachPtrExprComparator>
+          AttachPtrGroups{AttachPtrExprComparator(this)};
+
+      // Collect all MapInfo entries and group them by AttachPtrExpr
       for (const auto &M : Data.second) {
         for (const MapInfo &L : M) {
           assert(!L.Components.empty() &&
                  "Not expecting declaration with no component lists.");
 
+          const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
+          AttachPtrGroups[AttachPtrExpr].push_back(L);
+        }
+      }
+
+      // Process each group in order of their attach-pointers increasing
+      // complexity.
+      for (const auto &Entry : AttachPtrGroups) {
+        const SmallVector<MapInfo, 8> &GroupLists = Entry.second;
+        if (GroupLists.empty())
+          continue;
+
+        StructRangeInfoTy PartialStruct;
+        MapCombinedInfoTy GroupCurInfo;
+        // Current group's struct base information:
+        MapCombinedInfoTy GroupStructBaseCurInfo;
+        for (const MapInfo &L : GroupLists) {
           // Remember the current base pointer index.
-          unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
+          unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
           unsigned StructBasePointersIdx =
-              StructBaseCurInfo.BasePointers.size();
-          CurInfo.NonContigInfo.IsNonContiguous =
+              GroupStructBaseCurInfo.BasePointers.size();
+
+          GroupCurInfo.NonContigInfo.IsNonContiguous =
               L.Components.back().isNonContiguous();
           generateInfoForComponentList(
               L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
-              CurInfo, StructBaseCurInfo, PartialStruct,
+              GroupCurInfo, GroupStructBaseCurInfo, PartialStruct,
               /*IsFirstComponentList=*/false, L.IsImplicit,
               /*GenerateAllInfoForClauses*/ true, L.Mapper, L.ForDeviceAddr, VD,
               L.VarRef, /*OverlappedElements*/ {});
@@ -8802,12 +9061,12 @@ class MappableExprsHandler {
           // If this entry relates to a device pointer, set the relevant
           // declaration and add the 'return pointer' flag.
           if (L.ReturnDevicePointer) {
-            // Check whether a value was added to either CurInfo or
-            // StructBaseCurInfo and error if no value was added to either of
-            // them:
-            assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
+            // Check whether a value was added to either GroupCurInfo or
+            // GroupStructBaseCurInfo and error if no value was added to either
+            // of them:
+            assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
                     StructBasePointersIdx <
-                        StructBaseCurInfo.BasePointers.size()) &&
+                        GroupStructBaseCurInfo.BasePointers.size()) &&
                    "Unexpected number of mapped base pointers.");
 
             // Choose a base pointer index which is always valid:
@@ -8816,29 +9075,48 @@ class MappableExprsHandler {
             assert(RelevantVD &&
                    "No relevant declaration related with device pointer??");
 
-            // If StructBaseCurInfo has been updated this iteration then work on
-            // the first new entry added to it i.e. make sure that when multiple
-            // values are added to any of the lists, the first value added is
-            // being modified by the assignments below (not the last value
-            // added).
-            if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
-              StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
+            // If GroupStructBaseCurInfo has been updated this iteration then
+            // work on the first new entry added to it i.e. make sure that when
+            // multiple values are added to any of the lists, the first value
+            // added is being modified by the assignments below (not the last
+            // value added).
+            if (StructBasePointersIdx <
+                GroupStructBaseCurInfo.BasePointers.size()) {
+              GroupStructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
                   RelevantVD;
-              StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
+              GroupStructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
                   L.ForDeviceAddr ? DeviceInfoTy::Address
                                   : DeviceInfoTy::Pointer;
-              StructBaseCurInfo.Types[StructBasePointersIdx] |=
+              GroupStructBaseCurInfo.Types[StructBasePointersIdx] |=
                   OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
             } else {
-              CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
-              CurInfo.DevicePointers[CurrentBasePointersIdx] =
+              GroupCurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
+              GroupCurInfo.DevicePointers[CurrentBasePointersIdx] =
                   L.ForDeviceAddr ? DeviceInfoTy::Address
                                   : DeviceInfoTy::Pointer;
-              CurInfo.Types[CurrentBasePointersIdx] |=
+              GroupCurInfo.Types[CurrentBasePointersIdx] |=
                   OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
             }
           }
         }
+
+        // If there is an entry in PartialStruct it means we have a struct with
+        // individual members mapped. Emit an extra combined entry.
+        MapCombinedInfoTy AttachCombinedInfo;
+        if (PartialStruct.Base.isValid()) {
+          CurInfo.append(PartialStruct.PreliminaryMapData);
+          emitCombinedEntry(
+              CurInfo, AttachCombinedInfo, GroupCurInfo.Types, PartialStruct,
+              /*IsMapThis*/ !VD, OMPBuilder, VD,
+              /*OffsetForMemberOfFlag=*/0, /*NotTargetParam=*/true);
+        }
+
+        // Append this group's results to the overall CurInfo in the correct
+        // order: combined-entry -> individual-field-entries -> attach-entry
+        // First append struct base info, then component info
+        CurInfo.append(GroupStructBaseCurInfo);
+        CurInfo.append(GroupCurInfo);
+        CurInfo.append(AttachCombinedInfo);
       }
 
       // Append any pending zero-length pointers which are struct members and
@@ -8884,28 +9162,8 @@ class MappableExprsHandler {
         }
       }
 
-      // Unify entries in one list making sure the struct mapping precedes the
-      // individual fields:
-      MapCombinedInfoTy UnionCurInfo;
-      UnionCurInfo.append(StructBaseCurInfo);
-      UnionCurInfo.append(CurInfo);
-
-      // If there is an entry in PartialStruct it means we have a struct with
-      // individual members mapped. Emit an extra combined entry.
-      MapCombinedInfoTy AttachCombinedInfo;
-      if (PartialStruct.Base.isValid()) {
-        UnionCurInfo.NonContigInfo.Dims.push_back(0);
-        // Emit a combined entry:
-        emitCombinedEntry(CombinedInfo, AttachCombinedInfo, UnionCurInfo.Types,
-                          PartialStruct,
-                          /*IsMapThis*/ !VD, OMPBuilder, VD,
-                          /*OffsetForMemberOfFlag=*/0, /*NotTargetParam=*/true);
-      }
-
       // We need to append the results of this capture to what we already have.
-      CombinedInfo.append(UnionCurInfo);
-      // Append AttachCombinedInfo after UnionCurInfo
-      CombinedInfo.append(AttachCombinedInfo);
+      CombinedInfo.append(CurInfo);
     }
     // Append data for use_device_ptr clauses.
     CombinedInfo.append(UseDeviceDataCombinedInfo);
@@ -9400,7 +9658,8 @@ class MappableExprsHandler {
     //   map(ps->pt->d, ps->pt->e) | ps->pt
 
     // Group component lists by their AttachPtrExpr
-    llvm::MapVector<const Expr *, MapDataArrayTy> AttachPtrGroups;
+    std::map<const Expr *, MapDataArrayTy, AttachPtrExprComparator>
+        AttachPtrGroups{AttachPtrExprComparator(this)};
 
     for (const MapData &L : DeclComponentListsFromClauses) {
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components =

>From 788eb06e7ecc3c54c2c3cd21d8ce8e71046e4a9b Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 11 Aug 2025 05:25:55 -0700
Subject: [PATCH 59/66] Fix matching of use_device_ptr/addr with existing map
 clauses.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 93 ++++++++-------------------
 1 file changed, 28 insertions(+), 65 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 1594b77a6889c..0f6b5ccf603d7 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8851,7 +8851,6 @@ class MappableExprsHandler {
     auto &&IsMapInfoExist = [&Info, this](CodeGenFunction &CGF,
                                           const ValueDecl *VD, const Expr *IE,
                                           const Expr *DesiredAttachPtrExpr,
-                                          const Expr *DesiredFirstComponentExpr,
                                           bool IsDevAddr) -> bool {
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
@@ -8863,51 +8862,20 @@ class MappableExprsHandler {
       if (It != Info.end()) {
         bool Found = false;
         for (auto &Data : It->second) {
-          // Select the best candidate among all matches in this bucket, rather
-          // than stopping at the first one. This avoids accidentally picking a
-          // more complex component list (e.g., xpp[1][1]) when a simpler one
-          // (e.g., xpp[1]) exists and is the intended attach target for
-          // use_device_addr/use_device_ptr.
           MapInfo *CI = nullptr;
-          MapInfo *ChosenFirst = nullptr;
-          MapInfo *ChosenAttach = nullptr;
-          MapInfo *ChosenFallback = nullptr;
-          for (auto &MI : Data) {
-            bool Match = MI.Components.back().getAssociatedDeclaration() == VD;
-            if (!Match)
-              continue;
-            // 1) Prefer exact match on first component (e.g., xpp[1]).
-            if (DesiredFirstComponentExpr && !MI.Components.empty() &&
-                AttachPtrExprComparator(this).areEqual(
-                    MI.Components.front().getAssociatedExpression(),
-                    DesiredFirstComponentExpr)) {
-              if (!ChosenFirst ||
-                  MI.Components.size() < ChosenFirst->Components.size())
-                ChosenFirst = &MI;
-            }
-            // 2) Next preference: exact match on attach-pointer (e.g., xpp).
-            const Expr *MIAP = getAttachPtrExpr(MI.Components);
-            if (DesiredAttachPtrExpr && AttachPtrExprComparator(this).areEqual(
-                                            MIAP, DesiredAttachPtrExpr)) {
-              if (!ChosenAttach ||
-                  MI.Components.size() < ChosenAttach->Components.size())
-                ChosenAttach = &MI;
-            }
-            // 3) Fallback: least complex among all matches.
-            if (!ChosenFallback ||
-                MI.Components.size() < ChosenFallback->Components.size())
-              ChosenFallback = &MI;
-          }
+          // We potentially have multiple maps for the same decl. We need to
+          // only consider those for which the attach-ptr matches the desired
+          // attach-ptr. If found, return the first such map.
+          auto *It = llvm::find_if(Data, [&](const MapInfo &MI) {
+            if (MI.Components.back().getAssociatedDeclaration() != VD)
+              return false;
 
-          if (!CI) {
-            if (ChosenFirst) {
-              CI = ChosenFirst;
-            } else if (ChosenAttach) {
-              CI = ChosenAttach;
-            } else if (ChosenFallback) {
-              CI = ChosenFallback;
-            }
-          }
+            return AttachPtrExprComparator(this).areEqual(
+                getAttachPtrExpr(MI.Components), DesiredAttachPtrExpr);
+          });
+
+          if (It != Data.end())
+            CI = &*It;
 
           if (CI) {
             if (IsDevAddr) {
@@ -8958,11 +8926,13 @@ class MappableExprsHandler {
         const ValueDecl *VD = Components.back().getAssociatedDeclaration();
         VD = cast<ValueDecl>(VD->getCanonicalDecl());
         const Expr *IE = Components.back().getAssociatedExpression();
-        const Expr *DesiredAttach = getAttachPtrExpr(Components);
-        const Expr *DesiredFirst =
-            Components.empty() ? nullptr
-                               : Components.front().getAssociatedExpression();
-        if (IsMapInfoExist(CGF, VD, IE, DesiredAttach, DesiredFirst,
+        // For use_device_ptr, we match an existing map clause if its attach-ptr
+        // is same as the use_device_ptr operand. e.g.
+        //   map(p[1]) use_device_ptr(p)     // match
+        //   map(ps->a) use_device_ptr(ps)   // match
+        //   map(p) use_device_ptr(p)        // no match
+        const Expr *UDPFirstExpr = Components.front().getAssociatedExpression();
+        if (IsMapInfoExist(CGF, VD, IE, /*DesiredAttachPtrExpr=*/UDPFirstExpr,
                            /*IsDevAddr=*/false))
           continue;
         MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),
@@ -8985,22 +8955,15 @@ class MappableExprsHandler {
           continue;
         VD = cast<ValueDecl>(VD->getCanonicalDecl());
         const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
-        const Expr *DesiredAttach = getAttachPtrExpr(Components);
-        if (const auto *ASE_IE = dyn_cast_or_null<ArraySubscriptExpr>(
-                IE->IgnoreParenImpCasts())) {
-          const Expr *BaseIE = ASE_IE->getBase()->IgnoreParenImpCasts();
-          if (!isa<DeclRefExpr>(BaseIE)) {
-            llvm::errs() << "error: use_device_addr expects base-pointer to be "
-                            "an identifier (e.g., xpp or xpp[1]); got: ";
-            IE->dump();
-            // Continue without marking; fall back to generating a zero-size
-            // entry if needed.
-          }
-        }
-        const Expr *DesiredFirst =
-            Components.empty() ? nullptr
-                               : Components.front().getAssociatedExpression();
-        if (IsMapInfoExist(CGF, VD, IE, DesiredAttach, DesiredFirst,
+        // 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
+        //   map(p) use_device_addr(p[0])      // no match
+        const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
+        if (IsMapInfoExist(CGF, VD, IE,
+                           /*DesiredAttachPtrExpr=*/UDAAttachPtrExpr,
                            /*IsDevAddr=*/true))
           continue;
         MapInfoGen(CGF, IE, VD, Components, C->isImplicit(),

>From 3dd11c1a66781cfe9a89be190e3e836ef5635e8f Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 11 Aug 2025 16:46:30 -0700
Subject: [PATCH 60/66] Fix non-conforming tests.

---
 .../declare_mapper_nested_default_mappers.cpp |  2 +-
 .../mapping/declare_mapper_nested_mappers.cpp |  3 ++-
 .../target_derefence_array_pointrs.cpp        | 19 ++++++++++---------
 offload/test/mapping/target_has_device_addr.c |  4 ++--
 4 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/offload/test/mapping/declare_mapper_nested_default_mappers.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
index c6c5657ae6166..78b1fff7feedc 100644
--- a/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
+++ b/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
@@ -44,7 +44,7 @@ int main() {
 
   int spp00fa = -1, spp00fca = -1, spp00fb_r = -1;
   __intptr_t p = reinterpret_cast<__intptr_t>(&x[0]);
-#pragma omp target map(tofrom: spp[0][0]) firstprivate(p)                           \
+#pragma omp target map(tofrom: spp[0][0]) map(alloc: spp[0]) firstprivate(p) \
                    map(from: spp00fa, spp00fca, spp00fb_r)
   {
     spp00fa = spp[0][0].f.a;
diff --git a/offload/test/mapping/declare_mapper_nested_mappers.cpp b/offload/test/mapping/declare_mapper_nested_mappers.cpp
index a9e3f05e0f5fd..cdfc31b257d1d 100644
--- a/offload/test/mapping/declare_mapper_nested_mappers.cpp
+++ b/offload/test/mapping/declare_mapper_nested_mappers.cpp
@@ -42,7 +42,8 @@ int main() {
   int spp00fa = -1, spp00fb_r = -1, spp00fg1 = -1, spp00fg_r = -1;
   __intptr_t p = reinterpret_cast<__intptr_t>(&x[0]),
              p1 = reinterpret_cast<__intptr_t>(&y[0]);
-#pragma omp target map(tofrom : spp[0][0]) firstprivate(p, p1)                  \
+#pragma omp target map(tofrom : spp[0][0]) map(alloc:spp[0]) \
+                   firstprivate(p, p1)                  \
                    map(from: spp00fa, spp00fb_r, spp00fg1, spp00fg_r)
   {
     spp00fa = spp[0][0].f.a;
diff --git a/offload/test/mapping/target_derefence_array_pointrs.cpp b/offload/test/mapping/target_derefence_array_pointrs.cpp
index a6dd4069a8f58..3050e5b947439 100644
--- a/offload/test/mapping/target_derefence_array_pointrs.cpp
+++ b/offload/test/mapping/target_derefence_array_pointrs.cpp
@@ -18,23 +18,23 @@ void foo(int **t1d) {
 
   for (j = 0; j < 3; j++)
     (*t1d)[j] = 0;
-#pragma omp target map(tofrom : (*t1d)[0 : 3])
+#pragma omp target map(tofrom : (*t1d)[0 : 3]) map(alloc: *t1d)
   { (*t1d)[1] = 1; }
   // CHECK: 1
   printf("%d\n", (*t1d)[1]);
-#pragma omp target map(tofrom : (**t2d)[0 : 3])
+#pragma omp target map(tofrom : (**t2d)[0 : 3]) map(alloc:**t2d, *t2d)
   { (**t2d)[1] = 2; }
   // CHECK: 2
   printf("%d\n", (**t2d)[1]);
-#pragma omp target map(tofrom : (***t3d)[0 : 3])
+#pragma omp target map(tofrom : (***t3d)[0 : 3]) map(alloc:***t3d, **t3d, *t3d)
   { (***t3d)[1] = 3; }
   // CHECK: 3
   printf("%d\n", (***t3d)[1]);
-#pragma omp target map(tofrom : (**t1d))
+#pragma omp target map(tofrom : (**t1d)) map(alloc: *t1d)
   { (*t1d)[0] = 4; }
   // CHECK: 4
   printf("%d\n", (*t1d)[0]);
-#pragma omp target map(tofrom : (*(*(t1d + a) + b)))
+#pragma omp target map(tofrom : (*(*(t1d + a) + b))) map(to: *(t1d + a))
   { *(*(t1d + a) + b) = 5; }
   // CHECK: 5
   printf("%d\n", *(*(t1d + a) + b));
@@ -49,7 +49,7 @@ void bar() {
   for (int i = 0; i < 3; i++) {
     (**a)[1] = i;
   }
-#pragma omp target map((**a)[ : 3])
+#pragma omp target map((**a)[ : 3]) map(alloc: **a, *a)
   {
     (**a)[1] = 6;
     // CHECK: 6
@@ -73,7 +73,8 @@ void zoo(int **f, SSA *sa) {
   *(f + sa->i + 1) = t;
   *(sa->sa->i + *(f + sa->i + 1)) = 4;
   printf("%d\n", *(sa->sa->i + *(1 + sa->i + f)));
-#pragma omp target map(sa, *(sa->sa->i + *(1 + sa->i + f)))
+#pragma omp target map(*(sa->sa->i + *(1 + sa->i + f))) map(alloc: sa->sa) \
+                   map(to:sa->i) map(to:sa->sa->i) map(to:*(1 + sa->i + f))
   { *(sa->sa->i + *(1 + sa->i + f)) = 7; }
   // CHECK: 7
   printf("%d\n", *(sa->sa->i + *(1 + sa->i + f)));
@@ -87,13 +88,13 @@ void xoo() {
 
 void yoo(int **x) {
   *x = (int *)malloc(2 * sizeof(int));
-#pragma omp target map(**x)
+#pragma omp target map(**x) map(alloc: *x)
   {
     **x = 8;
     // CHECK: 8
     printf("%d\n", **x);
   }
-#pragma omp target map(*(*x + 1))
+#pragma omp target map(*(*x + 1)) map(alloc: *x)
   {
     *(*x + 1) = 9;
     // CHECK: 9
diff --git a/offload/test/mapping/target_has_device_addr.c b/offload/test/mapping/target_has_device_addr.c
index e8bfff868c7ed..efc7bbc70052d 100644
--- a/offload/test/mapping/target_has_device_addr.c
+++ b/offload/test/mapping/target_has_device_addr.c
@@ -66,8 +66,8 @@ void zoo() {
   short **xpp = &xp[0];
 
   x[1] = 111;
-#pragma omp target data map(tofrom : xpp[1][1]) use_device_addr(xpp[1][1])
-#pragma omp target has_device_addr(xpp[1][1])
+#pragma omp target data map(tofrom : xpp[1][1]) map(xpp[1]) use_device_addr(xpp[1])
+#pragma omp target has_device_addr(xpp[1])
   {
     xpp[1][1] = 222;
     // CHECK: 222

>From af72f9796bb83626015b42ebaae6215bc0f6243b Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 11 Aug 2025 16:45:11 -0700
Subject: [PATCH 61/66] Apply clang-format.

---
 .../declare_mapper_nested_default_mappers.cpp |  4 ++--
 .../mapping/declare_mapper_nested_mappers.cpp |  5 ++---
 offload/test/mapping/ptr_and_obj_motion.c     |  2 +-
 .../target_derefence_array_pointrs.cpp        | 21 ++++++++++---------
 offload/test/mapping/target_has_device_addr.c |  3 ++-
 5 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/offload/test/mapping/declare_mapper_nested_default_mappers.cpp b/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
index 78b1fff7feedc..45fd042aedb0e 100644
--- a/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
+++ b/offload/test/mapping/declare_mapper_nested_default_mappers.cpp
@@ -44,8 +44,8 @@ int main() {
 
   int spp00fa = -1, spp00fca = -1, spp00fb_r = -1;
   __intptr_t p = reinterpret_cast<__intptr_t>(&x[0]);
-#pragma omp target map(tofrom: spp[0][0]) map(alloc: spp[0]) firstprivate(p) \
-                   map(from: spp00fa, spp00fca, spp00fb_r)
+#pragma omp target map(tofrom : spp[0][0]) map(alloc : spp[0]) firstprivate(p) \
+    map(from : spp00fa, spp00fca, spp00fb_r)
   {
     spp00fa = spp[0][0].f.a;
     spp00fca = spp[0][0].f.c.a;
diff --git a/offload/test/mapping/declare_mapper_nested_mappers.cpp b/offload/test/mapping/declare_mapper_nested_mappers.cpp
index cdfc31b257d1d..a59ed6980ec4c 100644
--- a/offload/test/mapping/declare_mapper_nested_mappers.cpp
+++ b/offload/test/mapping/declare_mapper_nested_mappers.cpp
@@ -42,9 +42,8 @@ int main() {
   int spp00fa = -1, spp00fb_r = -1, spp00fg1 = -1, spp00fg_r = -1;
   __intptr_t p = reinterpret_cast<__intptr_t>(&x[0]),
              p1 = reinterpret_cast<__intptr_t>(&y[0]);
-#pragma omp target map(tofrom : spp[0][0]) map(alloc:spp[0]) \
-                   firstprivate(p, p1)                  \
-                   map(from: spp00fa, spp00fb_r, spp00fg1, spp00fg_r)
+#pragma omp target map(tofrom : spp[0][0]) map(alloc : spp[0])                 \
+    firstprivate(p, p1) map(from : spp00fa, spp00fb_r, spp00fg1, spp00fg_r)
   {
     spp00fa = spp[0][0].f.a;
     spp00fb_r = spp[0][0].f.b == reinterpret_cast<void *>(p) ? 1 : 0;
diff --git a/offload/test/mapping/ptr_and_obj_motion.c b/offload/test/mapping/ptr_and_obj_motion.c
index 224b59654ab9a..a94c07aadc1bc 100644
--- a/offload/test/mapping/ptr_and_obj_motion.c
+++ b/offload/test/mapping/ptr_and_obj_motion.c
@@ -17,7 +17,7 @@ void init(double vertexx[]) {
 }
 
 void change(DV *dvptr) {
-#pragma omp target map(dvptr->dataptr[0 : 100]) map(alloc: dvptr->dataptr)
+#pragma omp target map(dvptr->dataptr[0 : 100]) map(alloc : dvptr -> dataptr)
   {
     printf("In change: %lf, expected 77.0\n", dvptr->dataptr[77]);
     dvptr->dataptr[77] += 1.0;
diff --git a/offload/test/mapping/target_derefence_array_pointrs.cpp b/offload/test/mapping/target_derefence_array_pointrs.cpp
index 3050e5b947439..d213c87443634 100644
--- a/offload/test/mapping/target_derefence_array_pointrs.cpp
+++ b/offload/test/mapping/target_derefence_array_pointrs.cpp
@@ -18,23 +18,24 @@ void foo(int **t1d) {
 
   for (j = 0; j < 3; j++)
     (*t1d)[j] = 0;
-#pragma omp target map(tofrom : (*t1d)[0 : 3]) map(alloc: *t1d)
+#pragma omp target map(tofrom : (*t1d)[0 : 3]) map(alloc : *t1d)
   { (*t1d)[1] = 1; }
   // CHECK: 1
   printf("%d\n", (*t1d)[1]);
-#pragma omp target map(tofrom : (**t2d)[0 : 3]) map(alloc:**t2d, *t2d)
+#pragma omp target map(tofrom : (**t2d)[0 : 3]) map(alloc : **t2d, *t2d)
   { (**t2d)[1] = 2; }
   // CHECK: 2
   printf("%d\n", (**t2d)[1]);
-#pragma omp target map(tofrom : (***t3d)[0 : 3]) map(alloc:***t3d, **t3d, *t3d)
+#pragma omp target map(tofrom : (***t3d)[0 : 3])                               \
+    map(alloc : ***t3d, **t3d, *t3d)
   { (***t3d)[1] = 3; }
   // CHECK: 3
   printf("%d\n", (***t3d)[1]);
-#pragma omp target map(tofrom : (**t1d)) map(alloc: *t1d)
+#pragma omp target map(tofrom : (**t1d)) map(alloc : *t1d)
   { (*t1d)[0] = 4; }
   // CHECK: 4
   printf("%d\n", (*t1d)[0]);
-#pragma omp target map(tofrom : (*(*(t1d + a) + b))) map(to: *(t1d + a))
+#pragma omp target map(tofrom : (*(*(t1d + a) + b))) map(to : *(t1d + a))
   { *(*(t1d + a) + b) = 5; }
   // CHECK: 5
   printf("%d\n", *(*(t1d + a) + b));
@@ -49,7 +50,7 @@ void bar() {
   for (int i = 0; i < 3; i++) {
     (**a)[1] = i;
   }
-#pragma omp target map((**a)[ : 3]) map(alloc: **a, *a)
+#pragma omp target map((**a)[ : 3]) map(alloc : **a, *a)
   {
     (**a)[1] = 6;
     // CHECK: 6
@@ -73,8 +74,8 @@ void zoo(int **f, SSA *sa) {
   *(f + sa->i + 1) = t;
   *(sa->sa->i + *(f + sa->i + 1)) = 4;
   printf("%d\n", *(sa->sa->i + *(1 + sa->i + f)));
-#pragma omp target map(*(sa->sa->i + *(1 + sa->i + f))) map(alloc: sa->sa) \
-                   map(to:sa->i) map(to:sa->sa->i) map(to:*(1 + sa->i + f))
+#pragma omp target map(*(sa->sa->i + *(1 + sa->i + f))) map(alloc : sa->sa)    \
+    map(to : sa->i) map(to : sa->sa->i) map(to : *(1 + sa->i + f))
   { *(sa->sa->i + *(1 + sa->i + f)) = 7; }
   // CHECK: 7
   printf("%d\n", *(sa->sa->i + *(1 + sa->i + f)));
@@ -88,13 +89,13 @@ void xoo() {
 
 void yoo(int **x) {
   *x = (int *)malloc(2 * sizeof(int));
-#pragma omp target map(**x) map(alloc: *x)
+#pragma omp target map(**x) map(alloc : *x)
   {
     **x = 8;
     // CHECK: 8
     printf("%d\n", **x);
   }
-#pragma omp target map(*(*x + 1)) map(alloc: *x)
+#pragma omp target map(*(*x + 1)) map(alloc : *x)
   {
     *(*x + 1) = 9;
     // CHECK: 9
diff --git a/offload/test/mapping/target_has_device_addr.c b/offload/test/mapping/target_has_device_addr.c
index efc7bbc70052d..f238832c44054 100644
--- a/offload/test/mapping/target_has_device_addr.c
+++ b/offload/test/mapping/target_has_device_addr.c
@@ -66,7 +66,8 @@ void zoo() {
   short **xpp = &xp[0];
 
   x[1] = 111;
-#pragma omp target data map(tofrom : xpp[1][1]) map(xpp[1]) use_device_addr(xpp[1])
+#pragma omp target data map(tofrom : xpp[1][1]) map(xpp[1])                    \
+    use_device_addr(xpp[1])
 #pragma omp target has_device_addr(xpp[1])
   {
     xpp[1][1] = 222;

>From 2b3157228b77f73c113cf4726ee2eca4da09ee22 Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 11 Aug 2025 17:11:51 -0700
Subject: [PATCH 62/66] Add a fixme.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 98 ++++++++++++++++++++++++---
 1 file changed, 87 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 0f6b5ccf603d7..2fd046f36c42d 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8198,10 +8198,6 @@ class MappableExprsHandler {
     if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
       Address AttachPteeBeginAddr = FinalLowestElem;
 
-      assert(AttachPtrAddr.isValid() && "Attach ptr address is not valid.");
-      assert(AttachPteeBeginAddr.isValid() &&
-             "Attach ptee begin address is not valid.");
-
       if (PartialStruct.Base.isValid()) {
         // We're populating PartialStruct, delay ATTACH entry addition until
         // after emitCombinedEntry.
@@ -8619,12 +8615,16 @@ class MappableExprsHandler {
   static std::pair<const Expr *, std::optional<size_t>> findAttachPtrExpr(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
+    llvm::errs() << "DEBUG: [findAttachPtrExpr] Called with " << Components.size() << " components\n";
+    
     const auto *Begin = Components.begin();
 
     // If we only have a single component, we have a map like "map(p)", which
     // cannot have a base-pointer.
-    if (Components.size() < 2)
+    if (Components.size() < 2) {
+      llvm::errs() << "DEBUG: [findAttachPtrExpr] Only " << Components.size() << " components, returning nullptr\n";
       return {nullptr, std::nullopt};
+    }
 
     // To find the attach base-pointer, we start with the second component,
     // stripping away one component at a time, until we reach a pointer Expr
@@ -8632,23 +8632,36 @@ class MappableExprsHandler {
     // attach base-pointer for the component list.
     for (size_t I = 1; I < Components.size(); ++I) {
       const Expr *CurExpr = Components[I].getAssociatedExpression();
+      llvm::errs() << "DEBUG: [findAttachPtrExpr] Checking component " << I << ": ";
+      if (CurExpr) {
+        CurExpr->dump();
+        llvm::errs() << "DEBUG: [findAttachPtrExpr] Type: " << getComponentExprElementType(CurExpr)->getCanonicalTypeInternal().getAsString() << "\n";
+      } else {
+        llvm::errs() << "nullptr\n";
+      }
       if (!CurExpr)
         break;
 
       // If CurExpr is something like `p + 10`, we need to ignore it, since
       // we are looking for `p`.
-      if (isa<BinaryOperator>(CurExpr))
+      if (isa<BinaryOperator>(CurExpr)) {
+        llvm::errs() << "DEBUG: [findAttachPtrExpr] Skipping BinaryOperator\n";
         continue;
+      }
 
       // Keep going until we reach an Expr of pointer type.
       QualType CurType = getComponentExprElementType(CurExpr);
-      if (!CurType->isPointerType())
+      if (!CurType->isPointerType()) {
+        llvm::errs() << "DEBUG: [findAttachPtrExpr] Not a pointer type, continuing\n";
         continue;
+      }
 
       // We have found a pointer Expr. This must be the attach pointer.
+      llvm::errs() << "DEBUG: [findAttachPtrExpr] Found attach pointer at component " << I << "\n";
       return {CurExpr, Components.size() - I};
     }
 
+    llvm::errs() << "DEBUG: [findAttachPtrExpr] No attach pointer found\n";
     return {nullptr, std::nullopt};
   }
 
@@ -8852,6 +8865,16 @@ class MappableExprsHandler {
                                           const ValueDecl *VD, const Expr *IE,
                                           const Expr *DesiredAttachPtrExpr,
                                           bool IsDevAddr) -> bool {
+      // Debug: Print what we're looking for
+      llvm::errs() << "DEBUG: [IsMapInfoExist] VD: " << VD->getNameAsString() 
+                   << ", IsDevAddr: " << IsDevAddr 
+                   << ", DesiredAttachPtrExpr: ";
+      if (DesiredAttachPtrExpr) {
+        DesiredAttachPtrExpr->dump();
+      } else {
+        llvm::errs() << "nullptr\n";
+      }
+      
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
       // return true.
@@ -8869,9 +8892,20 @@ class MappableExprsHandler {
           auto *It = llvm::find_if(Data, [&](const MapInfo &MI) {
             if (MI.Components.back().getAssociatedDeclaration() != VD)
               return false;
-
-            return AttachPtrExprComparator(this).areEqual(
-                getAttachPtrExpr(MI.Components), DesiredAttachPtrExpr);
+ 
+            // Debug: Print what we're checking against
+            const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
+            llvm::errs() << "DEBUG: [IsMapInfoExist] Checking map clause with attach-ptr: ";
+            if (MapAttachPtr) {
+              MapAttachPtr->dump();
+            } else {
+              llvm::errs() << "nullptr\n";
+            }
+            
+            bool Match = AttachPtrExprComparator(this).areEqual(
+                MapAttachPtr, DesiredAttachPtrExpr);
+            llvm::errs() << "DEBUG: [IsMapInfoExist] Match result: " << Match << "\n";
+            return Match;
           });
 
           if (It != Data.end())
@@ -8932,6 +8966,8 @@ class MappableExprsHandler {
         //   map(ps->a) use_device_ptr(ps)   // match
         //   map(p) use_device_ptr(p)        // no match
         const Expr *UDPFirstExpr = Components.front().getAssociatedExpression();
+        llvm::errs() << "DEBUG: [use_device_ptr] First expression: ";
+        UDPFirstExpr->dump();
         if (IsMapInfoExist(CGF, VD, IE, /*DesiredAttachPtrExpr=*/UDPFirstExpr,
                            /*IsDevAddr=*/false))
           continue;
@@ -8955,13 +8991,42 @@ class MappableExprsHandler {
           continue;
         VD = cast<ValueDecl>(VD->getCanonicalDecl());
         const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
+        if (const auto *ASE_IE = dyn_cast_or_null<ArraySubscriptExpr>(
+                IE->IgnoreParenImpCasts())) {
+          const Expr *BaseIE = ASE_IE->getBase()->IgnoreParenImpCasts();
+          if (!isa<DeclRefExpr>(BaseIE)) {
+            llvm::errs() << "error: use_device_addr expects base-pointer to be "
+                            "an identifier (e.g., xpp or xpp[1]); got: ";
+            IE->dump();
+            // Continue without marking; fall back to generating a zero-size
+            // entry if needed.
+          }
+        }
         // 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
         //   map(p) use_device_addr(p[0])      // no match
+        //   map(pp) use_device_addr(pp[0][0]) // no match
+        const Expr *UDAFullExpr = Components.front().getAssociatedExpression();
+        llvm::errs() << "DEBUG: [use_device_addr] Full expression: ";
+        UDAFullExpr->dump();
+        llvm::errs() << "DEBUG: [use_device_addr] Components size: " << Components.size() << "\n";
+        for (size_t i = 0; i < Components.size(); ++i) {
+          llvm::errs() << "DEBUG: [use_device_addr] Component " << i << ": ";
+          Components[i].getAssociatedExpression()->dump();
+        }
+        // FIXME: getAttachPtrExpr does not work on use_device_addr, since
+        // the component-list only contains one component. We need to move
+        // attach-ptr calculation to the Sema phase.
         const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
+        llvm::errs() << "DEBUG: [use_device_addr] Attach-ptr from getAttachPtrExpr: ";
+        if (UDAAttachPtrExpr) {
+          UDAAttachPtrExpr->dump();
+        } else {
+          llvm::errs() << "nullptr\n";
+        }
         if (IsMapInfoExist(CGF, VD, IE,
                            /*DesiredAttachPtrExpr=*/UDAAttachPtrExpr,
                            /*IsDevAddr=*/true))
@@ -9707,12 +9772,23 @@ class MappableExprsHandler {
           // etc.), it is not an overlapping.
           // Same, if one component is a base and another component is a
           // dereferenced pointer memberexpr with the same base.
+          // 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
+          const Expr *AttachPtr1 = getAttachPtrExpr(Components);
+          const Expr *AttachPtr2 = getAttachPtrExpr(Components1);
           if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
               (std::prev(It)->getAssociatedDeclaration() &&
                std::prev(It)
                    ->getAssociatedDeclaration()
                    ->getType()
-                   ->isPointerType()) ||
+                   ->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
+               !(AttachPtr1 &&
+                 AttachPtr2 &&
+                 AttachPtr1 == AttachPtr2)) ||*/
               (It->getAssociatedDeclaration() &&
                It->getAssociatedDeclaration()->getType()->isPointerType() &&
                std::next(It) != CE && std::next(It) != SE))

>From dcd65fc1c33dce8c495776f1a572e4fdfdbcb6ae Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Mon, 11 Aug 2025 18:13:06 -0700
Subject: [PATCH 63/66] Remove debug-prints

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 2fd046f36c42d..2fc0fbd055a9f 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9009,24 +9009,10 @@ class MappableExprsHandler {
         //   map(ps->a) use_device_addr(ps->b) // match
         //   map(p) use_device_addr(p[0])      // no match
         //   map(pp) use_device_addr(pp[0][0]) // no match
-        const Expr *UDAFullExpr = Components.front().getAssociatedExpression();
-        llvm::errs() << "DEBUG: [use_device_addr] Full expression: ";
-        UDAFullExpr->dump();
-        llvm::errs() << "DEBUG: [use_device_addr] Components size: " << Components.size() << "\n";
-        for (size_t i = 0; i < Components.size(); ++i) {
-          llvm::errs() << "DEBUG: [use_device_addr] Component " << i << ": ";
-          Components[i].getAssociatedExpression()->dump();
-        }
         // FIXME: getAttachPtrExpr does not work on use_device_addr, since
         // the component-list only contains one component. We need to move
         // attach-ptr calculation to the Sema phase.
         const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
-        llvm::errs() << "DEBUG: [use_device_addr] Attach-ptr from getAttachPtrExpr: ";
-        if (UDAAttachPtrExpr) {
-          UDAAttachPtrExpr->dump();
-        } else {
-          llvm::errs() << "nullptr\n";
-        }
         if (IsMapInfoExist(CGF, VD, IE,
                            /*DesiredAttachPtrExpr=*/UDAAttachPtrExpr,
                            /*IsDevAddr=*/true))

>From cb21ea42d85cb6a307ea35004ffffd950e26b57a Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Wed, 13 Aug 2025 07:48:57 -0700
Subject: [PATCH 64/66] Use a lambda to avoid uninitialized TgtPteeBegin.

---
 offload/libomptarget/omptarget.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 4b2200b6ebaa5..32e89cc75efc9 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -823,10 +823,13 @@ int processAttachEntries(DeviceTy &Device, AttachInfoTy &AttachInfo,
 
     // Get device version of the pointee (e.g., &p[10]) first, as we can
     // release its TPR after extracting the pointer value.
-    void *TgtPteeBegin;
-    if (auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee"))
-      TgtPteeBegin = PteeTPROpt->TargetPointer;
-    else
+    void *TgtPteeBegin = [&]() -> void * {
+      if (auto PteeTPROpt = LookupTargetPointer(HstPteeBegin, 0, "pointee"))
+        return PteeTPROpt->TargetPointer;
+      return nullptr;
+    }();
+
+    if (!TgtPteeBegin)
       continue;
 
     // Get device version of the pointer (e.g., &p) next. We need to keep its

>From 63531f88b8549398bd145089867d1a841465430b Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Thu, 14 Aug 2025 13:44:56 -0700
Subject: [PATCH 65/66] Remove debug prints. Update some tests.

---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         |  61 +--
 clang/test/OpenMP/target_data_codegen.cpp     | 141 ++---
 .../OpenMP/target_data_map_codegen_hold.cpp   | 488 +++++++-----------
 ...ta_map_pointer_array_subscript_codegen.cpp |  34 +-
 ...et_map_array_section_no_length_codegen.cpp | 292 ++++++-----
 ...arget_map_both_pointer_pointee_codegen.cpp |  14 +-
 ...ap_both_pointer_pointee_codegen_global.cpp |  14 +-
 clang/test/OpenMP/target_map_codegen_18.inc   | 135 ++---
 clang/test/OpenMP/target_map_codegen_20.cpp   |  28 +-
 clang/test/OpenMP/target_map_codegen_23.cpp   | 286 +++++-----
 ...get_map_pointer_defalut_mapper_codegen.cpp |  31 +-
 11 files changed, 738 insertions(+), 786 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 2fc0fbd055a9f..173eef84093d9 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -8615,16 +8615,10 @@ class MappableExprsHandler {
   static std::pair<const Expr *, std::optional<size_t>> findAttachPtrExpr(
       OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
 
-    llvm::errs() << "DEBUG: [findAttachPtrExpr] Called with " << Components.size() << " components\n";
-    
-    const auto *Begin = Components.begin();
-
     // If we only have a single component, we have a map like "map(p)", which
     // cannot have a base-pointer.
-    if (Components.size() < 2) {
-      llvm::errs() << "DEBUG: [findAttachPtrExpr] Only " << Components.size() << " components, returning nullptr\n";
+    if (Components.size() < 2)
       return {nullptr, std::nullopt};
-    }
 
     // To find the attach base-pointer, we start with the second component,
     // stripping away one component at a time, until we reach a pointer Expr
@@ -8632,36 +8626,23 @@ class MappableExprsHandler {
     // attach base-pointer for the component list.
     for (size_t I = 1; I < Components.size(); ++I) {
       const Expr *CurExpr = Components[I].getAssociatedExpression();
-      llvm::errs() << "DEBUG: [findAttachPtrExpr] Checking component " << I << ": ";
-      if (CurExpr) {
-        CurExpr->dump();
-        llvm::errs() << "DEBUG: [findAttachPtrExpr] Type: " << getComponentExprElementType(CurExpr)->getCanonicalTypeInternal().getAsString() << "\n";
-      } else {
-        llvm::errs() << "nullptr\n";
-      }
       if (!CurExpr)
         break;
 
       // If CurExpr is something like `p + 10`, we need to ignore it, since
       // we are looking for `p`.
-      if (isa<BinaryOperator>(CurExpr)) {
-        llvm::errs() << "DEBUG: [findAttachPtrExpr] Skipping BinaryOperator\n";
+      if (isa<BinaryOperator>(CurExpr))
         continue;
-      }
 
       // Keep going until we reach an Expr of pointer type.
       QualType CurType = getComponentExprElementType(CurExpr);
-      if (!CurType->isPointerType()) {
-        llvm::errs() << "DEBUG: [findAttachPtrExpr] Not a pointer type, continuing\n";
+      if (!CurType->isPointerType())
         continue;
-      }
 
       // We have found a pointer Expr. This must be the attach pointer.
-      llvm::errs() << "DEBUG: [findAttachPtrExpr] Found attach pointer at component " << I << "\n";
       return {CurExpr, Components.size() - I};
     }
 
-    llvm::errs() << "DEBUG: [findAttachPtrExpr] No attach pointer found\n";
     return {nullptr, std::nullopt};
   }
 
@@ -8865,16 +8846,6 @@ class MappableExprsHandler {
                                           const ValueDecl *VD, const Expr *IE,
                                           const Expr *DesiredAttachPtrExpr,
                                           bool IsDevAddr) -> bool {
-      // Debug: Print what we're looking for
-      llvm::errs() << "DEBUG: [IsMapInfoExist] VD: " << VD->getNameAsString() 
-                   << ", IsDevAddr: " << IsDevAddr 
-                   << ", DesiredAttachPtrExpr: ";
-      if (DesiredAttachPtrExpr) {
-        DesiredAttachPtrExpr->dump();
-      } else {
-        llvm::errs() << "nullptr\n";
-      }
-      
       // We potentially have map information for this declaration already.
       // Look for the first set of components that refer to it. If found,
       // return true.
@@ -8892,19 +8863,11 @@ class MappableExprsHandler {
           auto *It = llvm::find_if(Data, [&](const MapInfo &MI) {
             if (MI.Components.back().getAssociatedDeclaration() != VD)
               return false;
- 
+
             // Debug: Print what we're checking against
             const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
-            llvm::errs() << "DEBUG: [IsMapInfoExist] Checking map clause with attach-ptr: ";
-            if (MapAttachPtr) {
-              MapAttachPtr->dump();
-            } else {
-              llvm::errs() << "nullptr\n";
-            }
-            
             bool Match = AttachPtrExprComparator(this).areEqual(
                 MapAttachPtr, DesiredAttachPtrExpr);
-            llvm::errs() << "DEBUG: [IsMapInfoExist] Match result: " << Match << "\n";
             return Match;
           });
 
@@ -8966,8 +8929,6 @@ class MappableExprsHandler {
         //   map(ps->a) use_device_ptr(ps)   // match
         //   map(p) use_device_ptr(p)        // no match
         const Expr *UDPFirstExpr = Components.front().getAssociatedExpression();
-        llvm::errs() << "DEBUG: [use_device_ptr] First expression: ";
-        UDPFirstExpr->dump();
         if (IsMapInfoExist(CGF, VD, IE, /*DesiredAttachPtrExpr=*/UDPFirstExpr,
                            /*IsDevAddr=*/false))
           continue;
@@ -8998,8 +8959,6 @@ class MappableExprsHandler {
             llvm::errs() << "error: use_device_addr expects base-pointer to be "
                             "an identifier (e.g., xpp or xpp[1]); got: ";
             IE->dump();
-            // Continue without marking; fall back to generating a zero-size
-            // entry if needed.
           }
         }
         // For use_device_addr, we match an existing map clause if its attach-ptr
@@ -10400,6 +10359,7 @@ static void genMapInfoForCaptures(
       // must have a base-variable, like map(s), map(s.x) etc. In such cases, we
       // do not need to handle default map generation for s.
       bool HasEntryWithoutAttachPtr = false;
+      bool AttachPtrIsMemberOfThis = false;
       for (const auto &MapData : DeclComponentLists) {
         OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
             std::get<0>(MapData);
@@ -10408,12 +10368,21 @@ static void genMapInfoForCaptures(
           HasEntryWithoutAttachPtr = true;
           break;
         }
+        // Check if the attach pointer is a member expression (this->member)
+        if (CI->capturesThis() && isa<MemberExpr>(AttachPtr)) {
+          const auto *ME = cast<MemberExpr>(AttachPtr);
+          if (ME->isImplicitCXXThis() ||
+              isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) {
+            AttachPtrIsMemberOfThis = true;
+          }
+        }
       }
 
       // Generate default map info first if there's no direct map with CV as
       // the base-variable, or attach pointer.
       if (DeclComponentLists.empty() ||
-          (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
+          (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr &&
+           !AttachPtrIsMemberOfThis))
         MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
 
       // If we have any information in the map clause, we use it, otherwise we
diff --git a/clang/test/OpenMP/target_data_codegen.cpp b/clang/test/OpenMP/target_data_codegen.cpp
index b1da245110fb1..b879378b626ee 100644
--- a/clang/test/OpenMP/target_data_codegen.cpp
+++ b/clang/test/OpenMP/target_data_codegen.cpp
@@ -37,8 +37,8 @@ double gc[100];
 
 // CK1: [[MTYPE03:@.+]] = {{.+}}constant [1 x i64] [i64 5]
 
-// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 24]
-// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 281474976710673]
+// CK1: [[SIZE04:@.+]] = {{.+}}constant [2 x i64] [i64 24, i64 {{4|8}}]
+// CK1: [[MTYPE04:@.+]] = {{.+}}constant [2 x i64] [i64 1, i64 [[#0x4000]]]
 
 // CK1: [[MTYPE05:@.+]] = {{.+}}constant [1 x i64] [i64 1025]
 
@@ -132,32 +132,32 @@ void foo(int arg) {
   {++arg;}
 
   // Region 04
-  // CK1-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%[^,]+]], ptr [[MTYPE04]], ptr null, ptr null)
+  //
+  // &gb.b[0], &gb.b[/*lb=*/0], 3 * sizeof(gb.b[0]), TO
+  // &gb.b, &gb.b[/*lb=*/0], sizeof(gb.b), ATTACH
+  //
+  // CK1-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE04]], ptr [[MTYPE04]], ptr null, ptr null)
   // CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
   // CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-  // CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[PSZ:%[^,]+]]
 
   // CK1-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
   // CK1-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-  // CK1-DAG: [[PS0:%.+]] = getelementptr inbounds {{.+}}[[PSZ]], i{{.+}} 0, i{{.+}} 0
-  // CK1-DAG: store ptr @gb, ptr [[BP0]]
-  // CK1-DAG: store ptr getelementptr inbounds nuw ([[ST]], ptr @gb, i32 0, i32 1), ptr [[P0]]
-  // CK1-DAG: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (ptr getelementptr (ptr, ptr getelementptr inbounds nuw (%struct.ST, ptr @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (ptr getelementptr inbounds nuw (%struct.ST, ptr @gb, i32 0, i32 1) to i64)), ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-  // CK1-DAG: store i64 [[DIV]], ptr [[PS0]],
+  // CK1-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
+  // CK1-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+  // CK1-DAG: [[VAR0]] = load ptr, ptr getelementptr inbounds nuw ([[ST]], ptr @gb, i32 0, i32 1)
+  // CK1-DAG: [[SEC0]] = getelementptr inbounds nuw double, ptr [[SEC00:.+]], i{{.+}} 0
+  // CK1-DAG: [[SEC00]] = load ptr, ptr getelementptr inbounds nuw ([[ST]], ptr @gb, i32 0, i32 1)
 
   // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
   // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
   // CK1-DAG: store ptr getelementptr inbounds nuw ([[ST]], ptr @gb, i32 0, i32 1), ptr [[BP1]]
-  // CK1-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-  // CK1-DAG: [[SEC1]] = getelementptr inbounds {{.+}}ptr [[SEC11:%[^,]+]], i{{.+}} 0
-  // CK1-DAG: [[SEC11]] = load ptr, ptr getelementptr inbounds nuw ([[ST]], ptr @gb, i32 0, i32 1),
+  // CK1-DAG: store ptr [[SEC0]], ptr [[P1]]
 
   // CK1: %{{.+}} = add nsw i32 %{{[^,]+}}, 1
 
-  // CK1-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%[^,]+]], ptr [[MTYPE04]], ptr null, ptr null)
+  // CK1-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE04]], ptr [[MTYPE04]], ptr null, ptr null)
   // CK1-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
   // CK1-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
-  // CK1-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[PSZ]]
   #pragma omp target data map(to: gb.b[:3])
   {++arg;}
 
@@ -342,8 +342,8 @@ struct ST {
   }
 };
 
-// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 24]
-// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 281474976710677]
+// CK2: [[SIZE00:@.+]] = {{.+}}constant [2 x i64] [i64 24, i64 {{4|8}}]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 5, i64 [[#0x4000]]]
 
 // CK2-LABEL: _Z3bari
 int bar(int arg){
@@ -352,30 +352,32 @@ int bar(int arg){
 }
 
 // Region 00
+//
+// &b[0], &b[1], 3 * sizeof(b[0]), ALWAYS | TO
+// &b, &b[1], sizeof(b), ATTACH
+//
 // CK2-DAG: [[DEV:%[^,]+]] = sext i32 [[DEVi32:%[^,]+]] to i64
 // CK2-DAG: [[DEVi32]] = load i32, ptr %{{[^,]+}},
 // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
 // CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%[^,]+]], ptr [[MTYPE00]], ptr null, ptr null)
+// CK2-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE00]], ptr [[MTYPE00]], ptr null, ptr null)
 // CK2-DAG: [[GEPBP]] = getelementptr inbounds [2 x ptr], ptr [[BP:%[^,]+]]
 // CK2-DAG: [[GEPP]] = getelementptr inbounds [2 x ptr], ptr [[P:%[^,]+]]
-// CK2-DAG: [[GEPS]] = getelementptr inbounds [2 x i64], ptr [[PS:%[^,]+]]
 
 // CK2-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK2-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK2-DAG: [[PS0:%.+]] = getelementptr inbounds [2 x i64], ptr [[PS]], i{{.+}} 0, i{{.+}} 0
 // CK2-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
 // CK2-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK2-DAG: store i64 {{%.+}}, ptr [[PS0]],
-// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}ptr [[VAR0]], i32 0, i32 1
+// CK2-DAG: [[VAR0]] = load ptr, ptr [[VAR00:%[^,]+]]
+// CK2-DAG: [[VAR00]] = getelementptr inbounds nuw [[ST]], ptr [[THIS:%this.*]], i32 0, i32 1
+// CK2-DAG: [[SEC0]] = getelementptr inbounds {{.*}}ptr [[SEC00:%[^,]+]], i{{.+}} 1
+// CK2-DAG: [[SEC00]] = load ptr, ptr [[SEC000:%[^,]+]],
+// CK2-DAG: [[SEC000]] = getelementptr inbounds {{.*}}ptr [[THIS]], i32 0, i32 1
 
 // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK2-DAG: store ptr [[SEC0]], ptr [[BP1]]
-// CK2-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK2-DAG: [[SEC1]] = getelementptr inbounds {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 1
-// CK2-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK2-DAG: [[SEC111]] = getelementptr inbounds {{.*}}ptr [[VAR0]], i32 0, i32 1
+// CK2-DAG: store ptr [[VAR00]], ptr [[BP1]]
+// CK2-DAG: store ptr [[SEC0]], ptr [[P1]]
 
 // CK2: br label %[[IFEND:[^,]+]]
 
@@ -386,10 +388,9 @@ int bar(int arg){
 // CK2: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
 
 // CK2: [[IFTHEN]]
-// CK2-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%[^,]+]], ptr [[MTYPE00]], ptr null, ptr null)
+// CK2-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE00]], ptr [[MTYPE00]], ptr null, ptr null)
 // CK2-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
 // CK2-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
-// CK2-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[PS]]
 // CK2: br label %[[IFEND:[^,]+]]
 // CK2: [[IFELSE]]
 // CK2: br label %[[IFEND]]
@@ -453,8 +454,8 @@ struct STT {
   }
 };
 
-// CK4: [[SIZE00:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 24]
-// CK4: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 0, i64 281474976711701]
+// CK4: [[SIZE00:@.+]] = {{.+}}constant [2 x i64] [i64 24, i64 {{4|8}}]
+// CK4: [[MTYPE00:@.+]] = {{.+}}constant [2 x i64] [i64 [[#0x405]], i64 [[#0x4000]]]
 
 // CK4-LABEL: _Z3bari
 int bar(int arg){
@@ -463,30 +464,32 @@ int bar(int arg){
 }
 
 // Region 00
+//
+// &b[0], &b[1], 3 * sizeof(b[0]), CLOSE | ALWAYS | TO
+// &b, &b[1], sizeof(b), ATTACH
+//
 // CK4-DAG: [[DEV:%[^,]+]] = sext i32 [[DEVi32:%[^,]+]] to i64
 // CK4-DAG: [[DEVi32]] = load i32, ptr %{{[^,]+}},
 // CK4: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
 // CK4: [[IFTHEN]]
-// CK4-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%.+]], ptr [[MTYPE00]], ptr null, ptr null)
+// CK4-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE00]], ptr [[MTYPE00]], ptr null, ptr null)
 // CK4-DAG: [[GEPBP]] = getelementptr inbounds [2 x ptr], ptr [[BP:%[^,]+]]
 // CK4-DAG: [[GEPP]] = getelementptr inbounds [2 x ptr], ptr [[P:%[^,]+]]
-// CK4-DAG: [[GEPS]] = getelementptr inbounds [2 x i64], ptr [[PS:%[^,]+]]
 
 // CK4-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK4-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK4-DAG: [[PS0:%.+]] = getelementptr inbounds {{.+}}[[PS]], i{{.+}} 0, i{{.+}} 0
 // CK4-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
 // CK4-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK4-DAG: store i64 {{%.+}}, ptr [[PS0]],
-// CK4-DAG: [[SEC0]] = getelementptr inbounds {{.*}}ptr [[VAR0]], i32 0, i32 1
+// CK4-DAG: [[VAR0]] = load ptr, ptr [[VAR00:%[^,]*]]
+// CK4-DAG: [[VAR00]] = getelementptr inbounds {{.*}}, ptr [[THIS:%this.*]], i32 0, i32 1
+// CK4-DAG: [[SEC0]] = getelementptr inbounds nuw double, ptr [[SEC00:%[^,]+]], i{{.+}} 1
+// CK4-DAG: [[SEC00]] = load ptr, ptr [[SEC000:%[^,]+]],
+// CK4-DAG: [[SEC000]] = getelementptr inbounds {{.*}}, ptr [[THIS]], i32 0, i32 1
 
 // CK4-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK4-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK4-DAG: store ptr [[SEC0]], ptr [[BP1]]
-// CK4-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK4-DAG: [[SEC1]] = getelementptr inbounds {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 1
-// CK4-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK4-DAG: [[SEC111]] = getelementptr inbounds {{.*}}ptr [[VAR0]], i32 0, i32 1
+// CK4-DAG: store ptr [[VAR00]], ptr [[BP1]]
+// CK4-DAG: store ptr [[SEC0]], ptr [[P1]]
 
 // CK4: br label %[[IFEND:[^,]+]]
 
@@ -497,10 +500,9 @@ int bar(int arg){
 // CK4: br i1 %{{[^,]+}}, label %[[IFTHEN:[^,]+]], label %[[IFELSE:[^,]+]]
 
 // CK4: [[IFTHEN]]
-// CK4-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[GEPS:%.+]], ptr [[MTYPE00]], ptr null, ptr null)
+// CK4-DAG: call void @__tgt_target_data_end_mapper(ptr @{{.+}}, i64 [[DEV]], i32 2, ptr [[GEPBP:%.+]], ptr [[GEPP:%.+]], ptr [[SIZE00]], ptr [[MTYPE00]], ptr null, ptr null)
 // CK4-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP]]
 // CK4-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P]]
-// CK4-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[PS]]
 // CK4: br label %[[IFEND:[^,]+]]
 // CK4: [[IFELSE]]
 // CK4: br label %[[IFEND]]
@@ -532,7 +534,12 @@ struct S2 {
 
 void test_close_modifier(int arg) {
   S2 *ps;
-// CK5: private unnamed_addr constant [5 x i64] [i64 1027, i64 0, i64 562949953421328, i64 16, i64 1043]
+// CK5: private unnamed_addr constant [3 x i64] [i64 1027, i64 1027, i64 16384]
+//
+// &arg, &arg, sizeof(arg), CLOSE | TOFROM
+// &ps->ps->ps->ps[0], &ps->ps->ps->ps[0].s, sizeof(ps->ps->ps->ps[0].s), CLOSE | TOFROM
+// &ps->ps->ps->ps, &ps->ps->ps->ps[0].s, sizeof(struct S2 *), ATTACH
+//
 #pragma omp target data map(close, tofrom \
                             : arg, ps->ps->ps->ps->s)
   {
@@ -623,44 +630,42 @@ void test_present_modifier(int arg) {
   S2 *ps1;
   S2 *ps2;
 
-  // Make sure the struct picks up present even if another element of the struct
-  // doesn't have present.
-  // CK8: private unnamed_addr constant [13 x i64] [i64 0, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 4, i64 {{4|8}}, i64 4, i64 0, i64 4, i64 {{4|8}}, i64 {{4|8}}, i64 4, i64 {{8|4}}]
-  // CK8: private unnamed_addr constant [13 x i64]
-
+// Make sure the struct picks up present even if another element of the struct
+// doesn't have present.
+// CK8: private unnamed_addr constant [9 x i64] [i64 4, i64 {{4|8}}, i64 4, i64 {{4|8}}, i64 4, i64 4, i64 {{4|8}}, i64 4, i64 {{4|8}}]
+// CK8: private unnamed_addr constant [9 x i64]
 // ps1
 //
-// PRESENT=0x1000 = 0x1000
-// MEMBER_OF_1=0x1000000000000 | PRESENT=0x1000 | PTR_AND_OBJ=0x10 = 0x1000000001010
-// PRESENT=0x1000 | PTR_AND_OBJ=0x10 = 0x1010
-// PRESENT=0x1000 | PTR_AND_OBJ=0x10 | FROM=0x2 | TO=0x1 = 0x1013
-// MEMBER_OF_1=0x1000000000000 | FROM=0x2 | TO=0x1 = 0x1000000000003
-// ATTACH=0x4000
+// &ps1[0], &ps1->s, sizeof(ps1->s), FROM | TO
+// &ps1, &ps1->s, sizeof(ps1), ATTACH
+//
+// CK8-SAME: {{^}} [i64 3, i64 [[#0x4000]],
 //
-// CK8-SAME: {{^}} [i64 [[#0x1000]], i64 [[#0x1000000001010]],
-// CK8-SAME: {{^}} i64 [[#0x1010]], i64 [[#0x1013]], i64 [[#0x1000000000003]],
-// CK8-SAME: {{^}} i64 [[#0x4000]],
+// &ps1->ps->ps->ps[0], &ps1->ps->ps->ps[0].s, sizeof(ps1->ps->ps->ps[0].s), PRESENT | FROM | TO
+// &ps1->ps->ps->ps, &ps1->ps->ps->ps[0].s, sizeof(struct S2 *), ATTACH
+//
+// CK8-SAME: {{^}} i64 [[#0x1003]], i64 [[#0x4000]],
 
 // arg
 //
-// PRESENT=0x1000 | FROM=0x2 | TO=0x1 = 0x1003
+// &arg, &arg, sizeof(arg), PRESENT | FROM | TO
 //
 // CK8-SAME: {{^}} i64 [[#0x1003]],
 
 // ps2
 //
-// PRESENT=0x1000 = 0x1000
-// MEMBER_OF_8=0x8000000000000 | PRESENT=0x1000 | FROM=0x2 | TO=0x1 = 0x8000000001003
-// MEMBER_OF_8=0x8000000000000 | PTR_AND_OBJ=0x10 = 0x8000000000010
-// PTR_AND_OBJ=0x10 = 0x10
-// PTR_AND_OBJ=0x10 | FROM=0x2 | TO=0x1 = 0x13
-// ATTACH=0x4000
+// &ps2[0], &ps2->s, sizeof(ps2->s), PRESENT | FROM | TO
+// &ps2, &ps2->s, sizeof(ps2), ATTACH
 //
-// CK8-SAME: {{^}} i64 [[#0x1000]], i64 [[#0x8000000001003]],
-// CK8-SAME: {{^}} i64 [[#0x8000000000010]], i64 [[#0x10]], i64 [[#0x13]],
-// CK8-SAME: {{^}} i64 [[#0x4000]]]
+// CK8-SAME: {{^}} i64 [[#0x1003]], i64 [[#0x4000]],
+//
+// &ps2->ps->ps->ps[0], &ps2->ps->ps->ps[0].s, sizeof(ps2->ps->ps->ps[0].s), FROM | TO
+// &ps2->ps->ps->ps, &ps2->ps->ps->ps[0].s, sizeof(struct S2 *), ATTACH
+//
+// CK8-SAME: {{^}} i64 3, i64 [[#0x4000]]]
+
 #pragma omp target data map(tofrom         \
-                            : ps1->s)      \
+  : ps1->s)      \
     map(present, tofrom                    \
         : arg, ps1->ps->ps->ps->s, ps2->s) \
         map(tofrom                         \
diff --git a/clang/test/OpenMP/target_data_map_codegen_hold.cpp b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
index 4b8b2f0a059e6..38fcf57e1473e 100644
--- a/clang/test/OpenMP/target_data_map_codegen_hold.cpp
+++ b/clang/test/OpenMP/target_data_map_codegen_hold.cpp
@@ -60,8 +60,8 @@ struct S2 {
 // CHECK-PPC64LE: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x2405]]]
 // CHECK-PPC64LE: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK-PPC64LE: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x2003]]]
-// CHECK-PPC64LE: @.offload_sizes.5 = private unnamed_addr constant [13 x i64] [i64 0, i64 4, i64 8, i64 8, i64 4, i64 8, i64 4, i64 0, i64 4, i64 8, i64 8, i64 4, i64 8]
-// CHECK-PPC64LE: @.offload_maptypes.6 = private unnamed_addr constant [13 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x8000000002003]], i64 [[#0x8000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]]]
+// CHECK-PPC64LE: @.offload_sizes.5 = private unnamed_addr constant [9 x i64] [i64 4, i64 8, i64 4, i64 8, i64 4, i64 4, i64 8, i64 4, i64 8]
+// CHECK-PPC64LE: @.offload_maptypes.6 = private unnamed_addr constant [9 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x2003]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2003]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-I386: @.offload_sizes = private unnamed_addr constant [1 x i64] [i64 20]
 // CHECK-I386: @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 [[#0x2001]]]
@@ -69,8 +69,8 @@ struct S2 {
 // CHECK-I386: @.offload_maptypes.2 = private unnamed_addr constant [1 x i64] [i64 [[#0x2405]]]
 // CHECK-I386: @.offload_sizes.3 = private unnamed_addr constant [1 x i64] [i64 4]
 // CHECK-I386: @.offload_maptypes.4 = private unnamed_addr constant [1 x i64] [i64 [[#0x2003]]]
-// CHECK-I386: @.offload_sizes.5 = private unnamed_addr constant [13 x i64] [i64 0, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 0, i64 4, i64 4, i64 4, i64 4, i64 4]
-// CHECK-I386: @.offload_maptypes.6 = private unnamed_addr constant [13 x i64] [i64 [[#0x2000]], i64 [[#0x1000000002003]], i64 [[#0x1000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2000]], i64 [[#0x8000000002003]], i64 [[#0x8000000002010]], i64 [[#0x2010]], i64 [[#0x2013]], i64 [[#0x4000]]]
+// CHECK-I386: @.offload_sizes.5 = private unnamed_addr constant [9 x i64] [i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4]
+// CHECK-I386: @.offload_maptypes.6 = private unnamed_addr constant [9 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x2003]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x2003]], i64 [[#0x4000]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-PPC64LE-LABEL: @_Z3fooi(
 // CHECK-PPC64LE-NEXT:  entry:
@@ -87,10 +87,9 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [13 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [13 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [13 x ptr], align 8
-// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_BASEPTRS23:%.*]] = alloca [9 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_PTRS24:%.*]] = alloca [9 x ptr], align 8
+// CHECK-PPC64LE-NEXT:    [[DOTOFFLOAD_MAPPERS25:%.*]] = alloca [9 x ptr], align 8
 // CHECK-PPC64LE-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-PPC64LE-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    store ptr [[LB]], ptr [[TMP0]], align 8
@@ -141,154 +140,103 @@ struct S2 {
 // CHECK-PPC64LE-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 8
 // CHECK-PPC64LE-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-PPC64LE-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS9]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS10]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 8
-// CHECK-PPC64LE-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
-// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-PPC64LE-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS11]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS12]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS13]], align 8
+// CHECK-PPC64LE-NEXT:    [[S14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[S15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS2]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP38:%.*]] = load ptr, ptr [[PS16]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP38]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP39:%.*]] = load ptr, ptr [[PS17]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP39]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[PS18]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP41:%.*]] = load ptr, ptr [[PS2]], align 8
 // CHECK-PPC64LE-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 8
-// CHECK-PPC64LE-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 8
-// CHECK-PPC64LE-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
-// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
-// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
-// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-PPC64LE-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DOTOFFLOAD_SIZES]], ptr align 8 @.offload_sizes.5, i64 104, i1 false)
-// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP61]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 0
+// CHECK-PPC64LE-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP42]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS19]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS20]], align 8
+// CHECK-PPC64LE-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS21]], align 8
+// CHECK-PPC64LE-NEXT:    [[S22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP46:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP46]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP47:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP47]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 0
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP48]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP49]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 1
+// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP50]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 1
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP51]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP29]], ptr [[TMP52]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 2
+// CHECK-PPC64LE-NEXT:    store ptr [[S14]], ptr [[TMP53]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP54:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 2
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP54]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP55:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP55]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP56:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 3
+// CHECK-PPC64LE-NEXT:    store ptr [[S14]], ptr [[TMP56]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP57:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 3
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP57]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP58:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP58]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP59:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 4
+// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP59]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 4
+// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP60]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP35]], ptr [[TMP61]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 5
+// CHECK-PPC64LE-NEXT:    store ptr [[S15]], ptr [[TMP62]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 5
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP63]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP65]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 1
+// CHECK-PPC64LE-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP64]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 6
+// CHECK-PPC64LE-NEXT:    store ptr [[S15]], ptr [[TMP65]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 6
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP66]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
-// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 2
+// CHECK-PPC64LE-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[TMP40]], ptr [[TMP67]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 7
+// CHECK-PPC64LE-NEXT:    store ptr [[S22]], ptr [[TMP68]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 7
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP69]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
-// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 3
+// CHECK-PPC64LE-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[PS18]], ptr [[TMP70]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 8
+// CHECK-PPC64LE-NEXT:    store ptr [[S22]], ptr [[TMP71]], align 8
+// CHECK-PPC64LE-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i64 0, i64 8
 // CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP72]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
-// CHECK-PPC64LE-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 4
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP75]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[PS1]], ptr [[TMP76]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
-// CHECK-PPC64LE-NEXT:    store ptr [[S]], ptr [[TMP77]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 5
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP78]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP79]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
-// CHECK-PPC64LE-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP80]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 6
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP81]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP82]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP83]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
-// CHECK-PPC64LE-NEXT:    store i64 [[TMP59]], ptr [[TMP84]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 7
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP85]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[TMP42]], ptr [[TMP86]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP87]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 8
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP88]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS19]], ptr [[TMP89]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
-// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP90]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 9
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP91]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[PS21]], ptr [[TMP92]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
-// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP93]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 10
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP94]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 11
-// CHECK-PPC64LE-NEXT:    store ptr [[PS24]], ptr [[TMP95]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 11
-// CHECK-PPC64LE-NEXT:    store ptr [[S28]], ptr [[TMP96]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 11
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP97]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 12
-// CHECK-PPC64LE-NEXT:    store ptr [[PS2]], ptr [[TMP98]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 12
-// CHECK-PPC64LE-NEXT:    store ptr [[S18]], ptr [[TMP99]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i64 0, i64 12
-// CHECK-PPC64LE-NEXT:    store ptr null, ptr [[TMP100]], align 8
-// CHECK-PPC64LE-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP101]], ptr [[TMP102]], ptr [[TMP103]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-PPC64LE-NEXT:    [[TMP104:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP104]], 1
-// CHECK-PPC64LE-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
-// CHECK-PPC64LE-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP105]], ptr [[TMP106]], ptr [[TMP107]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 9, ptr [[TMP73]], ptr [[TMP74]], ptr @.offload_sizes.5, ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-PPC64LE-NEXT:    [[TMP75:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[INC26:%.*]] = add nsw i32 [[TMP75]], 1
+// CHECK-PPC64LE-NEXT:    store i32 [[INC26]], ptr [[ARG_ADDR]], align 4
+// CHECK-PPC64LE-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-PPC64LE-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 9, ptr [[TMP76]], ptr [[TMP77]], ptr @.offload_sizes.5, ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-PPC64LE-NEXT:    ret void
 //
 // CHECK-I386-LABEL: @_Z3fooi(
@@ -306,10 +254,9 @@ struct S2 {
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS5:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS6:%.*]] = alloca [1 x ptr], align 4
 // CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS7:%.*]] = alloca [1 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS29:%.*]] = alloca [13 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS30:%.*]] = alloca [13 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS31:%.*]] = alloca [13 x ptr], align 4
-// CHECK-I386-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [13 x i64], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_BASEPTRS23:%.*]] = alloca [9 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_PTRS24:%.*]] = alloca [9 x ptr], align 4
+// CHECK-I386-NEXT:    [[DOTOFFLOAD_MAPPERS25:%.*]] = alloca [9 x ptr], align 4
 // CHECK-I386-NEXT:    store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
 // CHECK-I386-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
 // CHECK-I386-NEXT:    store ptr [[LB]], ptr [[TMP0]], align 4
@@ -360,154 +307,103 @@ struct S2 {
 // CHECK-I386-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[PS1]], align 4
 // CHECK-I386-NEXT:    [[S:%.*]] = getelementptr inbounds nuw [[STRUCT_S2:%.*]], ptr [[TMP25]], i32 0, i32 0
 // CHECK-I386-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS9]], align 4
-// CHECK-I386-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP29]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[PS:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP26]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[PS]], align 4
+// CHECK-I386-NEXT:    [[PS9:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP27]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP28:%.*]] = load ptr, ptr [[PS9]], align 4
+// CHECK-I386-NEXT:    [[PS10:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP28]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[PS10]], align 4
 // CHECK-I386-NEXT:    [[TMP30:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP30]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS11]], align 4
-// CHECK-I386-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS12]], align 4
-// CHECK-I386-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS1]], align 4
-// CHECK-I386-NEXT:    [[PS14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS14]], align 4
-// CHECK-I386-NEXT:    [[PS15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS15]], align 4
-// CHECK-I386-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP35]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS16]], align 4
-// CHECK-I386-NEXT:    [[S17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP37:%.*]] = getelementptr ptr, ptr [[PS]], i32 1
-// CHECK-I386-NEXT:    [[TMP38:%.*]] = ptrtoint ptr [[TMP37]] to i64
-// CHECK-I386-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[S]] to i64
-// CHECK-I386-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
-// CHECK-I386-NEXT:    [[TMP41:%.*]] = sdiv exact i64 [[TMP40]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
+// CHECK-I386-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[PS1]], align 4
+// CHECK-I386-NEXT:    [[PS11:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP31]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[PS11]], align 4
+// CHECK-I386-NEXT:    [[PS12:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP32]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[PS12]], align 4
+// CHECK-I386-NEXT:    [[PS13:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP33]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[PS13]], align 4
+// CHECK-I386-NEXT:    [[S14:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP34]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[S15:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP36]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP37:%.*]] = load ptr, ptr [[PS2]], align 4
+// CHECK-I386-NEXT:    [[PS16:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP37]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP38:%.*]] = load ptr, ptr [[PS16]], align 4
+// CHECK-I386-NEXT:    [[PS17:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP38]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP39:%.*]] = load ptr, ptr [[PS17]], align 4
+// CHECK-I386-NEXT:    [[PS18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP39]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[PS18]], align 4
+// CHECK-I386-NEXT:    [[TMP41:%.*]] = load ptr, ptr [[PS2]], align 4
 // CHECK-I386-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[S18:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP46:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP46]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP47:%.*]] = load ptr, ptr [[PS20]], align 4
-// CHECK-I386-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP47]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP48:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP48]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP49:%.*]] = load ptr, ptr [[PS22]], align 4
-// CHECK-I386-NEXT:    [[PS23:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP49]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP50:%.*]] = load ptr, ptr [[PS23]], align 4
-// CHECK-I386-NEXT:    [[PS24:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP50]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP51:%.*]] = load ptr, ptr [[PS2]], align 4
-// CHECK-I386-NEXT:    [[PS25:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP51]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP52:%.*]] = load ptr, ptr [[PS25]], align 4
-// CHECK-I386-NEXT:    [[PS26:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP52]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP53:%.*]] = load ptr, ptr [[PS26]], align 4
-// CHECK-I386-NEXT:    [[PS27:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP53]], i32 0, i32 1
-// CHECK-I386-NEXT:    [[TMP54:%.*]] = load ptr, ptr [[PS27]], align 4
-// CHECK-I386-NEXT:    [[S28:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP54]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP55:%.*]] = getelementptr ptr, ptr [[PS19]], i32 1
-// CHECK-I386-NEXT:    [[TMP56:%.*]] = ptrtoint ptr [[TMP55]] to i64
-// CHECK-I386-NEXT:    [[TMP57:%.*]] = ptrtoint ptr [[S18]] to i64
-// CHECK-I386-NEXT:    [[TMP58:%.*]] = sub i64 [[TMP56]], [[TMP57]]
-// CHECK-I386-NEXT:    [[TMP59:%.*]] = sdiv exact i64 [[TMP58]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-I386-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 104, i1 false)
-// CHECK-I386-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP60]], align 4
-// CHECK-I386-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP61]], align 4
-// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    store i64 [[TMP41]], ptr [[TMP62]], align 4
-// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[PS19:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP42]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[PS19]], align 4
+// CHECK-I386-NEXT:    [[PS20:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP43]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP44:%.*]] = load ptr, ptr [[PS20]], align 4
+// CHECK-I386-NEXT:    [[PS21:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP44]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP45:%.*]] = load ptr, ptr [[PS21]], align 4
+// CHECK-I386-NEXT:    [[S22:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[TMP45]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP46:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP46]], align 4
+// CHECK-I386-NEXT:    [[TMP47:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP47]], align 4
+// CHECK-I386-NEXT:    [[TMP48:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 0
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP48]], align 4
+// CHECK-I386-NEXT:    [[TMP49:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP49]], align 4
+// CHECK-I386-NEXT:    [[TMP50:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP50]], align 4
+// CHECK-I386-NEXT:    [[TMP51:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 1
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP51]], align 4
+// CHECK-I386-NEXT:    [[TMP52:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[TMP29]], ptr [[TMP52]], align 4
+// CHECK-I386-NEXT:    [[TMP53:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr [[S14]], ptr [[TMP53]], align 4
+// CHECK-I386-NEXT:    [[TMP54:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 2
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP54]], align 4
+// CHECK-I386-NEXT:    [[TMP55:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP55]], align 4
+// CHECK-I386-NEXT:    [[TMP56:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr [[S14]], ptr [[TMP56]], align 4
+// CHECK-I386-NEXT:    [[TMP57:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 3
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP57]], align 4
+// CHECK-I386-NEXT:    [[TMP58:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP58]], align 4
+// CHECK-I386-NEXT:    [[TMP59:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP59]], align 4
+// CHECK-I386-NEXT:    [[TMP60:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 4
+// CHECK-I386-NEXT:    store ptr null, ptr [[TMP60]], align 4
+// CHECK-I386-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[TMP35]], ptr [[TMP61]], align 4
+// CHECK-I386-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 5
+// CHECK-I386-NEXT:    store ptr [[S15]], ptr [[TMP62]], align 4
+// CHECK-I386-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 5
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP63]], align 4
-// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[TMP24]], ptr [[TMP64]], align 4
-// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 1
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP65]], align 4
-// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 1
+// CHECK-I386-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP64]], align 4
+// CHECK-I386-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 6
+// CHECK-I386-NEXT:    store ptr [[S15]], ptr [[TMP65]], align 4
+// CHECK-I386-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 6
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP66]], align 4
-// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS]], ptr [[TMP67]], align 4
-// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 2
-// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP68]], align 4
-// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 2
+// CHECK-I386-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[TMP40]], ptr [[TMP67]], align 4
+// CHECK-I386-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 7
+// CHECK-I386-NEXT:    store ptr [[S22]], ptr [[TMP68]], align 4
+// CHECK-I386-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 7
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP69]], align 4
-// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS10]], ptr [[TMP70]], align 4
-// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 3
-// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP71]], align 4
-// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 3
+// CHECK-I386-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[PS18]], ptr [[TMP70]], align 4
+// CHECK-I386-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 8
+// CHECK-I386-NEXT:    store ptr [[S22]], ptr [[TMP71]], align 4
+// CHECK-I386-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_MAPPERS25]], i32 0, i32 8
 // CHECK-I386-NEXT:    store ptr null, ptr [[TMP72]], align 4
-// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[PS13]], ptr [[TMP73]], align 4
-// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr [[S17]], ptr [[TMP74]], align 4
-// CHECK-I386-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 4
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP75]], align 4
-// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[PS1]], ptr [[TMP76]], align 4
-// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr [[S]], ptr [[TMP77]], align 4
-// CHECK-I386-NEXT:    [[TMP78:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 5
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP78]], align 4
-// CHECK-I386-NEXT:    [[TMP79:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP79]], align 4
-// CHECK-I386-NEXT:    [[TMP80:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr [[ARG_ADDR]], ptr [[TMP80]], align 4
-// CHECK-I386-NEXT:    [[TMP81:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 6
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP81]], align 4
-// CHECK-I386-NEXT:    [[TMP82:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP82]], align 4
-// CHECK-I386-NEXT:    [[TMP83:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP83]], align 4
-// CHECK-I386-NEXT:    [[TMP84:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 7
-// CHECK-I386-NEXT:    store i64 [[TMP59]], ptr [[TMP84]], align 4
-// CHECK-I386-NEXT:    [[TMP85:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 7
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP85]], align 4
-// CHECK-I386-NEXT:    [[TMP86:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[TMP42]], ptr [[TMP86]], align 4
-// CHECK-I386-NEXT:    [[TMP87:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP87]], align 4
-// CHECK-I386-NEXT:    [[TMP88:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 8
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP88]], align 4
-// CHECK-I386-NEXT:    [[TMP89:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS19]], ptr [[TMP89]], align 4
-// CHECK-I386-NEXT:    [[TMP90:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP90]], align 4
-// CHECK-I386-NEXT:    [[TMP91:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 9
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP91]], align 4
-// CHECK-I386-NEXT:    [[TMP92:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[PS21]], ptr [[TMP92]], align 4
-// CHECK-I386-NEXT:    [[TMP93:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP93]], align 4
-// CHECK-I386-NEXT:    [[TMP94:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 10
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP94]], align 4
-// CHECK-I386-NEXT:    [[TMP95:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr [[PS24]], ptr [[TMP95]], align 4
-// CHECK-I386-NEXT:    [[TMP96:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr [[S28]], ptr [[TMP96]], align 4
-// CHECK-I386-NEXT:    [[TMP97:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 11
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP97]], align 4
-// CHECK-I386-NEXT:    [[TMP98:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr [[PS2]], ptr [[TMP98]], align 4
-// CHECK-I386-NEXT:    [[TMP99:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr [[S18]], ptr [[TMP99]], align 4
-// CHECK-I386-NEXT:    [[TMP100:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_MAPPERS31]], i32 0, i32 12
-// CHECK-I386-NEXT:    store ptr null, ptr [[TMP100]], align 4
-// CHECK-I386-NEXT:    [[TMP101:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP102:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP101]], ptr [[TMP102]], ptr [[TMP103]], ptr @.offload_maptypes.6, ptr null, ptr null)
-// CHECK-I386-NEXT:    [[TMP104:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[INC32:%.*]] = add nsw i32 [[TMP104]], 1
-// CHECK-I386-NEXT:    store i32 [[INC32]], ptr [[ARG_ADDR]], align 4
-// CHECK-I386-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [13 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0
-// CHECK-I386-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [13 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 13, ptr [[TMP105]], ptr [[TMP106]], ptr [[TMP107]], ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_begin_mapper(ptr @[[GLOB1]], i64 -1, i32 9, ptr [[TMP73]], ptr [[TMP74]], ptr @.offload_sizes.5, ptr @.offload_maptypes.6, ptr null, ptr null)
+// CHECK-I386-NEXT:    [[TMP75:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[INC26:%.*]] = add nsw i32 [[TMP75]], 1
+// CHECK-I386-NEXT:    store i32 [[INC26]], ptr [[ARG_ADDR]], align 4
+// CHECK-I386-NEXT:    [[TMP76:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0
+// CHECK-I386-NEXT:    [[TMP77:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0
+// CHECK-I386-NEXT:    call void @__tgt_target_data_end_mapper(ptr @[[GLOB1]], i64 -1, i32 9, ptr [[TMP76]], ptr [[TMP77]], ptr @.offload_sizes.5, ptr @.offload_maptypes.6, ptr null, ptr null)
 // CHECK-I386-NEXT:    ret void
 //
 void foo(int arg) {
diff --git a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
index 60b65ba9a49da..3ef0c09d3a908 100644
--- a/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
+++ b/clang/test/OpenMP/target_data_map_pointer_array_subscript_codegen.cpp
@@ -35,8 +35,8 @@ MyObject *objects;
 
 // CHECK-DAG: [[SIZES0:@.+]] = private unnamed_addr constant [2 x i64] [i64 {{8|4}}, i64 {{8|4}}]
 // CHECK-DAG: [[MAPS0:@.+]] = private unnamed_addr constant [2 x i64] [i64 1, i64 16384]
-// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [2 x i64] [i64 0, i64 4]
-// CHECK-DAG: [[MAPS1:@.+]] = private unnamed_addr constant [2 x i64] [i64 0, i64 281474976710673]
+// CHECK-DAG: [[SIZES1:@.+]] = private unnamed_addr constant [2 x i64] [i64 4, i64 {{8|4}}]
+// CHECK-DAG: [[MAPS1:@.+]] = private unnamed_addr constant [2 x i64] [i64 1, i64 16384]
 // CHECK: @main
 int main(void) {
 
@@ -61,10 +61,32 @@ int main(void) {
 // CHECK-DAG: store ptr [[SEC0]], ptr [[P1]]
 
 #pragma omp target enter data map(to : objects [1:1])
-// CHECK: [[OBJ:%.+]] = load ptr, ptr @objects,
-// CHECK: [[BPTR0:%.+]] = getelementptr inbounds [2 x ptr], ptr %{{.+}}, i32 0, i32 0
-// CHECK: store ptr [[OBJ]], ptr [[BPTR0]],
-// CHECK: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr %{{.+}}, ptr %{{.+}}, ptr %{{.+}}, ptr [[MAPS1]], ptr null, ptr null)
+
+//  &objects[1].arr[0], &objects[1].arr[/*lb=*/0], 1 * sizeof(objects[1],arr[0:1]), TO
+//  &objects[1].arr, &objects[1].arr[/*lb=*/0], sizeof(objects[1].arr), ATTACH
+
+// CHECK-DAG: call void @__tgt_target_data_begin_mapper(ptr @{{.+}}, i64 -1, i32 2, ptr [[BPGEP:%.+]], ptr [[PGEP:%.+]], ptr [[SIZES1]], ptr [[MAPS1]], ptr null, ptr null)
+// CHECK-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+// CHECK-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+// CHECK-DAG: [[BP0:%.+]] = getelementptr inbounds {{.*}}ptr [[BP]], i32 0, i32 0
+// CHECK-DAG: [[P0:%.+]] = getelementptr inbounds {{.*}}ptr [[P]], i32 0, i32 0
+// CHECK-DAG: store ptr [[RVAR0:%.+]], ptr [[BP0]]
+// CHECK-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
+// CHECK-DAG: [[RVAR0]] = load ptr, ptr [[RVAR00:[^,]+]]
+// CHECK-DAG: [[RVAR00]] = getelementptr inbounds nuw %struct.MyObject, ptr [[RVAR000:%[^,]+]], i32 0, i32 0
+// CHECK-DAG: [[RVAR000]] = getelementptr inbounds %struct.MyObject, ptr [[RVAR0000:%[^,]+]], i{{.*}} 1
+// CHECK-DAG: [[RVAR0000]] = load ptr, ptr @objects
+// CHECK-DAG: [[SEC0]] = getelementptr inbounds nuw i32, ptr [[SEC00:%.*]], i{{.*}} 0
+// CHECK-DAG: [[SEC00]] = load ptr, ptr [[SEC000:[^,]+]]
+// CHECK-DAG: [[SEC000]] = getelementptr inbounds nuw %struct.MyObject, ptr [[SEC0000:%[^,]+]], i32 0, i32 0
+// CHECK-DAG: [[SEC0000]] = getelementptr inbounds %struct.MyObject, ptr [[SEC00000:%[^,]+]], i{{.*}} 1
+// CHECK-DAG: [[SEC00000]] = load ptr, ptr @objects
+
+// CHECK-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
+// CHECK-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
+// CHECK-DAG: store ptr [[RVAR00]], ptr [[BP1]]
+// CHECK-DAG: store ptr [[SEC0]], ptr [[P1]]
 #pragma omp target enter data map(to : objects[1].arr [0:1])
 
   return 0;
diff --git a/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
index 9030fff2108c6..3b742416dadbd 100644
--- a/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
+++ b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
@@ -37,10 +37,10 @@ void array_section_no_length_map_clause(float *d, int index) {
 // CHECK: @.offload_maptypes = private unnamed_addr constant [2 x i64] [i64 [[#0x23]], i64 [[#0x4000]]]
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [2 x i64] [i64 0, i64 4]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [2 x i64] [i64 [[#0x21]], i64 [[#0x4000]]]
-// CHECK: @.offload_sizes.3 = private unnamed_addr constant [3 x i64] [i64 4, i64 4, i64 4]
-// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [3 x i64] [i64 [[#0x20]], i64 [[#0x10]], i64 [[#0x320]]]
-// CHECK: @.offload_sizes.5 = private unnamed_addr constant [3 x i64] [i64 4, i64 0, i64 4]
-// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x13]], i64 [[#0x320]]]
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [4 x i64] [i64 0, i64 4, i64 4, i64 4]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [4 x i64] [i64 [[#0x220]], i64 [[#0x0]], i64 [[#0x4000]], i64 [[#0x320]]]
+// CHECK: @.offload_sizes.5 = private unnamed_addr constant [4 x i64] [i64 0, i64 0, i64 4, i64 4]
+// CHECK: @.offload_maptypes.6 = private unnamed_addr constant [4 x i64] [i64 [[#0x220]], i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x320]]]
 //.
 // CHECK-LABEL: define dso_local void @_Z34array_section_no_length_map_clausePfi(
 // CHECK-SAME: ptr noundef [[D:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -57,15 +57,15 @@ void array_section_no_length_map_clause(float *d, int index) {
 // CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [2 x ptr], align 4
 // CHECK-NEXT:    [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    [[INDEX_CASTED:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [3 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS12:%.*]] = alloca [3 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS13:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [4 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS12:%.*]] = alloca [4 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS13:%.*]] = alloca [4 x ptr], align 4
 // CHECK-NEXT:    [[KERNEL_ARGS14:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    [[INDEX_CASTED17:%.*]] = alloca i32, align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS22:%.*]] = alloca [3 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_PTRS23:%.*]] = alloca [3 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS24:%.*]] = alloca [3 x ptr], align 4
-// CHECK-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [3 x i64], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_BASEPTRS22:%.*]] = alloca [4 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_PTRS23:%.*]] = alloca [4 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_MAPPERS24:%.*]] = alloca [4 x ptr], align 4
+// CHECK-NEXT:    [[DOTOFFLOAD_SIZES:%.*]] = alloca [4 x i64], align 4
 // CHECK-NEXT:    [[KERNEL_ARGS25:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
 // CHECK-NEXT:    store ptr [[D]], ptr [[D_ADDR]], align 4
 // CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
@@ -176,144 +176,158 @@ void array_section_no_length_map_clause(float *d, int index) {
 // CHECK-NEXT:    store i32 [[TMP53]], ptr [[INDEX_CASTED]], align 4
 // CHECK-NEXT:    [[TMP54:%.*]] = load i32, ptr [[INDEX_CASTED]], align 4
 // CHECK-NEXT:    [[TMP55:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP56:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP57:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds ptr, ptr [[TMP56]], i32 [[TMP57]]
+// CHECK-NEXT:    [[TMP56:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX8:%.*]] = getelementptr inbounds ptr, ptr [[TMP55]], i32 [[TMP56]]
+// CHECK-NEXT:    [[TMP57:%.*]] = load ptr, ptr [[ARRAYIDX8]], align 4
 // CHECK-NEXT:    [[TMP58:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP59:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds ptr, ptr [[TMP58]], i32 [[TMP59]]
-// CHECK-NEXT:    [[TMP60:%.*]] = load ptr, ptr [[ARRAYIDX9]], align 4
-// CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw float, ptr [[TMP60]], i32 0
-// CHECK-NEXT:    [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[TMP55]], ptr [[TMP61]], align 4
-// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP62]], align 4
-// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP63]], align 4
-// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP64]], align 4
-// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP65]], align 4
-// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP66]], align 4
-// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP67]], align 4
-// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP68]], align 4
-// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP69]], align 4
-// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP72]], align 4
-// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP73]], align 4
-// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP70]], ptr [[TMP74]], align 4
-// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP71]], ptr [[TMP75]], align 4
-// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
-// CHECK-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP76]], align 4
-// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP77]], align 4
-// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP78]], align 4
-// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP79]], align 4
-// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP80]], align 8
-// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP81]], align 8
-// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP82]], align 4
-// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP83]], align 4
-// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP84]], align 4
-// CHECK-NEXT:    [[TMP85:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24.region_id, ptr [[KERNEL_ARGS14]])
-// CHECK-NEXT:    [[TMP86:%.*]] = icmp ne i32 [[TMP85]], 0
-// CHECK-NEXT:    br i1 [[TMP86]], label %[[OMP_OFFLOAD_FAILED15:.*]], label %[[OMP_OFFLOAD_CONT16:.*]]
+// CHECK-NEXT:    [[TMP59:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP60:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX9:%.*]] = getelementptr inbounds ptr, ptr [[TMP59]], i32 [[TMP60]]
+// CHECK-NEXT:    [[TMP61:%.*]] = load ptr, ptr [[ARRAYIDX9]], align 4
+// CHECK-NEXT:    [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw float, ptr [[TMP61]], i32 0
+// CHECK-NEXT:    [[TMP62:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP52]], ptr [[TMP62]], align 4
+// CHECK-NEXT:    [[TMP63:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP52]], ptr [[TMP63]], align 4
+// CHECK-NEXT:    [[TMP64:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP64]], align 4
+// CHECK-NEXT:    [[TMP65:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP57]], ptr [[TMP65]], align 4
+// CHECK-NEXT:    [[TMP66:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP66]], align 4
+// CHECK-NEXT:    [[TMP67:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP67]], align 4
+// CHECK-NEXT:    [[TMP68:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX8]], ptr [[TMP68]], align 4
+// CHECK-NEXT:    [[TMP69:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX10]], ptr [[TMP69]], align 4
+// CHECK-NEXT:    [[TMP70:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP70]], align 4
+// CHECK-NEXT:    [[TMP71:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 3
+// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP71]], align 4
+// CHECK-NEXT:    [[TMP72:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 3
+// CHECK-NEXT:    store i32 [[TMP54]], ptr [[TMP72]], align 4
+// CHECK-NEXT:    [[TMP73:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 3
+// CHECK-NEXT:    store ptr null, ptr [[TMP73]], align 4
+// CHECK-NEXT:    [[TMP74:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP75:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP76]], align 4
+// CHECK-NEXT:    [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
+// CHECK-NEXT:    store i32 4, ptr [[TMP77]], align 4
+// CHECK-NEXT:    [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP74]], ptr [[TMP78]], align 4
+// CHECK-NEXT:    [[TMP79:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP75]], ptr [[TMP79]], align 4
+// CHECK-NEXT:    [[TMP80:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
+// CHECK-NEXT:    store ptr @.offload_sizes.3, ptr [[TMP80]], align 4
+// CHECK-NEXT:    [[TMP81:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.4, ptr [[TMP81]], align 4
+// CHECK-NEXT:    [[TMP82:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP82]], align 4
+// CHECK-NEXT:    [[TMP83:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP83]], align 4
+// CHECK-NEXT:    [[TMP84:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP84]], align 8
+// CHECK-NEXT:    [[TMP85:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP85]], align 8
+// CHECK-NEXT:    [[TMP86:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP86]], align 4
+// CHECK-NEXT:    [[TMP87:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP87]], align 4
+// CHECK-NEXT:    [[TMP88:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP88]], align 4
+// CHECK-NEXT:    [[TMP89:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24.region_id, ptr [[KERNEL_ARGS14]])
+// CHECK-NEXT:    [[TMP90:%.*]] = icmp ne i32 [[TMP89]], 0
+// CHECK-NEXT:    br i1 [[TMP90]], label %[[OMP_OFFLOAD_FAILED15:.*]], label %[[OMP_OFFLOAD_CONT16:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED15]]:
 // CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24(ptr [[TMP52]], i32 [[TMP54]]) #[[ATTR2]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT16]]
 // CHECK:       [[OMP_OFFLOAD_CONT16]]:
-// CHECK-NEXT:    [[TMP87:%.*]] = load ptr, ptr [[F]], align 4
-// CHECK-NEXT:    [[TMP88:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    store i32 [[TMP88]], ptr [[INDEX_CASTED17]], align 4
-// CHECK-NEXT:    [[TMP89:%.*]] = load i32, ptr [[INDEX_CASTED17]], align 4
-// CHECK-NEXT:    [[TMP90:%.*]] = load ptr, ptr [[F]], align 4
 // CHECK-NEXT:    [[TMP91:%.*]] = load ptr, ptr [[F]], align 4
 // CHECK-NEXT:    [[TMP92:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds ptr, ptr [[TMP91]], i32 [[TMP92]]
-// CHECK-NEXT:    [[TMP93:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP93]], 1
+// CHECK-NEXT:    store i32 [[TMP92]], ptr [[INDEX_CASTED17]], align 4
+// CHECK-NEXT:    [[TMP93:%.*]] = load i32, ptr [[INDEX_CASTED17]], align 4
 // CHECK-NEXT:    [[TMP94:%.*]] = load ptr, ptr [[F]], align 4
 // CHECK-NEXT:    [[TMP95:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds ptr, ptr [[TMP94]], i32 [[TMP95]]
-// CHECK-NEXT:    [[TMP96:%.*]] = load ptr, ptr [[ARRAYIDX19]], align 4
-// CHECK-NEXT:    [[ARRAYIDX20:%.*]] = getelementptr inbounds nuw float, ptr [[TMP96]], i32 [[ADD]]
-// CHECK-NEXT:    [[TMP97:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
-// CHECK-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP97]], 1
-// CHECK-NEXT:    [[TMP98:%.*]] = mul nuw i32 [[ADD21]], 4
-// CHECK-NEXT:    [[TMP99:%.*]] = icmp ugt i32 4, [[TMP98]]
-// CHECK-NEXT:    [[TMP100:%.*]] = sub nuw i32 4, [[TMP98]]
-// CHECK-NEXT:    [[TMP101:%.*]] = select i1 [[TMP99]], i32 [[TMP100]], i32 0
-// CHECK-NEXT:    [[TMP102:%.*]] = sext i32 [[TMP101]] to i64
-// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 24, i1 false)
-// CHECK-NEXT:    [[TMP103:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[TMP90]], ptr [[TMP103]], align 4
-// CHECK-NEXT:    [[TMP104:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
-// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP104]], align 4
-// CHECK-NEXT:    [[TMP105:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 0
-// CHECK-NEXT:    store ptr null, ptr [[TMP105]], align 4
-// CHECK-NEXT:    [[TMP106:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP106]], align 4
-// CHECK-NEXT:    [[TMP107:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 1
-// CHECK-NEXT:    store ptr [[ARRAYIDX20]], ptr [[TMP107]], align 4
-// CHECK-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
-// CHECK-NEXT:    store i64 [[TMP102]], ptr [[TMP108]], align 4
-// CHECK-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 1
-// CHECK-NEXT:    store ptr null, ptr [[TMP109]], align 4
-// CHECK-NEXT:    [[TMP110:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP89]], ptr [[TMP110]], align 4
-// CHECK-NEXT:    [[TMP111:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 2
-// CHECK-NEXT:    store i32 [[TMP89]], ptr [[TMP111]], align 4
-// CHECK-NEXT:    [[TMP112:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 2
-// CHECK-NEXT:    store ptr null, ptr [[TMP112]], align 4
-// CHECK-NEXT:    [[TMP113:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP114:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP115:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 0
-// CHECK-NEXT:    store i32 3, ptr [[TMP116]], align 4
-// CHECK-NEXT:    [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 1
-// CHECK-NEXT:    store i32 3, ptr [[TMP117]], align 4
-// CHECK-NEXT:    [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 2
-// CHECK-NEXT:    store ptr [[TMP113]], ptr [[TMP118]], align 4
-// CHECK-NEXT:    [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 3
-// CHECK-NEXT:    store ptr [[TMP114]], ptr [[TMP119]], align 4
-// CHECK-NEXT:    [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 4
-// CHECK-NEXT:    store ptr [[TMP115]], ptr [[TMP120]], align 4
-// CHECK-NEXT:    [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 5
-// CHECK-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP121]], align 4
-// CHECK-NEXT:    [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 6
-// CHECK-NEXT:    store ptr null, ptr [[TMP122]], align 4
-// CHECK-NEXT:    [[TMP123:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 7
-// CHECK-NEXT:    store ptr null, ptr [[TMP123]], align 4
-// CHECK-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 8
-// CHECK-NEXT:    store i64 0, ptr [[TMP124]], align 8
-// CHECK-NEXT:    [[TMP125:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 9
-// CHECK-NEXT:    store i64 0, ptr [[TMP125]], align 8
-// CHECK-NEXT:    [[TMP126:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 10
-// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP126]], align 4
-// CHECK-NEXT:    [[TMP127:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 11
-// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP127]], align 4
-// CHECK-NEXT:    [[TMP128:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 12
-// CHECK-NEXT:    store i32 0, ptr [[TMP128]], align 4
-// CHECK-NEXT:    [[TMP129:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29.region_id, ptr [[KERNEL_ARGS25]])
-// CHECK-NEXT:    [[TMP130:%.*]] = icmp ne i32 [[TMP129]], 0
-// CHECK-NEXT:    br i1 [[TMP130]], label %[[OMP_OFFLOAD_FAILED26:.*]], label %[[OMP_OFFLOAD_CONT27:.*]]
+// CHECK-NEXT:    [[ARRAYIDX18:%.*]] = getelementptr inbounds ptr, ptr [[TMP94]], i32 [[TMP95]]
+// CHECK-NEXT:    [[TMP96:%.*]] = load ptr, ptr [[ARRAYIDX18]], align 4
+// CHECK-NEXT:    [[TMP97:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP98:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP98]], 1
+// CHECK-NEXT:    [[TMP99:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT:    [[TMP100:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ARRAYIDX19:%.*]] = getelementptr inbounds ptr, ptr [[TMP99]], i32 [[TMP100]]
+// CHECK-NEXT:    [[TMP101:%.*]] = load ptr, ptr [[ARRAYIDX19]], align 4
+// CHECK-NEXT:    [[ARRAYIDX20:%.*]] = getelementptr inbounds nuw float, ptr [[TMP101]], i32 [[ADD]]
+// CHECK-NEXT:    [[TMP102:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[ADD21:%.*]] = add nsw i32 [[TMP102]], 1
+// CHECK-NEXT:    [[TMP103:%.*]] = mul nuw i32 [[ADD21]], 4
+// CHECK-NEXT:    [[TMP104:%.*]] = icmp ugt i32 4, [[TMP103]]
+// CHECK-NEXT:    [[TMP105:%.*]] = sub nuw i32 4, [[TMP103]]
+// CHECK-NEXT:    [[TMP106:%.*]] = select i1 [[TMP104]], i32 [[TMP105]], i32 0
+// CHECK-NEXT:    [[TMP107:%.*]] = sext i32 [[TMP106]] to i64
+// CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 32, i1 false)
+// CHECK-NEXT:    [[TMP108:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP91]], ptr [[TMP108]], align 4
+// CHECK-NEXT:    [[TMP109:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT:    store ptr [[TMP91]], ptr [[TMP109]], align 4
+// CHECK-NEXT:    [[TMP110:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 0
+// CHECK-NEXT:    store ptr null, ptr [[TMP110]], align 4
+// CHECK-NEXT:    [[TMP111:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[TMP96]], ptr [[TMP111]], align 4
+// CHECK-NEXT:    [[TMP112:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 1
+// CHECK-NEXT:    store ptr [[ARRAYIDX20]], ptr [[TMP112]], align 4
+// CHECK-NEXT:    [[TMP113:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK-NEXT:    store i64 [[TMP107]], ptr [[TMP113]], align 4
+// CHECK-NEXT:    [[TMP114:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 1
+// CHECK-NEXT:    store ptr null, ptr [[TMP114]], align 4
+// CHECK-NEXT:    [[TMP115:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX18]], ptr [[TMP115]], align 4
+// CHECK-NEXT:    [[TMP116:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[ARRAYIDX20]], ptr [[TMP116]], align 4
+// CHECK-NEXT:    [[TMP117:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 2
+// CHECK-NEXT:    store ptr null, ptr [[TMP117]], align 4
+// CHECK-NEXT:    [[TMP118:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 3
+// CHECK-NEXT:    store i32 [[TMP93]], ptr [[TMP118]], align 4
+// CHECK-NEXT:    [[TMP119:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 3
+// CHECK-NEXT:    store i32 [[TMP93]], ptr [[TMP119]], align 4
+// CHECK-NEXT:    [[TMP120:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 3
+// CHECK-NEXT:    store ptr null, ptr [[TMP120]], align 4
+// CHECK-NEXT:    [[TMP121:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP122:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP123:%.*]] = getelementptr inbounds [4 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP124:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 0
+// CHECK-NEXT:    store i32 3, ptr [[TMP124]], align 4
+// CHECK-NEXT:    [[TMP125:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 1
+// CHECK-NEXT:    store i32 4, ptr [[TMP125]], align 4
+// CHECK-NEXT:    [[TMP126:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 2
+// CHECK-NEXT:    store ptr [[TMP121]], ptr [[TMP126]], align 4
+// CHECK-NEXT:    [[TMP127:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 3
+// CHECK-NEXT:    store ptr [[TMP122]], ptr [[TMP127]], align 4
+// CHECK-NEXT:    [[TMP128:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 4
+// CHECK-NEXT:    store ptr [[TMP123]], ptr [[TMP128]], align 4
+// CHECK-NEXT:    [[TMP129:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 5
+// CHECK-NEXT:    store ptr @.offload_maptypes.6, ptr [[TMP129]], align 4
+// CHECK-NEXT:    [[TMP130:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 6
+// CHECK-NEXT:    store ptr null, ptr [[TMP130]], align 4
+// CHECK-NEXT:    [[TMP131:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 7
+// CHECK-NEXT:    store ptr null, ptr [[TMP131]], align 4
+// CHECK-NEXT:    [[TMP132:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 8
+// CHECK-NEXT:    store i64 0, ptr [[TMP132]], align 8
+// CHECK-NEXT:    [[TMP133:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 9
+// CHECK-NEXT:    store i64 0, ptr [[TMP133]], align 8
+// CHECK-NEXT:    [[TMP134:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 10
+// CHECK-NEXT:    store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP134]], align 4
+// CHECK-NEXT:    [[TMP135:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 11
+// CHECK-NEXT:    store [3 x i32] zeroinitializer, ptr [[TMP135]], align 4
+// CHECK-NEXT:    [[TMP136:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 12
+// CHECK-NEXT:    store i32 0, ptr [[TMP136]], align 4
+// CHECK-NEXT:    [[TMP137:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29.region_id, ptr [[KERNEL_ARGS25]])
+// CHECK-NEXT:    [[TMP138:%.*]] = icmp ne i32 [[TMP137]], 0
+// CHECK-NEXT:    br i1 [[TMP138]], label %[[OMP_OFFLOAD_FAILED26:.*]], label %[[OMP_OFFLOAD_CONT27:.*]]
 // CHECK:       [[OMP_OFFLOAD_FAILED26]]:
-// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(ptr [[TMP87]], i32 [[TMP89]]) #[[ATTR2]]
+// CHECK-NEXT:    call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(ptr [[TMP91]], i32 [[TMP93]]) #[[ATTR2]]
 // CHECK-NEXT:    br label %[[OMP_OFFLOAD_CONT27]]
 // CHECK:       [[OMP_OFFLOAD_CONT27]]:
 // CHECK-NEXT:    ret void
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 737c855adc05b..7663a1c6ea87f 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen.cpp
@@ -60,9 +60,9 @@ void f6() {
 
 void f7() {
   int *ptr;
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
   // &ptr, &ptr[2], sizeof(ptr), ATTACH
-  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 11;
 }
@@ -80,8 +80,8 @@ void f7() {
 // CHECK: @.offload_maptypes.8 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
-// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
-// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x3]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -305,13 +305,13 @@ void f7() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr [[PTR]], align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP0]], ptr [[TMP2]], align 8
+// CHECK:    store ptr [[PTR]], ptr [[TMP2]], align 8
 // CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    store ptr [[PTR]], ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
 // CHECK:    store ptr null, ptr [[TMP4]], align 8
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr [[PTR]], ptr [[TMP5]], align 8
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
 // CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
 // CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
@@ -319,7 +319,7 @@ void f7() {
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
 // CHECK:    store ptr [[PTR]], ptr [[TMP8]], align 8
 // CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr [[PTR]], ptr [[TMP9]], align 8
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
 // CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
 // CHECK:    store ptr null, ptr [[TMP10]], align 8
 // CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
index 701d09a4889fa..4958e839207f6 100644
--- a/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
+++ b/clang/test/OpenMP/target_map_both_pointer_pointee_codegen_global.cpp
@@ -55,9 +55,9 @@ void f6() {
 }
 
 void f7() {
+  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   // &ptr[0], &ptr[2], sizeof(ptr[2]), TO | FROM
   // &ptr, &ptr[2], sizeof(ptr), ATTACH
-  // &ptr, &ptr, sizeof(ptr), TO | FROM | PARAM
   #pragma omp target data map(ptr[2], ptr)
     ptr[2] = 11;
 }
@@ -75,8 +75,8 @@ void f7() {
 // CHECK: @.offload_maptypes.8 = private unnamed_addr constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
 // CHECK: @.offload_sizes.9 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
 // CHECK: @.offload_maptypes.10 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
-// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 4, i64 8, i64 8]
-// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x4000]], i64 [[#0x3]]]
+// CHECK: @.offload_sizes.11 = private unnamed_addr constant [3 x i64] [i64 8, i64 4, i64 8]
+// CHECK: @.offload_maptypes.12 = private unnamed_addr constant [3 x i64] [i64 [[#0x3]], i64 [[#0x3]], i64 [[#0x4000]]]
 //.
 // CHECK-LABEL: define {{[^@]+}}@_Z2f1v
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
@@ -300,13 +300,13 @@ void f7() {
 // CHECK:    [[TMP1:%.*]] = load ptr, ptr @ptr, align 8
 // CHECK:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 2
 // CHECK:    [[TMP2:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[TMP0]], ptr [[TMP2]], align 8
+// CHECK:    store ptr @ptr, ptr [[TMP2]], align 8
 // CHECK:    [[TMP3:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS:%.*]], i32 0, i32 0
-// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP3]], align 8
+// CHECK:    store ptr @ptr, ptr [[TMP3]], align 8
 // CHECK:    [[TMP4:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS:%.*]], i64 0, i64 0
 // CHECK:    store ptr null, ptr [[TMP4]], align 8
 // CHECK:    [[TMP5:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 1
-// CHECK:    store ptr @ptr, ptr [[TMP5]], align 8
+// CHECK:    store ptr [[TMP0]], ptr [[TMP5]], align 8
 // CHECK:    [[TMP6:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 1
 // CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP6]], align 8
 // CHECK:    [[TMP7:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 1
@@ -314,7 +314,7 @@ void f7() {
 // CHECK:    [[TMP8:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 2
 // CHECK:    store ptr @ptr, ptr [[TMP8]], align 8
 // CHECK:    [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 2
-// CHECK:    store ptr @ptr, ptr [[TMP9]], align 8
+// CHECK:    store ptr [[ARRAYIDX]], ptr [[TMP9]], align 8
 // CHECK:    [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i64 0, i64 2
 // CHECK:    store ptr null, ptr [[TMP10]], align 8
 // CHECK:    [[TMP11:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/target_map_codegen_18.inc b/clang/test/OpenMP/target_map_codegen_18.inc
index a3a716b8fc8a1..57c89472634be 100644
--- a/clang/test/OpenMP/target_map_codegen_18.inc
+++ b/clang/test/OpenMP/target_map_codegen_18.inc
@@ -157,14 +157,16 @@
 // CK19-NOUSE: [[MTYPE27:@.+]] = private {{.*}}constant [1 x i64] [i64 3]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE28:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 16]
-// CK19-USE: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
-// CK19-NOUSE: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 3, i64 16, i64 19]
+// CK19-USE: [[SIZE28:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 16, i64 {{4|8}}]
+// CK19-USE: [[MTYPE28:@.+]] = private {{.*}}constant [3 x i64] [i64 544, i64 3, i64 16384]
+// CK19-NOUSE: [[SIZE28:@.+]] = private {{.*}}constant [2 x i64] [i64 16, i64 {{4|8}}]
+// CK19-NOUSE: [[MTYPE28:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE29:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 4]
-// CK19-USE: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
-// CK19-NOUSE: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 3, i64 16, i64 19]
+// CK19-USE: [[SIZE29:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 4, i64 {{4|8}}]
+// CK19-USE: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 544, i64 3, i64 16384]
+// CK19-NOUSE: [[SIZE29:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
+// CK19-NOUSE: [[MTYPE29:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK19-USE: [[SIZE30:@.+]] = private {{.*}}constant [4 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 {{8|4}}, i64 0]
@@ -228,9 +230,10 @@
 // CK19-NOUSE: [[MTYPE41:@.+]] = private {{.*}}constant [1 x i64] [i64 3]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK19: [[SIZE42:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 104]
-// CK19-USE: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19]
-// CK19-NOUSE: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 3, i64 16, i64 19]
+// CK19-USE: [[SIZE42:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 104, i64 {{4|8}}]
+// CK19-USE: [[MTYPE42:@.+]] = private {{.*}}constant [3 x i64] [i64 544, i64 3, i64 16384]
+// CK19-NOUSE: [[SIZE42:@.+]] = private {{.*}}constant [2 x i64] [i64 104, i64 {{4|8}}]
+// CK19-NOUSE: [[MTYPE42:@.+]] = private {{.*}}constant [2 x i64] [64 3, i64 16384]
 
 // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK19-USE: [[MTYPE43:@.+]] = private {{.*}}constant [1 x i64] [i64 35]
@@ -1171,6 +1174,11 @@ void explicit_maps_single (int ii){
   }
 
   // Region 28
+
+  // &mptr[0], &mptr[0], 0, IMPLICIT | PARAM
+  // &mptr[1][2][0], &mptr[1][2][2], sizeof(mptr[1][2][2:4]), TO | FROM
+  // &mptr[1][2], &mptr[1][2][2], sizeof(void*), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -1182,30 +1190,29 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-  // CK19-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%[^,]+]],
-  // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC00]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR0]], ptr [[P0]]
+  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%mptr]]
 
   // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
   // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-  // CK19-DAG: store ptr [[SEC0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
   // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+  // CK19-DAG: [[VAR11]] = getelementptr {{.*}}ptr [[VAR111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[VAR111]] = load ptr, ptr [[VAR1111:%[^,]+]],
+  // CK19-DAG: [[VAR1111]] = getelementptr {{.*}}ptr [[VAR11111:[^,]+]], i{{.+}} 1
+  // CK19-DAG: [[VAR11111]] = load ptr, ptr [[PTR]]
+  // CK19-DAG: [[SEC1:%.+]] = getelementptr {{.*}}i32, ptr [[SEC11:%.+]], i{{.*}} 2
+  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[SEC11111:%[^,]+]],
+  // CK19-DAG: [[SEC11111]] = getelementptr {{.*}}ptr [[SEC111111:[^,]+]], i{{.+}} 1
+  // CK19-DAG: [[SEC111111]] = load ptr, ptr [[PTR]]
 
   // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
   // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-  // CK19-DAG: store ptr [[SEC1]], ptr [[BP2]]
-  // CK19-DAG: store ptr [[SEC2:%.+]], ptr [[P2]]
-  // CK19-DAG: [[SEC2]] = getelementptr {{.*}}ptr [[SEC22:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC22]] = load ptr, ptr [[SEC222:%[^,]+]],
-  // CK19-DAG: [[SEC222]] = getelementptr {{.*}}ptr [[SEC2222:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC2222]] = load ptr, ptr [[SEC22222:%[^,]+]],
-  // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}ptr [[SEC222222:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC222222]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR11]], ptr [[BP2]]
+  // CK19-DAG: store ptr [[SEC1]], ptr [[P2]]
 
   // CK19-USE: call void [[CALL28:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL28:@.+]]()
@@ -1217,6 +1224,11 @@ void explicit_maps_single (int ii){
   }
 
   // Region 29
+
+  // &mptr[0], &mptr[0], 0, IMPLICIT | PARAM
+  // &mptr[1][2][0], &mptr[1][2][3], sizeof(mptr[1][2][3]), TO | FROM
+  // &mptr[1][2], &mptr[1][2][3], sizeof(void*), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -1228,30 +1240,29 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-  // CK19-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%[^,]+]],
-  // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC00]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR0]], ptr [[P0]]
+  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%mptr]]
 
   // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
   // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-  // CK19-DAG: store ptr [[SEC0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
   // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+  // CK19-DAG: [[VAR11]] = getelementptr {{.*}}ptr [[VAR111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[VAR111]] = load ptr, ptr [[VAR1111:%[^,]+]],
+  // CK19-DAG: [[VAR1111]] = getelementptr {{.*}}ptr [[VAR11111:[^,]+]], i{{.+}} 1
+  // CK19-DAG: [[VAR11111]] = load ptr, ptr [[PTR]]
+  // CK19-DAG: [[SEC1:%.+]] = getelementptr {{.*}}i32, ptr [[SEC11:%.+]], i{{.*}} 3
+  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[SEC11111:%[^,]+]],
+  // CK19-DAG: [[SEC11111]] = getelementptr {{.*}}ptr [[SEC111111:[^,]+]], i{{.+}} 1
+  // CK19-DAG: [[SEC111111]] = load ptr, ptr [[PTR]]
 
   // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
   // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-  // CK19-DAG: store ptr [[SEC1]], ptr [[BP2]]
-  // CK19-DAG: store ptr [[SEC2:%.+]], ptr [[P2]]
-  // CK19-DAG: [[SEC2]] = getelementptr {{.*}}ptr [[SEC22:[^,]+]], i{{.+}} 3
-  // CK19-DAG: [[SEC22]] = load ptr, ptr [[SEC222:%[^,]+]],
-  // CK19-DAG: [[SEC222]] = getelementptr {{.*}}ptr [[SEC2222:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC2222]] = load ptr, ptr [[SEC22222:%[^,]+]],
-  // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}ptr [[SEC222222:[^,]+]], i{{.+}} 1
-  // CK19-DAG: [[SEC222222]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR11]], ptr [[BP2]]
+  // CK19-DAG: store ptr [[SEC1]], ptr [[P2]]
 
   // CK19-USE: call void [[CALL29:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL29:@.+]]()
@@ -1754,6 +1765,11 @@ void explicit_maps_single (int ii){
   }
 
   // Region 42
+
+  // &mptras[0], &mptras[0], 0, IMPLICIT | PARAM
+  // &mptras[0][2][0], &mptras[0][2][0], sizeof(mptras[:1][2][:13]), TO | FROM
+  // &mptr[0][2], &mptr[0][2][0], sizeof(void*), ATTACH
+
   // CK19-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 [[DEVICE:.+]], i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
   // CK19-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
   // CK19-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -1765,30 +1781,29 @@ void explicit_maps_single (int ii){
   // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
   // CK19-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-  // CK19-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%[^,]+]],
-  // CK19-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:[^,]+]], i{{.+}} 0
-  // CK19-DAG: [[SEC00]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR0]], ptr [[P0]]
+  // CK19-DAG: [[VAR0]] = load ptr, ptr [[PTR:%mptras]]
 
   // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
   // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-  // CK19-DAG: store ptr [[SEC0]], ptr [[BP1]]
+  // CK19-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
   // CK19-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 0
-  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+  // CK19-DAG: [[VAR11]] = getelementptr {{.*}}ptr [[VAR111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[VAR111]] = load ptr, ptr [[VAR1111:%[^,]+]],
+  // CK19-DAG: [[VAR1111]] = getelementptr {{.*}}ptr [[VAR11111:[^,]+]], i{{.+}} 0
+  // CK19-DAG: [[VAR11111]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:[^,]+]], i{{.+}} 0
+  // CK19-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+  // CK19-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 2
+  // CK19-DAG: [[SEC1111]] = load ptr, ptr [[SEC11111:%[^,]+]],
+  // CK19-DAG: [[SEC11111]] = getelementptr {{.*}}ptr [[SEC111111:[^,]+]], i{{.+}} 0
+  // CK19-DAG: [[SEC111111]] = load ptr, ptr [[PTR]],
 
   // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
   // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-  // CK19-DAG: store ptr [[SEC1]], ptr [[BP2]]
-  // CK19-DAG: store ptr [[SEC2:%.+]], ptr [[P2]]
-  // CK19-DAG: [[SEC2]] = getelementptr {{.*}}ptr [[SEC22:[^,]+]], i{{.+}} 0
-  // CK19-DAG: [[SEC22]] = load ptr, ptr [[SEC222:%[^,]+]],
-  // CK19-DAG: [[SEC222]] = getelementptr {{.*}}ptr [[SEC2222:[^,]+]], i{{.+}} 2
-  // CK19-DAG: [[SEC2222]] = load ptr, ptr [[SEC22222:%[^,]+]],
-  // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}ptr [[SEC222222:[^,]+]], i{{.+}} 0
-  // CK19-DAG: [[SEC222222]] = load ptr, ptr [[PTR]],
+  // CK19-DAG: store ptr [[VAR11]], ptr [[BP2]]
+  // CK19-DAG: store ptr [[SEC1]], ptr [[P2]]
 
   // CK19-USE: call void [[CALL42:@.+]](ptr {{[^,]+}})
   // CK19-NOUSE: call void [[CALL42:@.+]]()
diff --git a/clang/test/OpenMP/target_map_codegen_20.cpp b/clang/test/OpenMP/target_map_codegen_20.cpp
index afaa35b79b889..5172ada2eefe1 100644
--- a/clang/test/OpenMP/target_map_codegen_20.cpp
+++ b/clang/test/OpenMP/target_map_codegen_20.cpp
@@ -74,9 +74,9 @@
 // CK21-NOUSE: [[MTYPE01:@.+]] = private {{.*}}constant [2 x i64] [i64 3, i64 16384]
 
 // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 500]
-// CK21-USE: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710674]
-// CK21-NOUSE: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 281474976710674]
+// CK21: [[SIZE02:@.+]] = private {{.*}}constant [2 x i64] [i64 500, i64 {{4|8}}]
+// CK21-USE: [[MTYPE02:@.+]] = private unnamed_addr constant [2 x i64] [i64 34, i64 16384]
+// CK21-NOUSE: [[MTYPE02:@.+]] = private {{.*}}constant [2 x i64] [i64 2, i64 16384]
 
 // CK21-LABEL: @.__omp_offloading_{{.*}}foo{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK21: [[SIZE03:@.+]] = private {{.*}}constant [1 x i64] [i64 492]
@@ -167,32 +167,32 @@ struct CC {
     }
 
 // Region 02
+
+//  &B[0], &B[X], 2 * sizeof(T), (FROM) / (FROM | PARAM)
+//  &B, &B[X], sizeof(T*), ATTACH
+
 // CK21-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK21-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK21-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK21-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK21-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK21-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK21-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK21-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK21-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK21-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK21-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK21-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK21-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK21-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
 // CK21-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK21-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK21-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[VAR0]], i{{.+}} 0, i{{.+}} 2
+// CK21-DAG: [[VAR0]] = load ptr, ptr [[VAR00:%[^,]+]]
+// CK21-DAG: [[VAR00]] = getelementptr inbounds nuw %struct.CC, ptr [[THIS:%.+]], i{{.*}} 0, i{{.*}} 2
+// CK21-DAG: [[SEC0]] = getelementptr inbounds nuw float, ptr [[SEC00:%.+]], i{{.*}} 123
+// CK21-DAG: [[SEC00]] = load ptr, ptr [[SEC000:%[^,]+]]
+// CK21-DAG: [[SEC000]] = getelementptr inbounds nuw %struct.CC, ptr [[THIS]], i{{.*}} 0, i{{.*}} 2
 
 // CK21-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK21-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK21-DAG: store ptr [[SEC0]], ptr [[BP1]]
-// CK21-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK21-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[RVAR1:%[^,]+]], i{{.+}} 123
-// CK21-DAG: [[RVAR1]] = load ptr, ptr [[SEC1_:%[^,]+]]
-// CK21-DAG: [[SEC1_]] = getelementptr {{.*}}ptr [[VAR0]], i{{.+}} 0, i{{.+}} 2
+// CK21-DAG: store ptr [[VAR00]], ptr [[BP1]]
+// CK21-DAG: store ptr [[SEC0]], ptr [[P1]]
 
 // CK21-USE: call void [[CALL02:@.+]](ptr {{[^,]+}})
 // CK21-NOUSE: call void [[CALL02:@.+]]()
diff --git a/clang/test/OpenMP/target_map_codegen_23.cpp b/clang/test/OpenMP/target_map_codegen_23.cpp
index 3801af995455a..a59560f6a5ceb 100644
--- a/clang/test/OpenMP/target_map_codegen_23.cpp
+++ b/clang/test/OpenMP/target_map_codegen_23.cpp
@@ -77,36 +77,36 @@ struct SC{
 // CK24: [[MTYPE16:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE17:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 {{3560|2880}}]
-// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675]
+// CK24: [[SIZE17:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{3560|2880}}, i64 {{4|8}}]
+// CK24: [[MTYPE17:@.+]] = private {{.*}}constant [3 x i64] [i64 544, i64 3, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK24: [[SIZE18:@.+]] = private {{.*}}constant [2 x i64] [i64 4, i64 {{4|8}}]
 // CK24: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 35, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE19:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{8|4}}, i64 4]
-// CK24: [[MTYPE19:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
+// CK24: [[SIZE19:@.+]] = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE19:@.+]] = private unnamed_addr constant [3 x i64] [i64 544, i64 3, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE20:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 4]
-// CK24: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 32, i64 281474976710675]
+// CK24: [[SIZE20:@.+]] = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE20:@.+]] = private unnamed_addr constant [3 x i64] [i64 544, i64 3, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE21:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{8|4}}, i64 4]
-// CK24: [[MTYPE21:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
+// CK24: [[SIZE21:@.+]] = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE21:@.+]] = private unnamed_addr constant [3 x i64] [i64 544, i64 3, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
 // CK24: [[SIZE22:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 8, i64 {{4|8}}]
 // CK24: [[MTYPE22:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE23:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 {{8|4}}, i64 8]
-// CK24: [[MTYPE23:@.+]] = private {{.*}}constant [3 x i64] [i64 32, i64 281474976710659, i64 281474976710675]
+// CK24: [[SIZE23:@.+]] = private unnamed_addr constant [4 x i64] [i64 0, i64 0, i64 8, i64 {{4|8}}]
+// CK24: [[MTYPE23:@.+]] = private unnamed_addr constant [4 x i64] [i64 544, i64 0, i64 562949953421315, i64 16384]
 
 // CK24-LABEL: @.__omp_offloading_{{.*}}explicit_maps_struct_fields{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0
-// CK24: [[SIZE24:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 {{8|4}}, i64 {{8|4}}, i64 4]
-// CK24: [[MTYPE24:@.+]] = private {{.*}}constant [4 x i64] [i64 32, i64 281474976710672, i64 16, i64 19]
+// CK24: [[SIZE24:@.+]] = private unnamed_addr constant [3 x i64] [i64 0, i64 4, i64 {{4|8}}]
+// CK24: [[MTYPE24:@.+]] = private unnamed_addr constant [3 x i64] [i64 544, i64 3, i64 16384]
 
 // CK24-LABEL: explicit_maps_struct_fields
 int explicit_maps_struct_fields(int a){
@@ -284,36 +284,41 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 17
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p[0]->p[0], &p->p[/*lb=*/0], sizeof(p->p[0:5]), TO | FROM
+//  &p[0]->p, &p->p[/*lb=*/0], sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK24-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK24-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK24-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK24-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK24-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK24-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK24-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP1]]
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
 // CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]],
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}%struct.SC, ptr [[VAR111:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[VAR111]] = load ptr, ptr %p
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}%struct.SB, ptr [[SEC11:%[^,]+]], i{{.+}} 0
 // CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC1111:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[SEC1111]] = load ptr, ptr %p
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
 // CK24: call void [[CALL17:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->p[:5])
@@ -359,124 +364,131 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 19
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p->s.sp[3][0], &p->s.sp[3]->a, sizeof(p->s.sp[3]->a), TO | FROM
+//  &p->s.sp[3], &p->s.sp[3]->a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK24-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK24-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK24-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK24-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK24-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK24-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK24-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: [[SEC00]] = getelementptr {{.*}}ptr [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: [[SEC000]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[VAR0]], ptr [[BP1]]
-// CK24-DAG: store ptr [[SEC0]], ptr [[P1]]
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}[10 x ptr], ptr [[VAR111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[VAR111]] = getelementptr {{.*}}%struct.SB, ptr [[VAR1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[VAR1111]] = getelementptr {{.*}}%struct.SC, ptr [[VAR11111:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[VAR11111]] = load ptr, ptr %p
+
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}%struct.SA, ptr [[SEC11:%.+]], i{{.*}} 0, i{{.*}} 0
+// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}[10 x ptr], ptr [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}%struct.SB, ptr [[SEC11111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[SEC11111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC111111:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[SEC111111]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP2]]
-// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P2]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}ptr [[SEC11111:%[^,]+]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: [[SEC11111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 1
-
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
 // CK24: call void [[CALL19:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.sp[3]->a)
   { p->a++; }
 
 // Region 20
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p->p[0], &p->p->a, sizeof(p->p->a), TO | FROM
+//  &p->p, &p->p->a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK24-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK24-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK24-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK24-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK24-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK24-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK24-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP1]]
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
 // CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0
-// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}%struct.SC, ptr [[VAR111:.+]], i{{.*}} 0, i{{.*}} 2
+// CK24-DAG: [[VAR111]] = load ptr, ptr %p
+
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}%struct.SB, ptr [[SEC11:%[^,]+]], i{{.+}} 0
+// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC1111:.+]], i{{.*}} 0, i{{.*}} 2
+// CK24-DAG: [[SEC1111]] = load ptr, ptr %p
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
 // CK24: call void [[CALL20:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->p->a)
   { p->a++; }
 
 // Region 21
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p->s.p[0], &p->s.p->a, sizeof(p->s.p->a), TO | FROM
+//  &p->s.p, &p->s.p->a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK24-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK24-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK24-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK24-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK24-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK24-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK24-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC00]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[VAR0]], ptr [[BP1]]
-// CK24-DAG: store ptr [[SEC0]], ptr [[P1]]
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}%struct.SB, ptr [[VAR111:[^,]+]], i{{.+}} 0, i{{.+}} 4
+// CK24-DAG: [[VAR111]] = getelementptr {{.*}}%struct.SC, ptr [[VAR1111:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[VAR1111]] = load ptr, ptr %p
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}%struct.SA, ptr [[SEC11:%[^,]+]], i{{.+}} 0
+// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}%struct.SB, ptr [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4
+// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC11111:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: [[SEC11111]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP2]]
-// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P2]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0
-// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[SEC1111:[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 1
-
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
 // CK24: call void [[CALL21:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.p->a)
@@ -484,8 +496,8 @@ int explicit_maps_struct_fields(int a){
 
 // Region 22
 
-//  &p[0], &p->s.s.b[0], sizeof(p->s.s.bb[0:2]), ALLOC | PARAM
-//  &p[0], &p->s.s.bb[0], sizeof(p->s.s.bb[0:2]), TO | FROM
+//  &p[0], &p->s.s.b[0], sizeof(p->s.s.b[0:2]), ALLOC | PARAM
+//  &p[0], &p->s.s.b[0], sizeof(p->s.s.b[0:2]), TO | FROM
 //  &p, &p->s.s.b[0], sizeof(p), ATTACH
 
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
@@ -528,6 +540,12 @@ int explicit_maps_struct_fields(int a){
   { p->a++; }
 
 // Region 23
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p->s.p[0], &p->s.p->b[0], sizeof(p->s.p->b[:2]), ALLOC
+//  &p->s.p[0], &p->s.p->b[0], sizeof(p->s.p->b[:2]),MEMBER_OF_1 | TO | FROM
+//  &p->s.p, &p->s.p->b[0], sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
@@ -541,91 +559,87 @@ int explicit_maps_struct_fields(int a){
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[SEC00:%[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC00]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[VAR0]], ptr [[BP1]]
-// CK24-DAG: store ptr [[SEC0]], ptr [[P1]]
+// CK24-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
+// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
+// CK24-DAG: store i64 {{%.+}}, ptr [[S1]]
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}%struct.SB, ptr [[VAR111:%.+]], i{{.*}} 0, i{{.*}} 4
+// CK24-DAG: [[VAR111]] = getelementptr {{.*}}%struct.SC, ptr [[VAR1111:%.+]], i{{.*}} 0, i{{.*}} 1
+// CK24-DAG: [[VAR1111]] = load ptr, ptr %p
+
+// CK24-DAG: [[SEC1]] = getelementptr {{.*}}[10 x i{{.*}}], ptr [[SEC11:%.+]], i{{.*}} 0, i{{.*}} 0
+// CK24-DAG: [[SEC11]] = getelementptr {{.*}}%struct.SA, ptr [[SEC111:%.+]], i{{.*}} 0, i{{.*}} 2
+// CK24-DAG: [[SEC111]] = load ptr, ptr [[SEC1111:%[^,]+]]
+// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}%struct.SB, ptr [[SEC11111:%.+]], i{{.*}} 0, i{{.*}} 4
+// CK24-DAG: [[SEC11111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC111111:%.+]], i{{.*}} 0, i{{.*}} 1
+// CK24-DAG: [[SEC111111]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP2]]
-// CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P2]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[SEC11]] = getelementptr {{.*}}ptr [[SEC111:%[^,]+]], i{{.+}} 0, i{{.+}} 2
-// CK24-DAG: [[SEC111]] = load ptr, ptr [[SEC1111:%[^,]+]],
-// CK24-DAG: [[SEC1111]] = getelementptr {{.*}}ptr [[SEC11111:%[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC11111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 1
+// CK24-DAG: store ptr [[VAR1]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP3]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P3]]
 
 // CK24: call void [[CALL23:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->s.p->b[:2])
   { p->a++; }
 
 // Region 24
+
+//  &p[0], &p[0], 0, IMPLICIT | PARAM
+//  &p->p->p->p[0], &p->p->p->p->a, sizeof(p->p->p->p->a), TO | FROM
+//  &p->p->p->p, &p->p->p->p->a, sizeof(p), ATTACH
+
 // CK24-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CK24-DAG: [[BPARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 2
 // CK24-DAG: store ptr [[BPGEP:%.+]], ptr [[BPARG]]
 // CK24-DAG: [[PARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 3
 // CK24-DAG: store ptr [[PGEP:%.+]], ptr [[PARG]]
-// CK24-DAG: [[SARG:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CK24-DAG: store ptr [[SIZES:%.+]], ptr [[SARG]]
 // CK24-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
 // CK24-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
-// CK24-DAG: [[SIZES]] = getelementptr inbounds {{.+}}[[S:%[^,]+]]
 
 // CK24-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0
 // CK24-DAG: store ptr [[VAR0:%.+]], ptr [[BP0]]
-// CK24-DAG: store ptr [[SEC0:%.+]], ptr [[P0]]
-// CK24-DAG: store i64 {{%.+}}, ptr [[S0]]
-// CK24-DAG: [[SEC0]] = getelementptr {{.*}}ptr [[VAR00:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: store ptr [[VAR0]], ptr [[P0]]
+// CK24-DAG: [[VAR0]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
 // CK24-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: store ptr [[SEC0]], ptr [[BP1]]
+// CK24-DAG: store ptr [[VAR1:%.+]], ptr [[BP1]]
 // CK24-DAG: store ptr [[SEC1:%.+]], ptr [[P1]]
-// CK24-DAG: [[SEC1]] = getelementptr {{.*}}ptr [[SEC11:%[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]],
-// CK24-DAG: [[SEC111]] = getelementptr {{.*}}ptr [[VAR000:%.+]], i{{.+}} 0, i{{.+}} 2
+// CK24-DAG: [[VAR1]] = load ptr, ptr [[VAR11:%[^,]+]]
+// CK24-DAG: [[VAR11]] = getelementptr {{.*}}%struct.SA, ptr [[VAR111:%.+]], i{{.*}} 0, i{{.*}} 1
+// CK24-DAG: [[VAR111]] = load ptr, ptr [[VAR1111:%[^,]+]]
+// CK24-DAG: [[VAR1111]] = getelementptr {{.*}}%struct.SB, ptr [[VAR11111:%.+]], i{{.*}} 0, i{{.*}} 4
+// CK24-DAG: [[VAR11111]] = load ptr, ptr [[VAR111111:%[^,]+]]
+// CK24-DAG: [[VAR111111]] = getelementptr {{.*}}%struct.SC, ptr [[VAR1111111:%.+]], i{{.*}} 0, i{{.*}} 2
+// CK24-DAG: [[VAR1111111]] = load ptr, ptr %p
+
+// CK24-DAG: [[SEC1:%.+]] = getelementptr {{.*}}%struct.SA, ptr [[SEC11:%.+]], i{{.*}} 0, i{{.*}} 0
+// CK24-DAG: [[SEC11]] = load ptr, ptr [[SEC111:%[^,]+]]
+// CK24-DAG: [[SEC111]] = getelementptr {{.*}}%struct.SA, ptr [[SEC1111:%.+]], i{{.*}} 0, i{{.*}} 1
+// CK24-DAG: [[SEC1111]] = load ptr, ptr [[SEC11111:%[^,]+]]
+// CK24-DAG: [[SEC11111]] = getelementptr {{.*}}%struct.SB, ptr [[SEC111111:%.+]], i{{.*}} 0, i{{.*}} 4
+// CK24-DAG: [[SEC111111]] = load ptr, ptr [[SEC1111111:%[^,]+]]
+// CK24-DAG: [[SEC1111111]] = getelementptr {{.*}}%struct.SC, ptr [[SEC11111111:%.+]], i{{.*}} 0, i{{.*}} 2
+// CK24-DAG: [[SEC11111111]] = load ptr, ptr %p
 
 // CK24-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
 // CK24-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
-// CK24-DAG: store ptr [[SEC1]], ptr [[BP2]]
-// CK24-DAG: store ptr [[SEC2:%.+]], ptr [[P2]]
-// CK24-DAG: [[SEC2]] = getelementptr {{.*}}ptr [[SEC22:%[^,]+]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: [[SEC22]] = load ptr, ptr [[SEC222:%[^,]+]],
-// CK24-DAG: [[SEC222]] = getelementptr {{.*}}ptr [[SEC2222:%[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC2222]] = load ptr, ptr [[SEC22222:%[^,]+]],
-// CK24-DAG: [[SEC22222]] = getelementptr {{.*}}ptr [[VAR0000:%.+]], i{{.+}} 0, i{{.+}} 2
-
-// CK24-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
-// CK24-DAG: store ptr [[SEC2]], ptr [[BP3]]
-// CK24-DAG: store ptr [[SEC3:%.+]], ptr [[P3]]
-// CK24-DAG: [[SEC3]] = getelementptr {{.*}}ptr [[SEC33:%[^,]+]], i{{.+}} 0, i{{.+}} 0
-// CK24-DAG: [[SEC33]] = load ptr, ptr [[SEC333:%[^,]+]],
-// CK24-DAG: [[SEC333]] = getelementptr {{.*}}ptr [[SEC3333:%[^,]+]], i{{.+}} 0, i{{.+}} 1
-// CK24-DAG: [[SEC3333]] = load ptr, ptr [[SEC33333:%[^,]+]],
-// CK24-DAG: [[SEC33333]] = getelementptr {{.*}}ptr [[SEC333333:%[^,]+]], i{{.+}} 0, i{{.+}} 4
-// CK24-DAG: [[SEC333333]] = load ptr, ptr [[SEC3333333:%[^,]+]],
-// CK24-DAG: [[SEC3333333]] = getelementptr {{.*}}ptr [[VAR00000:%.+]], i{{.+}} 0, i{{.+}} 2
-
-// CK24-DAG: [[VAR0]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR000]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR0000]] = load ptr, ptr %{{.+}}
-// CK24-DAG: [[VAR00000]] = load ptr, ptr %{{.+}}
+// CK24-DAG: store ptr [[VAR11]], ptr [[BP2]]
+// CK24-DAG: store ptr [[SEC1]], ptr [[P2]]
 
 // CK24: call void [[CALL24:@.+]](ptr {{[^,]+}})
 #pragma omp target map(p->p->p->p->a)
diff --git a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
index db569bfa6cf44..fbb4f75f0b32e 100644
--- a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
+++ b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
@@ -40,11 +40,28 @@ void foo() {
 }
 #endif
 
-// CHECK: @.offload_sizes = private unnamed_addr constant [5 x i64] [i64 8, i64 0, i64 0, i64 0, i64 4]
-// CHECK-NOT: @.offload_sizes = private unnamed_addr constant [6 x i64] [i64 8, i64 0, i64 0, i64 0, i64 8, i64 4]
-// CHECK: @.offload_maptypes = private unnamed_addr constant [5 x i64] [i64 35, i64 16, i64 562949953421315, i64 562949953421315, i64 562949953421827]
-// CHECK-NOT: .offload_maptypes = private unnamed_addr constant  [6 x i64] [i64 35, i64 0, i64 562949953421315, i64 562949953421315, i64 562949953421827, i64 562949953421843]
+// &spp[0],    &spp[0],      0,                 IMPLICIT | PARAM
+// &spp[0][0], &spp[0][0],   sizeof(spp[0][0]), ALLOC
+// &spp[0][0], &spp[0][0].e, sizeof(e),         MEMBER_OF_2 | TO | FROM
+// &spp[0][0], &spp[0][0].h, sizeof(h),         MEMBER_OF_2 | TO | FROM
+// &spp[0][0], &spp[0][0].f, sizeof(f),         MEMBER_OF_2 | TO | FROM | IMPLICIT, mapper_of_c
+// &spp[0],    &spp[0][0],   sizeof(void*),     ATTACH
+// CHECK: @.offload_sizes = private unnamed_addr constant [6 x i64] [i64 0, i64 0, i64 0, i64 0, i64 4, i64 8]
+// CHECK: @.offload_maptypes = private unnamed_addr constant [6 x i64] [i64 [[#0x220]], i64 0, i64 [[#0x2000000000003]], i64 [[#0x2000000000003]], i64 [[#0x2000000000203]], i64 [[#0x4000]]]
+
+// &sp[0], &sp[0],   sizeof(sp[0]), ALLOC | PARAM
+// &sp[0], &sp[0].e, sizeof(e),     MEMBER_OF_2 | TO | FROM
+// &sp[0], &sp[0].h, sizeof(h),     MEMBER_OF_2 | TO | FROM
+// &sp[0], &sp[0].f, sizeof(f),     MEMBER_OF_2 | TO | FROM | IMPLICIT, mapper_of_c
+// &sp,    &sp[0],   sizeof(void*), ATTACH
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 4, i64 8]
-// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 32, i64 281474976710659, i64 281474976710659, i64 281474976711171, i64 16384]
-// 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]
+// CHECK: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000203]], i64 [[#0x4000]]]
+
+// &sppp[0],       &sppp[0],         0,                     IMPLICIT | PARAM
+// &sppp[0][0][0], &sppp[0][0][0],   sizeof(sppp[0][0][0]), ALLOC
+// &sppp[0][0][0], &sppp[0][0][0].e, sizeof(e),             MEMBER_OF_2 | TO | FROM
+// &sppp[0][0][0], &sppp[0][0][0].h, sizeof(h),             MEMBER_OF_2 | TO | FROM
+// &sppp[0][0][0], &sppp[0][0][0].f, sizeof(f),             MEMBER_OF_2 | TO | FROM | IMPLICIT, mapper_of_c
+// &sppp[0][0],    &sppp[0][0][0],   sizeof(void*),         ATTACH
+// CHECK: @.offload_sizes.3 = private unnamed_addr constant [6 x i64] [i64 0, i64 0, i64 0, i64 0, i64 4, i64 8]
+// CHECK: @.offload_maptypes.4 = private unnamed_addr constant [6 x i64] [i64 [[#0x220]], i64 0, i64 [[#0x2000000000003]], i64 [[#0x2000000000003]], i64 [[#0x2000000000203]], i64 [[#0x4000]]]

>From 502dbb4d8088a235ba03e0b8ad79012d9b9905ea Mon Sep 17 00:00:00 2001
From: Abhinav Gaba <abhinav.gaba at intel.com>
Date: Thu, 14 Aug 2025 16:03:55 -0700
Subject: [PATCH 66/66] Update copy-gaps tests.

---
 clang/test/OpenMP/copy-gaps-1.cpp             | 25 +++++++++----
 clang/test/OpenMP/copy-gaps-6.cpp             | 35 +++++++++++--------
 ...get_map_pointer_defalut_mapper_codegen.cpp |  6 ++--
 3 files changed, 42 insertions(+), 24 deletions(-)

diff --git a/clang/test/OpenMP/copy-gaps-1.cpp b/clang/test/OpenMP/copy-gaps-1.cpp
index 3d4fae352eed6..2166d78764744 100644
--- a/clang/test/OpenMP/copy-gaps-1.cpp
+++ b/clang/test/OpenMP/copy-gaps-1.cpp
@@ -18,6 +18,17 @@ struct T : public S {
 int main() {
   T v;
 
+// &v,       &v,                 sizeof(v),                         ALLOC | PARAM
+// &v,       &v.z + sizeof(int), sizeof(v.p1 to v.p2),              TO | FROM | MEMBER_OF_1
+// &v,       &v.c + sizeof(int), sizeof(T) - (&v.c + sizeof(int))), TO | FROM | MEMBER_OF_1
+// &v,       &v.x,               sizeof(v.x),                       TO | FROM | MEMBER_OF_1
+// &v,       &v.y,               sizeof(v.y),                       TO | FROM | MEMBER_OF_1
+// &v,       &v.z,               sizeof(v.z),                       TO | FROM | MEMBER_OF_1
+// &v,       &v.a,               sizeof(v.a),                       TO | FROM | MEMBER_OF_1
+// &v,       &v.b,               sizeof(v.b),                       TO | FROM | MEMBER_OF_1
+// &v,       &v.c,               sizeof(v.c),                       TO | FROM | MEMBER_OF_1
+// &v.p1[0], &v.p1[0],           8 * sizeof(int),                   TO | FROM
+// &v.p1,    &v.p1[0],           sizeof(v.p1),                      ATTACH
 #pragma omp target map(tofrom: v, v.x, v.y, v.z, v.p1[:8], v.a, v.b, v.c)
   {
     v.x++;
@@ -32,21 +43,21 @@ int main() {
   return 0;
 }
 
-// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [10 x i64] [i64 0, i64 0, i64 0, i64 4, i64 4, i64 4, i64 32, i64 4, i64 4, i64 4]
-// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [10 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [11 x i64] [i64 0, i64 0, i64 0, i64 4, i64 4, i64 4, i64 4, i64 4, i64 4, i64 32, i64 8]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [11 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x3]], i64 [[#0x4000]]]
 
 // CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
 // CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
-// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [10 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [11 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
 
-// Check for filling of four non-constant size elements here: the whole struct
+// Check for filling of three non-constant size elements here: the whole struct
 // size, the (padded) region covering p1 & p2, and the padding at the end of
 // struct T.
 
-// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [11 x i64], ptr [[SIZES]], i32 0, i32 0
 // CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
-// CHECK-DAG: [[P1P2:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: [[P1P2:%.+]] = getelementptr inbounds [11 x i64], ptr [[SIZES]], i32 0, i32 1
 // CHECK-DAG: store i64 %{{.+}}, ptr [[P1P2]], align 8
-// CHECK-DAG: [[PAD:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: [[PAD:%.+]] = getelementptr inbounds [11 x i64], ptr [[SIZES]], i32 0, i32 2
 // CHECK-DAG: store i64 %{{.+}}, ptr [[PAD]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-6.cpp b/clang/test/OpenMP/copy-gaps-6.cpp
index 9c62fde1c3762..e09929a95e2d8 100644
--- a/clang/test/OpenMP/copy-gaps-6.cpp
+++ b/clang/test/OpenMP/copy-gaps-6.cpp
@@ -11,6 +11,10 @@ struct S {
 int main() {
   S v;
 
+// &v, &v,                 sizeof(v),            ALLOC | PARAM
+// &v, &v.x + sizeof(int), sizeof(v.arr to v.y), TO | FROM | MEMBER_OF_1
+// &v, &v.x,               sizeof(v.x),          TO | FROM | MEMBER_OF_1
+// &v, &v.z,               sizeof(v.z),          TO | FROM | MEMBER_OF_1
 #pragma omp target map(tofrom: v, v.x, v.z)
   {
     v.x++;
@@ -18,6 +22,11 @@ int main() {
     v.z += 3;
   }
 
+// &v,        &v,                 sizeof(v),            ALLOC | PARAM
+// &v,        &v.x + sizeof(int), sizeof(v.arr to v.z), TO | FROM | MEMBER_OF_1
+// &v,        &v.x,               sizeof(v.x),          TO | FROM | MEMBER_OF_1
+// &v.arr[0], &v.arr[0],          4 * sizeof(int),      TO | FROM
+// &v.arr,    &v.arr[0],          sizeof(void*),        ATTACH
 #pragma omp target map(tofrom: v, v.x, v.arr[:1])
   {
     v.x++;
@@ -26,6 +35,9 @@ int main() {
     v.z += 4;
   }
 
+// &v,        &v,        sizeof(v),       TO | FROM | PARAM
+// &v.arr[0], &v.arr[0], 4 * sizeof(int), TO | FROM
+// &v.arr,    &v.arr[0], sizeof(void*),   ATTACH
 #pragma omp target map(tofrom: v, v.arr[:1])
   {
     v.x++;
@@ -40,11 +52,11 @@ int main() {
 // CHECK: [[CSTSZ0:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 0, i64 4, i64 4]
 // CHECK: [[CSTTY0:@.+]] = private {{.*}}constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
 
-// CHECK: [[CSTSZ1:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 0, i64 4, i64 4]
-// CHECK: [[CSTTY1:@.+]] = private {{.*}}constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]]]
+// CHECK: [[CSTSZ1:@.+]] = private {{.*}}constant [5 x i64] [i64 0, i64 0, i64 4, i64 4, i64 8]
+// CHECK: [[CSTTY1:@.+]] = private {{.*}}constant [5 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x3]], i64 [[#0x4000]]]
 
-// CHECK: [[CSTSZ2:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 24, i64 4]
-// CHECK: [[CSTTY2:@.+]] = private {{.*}}constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]]]
+// CHECK: [[CSTSZ2:@.+]] = private {{.*}}constant [3 x i64] [i64 24, i64 4, i64 8]
+// CHECK: [[CSTTY2:@.+]] = private {{.*}}constant [3 x i64] [i64 [[#0x23]], i64 [[#0x3]], i64 [[#0x4000]]]
 
 // CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
@@ -64,24 +76,19 @@ int main() {
 // CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
 // CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
-// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [4 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [5 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
 
 // Fill two non-constant size elements here: the whole struct size, and the
 // region covering v.arr, v.y and v.z.
 
-// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [5 x i64], ptr [[SIZES]], i32 0, i32 0
 // CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
-// CHECK-DAG: [[ARRYZ:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: [[ARRYZ:%.+]] = getelementptr inbounds [5 x i64], ptr [[SIZES]], i32 0, i32 1
 // CHECK-DAG: store i64 %{{.+}}, ptr [[ARRYZ]], align 8
 
 // CHECK: call void
 
 // CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
 // CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
-// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
-// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [3 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
-
-// Fill one non-constant size element here: the whole struct size.
-
-// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [3 x i64], ptr [[SIZES]], i32 0, i32 0
-// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// No overlap, so no non-constant size element here.
+// CHECK-NOT: store ptr [[CSTSZ2]], ptr [[KSIZE]], align 8
diff --git a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
index fbb4f75f0b32e..93814ba7f1929 100644
--- a/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
+++ b/clang/test/OpenMP/target_map_pointer_defalut_mapper_codegen.cpp
@@ -50,9 +50,9 @@ void foo() {
 // CHECK: @.offload_maptypes = private unnamed_addr constant [6 x i64] [i64 [[#0x220]], i64 0, i64 [[#0x2000000000003]], i64 [[#0x2000000000003]], i64 [[#0x2000000000203]], i64 [[#0x4000]]]
 
 // &sp[0], &sp[0],   sizeof(sp[0]), ALLOC | PARAM
-// &sp[0], &sp[0].e, sizeof(e),     MEMBER_OF_2 | TO | FROM
-// &sp[0], &sp[0].h, sizeof(h),     MEMBER_OF_2 | TO | FROM
-// &sp[0], &sp[0].f, sizeof(f),     MEMBER_OF_2 | TO | FROM | IMPLICIT, mapper_of_c
+// &sp[0], &sp[0].e, sizeof(e),     MEMBER_OF_1 | TO | FROM
+// &sp[0], &sp[0].h, sizeof(h),     MEMBER_OF_1 | TO | FROM
+// &sp[0], &sp[0].f, sizeof(f),     MEMBER_OF_1 | TO | FROM | IMPLICIT, mapper_of_c
 // &sp,    &sp[0],   sizeof(void*), ATTACH
 // CHECK: @.offload_sizes.1 = private unnamed_addr constant [5 x i64] [i64 0, i64 0, i64 0, i64 4, i64 8]
 // CHECK: @.offload_maptypes.2 = private unnamed_addr constant [5 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000203]], i64 [[#0x4000]]]



More information about the cfe-commits mailing list