================ @@ -3421,6 +3441,85 @@ static void genMapInfos(llvm::IRBuilderBase &builder, } } +static llvm::Expected<llvm::Function *> +emitUserDefinedMapper(Operation *declMapperOp, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation); + +static llvm::Expected<llvm::Function *> +getOrCreateUserDefinedMapperFunc(Operation *declMapperOp, + llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + llvm::DenseMap<const Operation *, llvm::Function *> userDefMapperMap; + auto iter = userDefMapperMap.find(declMapperOp); + if (iter != userDefMapperMap.end()) + return iter->second; + llvm::Expected<llvm::Function *> mapperFunc = + emitUserDefinedMapper(declMapperOp, builder, moduleTranslation); + if (!mapperFunc) + return mapperFunc.takeError(); + userDefMapperMap.try_emplace(declMapperOp, *mapperFunc); + return userDefMapperMap.lookup(declMapperOp); +} + +static llvm::Expected<llvm::Function *> +emitUserDefinedMapper(Operation *op, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + auto declMapperOp = cast<omp::DeclareMapperOp>(op); + auto declMapperInfoOp = + *declMapperOp.getOps<omp::DeclareMapperInfoOp>().begin(); + DataLayout dl = DataLayout(declMapperOp->getParentOfType<ModuleOp>()); + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); + llvm::Type *varType = + moduleTranslation.convertType(declMapperOp.getVarType()); + std::string mapperName = ompBuilder->createPlatformSpecificName( + {"omp_mapper", declMapperOp.getSymName()}); + SmallVector<Value> mapVars = declMapperInfoOp.getMapVars(); + + using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; + + // Fill up the arrays with all the mapped variables. + MapInfosTy combinedInfo; + auto genMapInfoCB = + [&](InsertPointTy codeGenIP, llvm::Value *ptrPHI, + llvm::Value *unused2) -> llvm::OpenMPIRBuilder::MapInfosOrErrorTy { + builder.restoreIP(codeGenIP); + moduleTranslation.mapValue(declMapperOp.getRegion().getArgument(0), ptrPHI); + moduleTranslation.mapBlock(&declMapperOp.getRegion().front(), + builder.GetInsertBlock()); + if (failed(moduleTranslation.convertBlock(declMapperOp.getRegion().front(), + /*ignoreArguments=*/true, + builder))) + return llvm::make_error<PreviouslyReportedError>(); + MapInfoData mapData; + collectMapDataFromMapOperands(mapData, mapVars, moduleTranslation, dl, + builder); + genMapInfos(builder, moduleTranslation, dl, combinedInfo, mapData); + + // Drop the mapping that is no longer necessary so that the same region can + // be processed multiple times. + moduleTranslation.forgetMapping(declMapperOp.getRegion()); + return combinedInfo; + }; + + auto customMapperCB = [&](unsigned i, llvm::Function **mapperFunc) { + if (combinedInfo.Mappers[i]) { + // Call the corresponding mapper function. + llvm::Expected<llvm::Function *> newFn = getOrCreateUserDefinedMapperFunc( ---------------- TIFitis wrote:
I've updated the offloading test to trigger this recursion. Worklist for something like this might be an overkill. Clang implements declare mapper in a similar recursive manner. Also, cyclic recursions are not possible in legal code. Here's what the generated llvm IR looks like for the new test: ``` define void @_QQmain() { %.offload_baseptrs = alloca [2 x ptr], align 8 %.offload_ptrs = alloca [2 x ptr], align 8 %.offload_mappers = alloca [2 x ptr], align 8 %1 = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 %2 = alloca i32, i64 1, align 4 %3 = alloca i32, i64 1, align 4 %4 = alloca i32, i64 1, align 4 br label %5 5: ; preds = %9, %0 %6 = phi i32 [ %18, %9 ], [ 1, %0 ] %7 = phi i64 [ %19, %9 ], [ 1024, %0 ] %8 = icmp sgt i64 %7, 0 br i1 %8, label %9, label %20 9: ; preds = %5 store i32 %6, ptr %4, align 4 %10 = load i32, ptr %4, align 4 %11 = sext i32 %10 to i64 %12 = sub nsw i64 %11, 1 %13 = mul nsw i64 %12, 1 %14 = mul nsw i64 %13, 1 %15 = add nsw i64 %14, 0 %16 = getelementptr i32, ptr @_QFEobj, i64 %15 store i32 1, ptr %16, align 4 %17 = load i32, ptr %4, align 4 %18 = add nsw i32 %17, 1 %19 = sub i64 %7, 1 br label %5 20: ; preds = %5 store i32 %6, ptr %4, align 4 store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr @_QFEobj, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20240719, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] [[3 x i64] [i64 1, i64 1024, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64)]] }, ptr %1, align 8 %21 = call i32 @_FortranASumInteger4(ptr %1, ptr @_QQclXf46b0d060c890540d012b521bc3468aa, i32 21, i32 0, ptr null) store i32 %21, ptr %2, align 4 store i32 0, ptr %3, align 4 %22 = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 store ptr %3, ptr %22, align 8 %23 = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0 store ptr %3, ptr %23, align 8 %24 = getelementptr inbounds [2 x ptr], ptr %.offload_mappers, i64 0, i64 0 store ptr null, ptr %24, align 8 %25 = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 store ptr @_QFEobj, ptr %25, align 8 %26 = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 1 store ptr @_QFEobj, ptr %26, align 8 %27 = getelementptr inbounds [2 x ptr], ptr %.offload_mappers, i64 0, i64 1 store ptr @.omp_mapper._QQFmy_mapper2, ptr %27, align 8 %28 = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 %29 = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0 call void @__tgt_target_data_begin_mapper(ptr @7, i64 -1, i32 2, ptr %28, ptr %29, ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %.offload_mappers) br label %omp.data.region omp.data.region3: ; preds = %omp.data.region1 store i32 %43, ptr %4, align 4 br label %omp.region.cont omp.data.region2: ; preds = %omp.data.region1 store i32 %43, ptr %4, align 4 %30 = load i32, ptr %3, align 4 %31 = load i32, ptr %4, align 4 %32 = sext i32 %31 to i64 %33 = sub nsw i64 %32, 1 %34 = mul nsw i64 %33, 1 %35 = mul nsw i64 %34, 1 %36 = add nsw i64 %35, 0 %37 = getelementptr i32, ptr @_QFEobj, i64 %36 %38 = load i32, ptr %37, align 4 %39 = add i32 %30, %38 store i32 %39, ptr %3, align 4 %40 = load i32, ptr %4, align 4 %41 = add nsw i32 %40, 1 %42 = sub i64 %44, 1 br label %omp.data.region1 omp.data.region1: ; preds = %omp.data.region2, %omp.data.region %43 = phi i32 [ %41, %omp.data.region2 ], [ 1, %omp.data.region ] %44 = phi i64 [ %42, %omp.data.region2 ], [ 1024, %omp.data.region ] %45 = icmp sgt i64 %44, 0 br i1 %45, label %omp.data.region2, label %omp.data.region3 omp.data.region: ; preds = %20 br label %omp.data.region1 omp.region.cont: ; preds = %omp.data.region3 %46 = getelementptr inbounds [2 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 %47 = getelementptr inbounds [2 x ptr], ptr %.offload_ptrs, i32 0, i32 0 call void @__tgt_target_data_end_mapper(ptr @7, i64 -1, i32 2, ptr %46, ptr %47, ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr %.offload_mappers) %48 = call ptr @_FortranAioBeginExternalListOutput(i32 6, ptr @_QQclXf46b0d060c890540d012b521bc3468aa, i32 32) %49 = call i1 @_FortranAioOutputAscii(ptr %48, ptr @_QQclX53756D206F6E20686F73743A20202020, i64 16) %50 = load i32, ptr %2, align 4 %51 = call i1 @_FortranAioOutputInteger32(ptr %48, i32 %50) %52 = call i32 @_FortranAioEndIoStatement(ptr %48) %53 = call ptr @_FortranAioBeginExternalListOutput(i32 6, ptr @_QQclXf46b0d060c890540d012b521bc3468aa, i32 33) %54 = call i1 @_FortranAioOutputAscii(ptr %53, ptr @_QQclX53756D206F6E206465766963653A2020, i64 16) %55 = load i32, ptr %3, align 4 %56 = call i1 @_FortranAioOutputInteger32(ptr %53, i32 %55) %57 = call i32 @_FortranAioEndIoStatement(ptr %53) %58 = load i32, ptr %3, align 4 %59 = load i32, ptr %2, align 4 %60 = icmp eq i32 %58, %59 br i1 %60, label %61, label %65 61: ; preds = %omp.region.cont %62 = call ptr @_FortranAioBeginExternalListOutput(i32 6, ptr @_QQclXf46b0d060c890540d012b521bc3468aa, i32 36) %63 = call i1 @_FortranAioOutputAscii(ptr %62, ptr @_QQclX546573742070617373656421, i64 12) %64 = call i32 @_FortranAioEndIoStatement(ptr %62) br label %69 65: ; preds = %omp.region.cont %66 = call ptr @_FortranAioBeginExternalListOutput(i32 6, ptr @_QQclXf46b0d060c890540d012b521bc3468aa, i32 38) %67 = call i1 @_FortranAioOutputAscii(ptr %66, ptr @_QQclX54657374206661696C656421, i64 12) %68 = call i32 @_FortranAioEndIoStatement(ptr %66) br label %69 69: ; preds = %61, %65 ret void } ; Function Attrs: noinline nounwind define internal void @.omp_mapper._QQFmy_mapper2(ptr noundef %0, ptr noundef %1, ptr noundef %2, i64 noundef %3, i64 noundef %4, ptr noundef %5) #0 { entry: %6 = udiv exact i64 %3, 4096 %7 = getelementptr %_QFTmytype, ptr %2, i64 %6 %omp.arrayinit.isarray = icmp sgt i64 %6, 1 %8 = and i64 %4, 8 %9 = icmp ne ptr %1, %2 %10 = and i64 %4, 16 %11 = icmp ne i64 %10, 0 %12 = and i1 %9, %11 %13 = or i1 %omp.arrayinit.isarray, %12 %.omp.array..init..delete = icmp eq i64 %8, 0 %14 = and i1 %13, %.omp.array..init..delete br i1 %14, label %.omp.array..init, label %omp.arraymap.head .omp.array..init: ; preds = %entry %15 = mul nuw i64 %6, 4096 %16 = and i64 %4, -4 %17 = or i64 %16, 512 call void @__tgt_push_mapper_component(ptr %0, ptr %1, ptr %2, i64 %15, i64 %17, ptr %5) br label %omp.arraymap.head omp.arraymap.head: ; preds = %.omp.array..init, %entry %omp.arraymap.isempty = icmp eq ptr %2, %7 br i1 %omp.arraymap.isempty, label %omp.done, label %omp.arraymap.body omp.arraymap.body: ; preds = %omp.type.end, %omp.arraymap.head %omp.arraymap.ptrcurrent = phi ptr [ %2, %omp.arraymap.head ], [ %omp.arraymap.next, %omp.type.end ] %18 = getelementptr %_QFTmytype, ptr %omp.arraymap.ptrcurrent, i32 0, i32 0 %array_offset = getelementptr inbounds [1024 x i32], ptr %18, i64 0, i64 0 %19 = call i64 @__tgt_mapper_num_components(ptr %0) %20 = shl i64 %19, 48 %21 = add nuw i64 2, %20 %22 = and i64 %4, 3 %23 = icmp eq i64 %22, 0 br i1 %23, label %omp.type.alloc, label %omp.type.alloc.else omp.type.alloc: ; preds = %omp.arraymap.body %24 = and i64 %21, -4 br label %omp.type.end omp.type.alloc.else: ; preds = %omp.arraymap.body %25 = icmp eq i64 %22, 1 br i1 %25, label %omp.type.to, label %omp.type.to.else omp.type.to: ; preds = %omp.type.alloc.else %26 = and i64 %21, -3 br label %omp.type.end omp.type.to.else: ; preds = %omp.type.alloc.else %27 = icmp eq i64 %22, 2 br i1 %27, label %omp.type.from, label %omp.type.end omp.type.from: ; preds = %omp.type.to.else %28 = and i64 %21, -2 br label %omp.type.end omp.type.end: ; preds = %omp.type.from, %omp.type.to.else, %omp.type.to, %omp.type.alloc %omp.maptype = phi i64 [ %24, %omp.type.alloc ], [ %26, %omp.type.to ], [ %28, %omp.type.from ], [ %21, %omp.type.to.else ] call void @.omp_mapper._QQFmy_mapper1(ptr %0, ptr %omp.arraymap.ptrcurrent, ptr %array_offset, i64 4096, i64 %omp.maptype, ptr @3) #1 %omp.arraymap.next = getelementptr %_QFTmytype, ptr %omp.arraymap.ptrcurrent, i32 1 %omp.arraymap.isdone = icmp eq ptr %omp.arraymap.next, %7 br i1 %omp.arraymap.isdone, label %omp.arraymap.exit, label %omp.arraymap.body omp.arraymap.exit: ; preds = %omp.type.end %omp.arrayinit.isarray1 = icmp sgt i64 %6, 1 %29 = and i64 %4, 8 %.omp.array..del..delete = icmp ne i64 %29, 0 %30 = and i1 %omp.arrayinit.isarray1, %.omp.array..del..delete br i1 %30, label %.omp.array..del, label %omp.done .omp.array..del: ; preds = %omp.arraymap.exit %31 = mul nuw i64 %6, 4096 %32 = and i64 %4, -4 %33 = or i64 %32, 512 call void @__tgt_push_mapper_component(ptr %0, ptr %1, ptr %2, i64 %31, i64 %33, ptr %5) br label %omp.done omp.done: ; preds = %.omp.array..del, %omp.arraymap.exit, %omp.arraymap.head ret void } ; Function Attrs: noinline nounwind define internal void @.omp_mapper._QQFmy_mapper1(ptr noundef %0, ptr noundef %1, ptr noundef %2, i64 noundef %3, i64 noundef %4, ptr noundef %5) #0 { entry: %6 = udiv exact i64 %3, 4096 %7 = getelementptr %_QFTmytype, ptr %2, i64 %6 %omp.arrayinit.isarray = icmp sgt i64 %6, 1 %8 = and i64 %4, 8 %9 = icmp ne ptr %1, %2 %10 = and i64 %4, 16 %11 = icmp ne i64 %10, 0 %12 = and i1 %9, %11 %13 = or i1 %omp.arrayinit.isarray, %12 %.omp.array..init..delete = icmp eq i64 %8, 0 %14 = and i1 %13, %.omp.array..init..delete br i1 %14, label %.omp.array..init, label %omp.arraymap.head .omp.array..init: ; preds = %entry %15 = mul nuw i64 %6, 4096 %16 = and i64 %4, -4 %17 = or i64 %16, 512 call void @__tgt_push_mapper_component(ptr %0, ptr %1, ptr %2, i64 %15, i64 %17, ptr %5) br label %omp.arraymap.head omp.arraymap.head: ; preds = %.omp.array..init, %entry %omp.arraymap.isempty = icmp eq ptr %2, %7 br i1 %omp.arraymap.isempty, label %omp.done, label %omp.arraymap.body omp.arraymap.body: ; preds = %omp.type.end, %omp.arraymap.head %omp.arraymap.ptrcurrent = phi ptr [ %2, %omp.arraymap.head ], [ %omp.arraymap.next, %omp.type.end ] %18 = getelementptr %_QFTmytype, ptr %omp.arraymap.ptrcurrent, i32 0, i32 0 %array_offset = getelementptr inbounds [1024 x i32], ptr %18, i64 0, i64 0 %19 = call i64 @__tgt_mapper_num_components(ptr %0) %20 = shl i64 %19, 48 %21 = add nuw i64 1, %20 %22 = and i64 %4, 3 %23 = icmp eq i64 %22, 0 br i1 %23, label %omp.type.alloc, label %omp.type.alloc.else omp.type.alloc: ; preds = %omp.arraymap.body %24 = and i64 %21, -4 br label %omp.type.end omp.type.alloc.else: ; preds = %omp.arraymap.body %25 = icmp eq i64 %22, 1 br i1 %25, label %omp.type.to, label %omp.type.to.else omp.type.to: ; preds = %omp.type.alloc.else %26 = and i64 %21, -3 br label %omp.type.end omp.type.to.else: ; preds = %omp.type.alloc.else %27 = icmp eq i64 %22, 2 br i1 %27, label %omp.type.from, label %omp.type.end omp.type.from: ; preds = %omp.type.to.else %28 = and i64 %21, -2 br label %omp.type.end omp.type.end: ; preds = %omp.type.from, %omp.type.to.else, %omp.type.to, %omp.type.alloc %omp.maptype = phi i64 [ %24, %omp.type.alloc ], [ %26, %omp.type.to ], [ %28, %omp.type.from ], [ %21, %omp.type.to.else ] call void @__tgt_push_mapper_component(ptr %0, ptr %omp.arraymap.ptrcurrent, ptr %array_offset, i64 4096, i64 %omp.maptype, ptr @5) %omp.arraymap.next = getelementptr %_QFTmytype, ptr %omp.arraymap.ptrcurrent, i32 1 %omp.arraymap.isdone = icmp eq ptr %omp.arraymap.next, %7 br i1 %omp.arraymap.isdone, label %omp.arraymap.exit, label %omp.arraymap.body omp.arraymap.exit: ; preds = %omp.type.end %omp.arrayinit.isarray1 = icmp sgt i64 %6, 1 %29 = and i64 %4, 8 %.omp.array..del..delete = icmp ne i64 %29, 0 %30 = and i1 %omp.arrayinit.isarray1, %.omp.array..del..delete br i1 %30, label %.omp.array..del, label %omp.done .omp.array..del: ; preds = %omp.arraymap.exit %31 = mul nuw i64 %6, 4096 %32 = and i64 %4, -4 %33 = or i64 %32, 512 call void @__tgt_push_mapper_component(ptr %0, ptr %1, ptr %2, i64 %31, i64 %33, ptr %5) br label %omp.done omp.done: ; preds = %.omp.array..del, %omp.arraymap.exit, %omp.arraymap.head ret void } ``` https://github.com/llvm/llvm-project/pull/124746 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits