[clang] [llvm] [OpenMP][Clang] Migrate OpenMP UserDefinedMapper from Clang to OMPIRBuilder (PR #110001)

Akash Banerjee via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 25 08:12:08 PDT 2024


https://github.com/TIFitis created https://github.com/llvm/llvm-project/pull/110001

This patch migrates the OpenMP UserDefinedMapper codegen from Clang to the OpenMPIRBuilder. I will be adding further patches in the near future so that OpenMP dialect in MLIR can make use of these.

>From 387ac88d84d7fd56d3e36b6703e6c08d2dc908fc Mon Sep 17 00:00:00 2001
From: Akash Banerjee <Akash.Banerjee at amd.com>
Date: Wed, 25 Sep 2024 16:06:36 +0100
Subject: [PATCH] [OpenMP][Clang] Migrate OpenMP UserDefinedMapper from Clang
 to OMPIRBuilder

This patch migrates the OpenMP UserDefinedMapper codegen from Clang to the OpenMPIRBuilder.
I will be adding further patches in the near future so that OpenMP dialect in MLIR can make use of these.
---
 clang/lib/CodeGen/CGOpenMPRuntime.cpp         | 290 +++---------------
 clang/test/OpenMP/declare_mapper_codegen.cpp  |  48 +--
 clang/test/OpenMP/target_map_names.cpp        |   4 +-
 clang/test/OpenMP/target_map_names_attr.cpp   |   4 +-
 ...target_map_nest_defalut_mapper_codegen.cpp | 144 ++++-----
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       |  61 ++++
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 289 +++++++++++++++++
 7 files changed, 459 insertions(+), 381 deletions(-)

diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 807f9881f53f40..bde219406b6526 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9058,257 +9058,65 @@ void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
     return;
   ASTContext &C = CGM.getContext();
   QualType Ty = D->getType();
-  QualType PtrTy = C.getPointerType(Ty).withRestrict();
-  QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
   auto *MapperVarDecl =
       cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
-  SourceLocation Loc = D->getLocation();
   CharUnits ElementSize = C.getTypeSizeInChars(Ty);
   llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty);
 
-  // Prepare mapper function arguments and attributes.
-  ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
-                              C.VoidPtrTy, ImplicitParamKind::Other);
-  ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
-                            ImplicitParamKind::Other);
-  ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
-                             C.VoidPtrTy, ImplicitParamKind::Other);
-  ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
-                            ImplicitParamKind::Other);
-  ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
-                            ImplicitParamKind::Other);
-  ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
-                            ImplicitParamKind::Other);
-  FunctionArgList Args;
-  Args.push_back(&HandleArg);
-  Args.push_back(&BaseArg);
-  Args.push_back(&BeginArg);
-  Args.push_back(&SizeArg);
-  Args.push_back(&TypeArg);
-  Args.push_back(&NameArg);
-  const CGFunctionInfo &FnInfo =
-      CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
-  llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
-  SmallString<64> TyStr;
-  llvm::raw_svector_ostream Out(TyStr);
-  CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
-  std::string Name = getName({"omp_mapper", TyStr, D->getName()});
-  auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
-                                    Name, &CGM.getModule());
-  CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
-  Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
-  // Start the mapper function code generation.
   CodeGenFunction MapperCGF(CGM);
-  MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
-  // Compute the starting and end addresses of array elements.
-  llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
-      C.getPointerType(Int64Ty), Loc);
-  // Prepare common arguments for array initiation and deletion.
-  llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&HandleArg),
-      /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
-  llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&BaseArg),
-      /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
-  llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&BeginArg),
-      /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
-  // Convert the size in bytes into the number of array elements.
-  Size = MapperCGF.Builder.CreateExactUDiv(
-      Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
-  llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
-      BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy));
-  llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size);
-  llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
-      C.getPointerType(Int64Ty), Loc);
-  llvm::Value *MapName = MapperCGF.EmitLoadOfScalar(
-      MapperCGF.GetAddrOfLocalVar(&NameArg),
-      /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
-
-  // Emit array initiation if this is an array section and \p MapType indicates
-  // that memory allocation is required.
-  llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
-  emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
-                             MapName, ElementSize, HeadBB, /*IsInit=*/true);
-
-  // Emit a for loop to iterate through SizeArg of elements and map all of them.
-
-  // Emit the loop header block.
-  MapperCGF.EmitBlock(HeadBB);
-  llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
-  llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
-  // Evaluate whether the initial condition is satisfied.
-  llvm::Value *IsEmpty =
-      MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
-  MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
-  llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
+  MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
+  auto PrivatizeAndGenMapInfoCB =
+      [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
+          llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
+    MapperCGF.Builder.restoreIP(CodeGenIP);
+
+    // Privatize the declared variable of mapper to be the current array
+    // element.
+    Address PtrCurrent(
+        PtrPHI, ElemTy,
+        Address(BeginArg, MapperCGF.VoidPtrTy, CGM.getPointerAlign())
+            .getAlignment()
+            .alignmentOfArrayElement(ElementSize));
+    CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
+    Scope.addPrivate(MapperVarDecl, PtrCurrent);
+    (void)Scope.Privatize();
 
-  // Emit the loop body block.
-  MapperCGF.EmitBlock(BodyBB);
-  llvm::BasicBlock *LastBB = BodyBB;
-  llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
-      PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
-  PtrPHI->addIncoming(PtrBegin, EntryBB);
-  Address PtrCurrent(PtrPHI, ElemTy,
-                     MapperCGF.GetAddrOfLocalVar(&BeginArg)
-                         .getAlignment()
-                         .alignmentOfArrayElement(ElementSize));
-  // Privatize the declared variable of mapper to be the current array element.
-  CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
-  Scope.addPrivate(MapperVarDecl, PtrCurrent);
-  (void)Scope.Privatize();
+    // Get map clause information.
+    MappableExprsHandler MEHandler(*D, MapperCGF);
+    MEHandler.generateAllInfoForMapper(CombinedInfo, OMPBuilder);
+
+    auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
+      return emitMappingInformation(MapperCGF, OMPBuilder, MapExpr);
+    };
+    if (CGM.getCodeGenOpts().getDebugInfo() !=
+        llvm::codegenoptions::NoDebugInfo) {
+      CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
+      llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
+                      FillInfoMap);
+    }
 
-  // Get map clause information. Fill up the arrays with all mapped variables.
-  MappableExprsHandler::MapCombinedInfoTy Info;
-  MappableExprsHandler MEHandler(*D, MapperCGF);
-  MEHandler.generateAllInfoForMapper(Info, OMPBuilder);
+    return CombinedInfo;
+  };
 
-  // Call the runtime API __tgt_mapper_num_components to get the number of
-  // pre-existing components.
-  llvm::Value *OffloadingArgs[] = {Handle};
-  llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
-      OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
-                                            OMPRTL___tgt_mapper_num_components),
-      OffloadingArgs);
-  llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
-      PreviousSize,
-      MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
-
-  // Fill up the runtime mapper handle for all components.
-  for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
-    llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
-        Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
-    llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
-        Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
-    llvm::Value *CurSizeArg = Info.Sizes[I];
-    llvm::Value *CurNameArg =
-        (CGM.getCodeGenOpts().getDebugInfo() ==
-         llvm::codegenoptions::NoDebugInfo)
-            ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy)
-            : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]);
-
-    // Extract the MEMBER_OF field from the map type.
-    llvm::Value *OriMapType = MapperCGF.Builder.getInt64(
-        static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-            Info.Types[I]));
-    llvm::Value *MemberMapType =
-        MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
-
-    // Combine the map type inherited from user-defined mapper with that
-    // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
-    // bits of the \a MapType, which is the input argument of the mapper
-    // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
-    // bits of MemberMapType.
-    // [OpenMP 5.0], 1.2.6. map-type decay.
-    //        | alloc |  to   | from  | tofrom | release | delete
-    // ----------------------------------------------------------
-    // alloc  | alloc | alloc | alloc | alloc  | release | delete
-    // to     | alloc |  to   | alloc |   to   | release | delete
-    // from   | alloc | alloc | from  |  from  | release | delete
-    // tofrom | alloc |  to   | from  | tofrom | release | delete
-    llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
-        MapType,
-        MapperCGF.Builder.getInt64(
-            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_TO |
-                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
-    llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
-    llvm::BasicBlock *AllocElseBB =
-        MapperCGF.createBasicBlock("omp.type.alloc.else");
-    llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
-    llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
-    llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
-    llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
-    llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
-    MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
-    // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
-    MapperCGF.EmitBlock(AllocBB);
-    llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
-        MemberMapType,
-        MapperCGF.Builder.getInt64(
-            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_TO |
-                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
-    MapperCGF.Builder.CreateBr(EndBB);
-    MapperCGF.EmitBlock(AllocElseBB);
-    llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
-        LeftToFrom,
-        MapperCGF.Builder.getInt64(
-            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_TO)));
-    MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
-    // In case of to, clear OMP_MAP_FROM.
-    MapperCGF.EmitBlock(ToBB);
-    llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
-        MemberMapType,
-        MapperCGF.Builder.getInt64(
-            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
-    MapperCGF.Builder.CreateBr(EndBB);
-    MapperCGF.EmitBlock(ToElseBB);
-    llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
-        LeftToFrom,
-        MapperCGF.Builder.getInt64(
-            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
-    MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
-    // In case of from, clear OMP_MAP_TO.
-    MapperCGF.EmitBlock(FromBB);
-    llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
-        MemberMapType,
-        MapperCGF.Builder.getInt64(
-            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
-                OpenMPOffloadMappingFlags::OMP_MAP_TO)));
-    // In case of tofrom, do nothing.
-    MapperCGF.EmitBlock(EndBB);
-    LastBB = EndBB;
-    llvm::PHINode *CurMapType =
-        MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
-    CurMapType->addIncoming(AllocMapType, AllocBB);
-    CurMapType->addIncoming(ToMapType, ToBB);
-    CurMapType->addIncoming(FromMapType, FromBB);
-    CurMapType->addIncoming(MemberMapType, ToElseBB);
-
-    llvm::Value *OffloadingArgs[] = {Handle,     CurBaseArg, CurBeginArg,
-                                     CurSizeArg, CurMapType, CurNameArg};
-    if (Info.Mappers[I]) {
+  auto CustomMapperCB = [&](unsigned I, llvm::Function **MapperFunc) {
+    if (CombinedInfo.Mappers[I]) {
       // Call the corresponding mapper function.
-      llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc(
-          cast<OMPDeclareMapperDecl>(Info.Mappers[I]));
-      assert(MapperFunc && "Expect a valid mapper function is available.");
-      MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs);
-    } else {
-      // Call the runtime API __tgt_push_mapper_component to fill up the runtime
-      // data structure.
-      MapperCGF.EmitRuntimeCall(
-          OMPBuilder.getOrCreateRuntimeFunction(
-              CGM.getModule(), OMPRTL___tgt_push_mapper_component),
-          OffloadingArgs);
-    }
-  }
-
-  // Update the pointer to point to the next element that needs to be mapped,
-  // and check whether we have mapped all elements.
-  llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
-      ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
-  PtrPHI->addIncoming(PtrNext, LastBB);
-  llvm::Value *IsDone =
-      MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
-  llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
-  MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
-
-  MapperCGF.EmitBlock(ExitBB);
-  // Emit array deletion if this is an array section and \p MapType indicates
-  // that deletion is required.
-  emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
-                             MapName, ElementSize, DoneBB, /*IsInit=*/false);
-
-  // Emit the function exit block.
-  MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
-  MapperCGF.FinishFunction();
-  UDMMap.try_emplace(D, Fn);
+      *MapperFunc = getOrCreateUserDefinedMapperFunc(
+          cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I]));
+      assert(*MapperFunc && "Expect a valid mapper function is available.");
+      return true;
+    }
+    return false;
+  };
+
+  SmallString<64> TyStr;
+  llvm::raw_svector_ostream Out(TyStr);
+  CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
+  std::string Name = getName({"omp_mapper", TyStr, D->getName()});
+
+  auto *newFn = OMPBuilder.emitUserDefinedMapper(PrivatizeAndGenMapInfoCB,
+                                                 ElemTy, Name, CustomMapperCB);
+  UDMMap.try_emplace(D, newFn);
   if (CGF)
     FunctionUDMMap[CGF->CurFn].push_back(D);
 }
diff --git a/clang/test/OpenMP/declare_mapper_codegen.cpp b/clang/test/OpenMP/declare_mapper_codegen.cpp
index d2954b7a748217..f9da3d97766d96 100644
--- a/clang/test/OpenMP/declare_mapper_codegen.cpp
+++ b/clang/test/OpenMP/declare_mapper_codegen.cpp
@@ -86,19 +86,9 @@ class C {
 
 #pragma omp declare mapper(id: C s) map(s.a, s.b[0:2])
 
-// CK0: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
-// CK0: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK0: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK0: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK0: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK0: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK0-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
+// CK0: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
 // CK0-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
 // CK0-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8
-// CK0-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK0-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK0-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK0-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
 // CK0-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
 // CK0-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
 // CK0-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -597,18 +587,8 @@ class C {
 
 #pragma omp declare mapper(id: C<int> s) map(s.a)
 
-// CK1-LABEL: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id{{.*}}(ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
-// CK1: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK1: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK1: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK1: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK1: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK1-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
+// CK1:     define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id{{.*}}(ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
 // CK1-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 4
-// CK1-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK1-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK1-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK1-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
 // CK1-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
 // CK1-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
 // CK1-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -717,18 +697,8 @@ class C {
 
 // CK2: define {{.*}}void [[BMPRFUNC:@[.]omp_mapper[.].*B[.]default]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
 
-// CK2-LABEL: define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id(ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
-// CK2: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK2: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK2: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK2: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK2: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK2-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
+// CK2:     define {{.*}}void @.omp_mapper.{{.*}}C{{.*}}.id(ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
 // CK2-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
-// CK2-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK2-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK2-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK2-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
 // CK2-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
 // CK2-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
 // CK2-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
@@ -921,19 +891,9 @@ class C {
 
 #pragma omp declare mapper(id: C s) map(s.a, s.b[0:2])
 
-// CK4: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr{{.*}}, ptr{{.*}}, ptr{{.*}}, i64{{.*}}, i64{{.*}}, ptr{{.*}})
-// CK4: store ptr %{{[^,]+}}, ptr [[HANDLEADDR:%[^,]+]]
-// CK4: store ptr %{{[^,]+}}, ptr [[BPTRADDR:%[^,]+]]
-// CK4: store ptr %{{[^,]+}}, ptr [[VPTRADDR:%[^,]+]]
-// CK4: store i64 %{{[^,]+}}, ptr [[SIZEADDR:%[^,]+]]
-// CK4: store i64 %{{[^,]+}}, ptr [[TYPEADDR:%[^,]+]]
-// CK4-DAG: [[BYTESIZE:%.+]] = load i64, ptr [[SIZEADDR]]
+// CK4: define {{.*}}void [[MPRFUNC:@[.]omp_mapper[.].*C[.]id]](ptr noundef [[HANDLE:%.+]], ptr noundef [[BPTR:%.+]], ptr noundef [[BEGIN:%.+]], i64 noundef [[BYTESIZE:%.+]], i64 noundef [[TYPE:%.+]], ptr{{.*}})
 // CK4-64-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 16
 // CK4-32-DAG: [[SIZE:%.+]] = udiv exact i64 [[BYTESIZE]], 8
-// CK4-DAG: [[TYPE:%.+]] = load i64, ptr [[TYPEADDR]]
-// CK4-DAG: [[HANDLE:%.+]] = load ptr, ptr [[HANDLEADDR]]
-// CK4-DAG: [[BPTR:%.+]] = load ptr, ptr [[BPTRADDR]]
-// CK4-DAG: [[BEGIN:%.+]] = load ptr, ptr [[VPTRADDR]]
 // CK4-DAG: [[PTREND:%.+]] = getelementptr %class.C, ptr [[BEGIN]], i64 [[SIZE]]
 // CK4-DAG: [[ISARRAY:%.+]] = icmp sgt i64 [[SIZE]], 1
 // CK4-DAG: [[PTRSNE:%.+]] = icmp ne ptr [[BPTR]], [[BEGIN]]
diff --git a/clang/test/OpenMP/target_map_names.cpp b/clang/test/OpenMP/target_map_names.cpp
index c1c2015609fb79..3ee28d3ce5ce97 100644
--- a/clang/test/OpenMP/target_map_names.cpp
+++ b/clang/test/OpenMP/target_map_names.cpp
@@ -201,9 +201,7 @@ void secondMapNameInClause() {
 // DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
 // CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
 
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[NAME_ARG:%.+]])
-// DEBUG: store ptr [[NAME_ARG]], ptr [[NAME_STACK:%.+]]
-// DEBUG: [[MAPPER_NAME:%.+]] = load ptr, ptr [[NAME_STACK]]
+// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[MAPPER_NAME:%.+]])
 // DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]])
 
 #endif
diff --git a/clang/test/OpenMP/target_map_names_attr.cpp b/clang/test/OpenMP/target_map_names_attr.cpp
index cb108474b3561c..e6b0e1beb5bd5d 100644
--- a/clang/test/OpenMP/target_map_names_attr.cpp
+++ b/clang/test/OpenMP/target_map_names_attr.cpp
@@ -186,9 +186,7 @@ void secondMapNameInClause() {
 // DEBUG: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
 // CHECK-NOT: store ptr @[[NAME:.offload_mapnames.[0-9]+]], ptr %[[ARG:.+]]
 
-// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[NAME_ARG:%.+]])
-// DEBUG: store ptr [[NAME_ARG]], ptr [[NAME_STACK:%.+]]
-// DEBUG: [[MAPPER_NAME:%.+]] = load ptr, ptr [[NAME_STACK]]
+// DEBUG: void @.omp_mapper._ZTS2S3.id(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64 {{.*}}, i64 {{.*}}, ptr noundef [[MAPPER_NAME:%.+]])
 // DEBUG: call void @__tgt_push_mapper_component(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i64 %{{.*}}, i64 %{{.*}}, ptr [[MAPPER_NAME]])
 
 #endif
diff --git a/clang/test/OpenMP/target_map_nest_defalut_mapper_codegen.cpp b/clang/test/OpenMP/target_map_nest_defalut_mapper_codegen.cpp
index 775f0b296b1b63..0fc6de0e4279a5 100644
--- a/clang/test/OpenMP/target_map_nest_defalut_mapper_codegen.cpp
+++ b/clang/test/OpenMP/target_map_nest_defalut_mapper_codegen.cpp
@@ -109,30 +109,12 @@ void foo() {
 // CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1D.default
 // CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2:[0-9]+]] {
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[DOTADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR1:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR2:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR3:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTADDR4:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTADDR5:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[TMP0]], ptr [[DOTADDR]], align 8
-// CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
-// CHECK-NEXT:    store ptr [[TMP2]], ptr [[DOTADDR2]], align 8
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[DOTADDR3]], align 8
-// CHECK-NEXT:    store i64 [[TMP4]], ptr [[DOTADDR4]], align 8
-// CHECK-NEXT:    store ptr [[TMP5]], ptr [[DOTADDR5]], align 8
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr [[DOTADDR3]], align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 8
-// CHECK-NEXT:    [[TMP10:%.*]] = udiv exact i64 [[TMP6]], 12
-// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr [[STRUCT_D:%.*]], ptr [[TMP9]], i64 [[TMP10]]
-// CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr [[DOTADDR4]], align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTADDR5]], align 8
+// CHECK-NEXT:    [[TMP10:%.*]] = udiv exact i64 [[TMP3]], 12
+// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr [[STRUCT_D:%.*]], ptr [[TMP2]], i64 [[TMP10]]
 // CHECK-NEXT:    [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT:    [[TMP14:%.*]] = and i64 [[TMP12]], 8
-// CHECK-NEXT:    [[TMP15:%.*]] = icmp ne ptr [[TMP8]], [[TMP9]]
-// CHECK-NEXT:    [[TMP16:%.*]] = and i64 [[TMP12]], 16
+// CHECK-NEXT:    [[TMP14:%.*]] = and i64 [[TMP4]], 8
+// CHECK-NEXT:    [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]]
+// CHECK-NEXT:    [[TMP16:%.*]] = and i64 [[TMP4]], 16
 // CHECK-NEXT:    [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0
 // CHECK-NEXT:    [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]]
 // CHECK-NEXT:    [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]]
@@ -141,15 +123,15 @@ void foo() {
 // CHECK-NEXT:    br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]]
 // CHECK:       .omp.array..init:
 // CHECK-NEXT:    [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 12
-// CHECK-NEXT:    [[TMP22:%.*]] = and i64 [[TMP12]], -4
+// CHECK-NEXT:    [[TMP22:%.*]] = and i64 [[TMP4]], -4
 // CHECK-NEXT:    [[TMP23:%.*]] = or i64 [[TMP22]], 512
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP13]])
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP5]])
 // CHECK-NEXT:    br label [[OMP_ARRAYMAP_HEAD]]
 // CHECK:       omp.arraymap.head:
-// CHECK-NEXT:    [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP9]], [[TMP11]]
+// CHECK-NEXT:    [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]]
 // CHECK-NEXT:    br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]]
 // CHECK:       omp.arraymap.body:
-// CHECK-NEXT:    [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP9]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END25:%.*]] ]
+// CHECK-NEXT:    [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP2]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END25:%.*]] ]
 // CHECK-NEXT:    [[E:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0
 // CHECK-NEXT:    [[F:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 1
 // CHECK-NEXT:    [[H:%.*]] = getelementptr inbounds nuw [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 2
@@ -158,10 +140,10 @@ void foo() {
 // CHECK-NEXT:    [[TMP26:%.*]] = ptrtoint ptr [[E]] to i64
 // CHECK-NEXT:    [[TMP27:%.*]] = sub i64 [[TMP25]], [[TMP26]]
 // CHECK-NEXT:    [[TMP28:%.*]] = sdiv exact i64 [[TMP27]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK-NEXT:    [[TMP29:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP7]])
+// CHECK-NEXT:    [[TMP29:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP0]])
 // CHECK-NEXT:    [[TMP30:%.*]] = shl i64 [[TMP29]], 48
 // CHECK-NEXT:    [[TMP31:%.*]] = add nuw i64 0, [[TMP30]]
-// CHECK-NEXT:    [[TMP32:%.*]] = and i64 [[TMP12]], 3
+// CHECK-NEXT:    [[TMP32:%.*]] = and i64 [[TMP4]], 3
 // CHECK-NEXT:    [[TMP33:%.*]] = icmp eq i64 [[TMP32]], 0
 // CHECK-NEXT:    br i1 [[TMP33]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]]
 // CHECK:       omp.type.alloc:
@@ -181,87 +163,87 @@ void foo() {
 // CHECK-NEXT:    br label [[OMP_TYPE_END]]
 // CHECK:       omp.type.end:
 // CHECK-NEXT:    [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP34]], [[OMP_TYPE_ALLOC]] ], [ [[TMP36]], [[OMP_TYPE_TO]] ], [ [[TMP38]], [[OMP_TYPE_FROM]] ], [ [[TMP31]], [[OMP_TYPE_TO_ELSE]] ]
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 [[TMP28]], i64 [[OMP_MAPTYPE]], ptr null)
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 [[TMP28]], i64 [[OMP_MAPTYPE]], ptr null)
 // CHECK-NEXT:    [[TMP39:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT:    [[TMP40:%.*]] = and i64 [[TMP12]], 3
+// CHECK-NEXT:    [[TMP40:%.*]] = and i64 [[TMP4]], 3
 // CHECK-NEXT:    [[TMP41:%.*]] = icmp eq i64 [[TMP40]], 0
 // CHECK-NEXT:    br i1 [[TMP41]], label [[OMP_TYPE_ALLOC6:%.*]], label [[OMP_TYPE_ALLOC_ELSE7:%.*]]
-// CHECK:       omp.type.alloc6:
+// CHECK:       omp.type.alloc1:
 // CHECK-NEXT:    [[TMP42:%.*]] = and i64 [[TMP39]], -4
 // CHECK-NEXT:    br label [[OMP_TYPE_END11:%.*]]
-// CHECK:       omp.type.alloc.else7:
+// CHECK:       omp.type.alloc.else2:
 // CHECK-NEXT:    [[TMP43:%.*]] = icmp eq i64 [[TMP40]], 1
 // CHECK-NEXT:    br i1 [[TMP43]], label [[OMP_TYPE_TO8:%.*]], label [[OMP_TYPE_TO_ELSE9:%.*]]
-// CHECK:       omp.type.to8:
+// CHECK:       omp.type.to3:
 // CHECK-NEXT:    [[TMP44:%.*]] = and i64 [[TMP39]], -3
 // CHECK-NEXT:    br label [[OMP_TYPE_END11]]
-// CHECK:       omp.type.to.else9:
+// CHECK:       omp.type.to.else4:
 // CHECK-NEXT:    [[TMP45:%.*]] = icmp eq i64 [[TMP40]], 2
 // CHECK-NEXT:    br i1 [[TMP45]], label [[OMP_TYPE_FROM10:%.*]], label [[OMP_TYPE_END11]]
-// CHECK:       omp.type.from10:
+// CHECK:       omp.type.from5:
 // CHECK-NEXT:    [[TMP46:%.*]] = and i64 [[TMP39]], -2
 // CHECK-NEXT:    br label [[OMP_TYPE_END11]]
-// CHECK:       omp.type.end11:
+// CHECK:       omp.type.end6:
 // CHECK-NEXT:    [[OMP_MAPTYPE12:%.*]] = phi i64 [ [[TMP42]], [[OMP_TYPE_ALLOC6]] ], [ [[TMP44]], [[OMP_TYPE_TO8]] ], [ [[TMP46]], [[OMP_TYPE_FROM10]] ], [ [[TMP39]], [[OMP_TYPE_TO_ELSE9]] ]
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 4, i64 [[OMP_MAPTYPE12]], ptr null)
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[E]], i64 4, i64 [[OMP_MAPTYPE12]], ptr null)
 // CHECK-NEXT:    [[TMP47:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT:    [[TMP48:%.*]] = and i64 [[TMP12]], 3
+// CHECK-NEXT:    [[TMP48:%.*]] = and i64 [[TMP4]], 3
 // CHECK-NEXT:    [[TMP49:%.*]] = icmp eq i64 [[TMP48]], 0
 // CHECK-NEXT:    br i1 [[TMP49]], label [[OMP_TYPE_ALLOC13:%.*]], label [[OMP_TYPE_ALLOC_ELSE14:%.*]]
-// CHECK:       omp.type.alloc13:
+// CHECK:       omp.type.alloc8:
 // CHECK-NEXT:    [[TMP50:%.*]] = and i64 [[TMP47]], -4
 // CHECK-NEXT:    br label [[OMP_TYPE_END18:%.*]]
-// CHECK:       omp.type.alloc.else14:
+// CHECK:       omp.type.alloc.else9:
 // CHECK-NEXT:    [[TMP51:%.*]] = icmp eq i64 [[TMP48]], 1
 // CHECK-NEXT:    br i1 [[TMP51]], label [[OMP_TYPE_TO15:%.*]], label [[OMP_TYPE_TO_ELSE16:%.*]]
-// CHECK:       omp.type.to15:
+// CHECK:       omp.type.to10:
 // CHECK-NEXT:    [[TMP52:%.*]] = and i64 [[TMP47]], -3
 // CHECK-NEXT:    br label [[OMP_TYPE_END18]]
-// CHECK:       omp.type.to.else16:
+// CHECK:       omp.type.to.else11:
 // CHECK-NEXT:    [[TMP53:%.*]] = icmp eq i64 [[TMP48]], 2
 // CHECK-NEXT:    br i1 [[TMP53]], label [[OMP_TYPE_FROM17:%.*]], label [[OMP_TYPE_END18]]
-// CHECK:       omp.type.from17:
+// CHECK:       omp.type.from12:
 // CHECK-NEXT:    [[TMP54:%.*]] = and i64 [[TMP47]], -2
 // CHECK-NEXT:    br label [[OMP_TYPE_END18]]
-// CHECK:       omp.type.end18:
+// CHECK:       omp.type.end13:
 // CHECK-NEXT:    [[OMP_MAPTYPE19:%.*]] = phi i64 [ [[TMP50]], [[OMP_TYPE_ALLOC13]] ], [ [[TMP52]], [[OMP_TYPE_TO15]] ], [ [[TMP54]], [[OMP_TYPE_FROM17]] ], [ [[TMP47]], [[OMP_TYPE_TO_ELSE16]] ]
-// CHECK-NEXT:    call void @.omp_mapper._ZTS1C.default(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[F]], i64 4, i64 [[OMP_MAPTYPE19]], ptr null) #[[ATTR3]]
+// CHECK-NEXT:    call void @.omp_mapper._ZTS1C.default(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[F]], i64 4, i64 [[OMP_MAPTYPE19]], ptr null) #[[ATTR3]]
 // CHECK-NEXT:    [[TMP55:%.*]] = add nuw i64 281474976711171, [[TMP30]]
-// CHECK-NEXT:    [[TMP56:%.*]] = and i64 [[TMP12]], 3
+// CHECK-NEXT:    [[TMP56:%.*]] = and i64 [[TMP4]], 3
 // CHECK-NEXT:    [[TMP57:%.*]] = icmp eq i64 [[TMP56]], 0
 // CHECK-NEXT:    br i1 [[TMP57]], label [[OMP_TYPE_ALLOC20:%.*]], label [[OMP_TYPE_ALLOC_ELSE21:%.*]]
