summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGStmtOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGStmtOpenMP.cpp')
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp119
1 files changed, 107 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 985cc0e62ae..5efff2ccbde 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -24,6 +24,110 @@ using namespace CodeGen;
// OpenMP Directive Emission
//===----------------------------------------------------------------------===//
+void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
+ llvm::Value *PrivateAddr,
+ const Expr *AssignExpr,
+ QualType OriginalType,
+ const VarDecl *VDInit) {
+ EmitBlock(createBasicBlock(".omp.assign.begin."));
+ if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
+ // Perform simple memcpy.
+ EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
+ AssignExpr->getType());
+ } else {
+ // Perform element-by-element initialization.
+ QualType ElementTy;
+ auto SrcBegin = OriginalAddr.getAddress();
+ auto DestBegin = PrivateAddr;
+ auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
+ auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
+ auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
+ auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
+ auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
+ // The basic structure here is a do-while loop, because we don't
+ // need to check for the zero-element case.
+ auto BodyBB = createBasicBlock("omp.arraycpy.body");
+ auto DoneBB = createBasicBlock("omp.arraycpy.done");
+ auto IsEmpty =
+ Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
+ Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
+
+ // Enter the loop body, making that address the current address.
+ auto EntryBB = Builder.GetInsertBlock();
+ EmitBlock(BodyBB);
+ auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
+ "omp.arraycpy.srcElementPast");
+ SrcElementPast->addIncoming(SrcEnd, EntryBB);
+ auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
+ "omp.arraycpy.destElementPast");
+ DestElementPast->addIncoming(DestEnd, EntryBB);
+
+ // Shift the address back by one element.
+ auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
+ auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
+ "omp.arraycpy.dest.element");
+ auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
+ "omp.arraycpy.src.element");
+ {
+ // Create RunCleanScope to cleanup possible temps.
+ CodeGenFunction::RunCleanupsScope Init(*this);
+ // Emit initialization for single element.
+ LocalDeclMap[VDInit] = SrcElement;
+ EmitAnyExprToMem(AssignExpr, DestElement,
+ AssignExpr->getType().getQualifiers(),
+ /*IsInitializer*/ false);
+ LocalDeclMap.erase(VDInit);
+ }
+
+ // Check whether we've reached the end.
+ auto Done =
+ Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
+ Builder.CreateCondBr(Done, DoneBB, BodyBB);
+ DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
+ SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
+
+ // Done.
+ EmitBlock(DoneBB, true);
+ }
+ EmitBlock(createBasicBlock(".omp.assign.end."));
+}
+
+void CodeGenFunction::EmitOMPFirstprivateClause(
+ const OMPExecutableDirective &D,
+ CodeGenFunction::OuterDeclMapTy &OuterDeclMap) {
+ auto PrivateFilter = [](const OMPClause *C) -> bool {
+ return C->getClauseKind() == OMPC_firstprivate;
+ };
+ for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
+ I(D.clauses(), PrivateFilter); I; ++I) {
+ auto *C = cast<OMPFirstprivateClause>(*I);
+ auto IRef = C->varlist_begin();
+ auto InitsRef = C->inits().begin();
+ for (auto IInit : C->private_copies()) {
+ auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
+ if (*InitsRef != nullptr) {
+ // Emit VarDecl with copy init for arrays.
+ auto *FD = CapturedStmtInfo->lookup(
+ cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()));
+ LValue Base = MakeNaturalAlignAddrLValue(
+ CapturedStmtInfo->getContextValue(),
+ getContext().getTagDeclType(FD->getParent()));
+ auto OriginalAddr = EmitLValueForField(Base, FD);
+ auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
+ auto Emission = EmitAutoVarAlloca(*VD);
+ // Emit initialization of aggregate firstprivate vars.
+ EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
+ VD->getInit(), (*IRef)->getType(), VDInit);
+ EmitAutoVarCleanups(Emission);
+ } else
+ // Emit VarDecl with copy init.
+ EmitDecl(*VD);
+ OuterDeclMap[cast<DeclRefExpr>(*IRef)->getDecl()] = GetAddrOfLocalVar(VD);
+ ++IRef, ++InitsRef;
+ }
+ }
+}
+
void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
llvm::Value *CapturedStruct = GenerateCapturedStmtArgument(*CS);
@@ -31,22 +135,13 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
llvm::Value *OutlinedFn;
{
CodeGenFunction CGF(CGM, true);
- CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind());
+ CGOpenMPRegionInfo CGInfo(S, *CS, *CS->getCapturedDecl()->param_begin());
CGF.CapturedStmtInfo = &CGInfo;
OutlinedFn = CGF.GenerateCapturedStmtFunction(*CS);
}
- // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
- llvm::Value *Args[] = {
- CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
- Builder.getInt32(1), // Number of arguments after 'microtask' argument
- // (there is only one additional argument - 'context')
- Builder.CreateBitCast(OutlinedFn,
- CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
- EmitCastToVoidPtr(CapturedStruct)};
- llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction(
- CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
- EmitRuntimeCall(RTLFn, Args);
+ CGM.getOpenMPRuntime().EmitOMPParallelCall(*this, S.getLocStart(), OutlinedFn,
+ CapturedStruct);
}
void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
OpenPOWER on IntegriCloud