[clang] 89d9dba - [OPENMP50]Initial codegen for 'affinity' clauses.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 2 07:58:11 PDT 2020
Author: Alexey Bataev
Date: 2020-06-02T10:50:08-04:00
New Revision: 89d9dba2c6885949887edf4b80e1aabf8d8f3f88
URL: https://github.com/llvm/llvm-project/commit/89d9dba2c6885949887edf4b80e1aabf8d8f3f88
DIFF: https://github.com/llvm/llvm-project/commit/89d9dba2c6885949887edf4b80e1aabf8d8f3f88.diff
LOG: [OPENMP50]Initial codegen for 'affinity' clauses.
Summary:
Added initial codegen for 'affinity' clauses on task directives.
Emits next code:
```
kmp_task_affinity_info_t affs[<num_elems>];
void *td = __kmpc_task_alloc(..);
affs[<i>].base = &data_i;
affs[<i>].size = sizeof(data_i);
__kmpc_omp_reg_task_with_affinity(&loc, <gtid>, td, <num_elems>, affs);
```
The result returned by the call of `__kmpc_omp_reg_task_with_affinity`
function is ignored currently sincethe runtime currently ignores args
and returns 0 uncoditionally.
Reviewers: jdoerfert
Subscribers: yaxunl, guansong, sstefan1, llvm-commits, cfe-commits, caomhin
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D80240
Added:
clang/test/OpenMP/task_affinity_codegen.cpp
Modified:
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGOpenMPRuntime.h
llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index e9b1dffda0c4..231e4485aaeb 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -4024,6 +4024,135 @@ checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
return NeedsCleanup;
}
+namespace {
+/// Loop generator for OpenMP iterator expression.
+class OMPIteratorGeneratorScope final
+ : public CodeGenFunction::OMPPrivateScope {
+ CodeGenFunction &CGF;
+ const OMPIteratorExpr *E = nullptr;
+ SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
+ SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
+ OMPIteratorGeneratorScope() = delete;
+ OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete;
+
+public:
+ OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E)
+ : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
+ if (!E)
+ return;
+ SmallVector<llvm::Value *, 4> Uppers;
+ for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
+ Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
+ const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
+ addPrivate(VD, [&CGF, VD]() {
+ return CGF.CreateMemTemp(VD->getType(), VD->getName());
+ });
+ const OMPIteratorHelperData &HelperData = E->getHelper(I);
+ addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() {
+ return CGF.CreateMemTemp(HelperData.CounterVD->getType(),
+ "counter.addr");
+ });
+ }
+ Privatize();
+
+ for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
+ const OMPIteratorHelperData &HelperData = E->getHelper(I);
+ LValue CLVal =
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
+ HelperData.CounterVD->getType());
+ // Counter = 0;
+ CGF.EmitStoreOfScalar(
+ llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0),
+ CLVal);
+ CodeGenFunction::JumpDest &ContDest =
+ ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont"));
+ CodeGenFunction::JumpDest &ExitDest =
+ ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit"));
+ // N = <number-of_iterations>;
+ llvm::Value *N = Uppers[I];
+ // cont:
+ // if (Counter < N) goto body; else goto exit;
+ CGF.EmitBlock(ContDest.getBlock());
+ auto *CVal =
+ CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
+ llvm::Value *Cmp =
+ HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
+ ? CGF.Builder.CreateICmpSLT(CVal, N)
+ : CGF.Builder.CreateICmpULT(CVal, N);
+ llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body");
+ CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
+ // body:
+ CGF.EmitBlock(BodyBB);
+ // Iteri = Begini + Counter * Stepi;
+ CGF.EmitIgnoredExpr(HelperData.Update);
+ }
+ }
+ ~OMPIteratorGeneratorScope() {
+ if (!E)
+ return;
+ for (unsigned I = E->numOfIterators(); I > 0; --I) {
+ // Counter = Counter + 1;
+ const OMPIteratorHelperData &HelperData = E->getHelper(I - 1);
+ CGF.EmitIgnoredExpr(HelperData.CounterUpdate);
+ // goto cont;
+ CGF.EmitBranchThroughCleanup(ContDests[I - 1]);
+ // exit:
+ CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1);
+ }
+ }
+};
+} // namespace
+
+static std::pair<llvm::Value *, llvm::Value *>
+getPointerAndSize(CodeGenFunction &CGF, const Expr *E) {
+ const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
+ llvm::Value *Addr;
+ if (OASE) {
+ const Expr *Base = OASE->getBase();
+ Addr = CGF.EmitScalarExpr(Base);
+ } else {
+ Addr = CGF.EmitLValue(E).getPointer(CGF);
+ }
+ llvm::Value *SizeVal;
+ QualType Ty = E->getType();
+ if (OASE) {
+ SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType());
+ for (const Expr *SE : OASE->getDimensions()) {
+ llvm::Value *Sz = CGF.EmitScalarExpr(SE);
+ Sz = CGF.EmitScalarConversion(
+ Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc());
+ SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz);
+ }
+ } else if (const auto *ASE =
+ dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
+ LValue UpAddrLVal =
+ CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
+ llvm::Value *UpAddr =
+ CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
+ llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy);
+ llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy);
+ SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
+ } else {
+ SizeVal = CGF.getTypeSize(Ty);
+ }
+ return std::make_pair(Addr, SizeVal);
+}
+
+/// Builds kmp_depend_info, if it is not built yet, and builds flags type.
+static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) {
+ QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false);
+ if (KmpTaskAffinityInfoTy.isNull()) {
+ RecordDecl *KmpAffinityInfoRD =
+ C.buildImplicitRecord("kmp_task_affinity_info_t");
+ KmpAffinityInfoRD->startDefinition();
+ addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType());
+ addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType());
+ addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy);
+ KmpAffinityInfoRD->completeDefinition();
+ KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD);
+ }
+}
+
CGOpenMPRuntime::TaskResultTy
CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
const OMPExecutableDirective &D,
@@ -4202,6 +4331,142 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
Evt->getExprLoc());
CGF.EmitStoreOfScalar(EvtVal, EvtLVal);
}
+ // Process affinity clauses.
+ if (D.hasClausesOfKind<OMPAffinityClause>()) {
+ // Process list of affinity data.
+ ASTContext &C = CGM.getContext();
+ Address AffinitiesArray = Address::invalid();
+ // Calculate number of elements to form the array of affinity data.
+ llvm::Value *NumOfElements = nullptr;
+ unsigned NumAffinities = 0;
+ for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
+ if (const Expr *Modifier = C->getModifier()) {
+ const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts());
+ for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
+ llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper);
+ Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false);
+ NumOfElements =
+ NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
+ }
+ } else {
+ NumAffinities += C->varlist_size();
+ }
+ }
+ getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy);
+ // Fields ids in kmp_task_affinity_info record.
+ enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
+
+ QualType KmpTaskAffinityInfoArrayTy;
+ if (NumOfElements) {
+ NumOfElements = CGF.Builder.CreateNUWAdd(
+ llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements);
+ OpaqueValueExpr OVE(
+ Loc,
+ C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0),
+ VK_RValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
+ RValue::get(NumOfElements));
+ KmpTaskAffinityInfoArrayTy =
+ C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal,
+ /*IndexTypeQuals=*/0, SourceRange(Loc, Loc));
+ // Properly emit variable-sized array.
+ auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy,
+ ImplicitParamDecl::Other);
+ CGF.EmitVarDecl(*PD);
+ AffinitiesArray = CGF.GetAddrOfLocalVar(PD);
+ NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty,
+ /*isSigned=*/false);
+ } else {
+ KmpTaskAffinityInfoArrayTy = C.getConstantArrayType(
+ KmpTaskAffinityInfoTy,
+ llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr,
+ ArrayType::Normal, /*IndexTypeQuals=*/0);
+ AffinitiesArray =
+ CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr");
+ AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0);
+ NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities,
+ /*isSigned=*/false);
+ }
+
+ const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl();
+ // Fill array by elements without iterators.
+ unsigned Pos = 0;
+ bool HasIterator = false;
+ for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
+ if (C->getModifier()) {
+ HasIterator = true;
+ continue;
+ }
+ for (const Expr *E : C->varlists()) {
+ llvm::Value *Addr;
+ llvm::Value *Size;
+ std::tie(Addr, Size) = getPointerAndSize(CGF, E);
+ LValue Base =
+ CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos),
+ KmpTaskAffinityInfoTy);
+ // affs[i].base_addr = &<Affinities[i].second>;
+ LValue BaseAddrLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
+ CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
+ BaseAddrLVal);
+ // affs[i].len = sizeof(<Affinities[i].second>);
+ LValue LenLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
+ CGF.EmitStoreOfScalar(Size, LenLVal);
+ ++Pos;
+ }
+ }
+ LValue PosLVal;
+ if (HasIterator) {
+ PosLVal = CGF.MakeAddrLValue(
+ CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"),
+ C.getSizeType());
+ CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal);
+ }
+ // Process elements with iterators.
+ for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) {
+ const Expr *Modifier = C->getModifier();
+ if (!Modifier)
+ continue;
+ OMPIteratorGeneratorScope IteratorScope(
+ CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()));
+ for (const Expr *E : C->varlists()) {
+ llvm::Value *Addr;
+ llvm::Value *Size;
+ std::tie(Addr, Size) = getPointerAndSize(CGF, E);
+ llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
+ LValue Base = CGF.MakeAddrLValue(
+ Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx),
+ AffinitiesArray.getAlignment()),
+ KmpTaskAffinityInfoTy);
+ // affs[i].base_addr = &<Affinities[i].second>;
+ LValue BaseAddrLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
+ CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy),
+ BaseAddrLVal);
+ // affs[i].len = sizeof(<Affinities[i].second>);
+ LValue LenLVal = CGF.EmitLValueForField(
+ Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
+ CGF.EmitStoreOfScalar(Size, LenLVal);
+ Idx = CGF.Builder.CreateNUWAdd(
+ Idx, llvm::ConstantInt::get(Idx->getType(), 1));
+ CGF.EmitStoreOfScalar(Idx, PosLVal);
+ }
+ }
+ // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref,
+ // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32
+ // naffins, kmp_task_affinity_info_t *affin_list);
+ llvm::Value *LocRef = emitUpdateLocation(CGF, Loc);
+ llvm::Value *GTid = getThreadID(CGF, Loc);
+ llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ AffinitiesArray.getPointer(), CGM.VoidPtrTy);
+ // FIXME: Emit the function and ignore its result for now unless the
+ // runtime function is properly implemented.
+ (void)CGF.EmitRuntimeCall(
+ llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
+ {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
+ }
llvm::Value *NewTaskNewTaskTTy =
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
NewTask, KmpTaskTWithPrivatesPtrTy);
@@ -4350,85 +4615,6 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal,
return std::make_pair(NumDeps, Base);
}
-namespace {
-/// Loop generator for OpenMP iterator expression.
-class OMPIteratorGeneratorScope final
- : public CodeGenFunction::OMPPrivateScope {
- CodeGenFunction &CGF;
- const OMPIteratorExpr *E = nullptr;
- SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
- SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
- OMPIteratorGeneratorScope() = delete;
- OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete;
-
-public:
- OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E)
- : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
- if (!E)
- return;
- SmallVector<llvm::Value *, 4> Uppers;
- for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
- Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
- const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
- addPrivate(VD, [&CGF, VD]() {
- return CGF.CreateMemTemp(VD->getType(), VD->getName());
- });
- const OMPIteratorHelperData &HelperData = E->getHelper(I);
- addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() {
- return CGF.CreateMemTemp(HelperData.CounterVD->getType(),
- "counter.addr");
- });
- }
- Privatize();
-
- for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
- const OMPIteratorHelperData &HelperData = E->getHelper(I);
- LValue CLVal =
- CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
- HelperData.CounterVD->getType());
- // Counter = 0;
- CGF.EmitStoreOfScalar(
- llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0),
- CLVal);
- CodeGenFunction::JumpDest &ContDest =
- ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont"));
- CodeGenFunction::JumpDest &ExitDest =
- ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit"));
- // N = <number-of_iterations>;
- llvm::Value *N = Uppers[I];
- // cont:
- // if (Counter < N) goto body; else goto exit;
- CGF.EmitBlock(ContDest.getBlock());
- auto *CVal =
- CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
- llvm::Value *Cmp =
- HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
- ? CGF.Builder.CreateICmpSLT(CVal, N)
- : CGF.Builder.CreateICmpULT(CVal, N);
- llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body");
- CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
- // body:
- CGF.EmitBlock(BodyBB);
- // Iteri = Begini + Counter * Stepi;
- CGF.EmitIgnoredExpr(HelperData.Update);
- }
- }
- ~OMPIteratorGeneratorScope() {
- if (!E)
- return;
- for (unsigned I = E->numOfIterators(); I > 0; --I) {
- // Counter = Counter + 1;
- const OMPIteratorHelperData &HelperData = E->getHelper(I - 1);
- CGF.EmitIgnoredExpr(HelperData.CounterUpdate);
- // goto cont;
- CGF.EmitBranchThroughCleanup(ContDests[I - 1]);
- // exit:
- CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1);
- }
- }
-};
-} // namespace
-
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
llvm::PointerUnion<unsigned *, LValue *> Pos,
const OMPTaskDataTy::DependData &Data,
@@ -4446,37 +4632,9 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy,
Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts()
: nullptr));
for (const Expr *E : Data.DepExprs) {
- const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
llvm::Value *Addr;
- if (OASE) {
- const Expr *Base = OASE->getBase();
- Addr = CGF.EmitScalarExpr(Base);
- } else {
- Addr = CGF.EmitLValue(E).getPointer(CGF);
- }
llvm::Value *Size;
- QualType Ty = E->getType();
- if (OASE) {
- Size = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType());
- for (const Expr *SE : OASE->getDimensions()) {
- llvm::Value *Sz = CGF.EmitScalarExpr(SE);
- Sz = CGF.EmitScalarConversion(Sz, SE->getType(),
- CGF.getContext().getSizeType(),
- SE->getExprLoc());
- Size = CGF.Builder.CreateNUWMul(Size, Sz);
- }
- } else if (const auto *ASE =
- dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
- LValue UpAddrLVal =
- CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
- llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
- UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
- llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGM.SizeTy);
- llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
- Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
- } else {
- Size = CGF.getTypeSize(Ty);
- }
+ std::tie(Addr, Size) = getPointerAndSize(CGF, E);
LValue Base;
if (unsigned *P = Pos.dyn_cast<unsigned *>()) {
Base = CGF.MakeAddrLValue(
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index 3e8eacf950d7..dea92e16e59f 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -458,6 +458,16 @@ class CGOpenMPRuntime {
/// } flags;
/// } kmp_depend_info_t;
QualType KmpDependInfoTy;
+ /// Type typedef struct kmp_task_affinity_info {
+ /// kmp_intptr_t base_addr;
+ /// size_t len;
+ /// struct {
+ /// bool flag1 : 1;
+ /// bool flag2 : 1;
+ /// kmp_int32 reserved : 30;
+ /// } flags;
+ /// } kmp_task_affinity_info_t;
+ QualType KmpTaskAffinityInfoTy;
/// struct kmp_dim { // loop bounds info casted to kmp_int64
/// kmp_int64 lo; // lower
/// kmp_int64 up; // upper
diff --git a/clang/test/OpenMP/task_affinity_codegen.cpp b/clang/test/OpenMP/task_affinity_codegen.cpp
new file mode 100644
index 000000000000..bb418fd50bd1
--- /dev/null
+++ b/clang/test/OpenMP/task_affinity_codegen.cpp
@@ -0,0 +1,132 @@
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -fopenmp-version=50 -x c++ -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+//
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -fopenmp-version=50 -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+// CHECK-LABEL: @main
+int main() {
+ float *p;
+ int a = 10;
+ // kmp_task_affinity_info_t affs[1];
+ // CHECK: [[AFFS_ADDR:%.+]] = alloca [1 x %struct.kmp_task_affinity_info_t],
+ // CHECK: [[TD:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @{{.+}}, i32 [[GTID:%.+]], i32 1, i64 40, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* @{{.+}} to i32 (i32, i8*)*))
+ // CHECK: [[AFFINE_LST_ADDR:%.+]] = getelementptr inbounds [1 x %struct.kmp_task_affinity_info_t], [1 x %struct.kmp_task_affinity_info_t]* [[AFFS_ADDR]], i64 0, i64 0
+ // CHECK: [[P:%.+]] = load float*, float** [[P_ADDR:%.+]],
+ // CHECK: [[A_VAL:%.+]] = load i32, i32* [[A_ADDR:%.+]],
+ // CHECK: [[A_SZ:%.+]] = sext i32 [[A_VAL]] to i64
+ // CHECK: [[BYTES:%.+]] = mul nuw i64 4, [[A_SZ]]
+ // CHECK: [[SZ:%.+]] = mul nuw i64 [[BYTES]], 10
+ // CHECK: [[A_VAL:%.+]] = load i32, i32* [[A_ADDR]],
+ // CHECK: [[A_SZ1:%.+]] = sext i32 [[A_VAL]] to i64
+ // CHECK: [[SIZE:%.+]] = mul nuw i64 [[SZ]], [[A_SZ]]
+ // CHECK: [[AFFS_0_ADDR:%.+]] = getelementptr %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFINE_LST_ADDR]], i64 0
+
+ // affs[0].base = p;
+ // CHECK: [[AFFS_0_BASE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_0_ADDR]], i32 0, i32 0
+ // CHECK: [[P_INTPTR:%.+]] = ptrtoint float* [[P]] to i64
+ // CHECK: store i64 [[P_INTPTR]], i64* [[AFFS_0_BASE_ADDR]],
+
+ // affs[0].size = sizeof(*p) * a * 10 * a;
+ // CHECK: [[AFFS_0_SIZE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_0_ADDR]], i32 0, i32 1
+ // CHECK: store i64 [[SIZE]], i64* [[AFFS_0_SIZE_ADDR]],
+ // CHECK: [[BC:%.+]] = bitcast %struct.kmp_task_affinity_info_t* [[AFFINE_LST_ADDR]] to i8*
+ // CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(%struct.ident_t* @{{.+}}, i32 [[GTID]], i8* [[TD]], i32 1, i8* [[BC]])
+#pragma omp task affinity(([a][10][a])p)
+ ;
+ // CHECK: [[TD:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @{{.+}}, i32 [[GTID]], i32 1, i64 40, i64 1, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* @{{.+}} to i32 (i32, i8*)*))
+ // CHECK: [[A_VAL:%.+]] = load i32, i32* [[A_ADDR]],
+ // CHECK: [[SUB:%.+]] = sub nsw i32 [[A_VAL]], 0
+ // CHECK: [[CONV:%.+]] = zext i32 [[SUB]] to i64
+
+ // <num_elem> = <num_iters> + 1 constant affinity for affinity(a)
+ // CHECK: [[NUM_ELEMS:%.+]] = add nuw i64 1, [[CONV]]
+ // CHECK: [[SV:%.+]] = call i8* @llvm.stacksave()
+ // CHECK: store i8* [[SV]], i8** [[SV_ADDR:%.+]],
+
+ // kmp_task_affinity_info_t affs[<num_elem>];
+ // CHECK: [[AFFS_ADDR:%.+]] = alloca %struct.kmp_task_affinity_info_t, i64 [[NUM_ELEMS]],
+ // store i64 %21, i64* %__vla_expr0, align 8
+ // CHECK: [[NAFFS:%.+]] = trunc i64 [[NUM_ELEMS]] to i32
+ // CHECK: [[AFFS_0_ADDR:%.+]] = getelementptr %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_ADDR]], i64 0
+
+ // affs[0].base = &a;
+ // CHECK: [[AFFS_0_BASE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_0_ADDR]], i32 0, i32 0
+ // CHECK: [[A_INTPTR:%.+]] = ptrtoint i32* [[A_ADDR]] to i64
+ // CHECK: store i64 [[A_INTPTR]], i64* [[AFFS_0_BASE_ADDR]],
+
+ // affs[0].size = sizeof(a);
+ // CHECK: [[AFFS_0_SIZE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_0_ADDR]], i32 0, i32 1
+ // CHECK: store i64 4, i64* [[AFFS_0_SIZE_ADDR]],
+
+ // affs_cnt = 1;
+ // CHECK: store i64 1, i64* [[AFFS_CNT_ADDR:%.+]],
+ // CHECK: [[A_VAL:%.+]] = load i32, i32* [[A_ADDR]],
+ // CHECK: [[NITERS:%.+]] = sub nsw i32 [[A_VAL]], 0
+ // CHECK: store i32 0, i32* [[CNT_ADDR:%.+]],
+ // CHECK: br label %[[CONT:[^,]+]]
+
+ //for (int cnt = 0; cnt < (a-0); ++cnt) {
+ // int i = cnt + 0;
+ // affs[affs_cnt].base = &p[i];
+ // affs[affs_cnt].size = sizeof(p[i]);
+ // ++affs_cnt;
+ // }
+
+ // CHECK: [[CONT]]:
+ // CHECK: [[CNT:%.+]] = load i32, i32* [[CNT_ADDR]],
+ // CHECK: [[CMP:%.+]] = icmp slt i32 [[CNT]], [[NITERS]]
+ // CHECK: br i1 [[CMP]], label %[[BODY:[^,]+]], label %[[DONE:[^,]+]]
+
+ // CHECK: [[BODY]]:
+ // i = cnt + 0;
+ // CHECK: [[CNT:%.+]] = load i32, i32* [[CNT_ADDR]],
+ // CHECK: [[VAL:%.+]] = add nsw i32 0, [[CNT]]
+ // CHECK: store i32 [[VAL]], i32* [[I_ADDR:%.+]],
+
+ // &p[i]
+ // CHECK: [[P:%.+]] = load float*, float** [[P_ADDR]],
+ // CHECK: [[I:%.+]] = load i32, i32* [[I_ADDR]],
+ // CHECK: [[IDX:%.+]] = sext i32 [[I]] to i64
+ // CHECK: [[P_I_ADDR:%.+]] = getelementptr inbounds float, float* [[P]], i64 [[IDX]]
+
+ // affs[affs_cnt]
+ // CHECK: [[AFFS_CNT:%.+]] = load i64, i64* [[AFFS_CNT_ADDR]],
+ // CHECK: [[AFFS_ELEM_ADDR:%.+]] = getelementptr %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_ADDR]], i64 [[AFFS_CNT]]
+
+ // affs[affs_cnt].base = &p[i];
+ // CHECK: [[AFFS_ELEM_BASE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_ELEM_ADDR]], i32 0, i32 0
+ // CHECK: [[CAST:%.+]] = ptrtoint float* [[P_I_ADDR]] to i64
+ // CHECK: store i64 [[CAST]], i64* [[AFFS_ELEM_BASE_ADDR]],
+
+ // affs[affs_cnt].size = sizeof(p[i]);
+ // CHECK: [[AFFS_ELEM_SIZE_ADDR:%.+]] = getelementptr inbounds %struct.kmp_task_affinity_info_t, %struct.kmp_task_affinity_info_t* [[AFFS_ELEM_ADDR]], i32 0, i32 1
+ // CHECK: store i64 4, i64* [[AFFS_ELEM_SIZE_ADDR]],
+
+ // ++affs_cnt;
+ // CHECK: [[AFFS_CNT_NEXT:%.+]] = add nuw i64 [[AFFS_CNT]], 1
+ // CHECK: store i64 [[AFFS_CNT_NEXT]], i64* [[AFFS_CNT_ADDR]],
+
+ // ++cnt;
+ // CHECK: [[CNT:%.+]] = load i32, i32* [[CNT_ADDR]],
+ // CHECK: [[CNT_NEXT:%.+]] = add nsw i32 [[CNT]], 1
+ // CHECK: store i32 [[CNT_NEXT]], i32* [[CNT_ADDR]],
+ // CHECK: br label %[[CONT]]
+
+ // CHECK: [[DONE]]:
+ // CHECK: [[BC:%.+]] = bitcast %struct.kmp_task_affinity_info_t* [[AFFS_ADDR]] to i8*
+ // CHECK: call i32 @__kmpc_omp_reg_task_with_affinity(%struct.ident_t* @{{.+}} i32 [[GTID]], i8* [[TD]], i32 [[NAFFS]], i8* [[BC]])
+ // CHECK: [[SV:%.+]] = load i8*, i8** [[SV_ADDR]],
+ // CHECK: call void @llvm.stackrestore(i8* [[SV]])
+#pragma omp task affinity(iterator(i=0:a): p[i]) affinity(a)
+ ;
+ return 0;
+}
+
+#endif
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index 77f7648e47ad..2fa0c13e1408 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -336,6 +336,8 @@ __OMP_RTL(__kmpc_push_num_threads, false, Void, IdentPtr, Int32,
__OMP_RTL(__kmpc_push_proc_bind, false, Void, IdentPtr, Int32, /* Int */ Int32)
__OMP_RTL(__kmpc_serialized_parallel, false, Void, IdentPtr, Int32)
__OMP_RTL(__kmpc_end_serialized_parallel, false, Void, IdentPtr, Int32)
+__OMP_RTL(__kmpc_omp_reg_task_with_affinity, false, Int32, IdentPtr, Int32,
+ Int8Ptr, Int32, Int8Ptr)
__OMP_RTL(omp_get_thread_num, false, Int32, )
__OMP_RTL(omp_get_num_threads, false, Int32, )
More information about the cfe-commits
mailing list