diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 09749270b83037f..690634458622dc2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -5186,6 +5186,55 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, return Result; } +namespace { +/// Dependence kind for RTL. +enum RTLDependenceKindTy { + DepIn = 0x01, + DepInOut = 0x3, + DepMutexInOutSet = 0x4 +}; +/// Fields ids in kmp_depend_info record. +enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; +} // namespace + +/// Translates internal dependency kind into the runtime kind. +static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { + RTLDependenceKindTy DepKind; + switch (K) { + case OMPC_DEPEND_in: + DepKind = DepIn; + break; + // Out and InOut dependencies must use the same code. + case OMPC_DEPEND_out: + case OMPC_DEPEND_inout: + DepKind = DepInOut; + break; + case OMPC_DEPEND_mutexinoutset: + DepKind = DepMutexInOutSet; + break; + case OMPC_DEPEND_source: + case OMPC_DEPEND_sink: + case OMPC_DEPEND_unknown: + llvm_unreachable("Unknown task dependence type"); + } + return DepKind; +} + +/// Builds kmp_depend_info, if it is not built yet, and builds flags type. +static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, + QualType &FlagsTy) { + FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); + if (KmpDependInfoTy.isNull()) { + RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); + KmpDependInfoRD->startDefinition(); + addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); + addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); + addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); + KmpDependInfoRD->completeDefinition(); + KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); + } +} + Address CGOpenMPRuntime::emitDependClause( CodeGenFunction &CGF, ArrayRef> Dependencies, @@ -5195,28 +5244,11 @@ Address CGOpenMPRuntime::emitDependClause( Address DependenciesArray = Address::invalid(); unsigned NumDependencies = Dependencies.size(); if (NumDependencies) { - // Dependence kind for RTL. - enum RTLDependenceKindTy { - DepIn = 0x01, - DepInOut = 0x3, - DepMutexInOutSet = 0x4 - }; - enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; - RecordDecl *KmpDependInfoRD; - QualType FlagsTy = - C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); + QualType FlagsTy; + getDependTypes(C, KmpDependInfoTy, FlagsTy); + RecordDecl *KmpDependInfoRD = + cast(KmpDependInfoTy->getAsTagDecl()); llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); - if (KmpDependInfoTy.isNull()) { - KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); - KmpDependInfoRD->startDefinition(); - addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); - addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); - addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); - KmpDependInfoRD->completeDefinition(); - KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); - } else { - KmpDependInfoRD = cast(KmpDependInfoTy->getAsTagDecl()); - } // Define type kmp_depend_info[]; // For depobj reserve one extra element to store the number of elements. // It is required to handle depobj(x) update(in) construct. @@ -5289,38 +5321,36 @@ Address CGOpenMPRuntime::emitDependClause( Base, *std::next(KmpDependInfoRD->field_begin(), Len)); CGF.EmitStoreOfScalar(Size, LenLVal); // deps[i].flags = ; - RTLDependenceKindTy DepKind; - switch (Dependencies[I].first) { - case OMPC_DEPEND_in: - DepKind = DepIn; - break; - // Out and InOut dependencies must use the same code. - case OMPC_DEPEND_out: - case OMPC_DEPEND_inout: - DepKind = DepInOut; - break; - case OMPC_DEPEND_mutexinoutset: - DepKind = DepMutexInOutSet; - break; - case OMPC_DEPEND_source: - case OMPC_DEPEND_sink: - case OMPC_DEPEND_unknown: - llvm_unreachable("Unknown task dependence type"); - } + RTLDependenceKindTy DepKind = + translateDependencyKind(Dependencies[I].first); LValue FlagsLVal = CGF.EmitLValueForField( Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), FlagsLVal); } DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); + CGF.Builder.CreateConstArrayGEP(DependenciesArray, ForDepobj ? 1 : 0), + CGF.VoidPtrTy); } return DependenciesArray; } void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc) { - llvm::Value *DepObjAddr = CGF.EmitLoadOfScalar(DepobjLVal, Loc); + ASTContext &C = CGM.getContext(); + QualType FlagsTy; + getDependTypes(C, KmpDependInfoTy, FlagsTy); + LValue Base = CGF.EmitLoadOfPointerLValue( + DepobjLVal.getAddress(CGF), + C.getPointerType(C.VoidPtrTy).castAs()); + QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); + Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); + llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( + Addr.getPointer(), + llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); + DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, + CGF.VoidPtrTy); llvm::Value *ThreadID = getThreadID(CGF, Loc); // Use default allocator. llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); diff --git a/clang/test/OpenMP/depobj_codegen.cpp b/clang/test/OpenMP/depobj_codegen.cpp index 1d1809b2155cb0b..b777c2baf7a8a0d 100644 --- a/clang/test/OpenMP/depobj_codegen.cpp +++ b/clang/test/OpenMP/depobj_codegen.cpp @@ -59,10 +59,13 @@ int main(int argc, char **argv) { // CHECK: store i64 8, i64* [[SZ_ADDR]], // CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 2 // CHECK: store i8 3, i8* [[FLAGS_ADDR]], -// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 0 +// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [3 x %struct.kmp_depend_info], [3 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1 // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[BASE_ADDR]] to i8* // CHECK: store i8* [[DEP]], i8** [[MAIN_A]], // CHECK: [[B:%.+]] = load i8*, i8** [[B_ADDR]], +// CHECK: [[B_BASE:%.+]] = bitcast i8* [[B]] to %struct.kmp_depend_info* +// CHECK: [[B_REF:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i{{.+}} -1 +// CHECK: [[B:%.+]] = bitcast %struct.kmp_depend_info* [[B_REF]] to i8* // CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[B]], i8* null) // CHECK-LABEL: tmain @@ -80,10 +83,13 @@ int main(int argc, char **argv) { // CHECK: store i64 8, i64* [[SZ_ADDR]], // CHECK: [[FLAGS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[BASE_ADDR]], i{{.+}} 0, i{{.+}} 2 // CHECK: store i8 1, i8* [[FLAGS_ADDR]], -// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 0 +// CHECK: [[BASE_ADDR:%.+]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DEP_ADDR]], i{{.+}} 0, i{{.+}} 1 // CHECK: [[DEP:%.+]] = bitcast %struct.kmp_depend_info* [[BASE_ADDR]] to i8* // CHECK: store i8* [[DEP]], i8** [[TMAIN_A]], // CHECK: [[ARGC:%.+]] = load i8*, i8** [[ARGC_ADDR]], +// CHECK: [[ARGC_BASE:%.+]] = bitcast i8* [[ARGC]] to %struct.kmp_depend_info* +// CHECK: [[ARGC_REF:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i{{.+}} -1 +// CHECK: [[ARGC:%.+]] = bitcast %struct.kmp_depend_info* [[ARGC_REF]] to i8* // CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[ARGC]], i8* null) #endif