-// CHECK:       omp.type.alloc20:
+// CHECK:       omp.type.alloc15:
 // CHECK-NEXT:    [[TMP58:%.*]] = and i64 [[TMP55]], -4
 // CHECK-NEXT:    br label [[OMP_TYPE_END25]]
-// CHECK:       omp.type.alloc.else21:
+// CHECK:       omp.type.alloc.else16:
 // CHECK-NEXT:    [[TMP59:%.*]] = icmp eq i64 [[TMP56]], 1
 // CHECK-NEXT:    br i1 [[TMP59]], label [[OMP_TYPE_TO22:%.*]], label [[OMP_TYPE_TO_ELSE23:%.*]]
-// CHECK:       omp.type.to22:
+// CHECK:       omp.type.to17:
 // CHECK-NEXT:    [[TMP60:%.*]] = and i64 [[TMP55]], -3
 // CHECK-NEXT:    br label [[OMP_TYPE_END25]]
-// CHECK:       omp.type.to.else23:
+// CHECK:       omp.type.to.else18:
 // CHECK-NEXT:    [[TMP61:%.*]] = icmp eq i64 [[TMP56]], 2
 // CHECK-NEXT:    br i1 [[TMP61]], label [[OMP_TYPE_FROM24:%.*]], label [[OMP_TYPE_END25]]
-// CHECK:       omp.type.from24:
+// CHECK:       omp.type.from19:
 // CHECK-NEXT:    [[TMP62:%.*]] = and i64 [[TMP55]], -2
 // CHECK-NEXT:    br label [[OMP_TYPE_END25]]
-// CHECK:       omp.type.end25:
+// CHECK:       omp.type.end20:
 // CHECK-NEXT:    [[OMP_MAPTYPE26:%.*]] = phi i64 [ [[TMP58]], [[OMP_TYPE_ALLOC20]] ], [ [[TMP60]], [[OMP_TYPE_TO22]] ], [ [[TMP62]], [[OMP_TYPE_FROM24]] ], [ [[TMP55]], [[OMP_TYPE_TO_ELSE23]] ]
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[H]], i64 4, i64 [[OMP_MAPTYPE26]], ptr null)
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[H]], i64 4, i64 [[OMP_MAPTYPE26]], ptr null)
 // CHECK-NEXT:    [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_D]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1
 // CHECK-NEXT:    [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]]
 // CHECK-NEXT:    br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]]
 // CHECK:       omp.arraymap.exit:
 // CHECK-NEXT:    [[OMP_ARRAYINIT_ISARRAY27:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT:    [[TMP63:%.*]] = and i64 [[TMP12]], 8
+// CHECK-NEXT:    [[TMP63:%.*]] = and i64 [[TMP4]], 8
 // CHECK-NEXT:    [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP63]], 0
 // CHECK-NEXT:    [[TMP64:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY27]], [[DOTOMP_ARRAY__DEL__DELETE]]
 // CHECK-NEXT:    br i1 [[TMP64]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]]
 // CHECK:       .omp.array..del:
 // CHECK-NEXT:    [[TMP65:%.*]] = mul nuw i64 [[TMP10]], 12
-// CHECK-NEXT:    [[TMP66:%.*]] = and i64 [[TMP12]], -4
+// CHECK-NEXT:    [[TMP66:%.*]] = and i64 [[TMP4]], -4
 // CHECK-NEXT:    [[TMP67:%.*]] = or i64 [[TMP66]], 512
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP65]], i64 [[TMP67]], ptr [[TMP13]])
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP65]], i64 [[TMP67]], ptr [[TMP5]])
 // CHECK-NEXT:    br label [[OMP_DONE]]
 // CHECK:       omp.done:
 // CHECK-NEXT:    ret void
@@ -270,30 +252,12 @@ void foo() {
 // CHECK-LABEL: define {{[^@]+}}@.omp_mapper._ZTS1C.default
 // CHECK-SAME: (ptr noundef [[TMP0:%.*]], ptr noundef [[TMP1:%.*]], ptr noundef [[TMP2:%.*]], i64 noundef [[TMP3:%.*]], i64 noundef [[TMP4:%.*]], ptr noundef [[TMP5:%.*]]) #[[ATTR2]] {
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[DOTADDR:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR1:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR2:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    [[DOTADDR3:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTADDR4:%.*]] = alloca i64, align 8
-// CHECK-NEXT:    [[DOTADDR5:%.*]] = alloca ptr, align 8
-// CHECK-NEXT:    store ptr [[TMP0]], ptr [[DOTADDR]], align 8
-// CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
-// CHECK-NEXT:    store ptr [[TMP2]], ptr [[DOTADDR2]], align 8
-// CHECK-NEXT:    store i64 [[TMP3]], ptr [[DOTADDR3]], align 8
-// CHECK-NEXT:    store i64 [[TMP4]], ptr [[DOTADDR4]], align 8
-// CHECK-NEXT:    store ptr [[TMP5]], ptr [[DOTADDR5]], align 8
-// CHECK-NEXT:    [[TMP6:%.*]] = load i64, ptr [[DOTADDR3]], align 8
-// CHECK-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTADDR2]], align 8
-// CHECK-NEXT:    [[TMP10:%.*]] = udiv exact i64 [[TMP6]], 4
-// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[TMP9]], i64 [[TMP10]]
-// CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr [[DOTADDR4]], align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTADDR5]], align 8
+// CHECK-NEXT:    [[TMP10:%.*]] = udiv exact i64 [[TMP3]], 4
+// CHECK-NEXT:    [[TMP11:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[TMP2]], i64 [[TMP10]]
 // CHECK-NEXT:    [[OMP_ARRAYINIT_ISARRAY:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT:    [[TMP14:%.*]] = and i64 [[TMP12]], 8
-// CHECK-NEXT:    [[TMP15:%.*]] = icmp ne ptr [[TMP8]], [[TMP9]]
-// CHECK-NEXT:    [[TMP16:%.*]] = and i64 [[TMP12]], 16
+// CHECK-NEXT:    [[TMP14:%.*]] = and i64 [[TMP4]], 8
+// CHECK-NEXT:    [[TMP15:%.*]] = icmp ne ptr [[TMP1]], [[TMP2]]
+// CHECK-NEXT:    [[TMP16:%.*]] = and i64 [[TMP4]], 16
 // CHECK-NEXT:    [[TMP17:%.*]] = icmp ne i64 [[TMP16]], 0
 // CHECK-NEXT:    [[TMP18:%.*]] = and i1 [[TMP15]], [[TMP17]]
 // CHECK-NEXT:    [[TMP19:%.*]] = or i1 [[OMP_ARRAYINIT_ISARRAY]], [[TMP18]]
@@ -302,20 +266,20 @@ void foo() {
 // CHECK-NEXT:    br i1 [[TMP20]], label [[DOTOMP_ARRAY__INIT:%.*]], label [[OMP_ARRAYMAP_HEAD:%.*]]
 // CHECK:       .omp.array..init:
 // CHECK-NEXT:    [[TMP21:%.*]] = mul nuw i64 [[TMP10]], 4
-// CHECK-NEXT:    [[TMP22:%.*]] = and i64 [[TMP12]], -4
+// CHECK-NEXT:    [[TMP22:%.*]] = and i64 [[TMP4]], -4
 // CHECK-NEXT:    [[TMP23:%.*]] = or i64 [[TMP22]], 512
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP13]])
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP21]], i64 [[TMP23]], ptr [[TMP5]])
 // CHECK-NEXT:    br label [[OMP_ARRAYMAP_HEAD]]
 // CHECK:       omp.arraymap.head:
