forked from OSchip/llvm-project
[OPENMP 4.5] Codegen for data members in 'reduction' clause.
OpenMP 4.5 allows to privatize non-static data members of current class in non-static member functions. Patch supports codegen for non-static data members in 'reduction' clauses. llvm-svn: 262460
This commit is contained in:
parent
dcd3a88e29
commit
61205070c4
|
@ -1665,6 +1665,8 @@ public:
|
|||
///
|
||||
class OMPReductionClause final
|
||||
: public OMPVarListClause<OMPReductionClause>,
|
||||
public OMPClauseWithPreInit,
|
||||
public OMPClauseWithPostUpdate,
|
||||
private llvm::TrailingObjects<OMPReductionClause, Expr *> {
|
||||
friend TrailingObjects;
|
||||
friend OMPVarListClause;
|
||||
|
@ -1692,6 +1694,7 @@ class OMPReductionClause final
|
|||
const DeclarationNameInfo &NameInfo)
|
||||
: OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc,
|
||||
LParenLoc, EndLoc, N),
|
||||
OMPClauseWithPreInit(this), OMPClauseWithPostUpdate(this),
|
||||
ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
|
@ -1702,7 +1705,8 @@ class OMPReductionClause final
|
|||
: OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(),
|
||||
SourceLocation(), SourceLocation(),
|
||||
N),
|
||||
ColonLoc(), QualifierLoc(), NameInfo() {}
|
||||
OMPClauseWithPreInit(this), OMPClauseWithPostUpdate(this), ColonLoc(),
|
||||
QualifierLoc(), NameInfo() {}
|
||||
|
||||
/// \brief Sets location of ':' symbol in clause.
|
||||
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
|
||||
|
@ -1795,6 +1799,10 @@ public:
|
|||
/// \endcode
|
||||
/// Required for proper codegen of final reduction operation performed by the
|
||||
/// reduction clause.
|
||||
/// \param PreInit Statement that must be executed before entering the OpenMP
|
||||
/// region with this clause.
|
||||
/// \param PostUpdate Expression that must be executed after exit from the
|
||||
/// OpenMP region with this clause.
|
||||
///
|
||||
static OMPReductionClause *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
|
@ -1802,7 +1810,7 @@ public:
|
|||
NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
|
||||
ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
|
||||
ArrayRef<Expr *> ReductionOps);
|
||||
ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate);
|
||||
/// \brief Creates an empty clause with the place for \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
|
|
|
@ -2766,6 +2766,8 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
|
|||
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
|
||||
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(VisitOMPClauseWithPostUpdate(C));
|
||||
for (auto *E : C->privates()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
|
|
|
@ -7834,7 +7834,7 @@ public:
|
|||
/// constructs.
|
||||
VarDecl *IsOpenMPCapturedDecl(ValueDecl *D);
|
||||
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
|
||||
ExprObjectKind OK);
|
||||
ExprObjectKind OK, SourceLocation Loc);
|
||||
|
||||
/// \brief Check if the specified variable is used in 'private' clause.
|
||||
/// \param Level Relative level of nested OpenMP construct for that the check
|
||||
|
|
|
@ -44,6 +44,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
|
|||
return static_cast<const OMPFirstprivateClause *>(C);
|
||||
case OMPC_lastprivate:
|
||||
return static_cast<const OMPLastprivateClause *>(C);
|
||||
case OMPC_reduction:
|
||||
return static_cast<const OMPReductionClause *>(C);
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_if:
|
||||
|
@ -54,7 +56,6 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
|
|||
case OMPC_collapse:
|
||||
case OMPC_private:
|
||||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -99,6 +100,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
|
|||
switch (C->getClauseKind()) {
|
||||
case OMPC_lastprivate:
|
||||
return static_cast<const OMPLastprivateClause *>(C);
|
||||
case OMPC_reduction:
|
||||
return static_cast<const OMPReductionClause *>(C);
|
||||
case OMPC_schedule:
|
||||
case OMPC_dist_schedule:
|
||||
case OMPC_firstprivate:
|
||||
|
@ -112,7 +115,6 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
|
|||
case OMPC_collapse:
|
||||
case OMPC_private:
|
||||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -463,7 +465,8 @@ OMPReductionClause *OMPReductionClause::Create(
|
|||
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
|
||||
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
|
||||
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
|
||||
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps) {
|
||||
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
|
||||
Expr *PostUpdate) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
|
||||
OMPReductionClause *Clause = new (Mem) OMPReductionClause(
|
||||
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
|
||||
|
@ -472,6 +475,8 @@ OMPReductionClause *OMPReductionClause::Create(
|
|||
Clause->setLHSExprs(LHSExprs);
|
||||
Clause->setRHSExprs(RHSExprs);
|
||||
Clause->setReductionOps(ReductionOps);
|
||||
Clause->setPreInitStmt(PreInit);
|
||||
Clause->setPostUpdateExpr(PostUpdate);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
|
|
|
@ -399,6 +399,8 @@ void OMPClauseProfiler::VisitOMPReductionClause(
|
|||
C->getQualifierLoc().getNestedNameSpecifier());
|
||||
Profiler->VisitName(C->getNameInfo().getName());
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPreInit(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
|
|
|
@ -943,6 +943,31 @@ void CodeGenFunction::EmitOMPReductionClauseFinal(
|
|||
}
|
||||
}
|
||||
|
||||
static void emitPostUpdateForReductionClause(
|
||||
CodeGenFunction &CGF, const OMPExecutableDirective &D,
|
||||
const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) {
|
||||
if (!CGF.HaveInsertPoint())
|
||||
return;
|
||||
llvm::BasicBlock *DoneBB = nullptr;
|
||||
for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
|
||||
if (auto *PostUpdate = C->getPostUpdateExpr()) {
|
||||
if (!DoneBB) {
|
||||
if (auto *Cond = CondGen(CGF)) {
|
||||
// If the first post-update expression is found, emit conditional
|
||||
// block if it was requested.
|
||||
auto *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
|
||||
DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
|
||||
CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
|
||||
CGF.EmitBlock(ThenBB);
|
||||
}
|
||||
}
|
||||
CGF.EmitIgnoredExpr(PostUpdate);
|
||||
}
|
||||
}
|
||||
if (DoneBB)
|
||||
CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
|
||||
}
|
||||
|
||||
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF,
|
||||
const OMPExecutableDirective &S,
|
||||
OpenMPDirectiveKind InnermostKind,
|
||||
|
@ -998,6 +1023,8 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
|
|||
CGF.EmitOMPReductionClauseFinal(S);
|
||||
};
|
||||
emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen);
|
||||
emitPostUpdateForReductionClause(
|
||||
*this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
|
||||
|
@ -1346,6 +1373,8 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
|
|||
CGF.EmitOMPLastprivateClauseFinal(S);
|
||||
}
|
||||
CGF.EmitOMPReductionClauseFinal(S);
|
||||
emitPostUpdateForReductionClause(
|
||||
CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; });
|
||||
}
|
||||
CGF.EmitOMPSimdFinal(S);
|
||||
// Emit: if (PreCond) - end.
|
||||
|
@ -1669,6 +1698,12 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
|
|||
IL.getAddress(), Chunk);
|
||||
}
|
||||
EmitOMPReductionClauseFinal(S);
|
||||
// Emit post-update of the reduction variables if IsLastIter != 0.
|
||||
emitPostUpdateForReductionClause(
|
||||
*this, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
|
||||
return CGF.Builder.CreateIsNotNull(
|
||||
CGF.EmitLoadOfScalar(IL, S.getLocStart()));
|
||||
});
|
||||
// Emit final copy of the lastprivate variables if IsLastIter != 0.
|
||||
if (HasLastprivateClause)
|
||||
EmitOMPLastprivateClauseFinal(
|
||||
|
@ -1827,6 +1862,12 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
|
|||
// Tell the runtime we are done.
|
||||
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocStart());
|
||||
CGF.EmitOMPReductionClauseFinal(S);
|
||||
// Emit post-update of the reduction variables if IsLastIter != 0.
|
||||
emitPostUpdateForReductionClause(
|
||||
CGF, S, [&](CodeGenFunction &CGF) -> llvm::Value * {
|
||||
return CGF.Builder.CreateIsNotNull(
|
||||
CGF.EmitLoadOfScalar(IL, S.getLocStart()));
|
||||
});
|
||||
|
||||
// Emit final copy of the lastprivate variables if IsLastIter != 0.
|
||||
if (HasLastprivates)
|
||||
|
|
|
@ -1794,7 +1794,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
|
|||
if (S.getLangOpts().OpenMP && IsArrow &&
|
||||
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
|
||||
if (auto *PrivateCopy = S.IsOpenMPCapturedDecl(Field))
|
||||
return S.getOpenMPCapturedExpr(PrivateCopy, VK, OK);
|
||||
return S.getOpenMPCapturedExpr(PrivateCopy, VK, OK, OpLoc);
|
||||
}
|
||||
return ME;
|
||||
}
|
||||
|
|
|
@ -1705,7 +1705,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
|
|||
}
|
||||
|
||||
static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
|
||||
Expr *CaptureExpr) {
|
||||
Expr *CaptureExpr, bool WithInit) {
|
||||
ASTContext &C = S.getASTContext();
|
||||
Expr *Init = CaptureExpr->IgnoreImpCasts();
|
||||
QualType Ty = Init->getType();
|
||||
|
@ -1720,27 +1720,33 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
|
|||
return nullptr;
|
||||
Init = Res.get();
|
||||
}
|
||||
WithInit = true;
|
||||
}
|
||||
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty);
|
||||
S.CurContext->addHiddenDecl(CED);
|
||||
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
|
||||
/*TypeMayContainAuto=*/true);
|
||||
if (WithInit)
|
||||
S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
|
||||
/*TypeMayContainAuto=*/true);
|
||||
else
|
||||
S.ActOnUninitializedDecl(CED, /*TypeMayContainAuto=*/true);
|
||||
return CED;
|
||||
}
|
||||
|
||||
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr) {
|
||||
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
|
||||
bool WithInit) {
|
||||
OMPCapturedExprDecl *CD;
|
||||
if (auto *VD = S.IsOpenMPCapturedDecl(D))
|
||||
CD = cast<OMPCapturedExprDecl>(VD);
|
||||
else
|
||||
CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr);
|
||||
CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit);
|
||||
return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
|
||||
SourceLocation());
|
||||
}
|
||||
|
||||
static DeclRefExpr *buildCapture(Sema &S, Expr *CaptureExpr) {
|
||||
auto *CD = buildCaptureDecl(
|
||||
S, &S.getASTContext().Idents.get(".capture_expr."), CaptureExpr);
|
||||
auto *CD =
|
||||
buildCaptureDecl(S, &S.getASTContext().Idents.get(".capture_expr."),
|
||||
CaptureExpr, /*WithInit=*/true);
|
||||
return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
|
||||
SourceLocation());
|
||||
}
|
||||
|
@ -7077,8 +7083,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
|||
}
|
||||
|
||||
ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
|
||||
ExprObjectKind OK) {
|
||||
SourceLocation Loc = Capture->getInit()->getExprLoc();
|
||||
ExprObjectKind OK, SourceLocation Loc) {
|
||||
ExprResult Res = BuildDeclRefExpr(
|
||||
Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
|
||||
if (!Res.isUsable())
|
||||
|
@ -7236,7 +7241,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
|
|||
|
||||
DeclRefExpr *Ref = nullptr;
|
||||
if (!VD)
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr);
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
|
||||
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
|
||||
Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
|
||||
PrivateCopies.push_back(VDPrivateRefExpr);
|
||||
|
@ -7520,7 +7525,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
|||
if (TopDVar.CKind == OMPC_lastprivate)
|
||||
Ref = TopDVar.PrivateCopy;
|
||||
else {
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr);
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
|
||||
if (!IsOpenMPCapturedDecl(D))
|
||||
ExprCaptures.push_back(Ref->getDecl());
|
||||
}
|
||||
|
@ -7665,13 +7670,13 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
|
|||
if (TopDVar.CKind == OMPC_firstprivate)
|
||||
Ref = TopDVar.PrivateCopy;
|
||||
else {
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr);
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
|
||||
if (!IsOpenMPCapturedDecl(D))
|
||||
ExprCaptures.push_back(Ref->getDecl());
|
||||
}
|
||||
if (TopDVar.CKind == OMPC_firstprivate ||
|
||||
(!IsOpenMPCapturedDecl(D) &&
|
||||
!Ref->getDecl()->getType()->isReferenceType())) {
|
||||
!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit())) {
|
||||
ExprResult RefRes = DefaultLvalueConversion(Ref);
|
||||
if (!RefRes.isUsable())
|
||||
continue;
|
||||
|
@ -7754,7 +7759,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
|
|||
|
||||
DeclRefExpr *Ref = nullptr;
|
||||
if (!VD)
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr);
|
||||
Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
|
||||
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
|
||||
Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
|
||||
}
|
||||
|
@ -7811,7 +7816,7 @@ public:
|
|||
ExprResult TransformMemberExpr(MemberExpr *E) {
|
||||
if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
|
||||
E->getMemberDecl() == Field) {
|
||||
CapturedExpr = buildCapture(SemaRef, Field, E);
|
||||
CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
|
||||
return CapturedExpr;
|
||||
}
|
||||
return BaseTransform::TransformMemberExpr(E);
|
||||
|
@ -7929,6 +7934,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
SmallVector<Expr *, 8> LHSs;
|
||||
SmallVector<Expr *, 8> RHSs;
|
||||
SmallVector<Expr *, 8> ReductionOps;
|
||||
SmallVector<Decl *, 4> ExprCaptures;
|
||||
SmallVector<Expr *, 4> ExprPostUpdates;
|
||||
for (auto RefExpr : VarList) {
|
||||
assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
|
||||
// OpenMP [2.1, C/C++]
|
||||
|
@ -8265,8 +8272,24 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
VarsExpr =
|
||||
RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
|
||||
Ref = RebuildToCapture.getCapturedExpr();
|
||||
} else
|
||||
VarsExpr = Ref = buildCapture(*this, D, SimpleRefExpr);
|
||||
} else {
|
||||
VarsExpr = Ref =
|
||||
buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
|
||||
if (!IsOpenMPCapturedDecl(D)) {
|
||||
ExprCaptures.push_back(Ref->getDecl());
|
||||
if (!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit()) {
|
||||
ExprResult RefRes = DefaultLvalueConversion(Ref);
|
||||
if (!RefRes.isUsable())
|
||||
continue;
|
||||
ExprResult PostUpdateRes =
|
||||
BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
|
||||
SimpleRefExpr, RefRes.get());
|
||||
if (!PostUpdateRes.isUsable())
|
||||
continue;
|
||||
ExprPostUpdates.push_back(PostUpdateRes.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
|
||||
Vars.push_back(VarsExpr);
|
||||
|
@ -8278,11 +8301,29 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
|
|||
|
||||
if (Vars.empty())
|
||||
return nullptr;
|
||||
Stmt *PreInit = nullptr;
|
||||
if (!ExprCaptures.empty()) {
|
||||
PreInit = new (Context)
|
||||
DeclStmt(DeclGroupRef::Create(Context, ExprCaptures.begin(),
|
||||
ExprCaptures.size()),
|
||||
SourceLocation(), SourceLocation());
|
||||
}
|
||||
Expr *PostUpdate = nullptr;
|
||||
if (!ExprPostUpdates.empty()) {
|
||||
for (auto *E : ExprPostUpdates) {
|
||||
ExprResult PostUpdateRes =
|
||||
PostUpdate
|
||||
? CreateBuiltinBinOp(SourceLocation(), BO_Comma, PostUpdate, E)
|
||||
: E;
|
||||
PostUpdate = PostUpdateRes.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return OMPReductionClause::Create(
|
||||
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, Vars,
|
||||
ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId, Privates,
|
||||
LHSs, RHSs, ReductionOps);
|
||||
LHSs, RHSs, ReductionOps, PreInit, PostUpdate);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPLinearClause(
|
||||
|
|
|
@ -2063,6 +2063,8 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
NestedNameSpecifierLoc NNSL =
|
||||
|
|
|
@ -1911,6 +1911,8 @@ void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
|
||||
void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
|
||||
Writer->Writer.AddNestedNameSpecifierLoc(C->getQualifierLoc(), Record);
|
||||
|
|
|
@ -148,7 +148,7 @@ int main() {
|
|||
|
||||
// LAMBDA: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
|
||||
// LAMBDA: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 0
|
||||
// LAMBDA: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// LAMBDA-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// LAMBDA: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 2
|
||||
// LAMBDA: call void @__kmpc_for_static_init_4(
|
||||
// LAMBDA-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]*
|
||||
|
@ -326,7 +326,7 @@ int main() {
|
|||
|
||||
// BLOCKS: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
|
||||
// BLOCKS: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 0
|
||||
// BLOCKS: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// BLOCKS-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// BLOCKS: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 2
|
||||
// BLOCKS: call void @__kmpc_for_static_init_4(
|
||||
// BLOCKS-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]*
|
||||
|
|
|
@ -20,6 +20,62 @@ struct S {
|
|||
~S() {}
|
||||
};
|
||||
|
||||
struct SS {
|
||||
int a;
|
||||
int b : 4;
|
||||
int &c;
|
||||
SS(int &d) : a(0), b(0), c(d) {
|
||||
#pragma omp parallel reduction(+: a, b, c)
|
||||
#ifdef LAMBDA
|
||||
[&]() {
|
||||
++this->a, --b, (this)->c /= 1;
|
||||
#pragma omp parallel reduction(&: a, b, c)
|
||||
++(this)->a, --b, this->c /= 1;
|
||||
}();
|
||||
#elif defined(BLOCKS)
|
||||
^{
|
||||
++a;
|
||||
--this->b;
|
||||
(this)->c /= 1;
|
||||
#pragma omp parallel reduction(-: a, b, c)
|
||||
++(this)->a, --b, this->c /= 1;
|
||||
}();
|
||||
#else
|
||||
++this->a, --b, c /= 1;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct SST {
|
||||
T a;
|
||||
SST() : a(T()) {
|
||||
#pragma omp parallel reduction(*: a)
|
||||
#ifdef LAMBDA
|
||||
[&]() {
|
||||
[&]() {
|
||||
++this->a;
|
||||
#pragma omp parallel reduction(&& :a)
|
||||
++(this)->a;
|
||||
}();
|
||||
}();
|
||||
#elif defined(BLOCKS)
|
||||
^{
|
||||
^{
|
||||
++a;
|
||||
#pragma omp parallel reduction(|: a)
|
||||
++(this)->a;
|
||||
}();
|
||||
}();
|
||||
#else
|
||||
++(this)->a;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// CHECK: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
|
||||
// LAMBDA: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
|
||||
// BLOCKS: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
|
||||
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
|
||||
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
|
||||
// CHECK-DAG: [[REDUCTION_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 18, i32 0, i32 0, i8*
|
||||
|
@ -29,6 +85,7 @@ template <typename T>
|
|||
T tmain() {
|
||||
T t;
|
||||
S<T> test;
|
||||
SST<T> sst;
|
||||
T t_var __attribute__((aligned(128))) = T(), t_var1 __attribute__((aligned(128)));
|
||||
T vec[] = {1, 2};
|
||||
S<T> s_arr[] = {1, 2};
|
||||
|
@ -41,16 +98,62 @@ T tmain() {
|
|||
return T();
|
||||
}
|
||||
|
||||
int sivar;
|
||||
int main() {
|
||||
SS ss(sivar);
|
||||
#ifdef LAMBDA
|
||||
// LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
|
||||
// LAMBDA-LABEL: @main
|
||||
// LAMBDA: call void [[OUTER_LAMBDA:@.+]](
|
||||
// LAMBDA: alloca [[SS_TY]],
|
||||
// LAMBDA: alloca [[CAP_TY:%.+]],
|
||||
// LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@[^(]+]]([[CAP_TY]]*
|
||||
[&]() {
|
||||
// LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
|
||||
// LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i32* [[G]])
|
||||
#pragma omp parallel reduction(+:g)
|
||||
{
|
||||
// LAMBDA: define {{.+}} @{{.+}}([[SS_TY]]*
|
||||
// LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// LAMBDA: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
|
||||
// LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// LAMBDA: store i8
|
||||
// LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// LAMBDA-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// LAMBDA: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// LAMBDA: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*, i32*, i32*, i32*)* [[SS_MICROTASK:@.+]] to void
|
||||
// LAMBDA: [[B_REF:%.+]] = getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// LAMBDA: store i8 %{{.+}}, i8* [[B_REF]],
|
||||
// LAMBDA: ret
|
||||
|
||||
// LAMBDA: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}}, i32* {{.+}}, i32* {{.+}}, i32* {{.+}})
|
||||
// LAMBDA-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %
|
||||
// LAMBDA: call{{.*}} void
|
||||
// LAMBDA: ret void
|
||||
|
||||
// LAMBDA: define internal void @{{.+}}(i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]*
|
||||
// LAMBDA: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// LAMBDA: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// LAMBDA: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// LAMBDA: store i{{[0-9]+}} -1, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// LAMBDA: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
|
||||
// LAMBDA: store i{{[0-9]+}} -1, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// LAMBDA: store i{{[0-9]+}} -1, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// LAMBDA: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
|
||||
// LAMBDA: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]],
|
||||
// LAMBDA-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// LAMBDA-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
|
||||
// LAMBDA-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
|
||||
// LAMBDA-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// LAMBDA-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
|
||||
// LAMBDA-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
|
||||
// LAMBDA-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFC]],
|
||||
// LAMBDA-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// LAMBDA-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
|
||||
// LAMBDA-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
|
||||
// LAMBDA: call i32 @__kmpc_reduce_nowait(
|
||||
// LAMBDA: ret void
|
||||
|
||||
// LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, i32* dereferenceable(4) %{{.+}})
|
||||
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
||||
|
||||
|
@ -100,6 +203,7 @@ int main() {
|
|||
#elif defined(BLOCKS)
|
||||
// BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
|
||||
// BLOCKS-LABEL: @main
|
||||
// BLOCKS: call
|
||||
// BLOCKS: call void {{%.+}}(i8
|
||||
^{
|
||||
// BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
|
||||
|
@ -152,6 +256,47 @@ int main() {
|
|||
}
|
||||
}();
|
||||
return 0;
|
||||
// BLOCKS: define {{.+}} @{{.+}}([[SS_TY]]*
|
||||
// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
|
||||
// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// BLOCKS: store i8
|
||||
// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// BLOCKS-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// BLOCKS: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// BLOCKS: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*, i32*, i32*, i32*)* [[SS_MICROTASK:@.+]] to void
|
||||
// BLOCKS: [[B_REF:%.+]] = getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// BLOCKS: store i8 %{{.+}}, i8* [[B_REF]],
|
||||
// BLOCKS: ret
|
||||
|
||||
// BLOCKS: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}}, i32* {{.+}}, i32* {{.+}}, i32* {{.+}})
|
||||
// BLOCKS-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %
|
||||
// BLOCKS: call{{.*}} void
|
||||
// BLOCKS: ret void
|
||||
|
||||
// BLOCKS: define internal void @{{.+}}(i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}}, i32* {{.+}}, i32* {{.+}}, i32* {{.+}})
|
||||
// BLOCKS: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// BLOCKS: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// BLOCKS: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// BLOCKS: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
|
||||
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// BLOCKS: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
|
||||
// BLOCKS: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]],
|
||||
// BLOCKS-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// BLOCKS-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
|
||||
// BLOCKS-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
|
||||
// BLOCKS-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// BLOCKS-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
|
||||
// BLOCKS-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
|
||||
// BLOCKS-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFC]],
|
||||
// BLOCKS-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// BLOCKS-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
|
||||
// BLOCKS-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
|
||||
// BLOCKS: call i32 @__kmpc_reduce_nowait(
|
||||
// BLOCKS: ret void
|
||||
#else
|
||||
S<float> test;
|
||||
float t_var = 0, t_var1;
|
||||
|
@ -472,6 +617,43 @@ int main() {
|
|||
// CHECK: call {{.*}} [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
|
||||
// CHECK: ret
|
||||
//
|
||||
// CHECK: define {{.+}} @{{.+}}([[SS_TY]]*
|
||||
// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
|
||||
// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// CHECK: store i8
|
||||
// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 0
|
||||
// CHECK-NOT: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 1
|
||||
// CHECK: getelementptr inbounds [[SS_TY]], [[SS_TY]]* %{{.+}}, i32 0, i32 2
|
||||
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[SS_TY]]*, i{{[0-9]+}}*, i{{[0-9]+}}*, i{{[0-9]+}}*)* [[SS_MICROTASK:@.+]] to void
|
||||
// CHECK: [[B_REF:%.+]] = getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %{{.*}}, i32 0, i32 1
|
||||
// CHECK: store i8 %{{.+}}, i8* [[B_REF]],
|
||||
// CHECK: ret
|
||||
|
||||
// CHECK: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]*
|
||||
// CHECK: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||
// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// CHECK: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
|
||||
// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// CHECK: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
|
||||
// CHECK: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]],
|
||||
// CHECK-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
|
||||
// CHECK-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
|
||||
// CHECK-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
|
||||
// CHECK-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[B_PRIV]],
|
||||
// CHECK-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
|
||||
// CHECK-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
|
||||
// CHECK-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFC]],
|
||||
// CHECK-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[C_PRIV]],
|
||||
// CHECK-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
|
||||
// CHECK-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
|
||||
// CHECK: call i32 @__kmpc_reduce_nowait(
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}},
|
||||
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}}, align 128
|
||||
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]], align 128
|
||||
|
|
|
@ -2178,6 +2178,8 @@ void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
|
|||
}
|
||||
void OMPClauseEnqueue::VisitOMPReductionClause(const OMPReductionClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue