Should be fixed with r225060. On Wed, Dec 31, 2014 at 6:11 PM, David Majnemer <[email protected]> wrote:
> 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