-// CHECK-NEXT:    [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP9]], [[TMP11]]
+// CHECK-NEXT:    [[OMP_ARRAYMAP_ISEMPTY:%.*]] = icmp eq ptr [[TMP2]], [[TMP11]]
 // CHECK-NEXT:    br i1 [[OMP_ARRAYMAP_ISEMPTY]], label [[OMP_DONE:%.*]], label [[OMP_ARRAYMAP_BODY:%.*]]
 // CHECK:       omp.arraymap.body:
-// CHECK-NEXT:    [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP9]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END:%.*]] ]
+// CHECK-NEXT:    [[OMP_ARRAYMAP_PTRCURRENT:%.*]] = phi ptr [ [[TMP2]], [[OMP_ARRAYMAP_HEAD]] ], [ [[OMP_ARRAYMAP_NEXT:%.*]], [[OMP_TYPE_END:%.*]] ]
 // CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 0, i32 0
-// CHECK-NEXT:    [[TMP24:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP7]])
+// CHECK-NEXT:    [[TMP24:%.*]] = call i64 @__tgt_mapper_num_components(ptr [[TMP0]])
 // CHECK-NEXT:    [[TMP25:%.*]] = shl i64 [[TMP24]], 48
 // CHECK-NEXT:    [[TMP26:%.*]] = add nuw i64 1, [[TMP25]]
-// CHECK-NEXT:    [[TMP27:%.*]] = and i64 [[TMP12]], 3
+// CHECK-NEXT:    [[TMP27:%.*]] = and i64 [[TMP4]], 3
 // CHECK-NEXT:    [[TMP28:%.*]] = icmp eq i64 [[TMP27]], 0
 // CHECK-NEXT:    br i1 [[TMP28]], label [[OMP_TYPE_ALLOC:%.*]], label [[OMP_TYPE_ALLOC_ELSE:%.*]]
 // CHECK:       omp.type.alloc:
@@ -335,21 +299,21 @@ void foo() {
 // CHECK-NEXT:    br label [[OMP_TYPE_END]]
 // CHECK:       omp.type.end:
 // CHECK-NEXT:    [[OMP_MAPTYPE:%.*]] = phi i64 [ [[TMP29]], [[OMP_TYPE_ALLOC]] ], [ [[TMP31]], [[OMP_TYPE_TO]] ], [ [[TMP33]], [[OMP_TYPE_FROM]] ], [ [[TMP26]], [[OMP_TYPE_TO_ELSE]] ]
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[A]], i64 4, i64 [[OMP_MAPTYPE]], ptr null)
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], ptr [[A]], i64 4, i64 [[OMP_MAPTYPE]], ptr null)
 // CHECK-NEXT:    [[OMP_ARRAYMAP_NEXT]] = getelementptr [[STRUCT_C]], ptr [[OMP_ARRAYMAP_PTRCURRENT]], i32 1
 // CHECK-NEXT:    [[OMP_ARRAYMAP_ISDONE:%.*]] = icmp eq ptr [[OMP_ARRAYMAP_NEXT]], [[TMP11]]
 // CHECK-NEXT:    br i1 [[OMP_ARRAYMAP_ISDONE]], label [[OMP_ARRAYMAP_EXIT:%.*]], label [[OMP_ARRAYMAP_BODY]]
 // CHECK:       omp.arraymap.exit:
 // CHECK-NEXT:    [[OMP_ARRAYINIT_ISARRAY6:%.*]] = icmp sgt i64 [[TMP10]], 1
-// CHECK-NEXT:    [[TMP34:%.*]] = and i64 [[TMP12]], 8
+// CHECK-NEXT:    [[TMP34:%.*]] = and i64 [[TMP4]], 8
 // CHECK-NEXT:    [[DOTOMP_ARRAY__DEL__DELETE:%.*]] = icmp ne i64 [[TMP34]], 0
 // CHECK-NEXT:    [[TMP35:%.*]] = and i1 [[OMP_ARRAYINIT_ISARRAY6]], [[DOTOMP_ARRAY__DEL__DELETE]]
 // CHECK-NEXT:    br i1 [[TMP35]], label [[DOTOMP_ARRAY__DEL:%.*]], label [[OMP_DONE]]
 // CHECK:       .omp.array..del:
 // CHECK-NEXT:    [[TMP36:%.*]] = mul nuw i64 [[TMP10]], 4
-// CHECK-NEXT:    [[TMP37:%.*]] = and i64 [[TMP12]], -4
+// CHECK-NEXT:    [[TMP37:%.*]] = and i64 [[TMP4]], -4
 // CHECK-NEXT:    [[TMP38:%.*]] = or i64 [[TMP37]], 512
-// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP7]], ptr [[TMP8]], ptr [[TMP9]], i64 [[TMP36]], i64 [[TMP38]], ptr [[TMP13]])
+// CHECK-NEXT:    call void @__tgt_push_mapper_component(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]], i64 [[TMP36]], i64 [[TMP38]], ptr [[TMP5]])
 // CHECK-NEXT:    br label [[OMP_DONE]]
 // CHECK:       omp.done:
 // CHECK-NEXT:    ret void
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index 4be0159fb1dd9f..482f93863119ae 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -2801,6 +2801,67 @@ class OpenMPIRBuilder {
   using GenMapInfoCallbackTy =
       function_ref<MapInfosTy &(InsertPointTy CodeGenIP)>;
 
+private:
+  /// Emit the array initialization or deletion portion for user-defined mapper
+  /// code generation. First, it evaluates whether an array section is mapped
+  /// and whether the \a MapType instructs to delete this section. If \a IsInit
+  /// is true, and \a MapType indicates to not delete this array, array
+  /// initialization code is generated. If \a IsInit is false, and \a MapType
+  /// indicates to not this array, array deletion code is generated.
+  void emitUDMapperArrayInitOrDel(Function *MapperFn, llvm::Value *Handle,
+                                  llvm::Value *Base, llvm::Value *Begin,
+                                  llvm::Value *Size, llvm::Value *MapType,
+                                  llvm::Value *MapName, TypeSize ElementSize,
+                                  llvm::BasicBlock *ExitBB, bool IsInit);
+
+public:
+  /// Emit the user-defined mapper function. The code generation follows the
+  /// pattern in the example below.
+  /// \code
+  /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
+  ///                                           void *base, void *begin,
+  ///                                           int64_t size, int64_t type,
+  ///                                           void *name = nullptr) {
+  ///   // Allocate space for an array section first or add a base/begin for
+  ///   // pointer dereference.
+  ///   if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) &&
+  ///       !maptype.IsDelete)
+  ///     __tgt_push_mapper_component(rt_mapper_handle, base, begin,
+  ///                                 size*sizeof(Ty), clearToFromMember(type));
+  ///   // Map members.
+  ///   for (unsigned i = 0; i < size; i++) {
+  ///     // For each component specified by this mapper:
+  ///     for (auto c : begin[i]->all_components) {
+  ///       if (c.hasMapper())
+  ///         (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin,
+  ///         c.arg_size,
+  ///                       c.arg_type, c.arg_name);
+  ///       else
+  ///         __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
+  ///                                     c.arg_begin, c.arg_size, c.arg_type,
+  ///                                     c.arg_name);
+  ///     }
+  ///   }
+  ///   // Delete the array section.
+  ///   if (size > 1 && maptype.IsDelete)
+  ///     __tgt_push_mapper_component(rt_mapper_handle, base, begin,
+  ///                                 size*sizeof(Ty), clearToFromMember(type));
+  /// }
+  /// \endcode
+  ///
+  /// \param PrivAndGenMapInfoCB Callback that privatizes code and populates the
+  /// MapInfos and returns.
+  /// \param ElemTy DeclareMapper element type.
+  /// \param FuncName Optional param to specify mapper function name.
+  /// \param CustomMapperCB Optional callback to generate code related to
+  /// custom mappers.
+  Function *emitUserDefinedMapper(
+      function_ref<MapInfosTy &(InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
+                                llvm::Value *BeginArg)>
+          PrivAndGenMapInfoCB,
+      llvm::Type *ElemTy, StringRef FuncName = {},
+      function_ref<bool(unsigned int, Function **)> CustomMapperCB = nullptr);
+
   /// Generator for '#omp target data'
   ///
   /// \param Loc The location where the target data construct was encountered.
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 515b74cbb75883..6539ee891dac01 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -7488,6 +7488,295 @@ void OpenMPIRBuilder::emitNonContiguousDescriptor(InsertPointTy AllocaIP,
   }
 }
 
