From: Alexey Bataev Date: Tue, 19 May 2015 12:31:28 +0000 (+0000) Subject: [OPENMP] Fixed codegen for copying/initialization of array variables/parameters. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8db3eab2a3f9cf13c2ef341ceaf5ca52ef76ff06;p=clang [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237691 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 47cb1a391f..e96200a601 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1287,7 +1287,12 @@ static llvm::Value *emitCopyprivateCopyFunction( CGF.Builder.CreateStructGEP(nullptr, RHS, I), CGM.PointerAlignInBytes), CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType()))); - CGF.EmitOMPCopy(CGF, CopyprivateVars[I]->getType(), DestAddr, SrcAddr, + auto *VD = cast(CopyprivateVars[I])->getDecl(); + QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } + CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr, cast(cast(DestExprs[I])->getDecl()), cast(cast(SrcExprs[I])->getDecl()), AssignmentOps[I]); @@ -1654,8 +1659,12 @@ createPrivatesRecordDecl(CodeGenModule &CGM, auto *RD = C.buildImplicitRecord(".kmp_privates.t"); RD->startDefinition(); for (auto &&Pair : Privates) { - addFieldToRecordDecl( - C, RD, Pair.second.Original->getType().getNonReferenceType()); + auto Type = Pair.second.Original->getType(); + if (auto *PVD = dyn_cast(Pair.second.Original)) { + Type = PVD->getOriginalType(); + } + Type = Type.getNonReferenceType(); + addFieldToRecordDecl(C, RD, Type); } RD->completeDefinition(); return RD; @@ -1939,22 +1948,24 @@ void CGOpenMPRuntime::emitTaskCall( auto *SharedField = CapturesInfo.lookup(OriginalVD); auto SharedRefLValue = CGF.EmitLValueForField(SharedsBase, SharedField); - if (OriginalVD->getType()->isArrayType()) { + QualType Type = OriginalVD->getType(); + if (auto *PVD = dyn_cast(OriginalVD)) { + Type = PVD->getOriginalType(); + } + if (Type->isArrayType()) { // Initialize firstprivate array. if (!isa(Init) || CGF.isTrivialInitializer(Init)) { // Perform simple memcpy. CGF.EmitAggregateAssign(PrivateLValue.getAddress(), - SharedRefLValue.getAddress(), - OriginalVD->getType()); + SharedRefLValue.getAddress(), Type); } else { // Initialize firstprivate array using element-by-element // intialization. CGF.EmitOMPAggregateAssign( PrivateLValue.getAddress(), SharedRefLValue.getAddress(), - OriginalVD->getType(), - [&CGF, Elem, Init, &CapturesInfo](llvm::Value *DestElement, - llvm::Value *SrcElement) { + Type, [&CGF, Elem, Init, &CapturesInfo]( + llvm::Value *DestElement, llvm::Value *SrcElement) { // Clean up any temporaries needed by the initialization. CodeGenFunction::OMPPrivateScope InitScope(CGF); InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{ @@ -1996,8 +2007,12 @@ void CGOpenMPRuntime::emitTaskCall( auto *SharedField = CapturesInfo.lookup(OriginalVD); auto SharedRefLValue = CGF.EmitLValueForFieldInitialization(SharedsBase, SharedField); - CGF.EmitStoreThroughLValue(RValue::get(PrivateLValue.getAddress()), - SharedRefLValue); + CGF.EmitStoreThroughLValue( + RValue::get(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( + PrivateLValue.getAddress(), SharedRefLValue.getAddress() + ->getType() + ->getPointerElementType())), + SharedRefLValue); ++FI, ++I; } } diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index ce1b42dbbb..61945c63ab 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -132,7 +132,11 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OrigVD) != nullptr, (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); auto *OriginalAddr = EmitLValue(&DRE).getAddress(); - if (OrigVD->getType()->isArrayType()) { + QualType Type = OrigVD->getType(); + if (auto *PVD = dyn_cast(OrigVD)) { + Type = PVD->getOriginalType(); + } + if (Type->isArrayType()) { // Emit VarDecl with copy init for arrays. // Get the address of the original variable captured in current // captured region. @@ -142,11 +146,10 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, if (!isa(Init) || isTrivialInitializer(Init)) { // Perform simple memcpy. EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr, - (*IRef)->getType()); + Type); } else { EmitOMPAggregateAssign( - Emission.getAllocatedAddress(), OriginalAddr, - (*IRef)->getType(), + Emission.getAllocatedAddress(), OriginalAddr, Type, [this, VDInit, Init](llvm::Value *DestElement, llvm::Value *SrcElement) { // Clean up any temporaries needed by the initialization. @@ -225,6 +228,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { auto IDestRef = C->destination_exprs().begin(); for (auto *AssignOp : C->assignment_ops()) { auto *VD = cast(cast(*IRef)->getDecl()); + QualType Type = VD->getType(); + if (auto *PVD = dyn_cast(VD)) { + Type = PVD->getOriginalType(); + } if (CopiedVars.insert(VD->getCanonicalDecl()).second) { // Get the address of the master variable. auto *MasterAddr = VD->isStaticLocal() @@ -246,8 +253,8 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { } auto *SrcVD = cast(cast(*ISrcRef)->getDecl()); auto *DestVD = cast(cast(*IDestRef)->getDecl()); - EmitOMPCopy(*this, (*IRef)->getType(), PrivateAddr, MasterAddr, DestVD, - SrcVD, AssignOp); + EmitOMPCopy(*this, Type, PrivateAddr, MasterAddr, DestVD, SrcVD, + AssignOp); } ++IRef; ++ISrcRef; @@ -328,6 +335,10 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal( auto IDestRef = C->destination_exprs().begin(); for (auto *AssignOp : C->assignment_ops()) { auto *PrivateVD = cast(cast(*IRef)->getDecl()); + QualType Type = PrivateVD->getType(); + if (auto *PVD = dyn_cast(PrivateVD)) { + Type = PVD->getOriginalType(); + } if (AlreadyEmittedVars.insert(PrivateVD->getCanonicalDecl()).second) { auto *SrcVD = cast(cast(*ISrcRef)->getDecl()); auto *DestVD = cast(cast(*IDestRef)->getDecl()); @@ -335,8 +346,8 @@ void CodeGenFunction::EmitOMPLastprivateClauseFinal( auto *OriginalAddr = GetAddrOfLocalVar(DestVD); // Get the address of the private variable. auto *PrivateAddr = GetAddrOfLocalVar(PrivateVD); - EmitOMPCopy(*this, (*IRef)->getType(), OriginalAddr, PrivateAddr, - DestVD, SrcVD, AssignOp); + EmitOMPCopy(*this, Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, + AssignOp); } ++IRef; ++ISrcRef; diff --git a/test/OpenMP/parallel_copyin_codegen.cpp b/test/OpenMP/parallel_copyin_codegen.cpp index 0bb43693c9..086073286b 100644 --- a/test/OpenMP/parallel_copyin_codegen.cpp +++ b/test/OpenMP/parallel_copyin_codegen.cpp @@ -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 -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++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s // expected-no-diagnostics +#ifndef ARRAY #ifndef HEADER #define HEADER @@ -269,4 +271,26 @@ int main() { // CHECK: ret void #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 + diff --git a/test/OpenMP/parallel_firstprivate_codegen.cpp b/test/OpenMP/parallel_firstprivate_codegen.cpp index 25a0921d5a..64a12944fc 100644 --- a/test/OpenMP/parallel_firstprivate_codegen.cpp +++ b/test/OpenMP/parallel_firstprivate_codegen.cpp @@ -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 -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++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s // expected-no-diagnostics +#ifndef ARRAY #ifndef 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]]* // 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 + diff --git a/test/OpenMP/single_codegen.cpp b/test/OpenMP/single_codegen.cpp index 6b80426913..27d4787bb4 100644 --- a/test/OpenMP/single_codegen.cpp +++ b/test/OpenMP/single_codegen.cpp @@ -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++ -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 -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 +#ifndef ARRAY #ifndef 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_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 diff --git a/test/OpenMP/task_firstprivate_codegen.cpp b/test/OpenMP/task_firstprivate_codegen.cpp index 7091cc4e08..f22d718d19 100644 --- a/test/OpenMP/task_firstprivate_codegen.cpp +++ b/test/OpenMP/task_firstprivate_codegen.cpp @@ -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 -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++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s // expected-no-diagnostics // It doesn't pass on win32. // REQUIRES: shell +#ifndef ARRAY #ifndef HEADER #define HEADER @@ -397,4 +399,26 @@ int main() { // CHECK: ret i32 #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 diff --git a/test/OpenMP/task_private_codegen.cpp b/test/OpenMP/task_private_codegen.cpp index 197e8a8fa0..9cd69da258 100644 --- a/test/OpenMP/task_private_codegen.cpp +++ b/test/OpenMP/task_private_codegen.cpp @@ -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 -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++ -std=c++11 -DARRAY -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=ARRAY %s // expected-no-diagnostics // It doesn't pass on win32. Investigating. // REQUIRES: shell +#ifndef ARRAY #ifndef HEADER #define HEADER @@ -360,4 +362,26 @@ int main() { // CHECK: ret i32 #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