r224323 - [OPENMP] Bugfix for processing of global variables in OpenMP regions.
David Majnemer
david.majnemer at gmail.com
Thu Jan 1 01:51:57 PST 2015
Should be fixed with r225060.
On Wed, Dec 31, 2014 at 6:11 PM, David Majnemer <david.majnemer at gmail.com>
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 <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/20150101/95703aad/attachment.html>
More information about the cfe-commits
mailing list