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