r224323 - [OPENMP] Bugfix for processing of global variables in OpenMP regions.
David Majnemer
david.majnemer at gmail.com
Wed Dec 31 18:11:29 PST 2014
It looks like this caused PR22071, reverting r224323 makes the crash go
away.
On Mon, Dec 15, 2014 at 11:00 PM, Alexey Bataev <a.bataev at hotmail.com>
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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141231/fb0cc906/attachment.html>
More information about the cfe-commits
mailing list