(void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args);
}
+void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
+ OpenMPDependClauseKind NewDepKind,
+ SourceLocation Loc) {
+ ASTContext &C = CGM.getContext();
+ QualType FlagsTy;
+ getDependTypes(C, KmpDependInfoTy, FlagsTy);
+ RecordDecl *KmpDependInfoRD =
+ cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
+ llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
+ LValue Base = CGF.EmitLoadOfPointerLValue(
+ DepobjLVal.getAddress(CGF),
+ C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
+ QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy);
+ Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
+ Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
+ Base.getTBAAInfo());
+ llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
+ Addr.getPointer(),
+ llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
+ LValue NumDepsBase = CGF.MakeAddrLValue(
+ Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
+ Base.getBaseInfo(), Base.getTBAAInfo());
+ // NumDeps = deps[i].base_addr;
+ LValue BaseAddrLVal = CGF.EmitLValueForField(
+ NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
+ llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc);
+
+ Address Begin = Base.getAddress(CGF);
+ // Cast from pointer to array type to pointer to single element.
+ llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
+ // The basic structure here is a while-do loop.
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
+ llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
+ llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
+ CGF.EmitBlock(BodyBB);
+ llvm::PHINode *ElementPHI =
+ CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast");
+ ElementPHI->addIncoming(Begin.getPointer(), EntryBB);
+ Begin = Address(ElementPHI, Begin.getAlignment());
+ Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(),
+ Base.getTBAAInfo());
+ // deps[i].flags = NewDepKind;
+ RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind);
+ LValue FlagsLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
+ FlagsLVal);
+
+ // Shift the address forward by one element.
+ Address ElementNext =
+ CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext");
+ ElementPHI->addIncoming(ElementNext.getPointer(),
+ CGF.Builder.GetInsertBlock());
+ llvm::Value *IsEmpty =
+ CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty");
+ CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+ // Done.
+ CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
+}
+
void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
const OMPExecutableDirective &D,
llvm::Function *TaskFunction,
/// directive.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal,
SourceLocation Loc);
+
+ /// Updates the dependency kind in the specified depobj object.
+ /// \param DepobjLVal LValue for the main depobj object.
+ /// \param NewDepKind New dependency kind.
+ void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal,
+ OpenMPDependClauseKind NewDepKind, SourceLocation Loc);
};
/// Class supports emissionof SIMD-only code.
CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
return;
}
+ if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
+ CGM.getOpenMPRuntime().emitUpdateClause(
+ *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
+ return;
+ }
}
void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
// 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: [[B:%.+]] = load i8*, i8** [[B_ADDR]],
+// CHECK: [[B_BASE:%.+]] = bitcast i8* [[B]] to %struct.kmp_depend_info*
+// CHECK: [[NUMDEPS_BASE:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i64 -1
+// CHECK: [[NUMDEPS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[NUMDEPS_BASE]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[NUMDEPS:%.+]] = load i64, i64* [[NUMDEPS_ADDR]],
+// CHECK: [[END:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[B_BASE]], i64 [[NUMDEPS]]
+// CHECK: br label %[[BODY:.+]]
+// CHECK: [[BODY]]:
+// CHECK: [[EL:%.+]] = phi %struct.kmp_depend_info* [ [[B_BASE]], %{{.+}} ], [ [[EL_NEXT:%.+]], %[[BODY]] ]
+// CHECK: [[FLAG_BASE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 0, i{{.+}} 2
+// CHECK: store i8 4, i8* [[FLAG_BASE]],
+// CHECK: [[EL_NEXT]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 1
+// CHECK: [[IS_DONE:%.+]] = icmp eq %struct.kmp_depend_info* [[EL_NEXT]], [[END]]
+// CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[BODY]]
+// CHECK: [[DONE]]:
// CHECK-LABEL: tmain
// CHECK: [[ARGC_ADDR:%.+]] = alloca i8*,
// 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)
+// CHECK: [[ARGC:%.+]] = load i8*, i8** [[ARGC_ADDR]],
+// CHECK: [[ARGC_BASE:%.+]] = bitcast i8* [[ARGC]] to %struct.kmp_depend_info*
+// CHECK: [[NUMDEPS_BASE:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i64 -1
+// CHECK: [[NUMDEPS_ADDR:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[NUMDEPS_BASE]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[NUMDEPS:%.+]] = load i64, i64* [[NUMDEPS_ADDR]],
+// CHECK: [[END:%.+]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[ARGC_BASE]], i64 [[NUMDEPS]]
+// CHECK: br label %[[BODY:.+]]
+// CHECK: [[BODY]]:
+// CHECK: [[EL:%.+]] = phi %struct.kmp_depend_info* [ [[ARGC_BASE]], %{{.+}} ], [ [[EL_NEXT:%.+]], %[[BODY]] ]
+// CHECK: [[FLAG_BASE:%.+]] = getelementptr inbounds %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 0, i{{.+}} 2
+// CHECK: store i8 3, i8* [[FLAG_BASE]],
+// CHECK: [[EL_NEXT]] = getelementptr %struct.kmp_depend_info, %struct.kmp_depend_info* [[EL]], i{{.+}} 1
+// CHECK: [[IS_DONE:%.+]] = icmp eq %struct.kmp_depend_info* [[EL_NEXT]], [[END]]
+// CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[BODY]]
+// CHECK: [[DONE]]:
#endif