It looks like this caused PR22071, reverting r224323 makes the crash go away.
On Mon, Dec 15, 2014 at 11:00 PM, Alexey Bataev <[email protected]> wrote: > Author: abataev > Date: Tue Dec 16 01:00:22 2014 > New Revision: 224323 > > URL: http://llvm.org/viewvc/llvm-project?rev=224323&view=rev > Log: > [OPENMP] Bugfix for processing of global variables in OpenMP regions. > Currently, if global variable is marked as a private OpenMP variable, the > compiler crashes in debug version or generates incorrect code in release > version. It happens because in the OpenMP region the original global > variable is used instead of the generated private copy. It happens because > currently globals variables are not captured in the OpenMP region. > This patch adds capturing of global variables iff private copy of the > global variable must be used in the OpenMP region. > Differential Revision: http://reviews.llvm.org/D6259 > > Modified: > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/CodeGen/CGExpr.cpp > cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp > cfe/trunk/lib/CodeGen/CodeGenFunction.h > cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp > cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/lib/Sema/SemaOpenMP.cpp > cfe/trunk/test/OpenMP/parallel_firstprivate_codegen.cpp > cfe/trunk/test/OpenMP/parallel_private_codegen.cpp > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Tue Dec 16 01:00:22 2014 > @@ -3448,6 +3448,9 @@ public: > TryCaptureKind Kind = TryCapture_Implicit, > SourceLocation EllipsisLoc = SourceLocation()); > > + /// \brief Checks if the variable must be captured. > + bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc); > + > /// \brief Given a variable, determine the type that a reference to that > /// variable will have in the given scope. > QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); > @@ -7482,6 +7485,10 @@ private: > void DestroyDataSharingAttributesStack(); > ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, > OpenMPClauseKind > CKind); > + /// \brief Checks if the specified variable is used in one of the > private > + /// clauses in OpenMP constructs. > + bool IsOpenMPCapturedVar(VarDecl *VD); > + > public: > ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, > Expr *Op); > > Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Dec 16 01:00:22 2014 > @@ -1906,6 +1906,21 @@ LValue CodeGenFunction::EmitDeclRefLValu > QualType T = E->getType(); > > if (const auto *VD = dyn_cast<VarDecl>(ND)) { > + // Check for captured variables. > + if (E->refersToEnclosingLocal()) { > + if (auto *FD = LambdaCaptureFields.lookup(VD)) > + return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); > + else if (CapturedStmtInfo) { > + if (auto *V = LocalDeclMap.lookup(VD)) > + return MakeAddrLValue(V, T, Alignment); > + else > + return EmitCapturedFieldLValue(*this, > CapturedStmtInfo->lookup(VD), > + > CapturedStmtInfo->getContextValue()); > + } else > + return MakeAddrLValue(GetAddrOfBlockDecl(VD, > VD->hasAttr<BlocksAttr>()), > + T, Alignment); > + } > + > // Global Named registers access via intrinsics only > if (VD->getStorageClass() == SC_Register && > VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl()) > @@ -1956,21 +1971,6 @@ LValue CodeGenFunction::EmitDeclRefLValu > *this, VD, T, V, getTypes().ConvertTypeForMem(VD->getType()), > Alignment, E->getExprLoc()); > > - // Use special handling for lambdas. > - if (!V) { > - if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) { > - return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue); > - } else if (CapturedStmtInfo) { > - if (const FieldDecl *FD = CapturedStmtInfo->lookup(VD)) > - return EmitCapturedFieldLValue(*this, FD, > - > CapturedStmtInfo->getContextValue()); > - } > - > - assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal()); > - return MakeAddrLValue(GetAddrOfBlockDecl(VD, isBlockVariable), > - T, Alignment); > - } > - > assert(V && "DeclRefExpr not entered in LocalDeclMap?"); > > if (isBlockVariable) > > Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Tue Dec 16 01:00:22 2014 > @@ -20,6 +20,35 @@ > using namespace clang; > using namespace CodeGen; > > +namespace { > +/// \brief RAII for emitting code of CapturedStmt without function > outlining. > +class InlinedOpenMPRegion { > + CodeGenFunction &CGF; > + CodeGenFunction::CGCapturedStmtInfo *PrevCapturedStmtInfo; > + const Decl *StoredCurCodeDecl; > + > + /// \brief A class to emit CapturedStmt construct as inlined statement > without > + /// generating a function for outlined code. > + class CGInlinedOpenMPRegionInfo : public > CodeGenFunction::CGCapturedStmtInfo { > + public: > + CGInlinedOpenMPRegionInfo() : CGCapturedStmtInfo() {} > + }; > + > +public: > + InlinedOpenMPRegion(CodeGenFunction &CGF, const Stmt *S) > + : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo), > + StoredCurCodeDecl(CGF.CurCodeDecl) { > + CGF.CurCodeDecl = cast<CapturedStmt>(S)->getCapturedDecl(); > + CGF.CapturedStmtInfo = new CGInlinedOpenMPRegionInfo(); > + } > + ~InlinedOpenMPRegion() { > + delete CGF.CapturedStmtInfo; > + CGF.CapturedStmtInfo = PrevCapturedStmtInfo; > + CGF.CurCodeDecl = StoredCurCodeDecl; > + } > +}; > +} // namespace > + > > > //===----------------------------------------------------------------------===// > // OpenMP Directive Emission > > > //===----------------------------------------------------------------------===// > @@ -417,6 +446,7 @@ void CodeGenFunction::EmitOMPSimdDirecti > } > } > > + InlinedOpenMPRegion Region(*this, S.getAssociatedStmt()); > RunCleanupsScope DirectiveScope(*this); > > CGDebugInfo *DI = getDebugInfo(); > @@ -561,6 +591,7 @@ void CodeGenFunction::EmitOMPWorksharing > } > > void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { > + InlinedOpenMPRegion Region(*this, S.getAssociatedStmt()); > RunCleanupsScope DirectiveScope(*this); > > CGDebugInfo *DI = getDebugInfo(); > @@ -593,8 +624,8 @@ void CodeGenFunction::EmitOMPSingleDirec > } > > void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) > { > - CGM.getOpenMPRuntime().EmitOMPMasterRegion( > - *this, [&]() -> void { > + CGM.getOpenMPRuntime().EmitOMPMasterRegion(*this, [&]() -> void { > + InlinedOpenMPRegion Region(*this, S.getAssociatedStmt()); > RunCleanupsScope Scope(*this); > > EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); > EnsureInsertPoint(); > @@ -604,8 +635,10 @@ void CodeGenFunction::EmitOMPMasterDirec > void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective > &S) { > CGM.getOpenMPRuntime().EmitOMPCriticalRegion( > *this, S.getDirectiveName().getAsString(), [&]() -> void { > + InlinedOpenMPRegion Region(*this, S.getAssociatedStmt()); > RunCleanupsScope Scope(*this); > - > EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); > + EmitStmt( > + cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); > EnsureInsertPoint(); > }, S.getLocStart()); > } > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Dec 16 01:00:22 2014 > @@ -182,6 +182,8 @@ public: > /// \brief API for captured statement code generation. > class CGCapturedStmtInfo { > public: > + explicit CGCapturedStmtInfo(CapturedRegionKind K = CR_Default) > + : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) {} > explicit CGCapturedStmtInfo(const CapturedStmt &S, > CapturedRegionKind K = CR_Default) > : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) { > @@ -614,7 +616,6 @@ public: > addPrivate(const VarDecl *LocalVD, > const std::function<llvm::Value *()> &PrivateGen) { > assert(PerformCleanup && "adding private to dead scope"); > - assert(LocalVD->isLocalVarDecl() && "privatizing non-local > variable"); > if (SavedLocals.count(LocalVD) > 0) return false; > SavedLocals[LocalVD] = CGF.LocalDeclMap.lookup(LocalVD); > CGF.LocalDeclMap.erase(LocalVD); > > Modified: cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp (original) > +++ cfe/trunk/lib/Frontend/Rewrite/RewriteModernObjC.cpp Tue Dec 16 > 01:00:22 2014 > @@ -4563,16 +4563,12 @@ void RewriteModernObjC::GetBlockDeclRefE > GetBlockDeclRefExprs(*CI); > } > // Handle specific things. > - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { > - if (DRE->refersToEnclosingLocal()) { > + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) > + if (DRE->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DRE->getDecl())) > // FIXME: Handle enums. > - if (!isa<FunctionDecl>(DRE->getDecl())) > - BlockDeclRefs.push_back(DRE); > - if (HasLocalVariableExternalStorage(DRE->getDecl())) > - BlockDeclRefs.push_back(DRE); > - } > - } > - > + BlockDeclRefs.push_back(DRE); > + > return; > } > > @@ -4595,11 +4591,11 @@ void RewriteModernObjC::GetInnerBlockDec > } > // Handle specific things. > if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { > - if (DRE->refersToEnclosingLocal()) { > - if (!isa<FunctionDecl>(DRE->getDecl()) && > - !InnerContexts.count(DRE->getDecl()->getDeclContext())) > + if (DRE->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DRE->getDecl())) { > + if (!InnerContexts.count(DRE->getDecl()->getDeclContext())) > InnerBlockDeclRefs.push_back(DRE); > - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) > + if (VarDecl *Var = cast<VarDecl>(DRE->getDecl())) > if (Var->isFunctionOrMethodVarDecl()) > ImportedLocalExternalDecls.insert(Var); > } > @@ -4776,7 +4772,8 @@ Stmt *RewriteModernObjC::RewriteBlockDec > // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR > // for each DeclRefExp where BYREFVAR is name of the variable. > ValueDecl *VD = DeclRefExp->getDecl(); > - bool isArrow = DeclRefExp->refersToEnclosingLocal(); > + bool isArrow = DeclRefExp->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DeclRefExp->getDecl()); > > FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), > SourceLocation(), > > Modified: cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp (original) > +++ cfe/trunk/lib/Frontend/Rewrite/RewriteObjC.cpp Tue Dec 16 01:00:22 2014 > @@ -3671,16 +3671,12 @@ void RewriteObjC::GetBlockDeclRefExprs(S > GetBlockDeclRefExprs(*CI); > } > // Handle specific things. > - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { > - if (DRE->refersToEnclosingLocal()) { > + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) > + if (DRE->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DRE->getDecl())) > // FIXME: Handle enums. > - if (!isa<FunctionDecl>(DRE->getDecl())) > - BlockDeclRefs.push_back(DRE); > - if (HasLocalVariableExternalStorage(DRE->getDecl())) > - BlockDeclRefs.push_back(DRE); > - } > - } > - > + BlockDeclRefs.push_back(DRE); > + > return; > } > > @@ -3703,11 +3699,11 @@ void RewriteObjC::GetInnerBlockDeclRefEx > } > // Handle specific things. > if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { > - if (DRE->refersToEnclosingLocal()) { > - if (!isa<FunctionDecl>(DRE->getDecl()) && > - !InnerContexts.count(DRE->getDecl()->getDeclContext())) > + if (DRE->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DRE->getDecl())) { > + if (!InnerContexts.count(DRE->getDecl()->getDeclContext())) > InnerBlockDeclRefs.push_back(DRE); > - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) > + if (VarDecl *Var = cast<VarDecl>(DRE->getDecl())) > if (Var->isFunctionOrMethodVarDecl()) > ImportedLocalExternalDecls.insert(Var); > } > @@ -3865,7 +3861,8 @@ Stmt *RewriteObjC::RewriteBlockDeclRefEx > // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR > // for each DeclRefExp where BYREFVAR is name of the variable. > ValueDecl *VD = DeclRefExp->getDecl(); > - bool isArrow = DeclRefExp->refersToEnclosingLocal(); > + bool isArrow = DeclRefExp->refersToEnclosingLocal() || > + HasLocalVariableExternalStorage(DeclRefExp->getDecl()); > > FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), > SourceLocation(), > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Dec 16 01:00:22 2014 > @@ -1602,10 +1602,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua > } > > bool refersToEnclosingScope = > - (CurContext != D->getDeclContext() && > - D->getDeclContext()->isFunctionOrMethod()) || > - (isa<VarDecl>(D) && > - cast<VarDecl>(D)->isInitCapture()); > + isa<VarDecl>(D) && > + NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc()); > > DeclRefExpr *E; > if (isa<VarTemplateSpecializationDecl>(D)) { > @@ -11799,7 +11797,7 @@ static DeclContext *getParentOfCapturing > const bool Diagnose, Sema &S) { > if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || > isLambdaCallOperator(DC)) > return getLambdaAwareParentOfDeclContext(DC); > - else { > + else if (Var->hasLocalStorage()) { > if (Diagnose) > diagnoseUncapturableValueReference(S, Loc, Var, DC); > } > @@ -12241,7 +12239,7 @@ bool Sema::tryCaptureVariable(VarDecl *V > QualType &CaptureType, > QualType &DeclRefType, > const > unsigned *const FunctionScopeIndexToStopAt) { > - bool Nested = false; > + bool Nested = Var->isInitCapture(); > > DeclContext *DC = CurContext; > const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt > @@ -12259,8 +12257,13 @@ bool Sema::tryCaptureVariable(VarDecl *V > > // If the variable is declared in the current context (and is not an > // init-capture), there is no need to capture it. > - if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true; > - if (!Var->hasLocalStorage()) return true; > + if (!Nested && Var->getDeclContext() == DC) return true; > + > + // Capture global variables if it is required to use private copy of > this > + // variable. > + bool IsGlobal = !Var->hasLocalStorage(); > + if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedVar(Var))) > + return true; > > // Walk up the stack to determine whether we can capture the variable, > // performing the "simple" checks that don't depend on type. We stop > when > @@ -12281,8 +12284,17 @@ bool Sema::tryCaptureVariable(VarDecl *V > ExprLoc, > > BuildAndDiagnose, > *this); > - if (!ParentDC) return true; > - > + // We need to check for the parent *first* because, if we *have* > + // private-captured a global variable, we need to recursively capture > it in > + // intermediate blocks, lambdas, etc. > + if (!ParentDC) { > + if (IsGlobal) { > + FunctionScopesIndex = MaxFunctionScopesIndex - 1; > + break; > + } > + return true; > + } > + > FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex]; > CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI); > > @@ -12508,6 +12520,14 @@ bool Sema::tryCaptureVariable(VarDecl *V > DeclRefType, nullptr); > } > > +bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) { > + QualType CaptureType; > + QualType DeclRefType; > + return !tryCaptureVariable(Var, Loc, TryCapture_Implicit, > SourceLocation(), > + /*BuildAndDiagnose=*/false, CaptureType, > + DeclRefType, nullptr); > +} > + > QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { > QualType CaptureType; > QualType DeclRefType; > > Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Dec 16 01:00:22 2014 > @@ -551,6 +551,19 @@ void Sema::InitDataSharingAttributesStac > > #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) > > +bool Sema::IsOpenMPCapturedVar(VarDecl *VD) { > + assert(LangOpts.OpenMP && "OpenMP is not allowed"); > + if (DSAStack->getCurrentDirective() != OMPD_unknown) { > + auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false); > + if (DVarPrivate.CKind != OMPC_unknown && > isOpenMPPrivate(DVarPrivate.CKind)) > + return true; > + DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), > + /*FromParent=*/false); > + return DVarPrivate.CKind != OMPC_unknown; > + } > + return false; > +} > + > void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } > > void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, > @@ -4378,7 +4391,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivate > VDInitRefExpr = DeclRefExpr::Create( > Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), > /*TemplateKWLoc*/ SourceLocation(), VDInit, > - /*isEnclosingLocal*/ false, ELoc, Type, > + /*isEnclosingLocal*/ true, ELoc, Type, > /*VK*/ VK_LValue); > VDInit->setIsUsed(); > auto Init = DefaultLvalueConversion(VDInitRefExpr).get(); > @@ -4392,8 +4405,14 @@ OMPClause *Sema::ActOnOpenMPFirstprivate > else > VDPrivate->setInit(Result.getAs<Expr>()); > } else { > - AddInitializerToDecl(VDPrivate, DefaultLvalueConversion(DE).get(), > - /*DirectInit*/ false, /*TypeMayContainAuto*/ > false); > + AddInitializerToDecl( > + VDPrivate, DefaultLvalueConversion( > + DeclRefExpr::Create(Context, > NestedNameSpecifierLoc(), > + SourceLocation(), > DE->getDecl(), > + /*isEnclosingLocal=*/true, > + DE->getExprLoc(), > DE->getType(), > + /*VK=*/VK_LValue)).get(), > + /*DirectInit=*/false, /*TypeMayContainAuto=*/false); > } > if (VDPrivate->isInvalidDecl()) { > if (IsImplicitClause) { > > Modified: cfe/trunk/test/OpenMP/parallel_firstprivate_codegen.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_firstprivate_codegen.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/test/OpenMP/parallel_firstprivate_codegen.cpp (original) > +++ cfe/trunk/test/OpenMP/parallel_firstprivate_codegen.cpp Tue Dec 16 > 01:00:22 2014 > @@ -1,6 +1,8 @@ > // RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -triple > %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s > // RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple > %itanium_abi_triple -emit-pch -o %t %s > // RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple %itanium_abi_triple > -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s > +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DLAMBDA > -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck > -check-prefix=LAMBDA %s > +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS > -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck > -check-prefix=BLOCKS %s > // expected-no-diagnostics > #ifndef HEADER > #define HEADER > @@ -12,7 +14,7 @@ struct St { > ~St() {} > }; > > -volatile int g; > +volatile int g = 1212; > > template <class T> > struct S { > @@ -47,6 +49,83 @@ T tmain() { > } > > int main() { > +#ifdef LAMBDA > + // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212, > + // LAMBDA-LABEL: @main > + // LAMBDA: call void [[OUTER_LAMBDA:@.+]]( > + [&]() { > + // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]]( > + // LAMBDA: [[G_LOCAL_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[AGG_CAPTURED:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: store i{{[0-9]+}}* [[G]], i{{[0-9]+}}** [[G_LOCAL_REF]] > + // LAMBDA: [[ARG:%.+]] = bitcast %{{.+}}* [[AGG_CAPTURED]] to i8* > + // LAMBDA: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* > [[OMP_REGION:@.+]] to {{.+}}, i8* [[ARG]]) > +#pragma omp parallel firstprivate(g) > + { > + // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* > %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) > + // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, > + // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], > + // LAMBDA: [[ARG:%.+]] = load %{{.+}}** [[ARG_REF]] > + // LAMBDA: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}* > [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}** [[G_REF_ADDR]] > + // LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}* [[G_REF]] > + // LAMBDA: store volatile i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* > [[G_PRIVATE_ADDR]] > + // LAMBDA: call i32 @__kmpc_cancel_barrier( > + g = 1; > + // LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* > [[G_PRIVATE_ADDR]], > + // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds > %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** > [[G_PRIVATE_ADDR_REF]] > + // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]]) > + [&]() { > + // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* > [[ARG_PTR:%.+]]) > + // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** > [[ARG_PTR_REF:%.+]], > + g = 2; > + // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}** [[ARG_PTR_REF]] > + // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}** [[G_PTR_REF]] > + // LAMBDA: store volatile i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]] > + }(); > + } > + }(); > + return 0; > +#elif defined(BLOCKS) > + // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212, > + // BLOCKS-LABEL: @main > + // BLOCKS: call void {{%.+}}(i8* > + ^{ > + // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8* > + // BLOCKS: [[G_LOCAL_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[AGG_CAPTURED:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // BLOCKS: store i{{[0-9]+}}* [[G]], i{{[0-9]+}}** [[G_LOCAL_REF]] > + // BLOCKS: [[ARG:%.+]] = bitcast %{{.+}}* [[AGG_CAPTURED]] to i8* > + // BLOCKS: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* > [[OMP_REGION:@.+]] to {{.+}}, i8* [[ARG]]) > +#pragma omp parallel firstprivate(g) > + { > + // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* > %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) > + // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, > + // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], > + // BLOCKS: [[ARG:%.+]] = load %{{.+}}** [[ARG_REF]] > + // BLOCKS: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}* > [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}** [[G_REF_ADDR]] > + // BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}* [[G_REF]] > + // BLOCKS: store volatile i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* > [[G_PRIVATE_ADDR]] > + // BLOCKS: call i32 @__kmpc_cancel_barrier( > + g = 1; > + // BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* > [[G_PRIVATE_ADDR]], > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]] > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: call void {{%.+}}(i8* > + ^{ > + // BLOCKS: define {{.+}} void {{@.+}}(i8* > + g = 2; > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: store volatile i{{[0-9]+}} 2, i{{[0-9]+}}* > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: ret > + }(); > + } > + }(); > + return 0; > +#else > S<float> test; > int t_var = 0; > int vec[] = {1, 2}; > @@ -58,6 +137,7 @@ int main() { > s_arr[0] = var; > } > return tmain<int>(); > +#endif > } > > // CHECK: define {{.*}}i{{[0-9]+}} @main() > > Modified: cfe/trunk/test/OpenMP/parallel_private_codegen.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_private_codegen.cpp?rev=224323&r1=224322&r2=224323&view=diff > > ============================================================================== > --- cfe/trunk/test/OpenMP/parallel_private_codegen.cpp (original) > +++ cfe/trunk/test/OpenMP/parallel_private_codegen.cpp Tue Dec 16 01:00:22 > 2014 > @@ -1,6 +1,8 @@ > // RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -triple > x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s > // RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple > x86_64-unknown-unknown -emit-pch -o %t %s > // RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple > x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o > - | FileCheck %s > +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DLAMBDA > -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck > -check-prefix=LAMBDA %s > +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS > -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck > -check-prefix=BLOCKS %s > // expected-no-diagnostics > #ifndef HEADER > #define HEADER > @@ -14,6 +16,8 @@ struct S { > ~S() {} > }; > > +volatile int g = 1212; > + > // CHECK: [[S_FLOAT_TY:%.+]] = type { float } > // CHECK: [[CAP_MAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, > [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]* } > // CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} } > @@ -22,7 +26,7 @@ struct S { > template <typename T> > T tmain() { > S<T> test; > - T t_var; > + T t_var = T(); > T vec[] = {1, 2}; > S<T> s_arr[] = {1, 2}; > S<T> var(3); > @@ -35,8 +39,75 @@ T tmain() { > } > > int main() { > +#ifdef LAMBDA > + // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212, > + // LAMBDA-LABEL: @main > + // LAMBDA: call void [[OUTER_LAMBDA:@.+]]( > + [&]() { > + // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]]( > + // LAMBDA: [[G_LOCAL_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[AGG_CAPTURED:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: store i{{[0-9]+}}* [[G]], i{{[0-9]+}}** [[G_LOCAL_REF]] > + // LAMBDA: [[ARG:%.+]] = bitcast %{{.+}}* [[AGG_CAPTURED]] to i8* > + // LAMBDA: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* > [[OMP_REGION:@.+]] to {{.+}}, i8* [[ARG]]) > +#pragma omp parallel private(g) > + { > + // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* > %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) > + // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, > + // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], > + // LAMBDA: call i32 @__kmpc_cancel_barrier( > + g = 1; > + // LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* > [[G_PRIVATE_ADDR]], > + // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds > %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** > [[G_PRIVATE_ADDR_REF]] > + // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]]) > + [&]() { > + // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* > [[ARG_PTR:%.+]]) > + // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** > [[ARG_PTR_REF:%.+]], > + g = 2; > + // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}** [[ARG_PTR_REF]] > + // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}** [[G_PTR_REF]] > + // LAMBDA: store volatile i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]] > + }(); > + } > + }(); > + return 0; > +#elif defined(BLOCKS) > + // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212, > + // BLOCKS-LABEL: @main > + // BLOCKS: call void {{%.+}}(i8* > + ^{ > + // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8* > + // BLOCKS: [[G_LOCAL_REF:%.+]] = getelementptr inbounds %{{.+}}* > [[AGG_CAPTURED:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 > + // BLOCKS: store i{{[0-9]+}}* [[G]], i{{[0-9]+}}** [[G_LOCAL_REF]] > + // BLOCKS: [[ARG:%.+]] = bitcast %{{.+}}* [[AGG_CAPTURED]] to i8* > + // BLOCKS: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* > [[OMP_REGION:@.+]] to {{.+}}, i8* [[ARG]]) > +#pragma omp parallel private(g) > + { > + // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* > %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]]) > + // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}, > + // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]], > + // BLOCKS: call i32 @__kmpc_cancel_barrier( > + g = 1; > + // BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* > [[G_PRIVATE_ADDR]], > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]] > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: call void {{%.+}}(i8* > + ^{ > + // BLOCKS: define {{.+}} void {{@.+}}(i8* > + g = 2; > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: store volatile i{{[0-9]+}} 2, i{{[0-9]+}}* > + // BLOCKS-NOT: [[G]]{{[[^:word:]]}} > + // BLOCKS: ret > + }(); > + } > + }(); > + return 0; > +#else > S<float> test; > - int t_var; > + int t_var = 0; > int vec[] = {1, 2}; > S<float> s_arr[] = {1, 2}; > S<float> var(3); > @@ -46,6 +117,7 @@ int main() { > s_arr[0] = var; > } > return tmain<int>(); > +#endif > } > > // CHECK: define i{{[0-9]+}} @main() > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