+void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
+    Function *MapperFn, Value *Handle, Value *Base, Value *Begin, Value *Size,
+    Value *MapType, Value *MapName, TypeSize ElementSize, BasicBlock *ExitBB,
+    bool IsInit) {
+  StringRef Prefix = IsInit ? ".init" : ".del";
+
+  // Evaluate if this is an array section.
+  BasicBlock *BodyBB = BasicBlock::Create(
+      M.getContext(), createPlatformSpecificName({"omp.array", Prefix}));
+  Value *IsArray =
+      Builder.CreateICmpSGT(Size, Builder.getInt64(1), "omp.arrayinit.isarray");
+  Value *DeleteBit = Builder.CreateAnd(
+      MapType,
+      Builder.getInt64(
+          static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+              OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
+  Value *DeleteCond;
+  Value *Cond;
+  if (IsInit) {
+    // base != begin?
+    Value *BaseIsBegin = Builder.CreateICmpNE(Base, Begin);
+    // IsPtrAndObj?
+    Value *PtrAndObjBit = Builder.CreateAnd(
+        MapType,
+        Builder.getInt64(
+            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)));
+    PtrAndObjBit = Builder.CreateIsNotNull(PtrAndObjBit);
+    BaseIsBegin = Builder.CreateAnd(BaseIsBegin, PtrAndObjBit);
+    Cond = Builder.CreateOr(IsArray, BaseIsBegin);
+    DeleteCond = Builder.CreateIsNull(
+        DeleteBit,
+        createPlatformSpecificName({"omp.array", Prefix, ".delete"}));
+  } else {
+    Cond = IsArray;
+    DeleteCond = Builder.CreateIsNotNull(
+        DeleteBit,
+        createPlatformSpecificName({"omp.array", Prefix, ".delete"}));
+  }
+  Cond = Builder.CreateAnd(Cond, DeleteCond);
+  Builder.CreateCondBr(Cond, BodyBB, ExitBB);
+
+  emitBlock(BodyBB, MapperFn);
+  // Get the array size by multiplying element size and element number (i.e., \p
+  // Size).
+  Value *ArraySize = Builder.CreateNUWMul(Size, Builder.getInt64(ElementSize));
+  // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
+  // memory allocation/deletion purpose only.
+  Value *MapTypeArg = Builder.CreateAnd(
+      MapType,
+      Builder.getInt64(
+          ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+              OpenMPOffloadMappingFlags::OMP_MAP_TO |
+              OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
+  MapTypeArg = Builder.CreateOr(
+      MapTypeArg,
+      Builder.getInt64(
+          static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+              OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
+
+  // Call the runtime API __tgt_push_mapper_component to fill up the runtime
+  // data structure.
+  Value *OffloadingArgs[] = {Handle,    Base,       Begin,
+                             ArraySize, MapTypeArg, MapName};
+  Builder.CreateCall(
+      getOrCreateRuntimeFunction(M, OMPRTL___tgt_push_mapper_component),
+      OffloadingArgs);
+}
+
+Function *OpenMPIRBuilder::emitUserDefinedMapper(
+    function_ref<MapInfosTy &(InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
+                              llvm::Value *BeginArg)>
+        GenMapInfoCB,
+    Type *ElemTy, StringRef FuncName,
+    function_ref<bool(unsigned int, Function **)> CustomMapperCB) {
+  SmallVector<Type *> Params;
+  Params.emplace_back(Builder.getPtrTy());
+  Params.emplace_back(Builder.getPtrTy());
+  Params.emplace_back(Builder.getPtrTy());
+  Params.emplace_back(Builder.getInt64Ty());
+  Params.emplace_back(Builder.getInt64Ty());
+  Params.emplace_back(Builder.getPtrTy());
+
+  auto *FnTy =
+      FunctionType::get(Builder.getVoidTy(), Params, /* IsVarArg */ false);
+
+  SmallString<64> TyStr;
+  raw_svector_ostream Out(TyStr);
+  if (FuncName == "")
+    FuncName = StringRef{createPlatformSpecificName({"omp_mapper"})};
+  Function *MapperFn =
+      Function::Create(FnTy, GlobalValue::InternalLinkage, FuncName, M);
+  MapperFn->addFnAttr(Attribute::NoInline);
+  MapperFn->addFnAttr(Attribute::NoUnwind);
+  MapperFn->addParamAttr(0, Attribute::NoUndef);
+  MapperFn->addParamAttr(1, Attribute::NoUndef);
+  MapperFn->addParamAttr(2, Attribute::NoUndef);
+  MapperFn->addParamAttr(3, Attribute::NoUndef);
+  MapperFn->addParamAttr(4, Attribute::NoUndef);
+  MapperFn->addParamAttr(5, Attribute::NoUndef);
+
+  // Start the mapper function code generation.
+  BasicBlock *EntryBB = BasicBlock::Create(M.getContext(), "entry", MapperFn);
+  auto SavedIP = Builder.saveIP();
+  Builder.SetInsertPoint(EntryBB);
+
+  Value *Handle = MapperFn->getArg(0);
+  Value *BaseIn = MapperFn->getArg(1);
+  Value *BeginIn = MapperFn->getArg(2);
+  Value *Size = MapperFn->getArg(3);
+  Value *MapType = MapperFn->getArg(4);
+  Value *MapName = MapperFn->getArg(5);
+
+  // Compute the starting and end addresses of array elements.
+  // Prepare common arguments for array initiation and deletion.
+  // Convert the size in bytes into the number of array elements.
+  TypeSize ElementSize = M.getDataLayout().getTypeStoreSize(ElemTy);
+  Size = Builder.CreateExactUDiv(Size, Builder.getInt64(ElementSize));
+  Value *PtrBegin = Builder.CreateBitCast(BeginIn, Builder.getPtrTy());
+  Value *PtrEnd = Builder.CreateGEP(ElemTy, PtrBegin, Size);
+
+  // Emit array initiation if this is an array section and \p MapType indicates
+  // that memory allocation is required.
+  BasicBlock *HeadBB = BasicBlock::Create(M.getContext(), "omp.arraymap.head");
+  emitUDMapperArrayInitOrDel(MapperFn, Handle, BaseIn, BeginIn, Size, MapType,
+                             MapName, ElementSize, HeadBB, /*IsInit=*/true);
+
+  // Emit a for loop to iterate through SizeArg of elements and map all of them.
+
+  // Emit the loop header block.
+  emitBlock(HeadBB, MapperFn);
+  BasicBlock *BodyBB = BasicBlock::Create(M.getContext(), "omp.arraymap.body");
+  BasicBlock *DoneBB = BasicBlock::Create(M.getContext(), "omp.done");
+  // Evaluate whether the initial condition is satisfied.
+  Value *IsEmpty =
+      Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
+  Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+
+  // Emit the loop body block.
+  emitBlock(BodyBB, MapperFn);
+  BasicBlock *LastBB = BodyBB;
+  PHINode *PtrPHI =
+      Builder.CreatePHI(PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
+  PtrPHI->addIncoming(PtrBegin, HeadBB);
+
+  // Get map clause information. Fill up the arrays with all mapped variables.
+  MapInfosTy &Info = GenMapInfoCB(Builder.saveIP(), PtrPHI, BeginIn);
+
+  // Call the runtime API __tgt_mapper_num_components to get the number of
+  // pre-existing components.
+  Value *OffloadingArgs[] = {Handle};
+  Value *PreviousSize = Builder.CreateCall(
+      getOrCreateRuntimeFunction(M, OMPRTL___tgt_mapper_num_components),
+      OffloadingArgs);
+  Value *ShiftedPreviousSize =
+      Builder.CreateShl(PreviousSize, Builder.getInt64(getFlagMemberOffset()));
+
+  // Fill up the runtime mapper handle for all components.
+  for (unsigned I = 0; I < Info.BasePointers.size(); ++I) {
+    Value *CurBaseArg =
+        Builder.CreateBitCast(Info.BasePointers[I], Builder.getPtrTy());
+    Value *CurBeginArg =
+        Builder.CreateBitCast(Info.Pointers[I], Builder.getPtrTy());
+    Value *CurSizeArg = Info.Sizes[I];
+    Value *CurNameArg = Info.Names.size()
+                            ? Info.Names[I]
+                            : Constant::getNullValue(Builder.getPtrTy());
+
+    // Extract the MEMBER_OF field from the map type.
+    Value *OriMapType = Builder.getInt64(
+        static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+            Info.Types[I]));
+    Value *MemberMapType =
+        Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
+
+    // Combine the map type inherited from user-defined mapper with that
+    // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
+    // bits of the \a MapType, which is the input argument of the mapper
+    // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
+    // bits of MemberMapType.
+    // [OpenMP 5.0], 1.2.6. map-type decay.
+    //        | alloc |  to   | from  | tofrom | release | delete
+    // ----------------------------------------------------------
+    // alloc  | alloc | alloc | alloc | alloc  | release | delete
+    // to     | alloc |  to   | alloc |   to   | release | delete
+    // from   | alloc | alloc | from  |  from  | release | delete
+    // tofrom | alloc |  to   | from  | tofrom | release | delete
+    Value *LeftToFrom = Builder.CreateAnd(
+        MapType,
+        Builder.getInt64(
+            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_TO |
+                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
+    BasicBlock *AllocBB = BasicBlock::Create(M.getContext(), "omp.type.alloc");
+    BasicBlock *AllocElseBB =
+        BasicBlock::Create(M.getContext(), "omp.type.alloc.else");
+    BasicBlock *ToBB = BasicBlock::Create(M.getContext(), "omp.type.to");
+    BasicBlock *ToElseBB =
+        BasicBlock::Create(M.getContext(), "omp.type.to.else");
+    BasicBlock *FromBB = BasicBlock::Create(M.getContext(), "omp.type.from");
+    BasicBlock *EndBB = BasicBlock::Create(M.getContext(), "omp.type.end");
+    Value *IsAlloc = Builder.CreateIsNull(LeftToFrom);
+    Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
+    // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
+    emitBlock(AllocBB, MapperFn);
+    Value *AllocMapType = Builder.CreateAnd(
+        MemberMapType,
+        Builder.getInt64(
+            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_TO |
+                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
+    Builder.CreateBr(EndBB);
+    emitBlock(AllocElseBB, MapperFn);
+    Value *IsTo = Builder.CreateICmpEQ(
+        LeftToFrom,
+        Builder.getInt64(
+            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_TO)));
+    Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
+    // In case of to, clear OMP_MAP_FROM.
+    emitBlock(ToBB, MapperFn);
+    Value *ToMapType = Builder.CreateAnd(
+        MemberMapType,
+        Builder.getInt64(
+            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
+    Builder.CreateBr(EndBB);
+    emitBlock(ToElseBB, MapperFn);
+    Value *IsFrom = Builder.CreateICmpEQ(
+        LeftToFrom,
+        Builder.getInt64(
+            static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
+    Builder.CreateCondBr(IsFrom, FromBB, EndBB);
+    // In case of from, clear OMP_MAP_TO.
+    emitBlock(FromBB, MapperFn);
+    Value *FromMapType = Builder.CreateAnd(
+        MemberMapType,
+        Builder.getInt64(
+            ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
+                OpenMPOffloadMappingFlags::OMP_MAP_TO)));
+    // In case of tofrom, do nothing.
+    emitBlock(EndBB, MapperFn);
+    LastBB = EndBB;
+    PHINode *CurMapType =
+        Builder.CreatePHI(Builder.getInt64Ty(), 4, "omp.maptype");
+    CurMapType->addIncoming(AllocMapType, AllocBB);
+    CurMapType->addIncoming(ToMapType, ToBB);
+    CurMapType->addIncoming(FromMapType, FromBB);
+    CurMapType->addIncoming(MemberMapType, ToElseBB);
+
+    Value *OffloadingArgs[] = {Handle,     CurBaseArg, CurBeginArg,
+                               CurSizeArg, CurMapType, CurNameArg};
+    Function *ChildMapperFn = nullptr;
+    if (CustomMapperCB && CustomMapperCB(I, &ChildMapperFn)) {
+      // Call the corresponding mapper function.
+      Builder.CreateCall(ChildMapperFn, OffloadingArgs)->setDoesNotThrow();
+    } else {
+      // Call the runtime API __tgt_push_mapper_component to fill up the runtime
+      // data structure.
+      Builder.CreateCall(
+          getOrCreateRuntimeFunction(M, OMPRTL___tgt_push_mapper_component),
+          OffloadingArgs);
+    }
+  }
+
+  // Update the pointer to point to the next element that needs to be mapped,
+  // and check whether we have mapped all elements.
+  Value *PtrNext = Builder.CreateConstGEP1_32(ElemTy, PtrPHI, /*Idx0=*/1,
+                                              "omp.arraymap.next");
+  PtrPHI->addIncoming(PtrNext, LastBB);
+  Value *IsDone = Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
+  BasicBlock *ExitBB = BasicBlock::Create(M.getContext(), "omp.arraymap.exit");
+  Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
+
+  emitBlock(ExitBB, MapperFn);
+  // Emit array deletion if this is an array section and \p MapType indicates
+  // that deletion is required.
+  emitUDMapperArrayInitOrDel(MapperFn, Handle, BaseIn, BeginIn, Size, MapType,
+                             MapName, ElementSize, DoneBB, /*IsInit=*/false);
+
+  // Emit the function exit block.
+  emitBlock(DoneBB, MapperFn, /*IsFinished=*/true);
+
+  Builder.CreateRetVoid();
+  Builder.restoreIP(SavedIP);
+  return MapperFn;
+}
+
 void OpenMPIRBuilder::emitOffloadingArrays(
     InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo,
     TargetDataInfo &Info, bool IsNonContiguous,



More information about the cfe-commits mailing list