forked from OSchip/llvm-project
[OPENMP] Fixed codegen for copying/initialization of array variables/parameters.
This modification generates proper copyin/initialization sequences for array variables/parameters. Before they were considered as pointers, not arrays. llvm-svn: 237691
This commit is contained in:
parent
9310166a63
commit
1d9c15cf18
|
@ -1287,7 +1287,12 @@ static llvm::Value *emitCopyprivateCopyFunction(
|
||||||
CGF.Builder.CreateStructGEP(nullptr, RHS, I),
|
CGF.Builder.CreateStructGEP(nullptr, RHS, I),
|
||||||
CGM.PointerAlignInBytes),
|
CGM.PointerAlignInBytes),
|
||||||
CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
|
CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType())));
|
||||||
CGF.EmitOMPCopy(CGF, CopyprivateVars[I]->getType(), DestAddr, SrcAddr,
|
auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
|
||||||
|
QualType Type = VD->getType();
|
||||||
|
if (auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
|
CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr,
|
||||||
cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
|
cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()),
|
||||||
cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
|
cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()),
|
||||||
AssignmentOps[I]);
|
AssignmentOps[I]);
|
||||||
|
@ -1654,8 +1659,12 @@ createPrivatesRecordDecl(CodeGenModule &CGM,
|
||||||
auto *RD = C.buildImplicitRecord(".kmp_privates.t");
|
auto *RD = C.buildImplicitRecord(".kmp_privates.t");
|
||||||
RD->startDefinition();
|
RD->startDefinition();
|
||||||
for (auto &&Pair : Privates) {
|
for (auto &&Pair : Privates) {
|
||||||
addFieldToRecordDecl(
|
auto Type = Pair.second.Original->getType();
|
||||||
C, RD, Pair.second.Original->getType().getNonReferenceType());
|
if (auto *PVD = dyn_cast<ParmVarDecl>(Pair.second.Original)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
|
Type = Type.getNonReferenceType();
|
||||||
|
addFieldToRecordDecl(C, RD, Type);
|
||||||
}
|
}
|
||||||
RD->completeDefinition();
|
RD->completeDefinition();
|
||||||
return RD;
|
return RD;
|
||||||
|
@ -1939,22 +1948,24 @@ void CGOpenMPRuntime::emitTaskCall(
|
||||||
auto *SharedField = CapturesInfo.lookup(OriginalVD);
|
auto *SharedField = CapturesInfo.lookup(OriginalVD);
|
||||||
auto SharedRefLValue =
|
auto SharedRefLValue =
|
||||||
CGF.EmitLValueForField(SharedsBase, SharedField);
|
CGF.EmitLValueForField(SharedsBase, SharedField);
|
||||||
if (OriginalVD->getType()->isArrayType()) {
|
QualType Type = OriginalVD->getType();
|
||||||
|
if (auto *PVD = dyn_cast<ParmVarDecl>(OriginalVD)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
|
if (Type->isArrayType()) {
|
||||||
// Initialize firstprivate array.
|
// Initialize firstprivate array.
|
||||||
if (!isa<CXXConstructExpr>(Init) ||
|
if (!isa<CXXConstructExpr>(Init) ||
|
||||||
CGF.isTrivialInitializer(Init)) {
|
CGF.isTrivialInitializer(Init)) {
|
||||||
// Perform simple memcpy.
|
// Perform simple memcpy.
|
||||||
CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
|
CGF.EmitAggregateAssign(PrivateLValue.getAddress(),
|
||||||
SharedRefLValue.getAddress(),
|
SharedRefLValue.getAddress(), Type);
|
||||||
OriginalVD->getType());
|
|
||||||
} else {
|
} else {
|
||||||
// Initialize firstprivate array using element-by-element
|
// Initialize firstprivate array using element-by-element
|
||||||
// intialization.
|
// intialization.
|
||||||
CGF.EmitOMPAggregateAssign(
|
CGF.EmitOMPAggregateAssign(
|
||||||
PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
|
PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
|
||||||
OriginalVD->getType(),
|
Type, [&CGF, Elem, Init, &CapturesInfo](
|
||||||
[&CGF, Elem, Init, &CapturesInfo](llvm::Value *DestElement,
|
llvm::Value *DestElement, llvm::Value *SrcElement) {
|
||||||
llvm::Value *SrcElement) {
|
|
||||||
// Clean up any temporaries needed by the initialization.
|
// Clean up any temporaries needed by the initialization.
|
||||||
CodeGenFunction::OMPPrivateScope InitScope(CGF);
|
CodeGenFunction::OMPPrivateScope InitScope(CGF);
|
||||||
InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
|
InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{
|
||||||
|
@ -1996,8 +2007,12 @@ void CGOpenMPRuntime::emitTaskCall(
|
||||||
auto *SharedField = CapturesInfo.lookup(OriginalVD);
|
auto *SharedField = CapturesInfo.lookup(OriginalVD);
|
||||||
auto SharedRefLValue =
|
auto SharedRefLValue =
|
||||||
CGF.EmitLValueForFieldInitialization(SharedsBase, SharedField);
|
CGF.EmitLValueForFieldInitialization(SharedsBase, SharedField);
|
||||||
CGF.EmitStoreThroughLValue(RValue::get(PrivateLValue.getAddress()),
|
CGF.EmitStoreThroughLValue(
|
||||||
SharedRefLValue);
|
RValue::get(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
|
||||||
|
PrivateLValue.getAddress(), SharedRefLValue.getAddress()
|
||||||
|
->getType()
|
||||||
|
->getPointerElementType())),
|
||||||
|
SharedRefLValue);
|
||||||
++FI, ++I;
|
++FI, ++I;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,11 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
||||||
OrigVD) != nullptr,
|
OrigVD) != nullptr,
|
||||||
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
|
(*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
|
||||||
auto *OriginalAddr = EmitLValue(&DRE).getAddress();
|
auto *OriginalAddr = EmitLValue(&DRE).getAddress();
|
||||||
if (OrigVD->getType()->isArrayType()) {
|
QualType Type = OrigVD->getType();
|
||||||
|
if (auto *PVD = dyn_cast<ParmVarDecl>(OrigVD)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
|
if (Type->isArrayType()) {
|
||||||
// Emit VarDecl with copy init for arrays.
|
// Emit VarDecl with copy init for arrays.
|
||||||
// Get the address of the original variable captured in current
|
// Get the address of the original variable captured in current
|
||||||
// captured region.
|
// captured region.
|
||||||
|
@ -142,11 +146,10 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
|
||||||
if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
|
if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) {
|
||||||
// Perform simple memcpy.
|
// Perform simple memcpy.
|
||||||
EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
|
EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr,
|
||||||
(*IRef)->getType());
|
Type);
|
||||||
} else {
|
} else {
|
||||||
EmitOMPAggregateAssign(
|
EmitOMPAggregateAssign(
|
||||||
Emission.getAllocatedAddress(), OriginalAddr,
|
Emission.getAllocatedAddress(), OriginalAddr, Type,
|
||||||
(*IRef)->getType(),
|
|
||||||
[this, VDInit, Init](llvm::Value *DestElement,
|
[this, VDInit, Init](llvm::Value *DestElement,
|
||||||
llvm::Value *SrcElement) {
|
llvm::Value *SrcElement) {
|
||||||
// Clean up any temporaries needed by the initialization.
|
// Clean up any temporaries needed by the initialization.
|
||||||
|
@ -225,6 +228,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
|
||||||
auto IDestRef = C->destination_exprs().begin();
|
auto IDestRef = C->destination_exprs().begin();
|
||||||
for (auto *AssignOp : C->assignment_ops()) {
|
for (auto *AssignOp : C->assignment_ops()) {
|
||||||
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
||||||
|
QualType Type = VD->getType();
|
||||||
|
if (auto *PVD = dyn_cast<ParmVarDecl>(VD)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
|
if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
|
||||||
// Get the address of the master variable.
|
// Get the address of the master variable.
|
||||||
auto *MasterAddr = VD->isStaticLocal()
|
auto *MasterAddr = VD->isStaticLocal()
|
||||||
|
@ -246,8 +253,8 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
|
||||||
}
|
}
|
||||||
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
|
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
|
||||||
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
|
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
|
||||||
EmitOMPCopy(*this, (*IRef)->getType(), PrivateAddr, MasterAddr, DestVD,
|
EmitOMPCopy(*this, Type, PrivateAddr, MasterAddr, DestVD, SrcVD,
|
||||||
SrcVD, AssignOp);
|
AssignOp);
|
||||||
}
|
}
|
||||||
++IRef;
|
++IRef;
|
||||||
++ISrcRef;
|
++ISrcRef;
|
||||||
|
@ -328,6 +335,10 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
|
||||||
auto IDestRef = C->destination_exprs().begin();
|
auto IDestRef = C->destination_exprs().begin();
|
||||||
for (auto *AssignOp : C->assignment_ops()) {
|
for (auto *AssignOp : C->assignment_ops()) {
|
||||||
auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
|
||||||
|
QualType Type = PrivateVD->getType();
|
||||||
|
if (auto *PVD = dyn_cast<ParmVarDecl>(PrivateVD)) {
|
||||||
|
Type = PVD->getOriginalType();
|
||||||
|
}
|
||||||
if (AlreadyEmittedVars.insert(PrivateVD->getCanonicalDecl()).second) {
|
if (AlreadyEmittedVars.insert(PrivateVD->getCanonicalDecl()).second) {
|
||||||
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
|
auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
|
||||||
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
|
auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
|
||||||
|
@ -335,8 +346,8 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal(
|
||||||
auto *OriginalAddr = GetAddrOfLocalVar(DestVD);
|
auto *OriginalAddr = GetAddrOfLocalVar(DestVD);
|
||||||
// Get the address of the private variable.
|
// Get the address of the private variable.
|
||||||
auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD);
|
auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD);
|
||||||
EmitOMPCopy(*this, (*IRef)->getType(), OriginalAddr, PrivateAddr,
|
EmitOMPCopy(*this, Type, OriginalAddr, PrivateAddr, DestVD, SrcVD,
|
||||||
DestVD, SrcVD, AssignOp);
|
AssignOp);
|
||||||
}
|
}
|
||||||
++IRef;
|
++IRef;
|
||||||
++ISrcRef;
|
++ISrcRef;
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
// 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 -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++ -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
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
#ifndef ARRAY
|
||||||
#ifndef HEADER
|
#ifndef HEADER
|
||||||
#define HEADER
|
#define HEADER
|
||||||
|
|
||||||
|
@ -269,4 +271,26 @@ int main() {
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
// ARRAY-LABEL: array_func
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St &operator=(const St &) { return *this; };
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void array_func() {
|
||||||
|
static int a[2];
|
||||||
|
static St s[2];
|
||||||
|
// ARRAY: @__kmpc_fork_call(
|
||||||
|
// ARRAY: call i8* @__kmpc_threadprivate_cached(
|
||||||
|
// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* bitcast ([2 x i32]* @{{.+}} to i8*), i64 8, i32 4, i1 false)
|
||||||
|
// ARRAY: call dereferenceable(8) %struct.St* @{{.+}}(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}})
|
||||||
|
#pragma omp threadprivate(a, s)
|
||||||
|
#pragma omp parallel copyin(a, s)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
// 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 -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++ -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
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
#ifndef ARRAY
|
||||||
#ifndef HEADER
|
#ifndef HEADER
|
||||||
#define HEADER
|
#define HEADER
|
||||||
|
|
||||||
|
@ -237,5 +239,24 @@ int main() {
|
||||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
|
||||||
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// ARRAY-LABEL: array_func
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St(const St &) { }
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void array_func(int a[3], St s[2]) {
|
||||||
|
// ARRAY: @__kmpc_fork_call(
|
||||||
|
// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 12, i32 4, i1 false)
|
||||||
|
// ARRAY: call void @_ZN2StC1ERKS_(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}}
|
||||||
|
#pragma omp parallel firstprivate(a, s)
|
||||||
|
;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
|
||||||
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
||||||
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp=libiomp5 -fexceptions -fcxx-exceptions -gline-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
|
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp=libiomp5 -fexceptions -fcxx-exceptions -gline-tables-only -x c++ -emit-llvm %s -o - | FileCheck %s --check-prefix=TERM_DEBUG
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
|
||||||
|
#ifndef ARRAY
|
||||||
#ifndef HEADER
|
#ifndef HEADER
|
||||||
#define HEADER
|
#define HEADER
|
||||||
|
|
||||||
|
@ -166,5 +168,22 @@ void parallel_single() {
|
||||||
}
|
}
|
||||||
// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-12]],
|
// TERM_DEBUG-DAG: [[DBG_LOC_START]] = !DILocation(line: [[@LINE-12]],
|
||||||
// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-3]],
|
// TERM_DEBUG-DAG: [[DBG_LOC_END]] = !DILocation(line: [[@LINE-3]],
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// ARRAY-LABEL: array_func
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St &operator=(const St &) { return *this; };
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void array_func(int a[3], St s[2]) {
|
||||||
|
// ARRAY: call void @__kmpc_copyprivate(%ident_t* @{{.+}}, i32 %{{.+}}, i64 16, i8* %{{.+}}, void (i8*, i8*)* [[CPY:@.+]], i32 %{{.+}})
|
||||||
|
#pragma omp single copyprivate(a, s)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
// ARRAY: define internal void [[CPY]]
|
||||||
|
// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 12, i32 4, i1 false)
|
||||||
|
// ARRAY: call dereferenceable(8) %struct.St* @_ZN2StaSERKS_(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}})
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -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 x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
|
||||||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
|
||||||
// It doesn't pass on win32.
|
// It doesn't pass on win32.
|
||||||
// REQUIRES: shell
|
// REQUIRES: shell
|
||||||
|
#ifndef ARRAY
|
||||||
#ifndef HEADER
|
#ifndef HEADER
|
||||||
#define HEADER
|
#define HEADER
|
||||||
|
|
||||||
|
@ -397,4 +399,26 @@ int main() {
|
||||||
// CHECK: ret i32
|
// CHECK: ret i32
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
// ARRAY-LABEL: array_func
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St(const St &) {}
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void array_func(int a[3], St s[2]) {
|
||||||
|
// ARRAY: call i8* @__kmpc_omp_task_alloc(
|
||||||
|
// ARRAY: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 12, i32 4, i1 false)
|
||||||
|
// ARRAY: call void @_ZN2StC1ERKS_(%struct.St* %{{.+}}, %struct.St* dereferenceable(8) %{{.+}})
|
||||||
|
// ARRAY: store i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** %{{.+}},
|
||||||
|
// ARRAY: call i32 @__kmpc_omp_task(
|
||||||
|
// ARRAY: define internal i32 [[DESTRUCTORS]](i32,
|
||||||
|
// ARRAY: call void @_ZN2StD1Ev(%struct.St* %{{.+}})
|
||||||
|
// ARRAY: br i1
|
||||||
|
#pragma omp task firstprivate(a, s)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
|
// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-apple-darwin10 -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 x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
|
||||||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
|
||||||
|
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s
|
||||||
// expected-no-diagnostics
|
// expected-no-diagnostics
|
||||||
|
|
||||||
// It doesn't pass on win32. Investigating.
|
// It doesn't pass on win32. Investigating.
|
||||||
// REQUIRES: shell
|
// REQUIRES: shell
|
||||||
|
|
||||||
|
#ifndef ARRAY
|
||||||
#ifndef HEADER
|
#ifndef HEADER
|
||||||
#define HEADER
|
#define HEADER
|
||||||
|
|
||||||
|
@ -360,4 +362,26 @@ int main() {
|
||||||
// CHECK: ret i32
|
// CHECK: ret i32
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
// ARRAY-LABEL: array_func
|
||||||
|
struct St {
|
||||||
|
int a, b;
|
||||||
|
St() : a(0), b(0) {}
|
||||||
|
St &operator=(const St &) { return *this; };
|
||||||
|
~St() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
void array_func(int a[2], St s[2]) {
|
||||||
|
// ARRAY: call i8* @__kmpc_omp_task_alloc(
|
||||||
|
// ARRAY-NOT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.+}}, i8* %{{.+}}, i64 12, i32 4, i1 false)
|
||||||
|
// ARRAY: call void @_ZN2StC1Ev(%struct.St* %{{.+}})
|
||||||
|
// ARRAY: store i32 (i32, i8*)* bitcast (i32 (i32, %{{[^*]+}}*)* [[DESTRUCTORS:@.+]] to i32 (i32, i8*)*), i32 (i32, i8*)** %{{.+}},
|
||||||
|
// ARRAY: call i32 @__kmpc_omp_task(
|
||||||
|
// ARRAY: define internal i32 [[DESTRUCTORS]](i32,
|
||||||
|
// ARRAY: call void @_ZN2StD1Ev(%struct.St* %{{.+}})
|
||||||
|
// ARRAY: br i1
|
||||||
|
#pragma omp task private(a, s)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue