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