forked from OSchip/llvm-project
[OPENMP] Codegen for 'firstprivate' clause in 'for' directive.
Adds proper codegen for 'firstprivate' clause in for directive. Initially codegen for 'firstprivate' clause was implemented for 'parallel' directive only. Also this patch emits sync point only after initialization of firstprivate variables, not all private variables. This sync point is not required for privates, lastprivates etc., only for initialization of firstprivate variables. Differential Revision: http://reviews.llvm.org/D8660 llvm-svn: 234978
This commit is contained in:
parent
042e35cab9
commit
69c62a9bdb
|
@ -161,8 +161,9 @@ public:
|
||||||
const FieldDecl *lookup(const VarDecl *VD) const override {
|
const FieldDecl *lookup(const VarDecl *VD) const override {
|
||||||
if (OuterRegionInfo)
|
if (OuterRegionInfo)
|
||||||
return OuterRegionInfo->lookup(VD);
|
return OuterRegionInfo->lookup(VD);
|
||||||
llvm_unreachable("Trying to reference VarDecl that is neither local nor "
|
// If there is no outer outlined region,no need to lookup in a list of
|
||||||
"captured in outer OpenMP region");
|
// captured variables, we can use the original one.
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
FieldDecl *getThisFieldDecl() const override {
|
FieldDecl *getThisFieldDecl() const override {
|
||||||
if (OuterRegionInfo)
|
if (OuterRegionInfo)
|
||||||
|
|
|
@ -158,68 +158,82 @@ void CodeGenFunction::EmitOMPCopy(CodeGenFunction &CGF,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitOMPFirstprivateClause(
|
bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
||||||
const OMPExecutableDirective &D,
|
OMPPrivateScope &PrivateScope) {
|
||||||
CodeGenFunction::OMPPrivateScope &PrivateScope) {
|
auto FirstprivateFilter = [](const OMPClause *C) -> bool {
|
||||||
auto PrivateFilter = [](const OMPClause *C) -> bool {
|
|
||||||
return C->getClauseKind() == OMPC_firstprivate;
|
return C->getClauseKind() == OMPC_firstprivate;
|
||||||
};
|
};
|
||||||
for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
|
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
|
||||||
I(D.clauses(), PrivateFilter); I; ++I) {
|
for (OMPExecutableDirective::filtered_clause_iterator<decltype(
|
||||||
|
FirstprivateFilter)> I(D.clauses(), FirstprivateFilter);
|
||||||
|
I; ++I) {
|
||||||
auto *C = cast<OMPFirstprivateClause>(*I);
|
auto *C = cast<OMPFirstprivateClause>(*I);
|
||||||
auto IRef = C->varlist_begin();
|
auto IRef = C->varlist_begin();
|
||||||
auto InitsRef = C->inits().begin();
|
auto InitsRef = C->inits().begin();
|
||||||
for (auto IInit : C->private_copies()) {
|
for (auto IInit : C->private_copies()) {
|
||||||
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
||||||
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
|
if (EmittedAsFirstprivate.count(OrigVD) == 0) {
|
||||||
bool IsRegistered;
|
EmittedAsFirstprivate.insert(OrigVD);
|
||||||
if (*InitsRef != nullptr) {
|
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
|
||||||
// Emit VarDecl with copy init for arrays.
|
auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
|
||||||
auto *FD = CapturedStmtInfo->lookup(OrigVD);
|
bool IsRegistered;
|
||||||
LValue Base = MakeNaturalAlignAddrLValue(
|
DeclRefExpr DRE(
|
||||||
CapturedStmtInfo->getContextValue(),
|
const_cast<VarDecl *>(OrigVD),
|
||||||
getContext().getTagDeclType(FD->getParent()));
|
/*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup(
|
||||||
auto *OriginalAddr = EmitLValueForField(Base, FD).getAddress();
|
OrigVD) != nullptr,
|
||||||
auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
|
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
|
||||||
IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
|
auto *OriginalAddr = EmitLValue(&DRE).getAddress();
|
||||||
auto Emission = EmitAutoVarAlloca(*VD);
|
if (OrigVD->getType()->isArrayType()) {
|
||||||
// Emit initialization of aggregate firstprivate vars.
|
// Emit VarDecl with copy init for arrays.
|
||||||
auto *Init = VD->getInit();
|
// Get the address of the original variable captured in current
|
||||||
if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
|
// captured region.
|
||||||
// Perform simple memcpy.
|
IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
|
||||||
EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
|
auto Emission = EmitAutoVarAlloca(*VD);
|
||||||
(*IRef)->getType());
|
auto *Init = VD->getInit();
|
||||||
} else {
|
if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
|
||||||
EmitOMPAggregateAssign(
|
// Perform simple memcpy.
|
||||||
Emission.getAllocatedAddress(), OriginalAddr,
|
EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
|
||||||
(*IRef)->getType(),
|
(*IRef)->getType());
|
||||||
[this, VDInit, Init](llvm::Value *DestElement,
|
} else {
|
||||||
llvm::Value *SrcElement) {
|
EmitOMPAggregateAssign(
|
||||||
// Clean up any temporaries needed by the initialization.
|
Emission.getAllocatedAddress(), OriginalAddr,
|
||||||
RunCleanupsScope InitScope(*this);
|
(*IRef)->getType(),
|
||||||
// Emit initialization for single element.
|
[this, VDInit, Init](llvm::Value *DestElement,
|
||||||
LocalDeclMap[VDInit] = SrcElement;
|
llvm::Value *SrcElement) {
|
||||||
EmitAnyExprToMem(Init, DestElement,
|
// Clean up any temporaries needed by the initialization.
|
||||||
Init->getType().getQualifiers(),
|
RunCleanupsScope InitScope(*this);
|
||||||
/*IsInitializer*/ false);
|
// Emit initialization for single element.
|
||||||
LocalDeclMap.erase(VDInit);
|
LocalDeclMap[VDInit] = SrcElement;
|
||||||
});
|
EmitAnyExprToMem(Init, DestElement,
|
||||||
}
|
Init->getType().getQualifiers(),
|
||||||
EmitAutoVarCleanups(Emission);
|
/*IsInitializer*/ false);
|
||||||
return Emission.getAllocatedAddress();
|
LocalDeclMap.erase(VDInit);
|
||||||
});
|
});
|
||||||
} else
|
}
|
||||||
IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
|
EmitAutoVarCleanups(Emission);
|
||||||
// Emit private VarDecl with copy init.
|
return Emission.getAllocatedAddress();
|
||||||
EmitDecl(*VD);
|
});
|
||||||
return GetAddrOfLocalVar(VD);
|
} else {
|
||||||
});
|
IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value *{
|
||||||
assert(IsRegistered && "firstprivate var already registered as private");
|
// Emit private VarDecl with copy init.
|
||||||
// Silence the warning about unused variable.
|
// Remap temp VDInit variable to the address of the original
|
||||||
(void)IsRegistered;
|
// variable
|
||||||
|
// (for proper handling of captured global variables).
|
||||||
|
LocalDeclMap[VDInit] = OriginalAddr;
|
||||||
|
EmitDecl(*VD);
|
||||||
|
LocalDeclMap.erase(VDInit);
|
||||||
|
return GetAddrOfLocalVar(VD);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
assert(IsRegistered &&
|
||||||
|
"firstprivate var already registered as private");
|
||||||
|
// Silence the warning about unused variable.
|
||||||
|
(void)IsRegistered;
|
||||||
|
}
|
||||||
++IRef, ++InitsRef;
|
++IRef, ++InitsRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return !EmittedAsFirstprivate.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitOMPPrivateClause(
|
void CodeGenFunction::EmitOMPPrivateClause(
|
||||||
|
@ -358,13 +372,15 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
|
||||||
// Emit parallel region as a standalone region.
|
// Emit parallel region as a standalone region.
|
||||||
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
|
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
|
||||||
OMPPrivateScope PrivateScope(CGF);
|
OMPPrivateScope PrivateScope(CGF);
|
||||||
CGF.EmitOMPPrivateClause(S, PrivateScope);
|
if (CGF.EmitOMPFirstprivateClause(S, PrivateScope)) {
|
||||||
CGF.EmitOMPFirstprivateClause(S, PrivateScope);
|
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||||
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
|
// initialization of firstprivate variables.
|
||||||
if (PrivateScope.Privatize())
|
|
||||||
// Emit implicit barrier to synchronize threads and avoid data races.
|
|
||||||
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
|
CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getLocStart(),
|
||||||
OMPD_unknown);
|
OMPD_unknown);
|
||||||
|
}
|
||||||
|
CGF.EmitOMPPrivateClause(S, PrivateScope);
|
||||||
|
CGF.EmitOMPReductionClauseInit(S, PrivateScope);
|
||||||
|
(void)PrivateScope.Privatize();
|
||||||
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
|
||||||
CGF.EmitOMPReductionClauseFinal(S);
|
CGF.EmitOMPReductionClauseFinal(S);
|
||||||
// Emit implicit barrier at the end of the 'parallel' directive.
|
// Emit implicit barrier at the end of the 'parallel' directive.
|
||||||
|
@ -844,6 +860,12 @@ void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
|
||||||
EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
|
EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
|
||||||
|
|
||||||
OMPPrivateScope LoopScope(*this);
|
OMPPrivateScope LoopScope(*this);
|
||||||
|
if (EmitOMPFirstprivateClause(S, LoopScope)) {
|
||||||
|
// Emit implicit barrier to synchronize threads and avoid data races on
|
||||||
|
// initialization of firstprivate variables.
|
||||||
|
CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(),
|
||||||
|
OMPD_unknown);
|
||||||
|
}
|
||||||
EmitPrivateLoopCounters(*this, LoopScope, S.counters());
|
EmitPrivateLoopCounters(*this, LoopScope, S.counters());
|
||||||
(void)LoopScope.Privatize();
|
(void)LoopScope.Privatize();
|
||||||
|
|
||||||
|
|
|
@ -2064,7 +2064,7 @@ public:
|
||||||
LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
|
LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
|
||||||
llvm::AtomicOrdering AO, SourceLocation Loc,
|
llvm::AtomicOrdering AO, SourceLocation Loc,
|
||||||
const llvm::function_ref<RValue(RValue)> &CommonGen);
|
const llvm::function_ref<RValue(RValue)> &CommonGen);
|
||||||
void EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
||||||
OMPPrivateScope &PrivateScope);
|
OMPPrivateScope &PrivateScope);
|
||||||
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
|
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
|
||||||
OMPPrivateScope &PrivateScope);
|
OMPPrivateScope &PrivateScope);
|
||||||
|
|
|
@ -4805,7 +4805,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
||||||
// A variable of class type (or array thereof) that appears in a private
|
// A variable of class type (or array thereof) that appears in a private
|
||||||
// clause requires an accessible, unambiguous copy constructor for the
|
// clause requires an accessible, unambiguous copy constructor for the
|
||||||
// class type.
|
// class type.
|
||||||
Type = Context.getBaseElementType(Type);
|
Type = Context.getBaseElementType(Type).getNonReferenceType();
|
||||||
|
|
||||||
// If an implicit firstprivate variable found it was checked already.
|
// If an implicit firstprivate variable found it was checked already.
|
||||||
if (!IsImplicitClause) {
|
if (!IsImplicitClause) {
|
||||||
|
@ -4895,10 +4895,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type = Type.getUnqualifiedType();
|
auto VDPrivate =
|
||||||
auto VDPrivate = VarDecl::Create(Context, CurContext, DE->getLocStart(),
|
VarDecl::Create(Context, CurContext, DE->getLocStart(), ELoc,
|
||||||
ELoc, VD->getIdentifier(), VD->getType(),
|
VD->getIdentifier(), VD->getType().getUnqualifiedType(),
|
||||||
VD->getTypeSourceInfo(), /*S*/ SC_Auto);
|
VD->getTypeSourceInfo(), /*S*/ SC_Auto);
|
||||||
// Generate helper private variable and initialize it with the value of the
|
// Generate helper private variable and initialize it with the value of the
|
||||||
// original variable. The address of the original variable is replaced by
|
// original variable. The address of the original variable is replaced by
|
||||||
// the address of the new private variable in the CodeGen. This new variable
|
// the address of the new private variable in the CodeGen. This new variable
|
||||||
|
@ -4917,9 +4917,12 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
||||||
/*TemplateKWLoc*/ SourceLocation(), VDInit,
|
/*TemplateKWLoc*/ SourceLocation(), VDInit,
|
||||||
/*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type,
|
/*RefersToEnclosingVariableOrCapture*/ true, ELoc, Type,
|
||||||
/*VK*/ VK_LValue);
|
/*VK*/ VK_LValue);
|
||||||
VDInit->setIsUsed();
|
|
||||||
auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
|
auto Init = DefaultLvalueConversion(VDInitRefExpr).get();
|
||||||
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDInit);
|
auto *VDInitTemp =
|
||||||
|
BuildVarDecl(*this, DE->getLocStart(), Type.getUnqualifiedType(),
|
||||||
|
".firstprivate.temp");
|
||||||
|
InitializedEntity Entity =
|
||||||
|
InitializedEntity::InitializeVariable(VDInitTemp);
|
||||||
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
|
InitializationKind Kind = InitializationKind::CreateCopy(ELoc, ELoc);
|
||||||
|
|
||||||
InitializationSequence InitSeq(*this, Entity, Kind, Init);
|
InitializationSequence InitSeq(*this, Entity, Kind, Init);
|
||||||
|
@ -4929,15 +4932,13 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
||||||
else
|
else
|
||||||
VDPrivate->setInit(Result.getAs<Expr>());
|
VDPrivate->setInit(Result.getAs<Expr>());
|
||||||
} else {
|
} else {
|
||||||
AddInitializerToDecl(
|
auto *VDInit =
|
||||||
VDPrivate,
|
BuildVarDecl(*this, DE->getLocStart(), Type, ".firstprivate.temp");
|
||||||
DefaultLvalueConversion(
|
VDInitRefExpr =
|
||||||
DeclRefExpr::Create(Context, NestedNameSpecifierLoc(),
|
BuildDeclRefExpr(VDInit, Type, VK_LValue, DE->getExprLoc()).get();
|
||||||
SourceLocation(), DE->getDecl(),
|
AddInitializerToDecl(VDPrivate,
|
||||||
/*RefersToEnclosingVariableOrCapture=*/true,
|
DefaultLvalueConversion(VDInitRefExpr).get(),
|
||||||
DE->getExprLoc(), DE->getType(),
|
/*DirectInit=*/false, /*TypeMayContainAuto=*/false);
|
||||||
/*VK=*/VK_LValue)).get(),
|
|
||||||
/*DirectInit=*/false, /*TypeMayContainAuto=*/false);
|
|
||||||
}
|
}
|
||||||
if (VDPrivate->isInvalidDecl()) {
|
if (VDPrivate->isInvalidDecl()) {
|
||||||
if (IsImplicitClause) {
|
if (IsImplicitClause) {
|
||||||
|
@ -4947,12 +4948,11 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CurContext->addDecl(VDPrivate);
|
CurContext->addDecl(VDPrivate);
|
||||||
auto VDPrivateRefExpr =
|
auto VDPrivateRefExpr = DeclRefExpr::Create(
|
||||||
DeclRefExpr::Create(Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
|
Context, /*QualifierLoc*/ NestedNameSpecifierLoc(),
|
||||||
/*TemplateKWLoc*/ SourceLocation(), VDPrivate,
|
/*TemplateKWLoc*/ SourceLocation(), VDPrivate,
|
||||||
/*RefersToEnclosingVariableOrCapture*/ false,
|
/*RefersToEnclosingVariableOrCapture*/ false, DE->getLocStart(),
|
||||||
DE->getLocStart(), DE->getType(),
|
DE->getType().getUnqualifiedType(), /*VK*/ VK_LValue);
|
||||||
/*VK*/ VK_LValue);
|
|
||||||
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
|
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
|
||||||
Vars.push_back(DE);
|
Vars.push_back(DE);
|
||||||
PrivateCopies.push_back(VDPrivateRefExpr);
|
PrivateCopies.push_back(VDPrivateRefExpr);
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St(const St &st) : a(st.a + st.b), b(0) {}
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile int g = 1212;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct S {
|
||||||
|
T f;
|
||||||
|
S(T a) : f(a + g) {}
|
||||||
|
S() : f(g) {}
|
||||||
|
S(const S &s, St t = St()) : f(s.f + t.a) {}
|
||||||
|
operator T() { return T(); }
|
||||||
|
~S() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
|
||||||
|
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
|
||||||
|
// CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
|
||||||
|
// CHECK-DAG: [[CAP_TMAIN_TY:%.+]] = type { i{{[0-9]+}}*, [2 x i{{[0-9]+}}]*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T tmain() {
|
||||||
|
S<T> test;
|
||||||
|
T t_var = T();
|
||||||
|
T vec[] = {1, 2};
|
||||||
|
S<T> s_arr[] = {1, 2};
|
||||||
|
S<T> var(3);
|
||||||
|
#pragma omp parallel
|
||||||
|
#pragma omp for firstprivate(t_var, vec, s_arr, var)
|
||||||
|
for (int i = 0; i < 0; ++i) {
|
||||||
|
vec[i] = t_var;
|
||||||
|
s_arr[i] = var;
|
||||||
|
}
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: [[TEST:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
|
||||||
|
S<float> test;
|
||||||
|
// CHECK-DAG: [[T_VAR:@.+]] = global i{{[0-9]+}} 333,
|
||||||
|
int t_var = 333;
|
||||||
|
// CHECK-DAG: [[VEC:@.+]] = global [2 x i{{[0-9]+}}] [i{{[0-9]+}} 1, i{{[0-9]+}} 2],
|
||||||
|
int vec[] = {1, 2};
|
||||||
|
// CHECK-DAG: [[S_ARR:@.+]] = global [2 x [[S_FLOAT_TY]]] zeroinitializer,
|
||||||
|
S<float> s_arr[] = {1, 2};
|
||||||
|
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
|
||||||
|
S<float> var(3);
|
||||||
|
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
||||||
|
|
||||||
|
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
|
||||||
|
// CHECK: ([[S_FLOAT_TY]]*)* [[S_FLOAT_TY_DESTR:@[^ ]+]] {{[^,]+}}, {{.+}}([[S_FLOAT_TY]]* [[TEST]]
|
||||||
|
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: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
|
||||||
|
#pragma omp parallel
|
||||||
|
#pragma omp for firstprivate(g)
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
// LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
||||||
|
// Skip temp vars for loop
|
||||||
|
// LAMBDA: alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
||||||
|
// LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
|
||||||
|
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
|
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
||||||
|
g = 1;
|
||||||
|
// LAMBDA: call void @__kmpc_for_static_init_4(
|
||||||
|
// 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: call void @__kmpc_for_static_fini(
|
||||||
|
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
||||||
|
[&]() {
|
||||||
|
// 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]+}}*, 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: call void {{.+}}* @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
|
||||||
|
#pragma omp parallel
|
||||||
|
#pragma omp for firstprivate(g)
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
// BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
||||||
|
// Skip temp vars for loop
|
||||||
|
// BLOCKS: alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
||||||
|
// BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G]]
|
||||||
|
// BLOCKS: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
|
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
||||||
|
g = 1;
|
||||||
|
// BLOCKS: call void @__kmpc_for_static_init_4(
|
||||||
|
// 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: call void @__kmpc_for_static_fini(
|
||||||
|
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
||||||
|
^{
|
||||||
|
// 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
|
||||||
|
#pragma omp for firstprivate(t_var, vec, s_arr, var)
|
||||||
|
for (int i = 0; i < 0; ++i) {
|
||||||
|
vec[i] = t_var;
|
||||||
|
s_arr[i] = var;
|
||||||
|
}
|
||||||
|
return tmain<int>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: define {{.*}}i{{[0-9]+}} @main()
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// Skip temp vars for loop
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||||
|
// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
|
||||||
|
// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]],
|
||||||
|
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]],
|
||||||
|
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
|
||||||
|
|
||||||
|
// firstprivate t_var(t_var)
|
||||||
|
// CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR]],
|
||||||
|
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]],
|
||||||
|
|
||||||
|
// firstprivate vec(vec)
|
||||||
|
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
|
||||||
|
// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* bitcast ([2 x i{{[0-9]+}}]* [[VEC]] to i8*),
|
||||||
|
|
||||||
|
// firstprivate s_arr(s_arr)
|
||||||
|
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
|
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_FLOAT_TY]], [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
|
||||||
|
// CHECK: [[IS_EMPTY:%.+]] = icmp eq [[S_FLOAT_TY]]* [[S_ARR_PRIV_BEGIN]], [[S_ARR_PRIV_END]]
|
||||||
|
// CHECK: br i1 [[IS_EMPTY]], label %[[S_ARR_BODY_DONE:.+]], label %[[S_ARR_BODY:.+]]
|
||||||
|
// CHECK: [[S_ARR_BODY]]
|
||||||
|
// CHECK: getelementptr inbounds ([2 x [[S_FLOAT_TY]]], [2 x [[S_FLOAT_TY]]]* [[S_ARR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0)
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
|
||||||
|
// CHECK: call {{.*}} [[S_FLOAT_TY_COPY_CONSTR:@.+]]([[S_FLOAT_TY]]* {{.+}}, [[S_FLOAT_TY]]* {{.+}}, [[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DESTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: br i1 {{.+}}, label %{{.+}}, label %[[S_ARR_BODY]]
|
||||||
|
|
||||||
|
// firstprivate var(var)
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
|
||||||
|
// CHECK: call {{.*}} [[S_FLOAT_TY_COPY_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]* {{.*}} [[VAR]], [[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
|
||||||
|
// Synchronization for initialization.
|
||||||
|
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||||
|
|
||||||
|
// CHECK: call void @__kmpc_for_static_init_4(
|
||||||
|
// CHECK: call void @__kmpc_for_static_fini(
|
||||||
|
|
||||||
|
// ~(firstprivate var), ~(firstprivate s_arr)
|
||||||
|
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||||
|
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||||
|
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||||
|
|
||||||
|
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()
|
||||||
|
|
||||||
|
// CHECK: ret void
|
||||||
|
|
||||||
|
// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
|
||||||
|
// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
|
||||||
|
// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
|
||||||
|
// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)* @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void
|
||||||
|
// CHECK: call {{.*}} [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
|
||||||
|
// CHECK: ret
|
||||||
|
//
|
||||||
|
// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}})
|
||||||
|
// Skip temp vars for loop
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: alloca i{{[0-9]+}},
|
||||||
|
// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}},
|
||||||
|
// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}],
|
||||||
|
// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]],
|
||||||
|
// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]],
|
||||||
|
// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]],
|
||||||
|
|
||||||
|
// firstprivate t_var(t_var)
|
||||||
|
// CHECK: [[T_VAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
|
// CHECK: [[T_VAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_PTR_REF]],
|
||||||
|
// CHECK: [[T_VAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[T_VAR_REF]],
|
||||||
|
// CHECK: store i{{[0-9]+}} [[T_VAR_VAL]], i{{[0-9]+}}* [[T_VAR_PRIV]],
|
||||||
|
|
||||||
|
// firstprivate vec(vec)
|
||||||
|
// CHECK: [[VEC_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
|
||||||
|
// CHECK: [[VEC_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_PTR_REF:%.+]],
|
||||||
|
// CHECK: [[VEC_DEST:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8*
|
||||||
|
// CHECK: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_REF]] to i8*
|
||||||
|
// CHECK: call void @llvm.memcpy.{{.+}}(i8* [[VEC_DEST]], i8* [[VEC_SRC]],
|
||||||
|
|
||||||
|
// firstprivate s_arr(s_arr)
|
||||||
|
// CHECK: [[S_ARR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
|
||||||
|
// CHECK: [[S_ARR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_REF]],
|
||||||
|
// CHECK: [[S_ARR_PRIV_BEGIN:%.+]] = getelementptr inbounds [2 x [[S_INT_TY]]], [2 x [[S_INT_TY]]]* [[S_ARR_PRIV]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
|
// CHECK: [[S_ARR_PRIV_END:%.+]] = getelementptr [[S_INT_TY]], [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], i{{[0-9]+}} 2
|
||||||
|
// CHECK: [[IS_EMPTY:%.+]] = icmp eq [[S_INT_TY]]* [[S_ARR_PRIV_BEGIN]], [[S_ARR_PRIV_END]]
|
||||||
|
// CHECK: br i1 [[IS_EMPTY]], label %[[S_ARR_BODY_DONE:.+]], label %[[S_ARR_BODY:.+]]
|
||||||
|
// CHECK: [[S_ARR_BODY]]
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
|
||||||
|
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR:@.+]]([[S_INT_TY]]* {{.+}}, [[S_INT_TY]]* {{.+}}, [[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DESTR:@.+]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: br i1 {{.+}}, label %{{.+}}, label %[[S_ARR_BODY]]
|
||||||
|
|
||||||
|
// firstprivate var(var)
|
||||||
|
// CHECK: [[VAR_REF_PTR:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 3
|
||||||
|
// CHECK: [[VAR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_REF_PTR]],
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
|
||||||
|
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
|
||||||
|
|
||||||
|
// Synchronization for initialization.
|
||||||
|
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||||
|
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||||
|
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||||
|
|
||||||
|
// CHECK: call void @__kmpc_for_static_init_4(
|
||||||
|
// CHECK: call void @__kmpc_for_static_fini(
|
||||||
|
|
||||||
|
// ~(firstprivate var), ~(firstprivate s_arr)
|
||||||
|
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||||
|
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
||||||
|
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||||
|
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||||
|
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
||||||
|
// CHECK: ret void
|
||||||
|
#endif
|
||||||
|
|
|
@ -26,8 +26,8 @@ class S3 {
|
||||||
S3 &operator=(const S3 &s3);
|
S3 &operator=(const S3 &s3);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
|
S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
|
||||||
S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
|
S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
|
||||||
};
|
};
|
||||||
const S3 c;
|
const S3 c;
|
||||||
const S3 ca[5];
|
const S3 ca[5];
|
||||||
|
@ -194,7 +194,7 @@ int main(int argc, char **argv) {
|
||||||
for (i = 0; i < argc; ++i)
|
for (i = 0; i < argc; ++i)
|
||||||
foo();
|
foo();
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
#pragma omp for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{no matching constructor for initialization of 'const S3'}}
|
#pragma omp for firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{no matching constructor for initialization of 'S3'}}
|
||||||
for (i = 0; i < argc; ++i)
|
for (i = 0; i < argc; ++i)
|
||||||
foo();
|
foo();
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
|
@ -210,7 +210,7 @@ int main(int argc, char **argv) {
|
||||||
for (i = 0; i < argc; ++i)
|
for (i = 0; i < argc; ++i)
|
||||||
foo();
|
foo();
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
#pragma omp for firstprivate(ca) // OK
|
#pragma omp for firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
|
||||||
for (i = 0; i < argc; ++i)
|
for (i = 0; i < argc; ++i)
|
||||||
foo();
|
foo();
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
|
|
|
@ -70,7 +70,7 @@ int main() {
|
||||||
// LAMBDA: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
// LAMBDA: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
// LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
// LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
||||||
// LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]]
|
// LAMBDA: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]]
|
||||||
// LAMBDA: store volatile i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
||||||
g = 1;
|
g = 1;
|
||||||
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||||
|
@ -108,7 +108,7 @@ int main() {
|
||||||
// BLOCKS: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
// BLOCKS: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
// BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
// BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
||||||
// BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]]
|
// BLOCKS: [[G_VAL:%.+]] = load volatile i{{[0-9]+}}, i{{[0-9]+}}* [[G_REF]]
|
||||||
// BLOCKS: store volatile i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
// BLOCKS: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
||||||
g = 1;
|
g = 1;
|
||||||
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||||
|
|
|
@ -22,7 +22,6 @@ volatile int g = 1212;
|
||||||
// CHECK: [[CAP_MAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]* }
|
// 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]+}} }
|
// CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
|
||||||
// CHECK: [[CAP_TMAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
|
// CHECK: [[CAP_TMAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
|
||||||
// CHECK: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T tmain() {
|
T tmain() {
|
||||||
S<T> test;
|
S<T> test;
|
||||||
|
@ -54,7 +53,6 @@ int main() {
|
||||||
// LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
// LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
||||||
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
// LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
||||||
// LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
|
// LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
|
||||||
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
|
||||||
g = 1;
|
g = 1;
|
||||||
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// 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: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
|
@ -87,7 +85,6 @@ int main() {
|
||||||
// BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
// BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
|
||||||
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
// BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
|
||||||
// BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
|
// BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
|
||||||
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
|
||||||
g = 1;
|
g = 1;
|
||||||
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||||
// BLOCKS-NOT: [[G]]{{[[^:word:]]}}
|
// BLOCKS-NOT: [[G]]{{[[^:word:]]}}
|
||||||
|
@ -143,9 +140,6 @@ int main() {
|
||||||
// CHECK-NOT: [[T_VAR_PRIV]]
|
// CHECK-NOT: [[T_VAR_PRIV]]
|
||||||
// CHECK-NOT: [[VEC_PRIV]]
|
// CHECK-NOT: [[VEC_PRIV]]
|
||||||
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
|
|
||||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
|
||||||
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
|
||||||
// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]])
|
||||||
// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
@ -171,9 +165,6 @@ int main() {
|
||||||
// CHECK-NOT: [[T_VAR_PRIV]]
|
// CHECK-NOT: [[T_VAR_PRIV]]
|
||||||
// CHECK-NOT: [[VEC_PRIV]]
|
// CHECK-NOT: [[VEC_PRIV]]
|
||||||
// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_REF]]
|
|
||||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
|
||||||
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
|
||||||
// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||||
// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|
|
@ -67,7 +67,6 @@ int main() {
|
||||||
// LAMBDA: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
// LAMBDA: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
// LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
// LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
||||||
// LAMBDA: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
// LAMBDA: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
// LAMBDA: call i32 @__kmpc_cancel_barrier(
|
|
||||||
g = 1;
|
g = 1;
|
||||||
// LAMBDA: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// 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: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
|
@ -129,7 +128,6 @@ int main() {
|
||||||
// BLOCKS: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
// BLOCKS: [[G_REF_ADDR:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
|
||||||
// BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
// BLOCKS: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_REF_ADDR]]
|
||||||
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
|
||||||
// BLOCKS: call i32 @__kmpc_cancel_barrier(
|
|
||||||
g = 1;
|
g = 1;
|
||||||
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
// BLOCKS: store volatile i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
|
||||||
// BLOCKS-NOT: [[G]]{{[[^:word:]]}}
|
// BLOCKS-NOT: [[G]]{{[[^:word:]]}}
|
||||||
|
@ -223,10 +221,6 @@ int main() {
|
||||||
// For min reduction operation initial value of private variable is largest repesentable value.
|
// For min reduction operation initial value of private variable is largest repesentable value.
|
||||||
// CHECK: store float 0x47EFFFFFE0000000, float* [[T_VAR1_PRIV]],
|
// CHECK: store float 0x47EFFFFFE0000000, float* [[T_VAR1_PRIV]],
|
||||||
|
|
||||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
|
||||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
|
||||||
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
|
||||||
|
|
||||||
// Skip checks for internal operations.
|
// Skip checks for internal operations.
|
||||||
|
|
||||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||||
|
@ -246,6 +240,8 @@ int main() {
|
||||||
|
|
||||||
// res = __kmpc_reduce_nowait(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
// res = __kmpc_reduce_nowait(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||||
|
|
||||||
|
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||||
|
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||||
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
||||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||||
|
|
||||||
|
@ -496,10 +492,6 @@ int main() {
|
||||||
// For min reduction operation initial value of private variable is largest repesentable value.
|
// For min reduction operation initial value of private variable is largest repesentable value.
|
||||||
// CHECK: store i{{[0-9]+}} 2147483647, i{{[0-9]+}}* [[T_VAR1_PRIV]],
|
// CHECK: store i{{[0-9]+}} 2147483647, i{{[0-9]+}}* [[T_VAR1_PRIV]],
|
||||||
|
|
||||||
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
|
||||||
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
|
||||||
// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
|
|
||||||
|
|
||||||
// Skip checks for internal operations.
|
// Skip checks for internal operations.
|
||||||
|
|
||||||
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
// void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
|
||||||
|
@ -519,6 +511,8 @@ int main() {
|
||||||
|
|
||||||
// res = __kmpc_reduce_nowait(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
// res = __kmpc_reduce_nowait(<loc>, <gtid>, <n>, sizeof(RedList), RedList, reduce_func, &<lock>);
|
||||||
|
|
||||||
|
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
|
||||||
|
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
|
||||||
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
// CHECK: [[BITCAST:%.+]] = bitcast [4 x i8*]* [[RED_LIST]] to i8*
|
||||||
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
// CHECK: [[RES:%.+]] = call i32 @__kmpc_reduce_nowait(%{{.+}}* [[REDUCTION_LOC]], i32 [[GTID]], i32 4, i64 32, i8* [[BITCAST]], void (i8*, i8*)* [[REDUCTION_FUNC:@.+]], [8 x i32]* [[REDUCTION_LOCK]])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue