[OPENMP] Simplified interface for codegen of tasks, NFC.

Reduced number of arguments in member functions of runtime support
library for task-based directives.

llvm-svn: 267863
This commit is contained in:
Alexey Bataev 2016-04-28 09:23:51 +00:00
parent 2b19a6fe53
commit 24b5baed27
4 changed files with 144 additions and 245 deletions

View File

@ -3361,20 +3361,16 @@ static int array_pod_sort_comparator(const PrivateDataTy *P1,
return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0);
} }
CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit( CGOpenMPRuntime::TaskResultTy
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, const OMPExecutableDirective &D,
unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *TaskFunction, QualType SharedsTy,
Address Shareds, ArrayRef<const Expr *> PrivateVars, Address Shareds, const OMPTaskDataTy &Data) {
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits) {
auto &C = CGM.getContext(); auto &C = CGM.getContext();
llvm::SmallVector<PrivateDataTy, 4> Privates; llvm::SmallVector<PrivateDataTy, 4> Privates;
// Aggregate privates and sort them by the alignment. // Aggregate privates and sort them by the alignment.
auto I = PrivateCopies.begin(); auto I = Data.PrivateCopies.begin();
for (auto *E : PrivateVars) { for (auto *E : Data.PrivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Privates.push_back(std::make_pair( Privates.push_back(std::make_pair(
C.getDeclAlign(VD), C.getDeclAlign(VD),
@ -3382,9 +3378,9 @@ CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
/*PrivateElemInit=*/nullptr))); /*PrivateElemInit=*/nullptr)));
++I; ++I;
} }
I = FirstprivateCopies.begin(); I = Data.FirstprivateCopies.begin();
auto IElemInitRef = FirstprivateInits.begin(); auto IElemInitRef = Data.FirstprivateInits.begin();
for (auto *E : FirstprivateVars) { for (auto *E : Data.FirstprivateVars) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Privates.push_back(std::make_pair( Privates.push_back(std::make_pair(
C.getDeclAlign(VD), C.getDeclAlign(VD),
@ -3424,8 +3420,9 @@ CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
->getType(); ->getType();
if (!Privates.empty()) { if (!Privates.empty()) {
auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
TaskPrivatesMap = emitTaskPrivateMappingFunction( TaskPrivatesMap = emitTaskPrivateMappingFunction(CGM, Loc, Data.PrivateVars,
CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates); Data.FirstprivateVars,
FI->getType(), Privates);
TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
TaskPrivatesMap, TaskPrivatesMapTy); TaskPrivatesMap, TaskPrivatesMapTy);
} else { } else {
@ -3447,13 +3444,13 @@ CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
// description of kmp_tasking_flags struct. // description of kmp_tasking_flags struct.
const unsigned TiedFlag = 0x1; const unsigned TiedFlag = 0x1;
const unsigned FinalFlag = 0x2; const unsigned FinalFlag = 0x2;
unsigned Flags = Tied ? TiedFlag : 0; unsigned Flags = Data.Tied ? TiedFlag : 0;
auto *TaskFlags = auto *TaskFlags =
Final.getPointer() Data.Final.getPointer()
? CGF.Builder.CreateSelect(Final.getPointer(), ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
CGF.Builder.getInt32(FinalFlag), CGF.Builder.getInt32(FinalFlag),
CGF.Builder.getInt32(/*C=*/0)) CGF.Builder.getInt32(/*C=*/0))
: CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0); : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
@ -3489,7 +3486,7 @@ CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
auto PrivatesBase = CGF.EmitLValueForField(Base, *FI); auto PrivatesBase = CGF.EmitLValueForField(Base, *FI);
FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
LValue SharedsBase; LValue SharedsBase;
if (!FirstprivateVars.empty()) { if (!Data.FirstprivateVars.empty()) {
SharedsBase = CGF.MakeAddrLValue( SharedsBase = CGF.MakeAddrLValue(
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
@ -3569,41 +3566,35 @@ CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit(
CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
DestructorFn, KmpRoutineEntryPtrTy), DestructorFn, KmpRoutineEntryPtrTy),
Destructor); Destructor);
TaskDataTy Data; TaskResultTy Result;
Data.NewTask = NewTask; Result.NewTask = NewTask;
Data.TaskEntry = TaskEntry; Result.TaskEntry = TaskEntry;
Data.NewTaskNewTaskTTy = NewTaskNewTaskTTy; Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
Data.TDBase = TDBase; Result.TDBase = TDBase;
Data.KmpTaskTQTyRD = KmpTaskTQTyRD; Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
return Data; return Result;
} }
void CGOpenMPRuntime::emitTaskCall( void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, const OMPExecutableDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, llvm::Value *TaskFunction,
unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, QualType SharedsTy, Address Shareds,
Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, const Expr *IfCond,
ArrayRef<const Expr *> PrivateCopies, const OMPTaskDataTy &Data) {
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits,
ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) {
if (!CGF.HaveInsertPoint()) if (!CGF.HaveInsertPoint())
return; return;
TaskDataTy Data = TaskResultTy Result =
emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction, emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
SharedsTy, Shareds, PrivateVars, PrivateCopies, llvm::Value *NewTask = Result.NewTask;
FirstprivateVars, FirstprivateCopies, FirstprivateInits); llvm::Value *TaskEntry = Result.TaskEntry;
llvm::Value *NewTask = Data.NewTask; llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
llvm::Value *TaskEntry = Data.TaskEntry; LValue TDBase = Result.TDBase;
llvm::Value *NewTaskNewTaskTTy = Data.NewTaskNewTaskTTy; RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
LValue TDBase = Data.TDBase;
RecordDecl *KmpTaskTQTyRD = Data.KmpTaskTQTyRD;
auto &C = CGM.getContext(); auto &C = CGM.getContext();
// Process list of dependences. // Process list of dependences.
Address DependenciesArray = Address::invalid(); Address DependenciesArray = Address::invalid();
unsigned NumDependencies = Dependences.size(); unsigned NumDependencies = Data.Dependences.size();
if (NumDependencies) { if (NumDependencies) {
// Dependence kind for RTL. // Dependence kind for RTL.
enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 }; enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 };
@ -3620,9 +3611,8 @@ void CGOpenMPRuntime::emitTaskCall(
addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
KmpDependInfoRD->completeDefinition(); KmpDependInfoRD->completeDefinition();
KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
} else { } else
KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
}
CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy); CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy);
// Define type kmp_depend_info[<Dependences.size()>]; // Define type kmp_depend_info[<Dependences.size()>];
QualType KmpDependInfoArrayTy = C.getConstantArrayType( QualType KmpDependInfoArrayTy = C.getConstantArrayType(
@ -3632,7 +3622,7 @@ void CGOpenMPRuntime::emitTaskCall(
DependenciesArray = DependenciesArray =
CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
for (unsigned i = 0; i < NumDependencies; ++i) { for (unsigned i = 0; i < NumDependencies; ++i) {
const Expr *E = Dependences[i].second; const Expr *E = Data.Dependences[i].second;
auto Addr = CGF.EmitLValue(E); auto Addr = CGF.EmitLValue(E);
llvm::Value *Size; llvm::Value *Size;
QualType Ty = E->getType(); QualType Ty = E->getType();
@ -3662,7 +3652,7 @@ void CGOpenMPRuntime::emitTaskCall(
CGF.EmitStoreOfScalar(Size, LenLVal); CGF.EmitStoreOfScalar(Size, LenLVal);
// deps[i].flags = <Dependences[i].first>; // deps[i].flags = <Dependences[i].first>;
RTLDependenceKindTy DepKind; RTLDependenceKindTy DepKind;
switch (Dependences[i].first) { switch (Data.Dependences[i].first) {
case OMPC_DEPEND_in: case OMPC_DEPEND_in:
DepKind = DepIn; DepKind = DepIn;
break; break;
@ -3705,10 +3695,10 @@ void CGOpenMPRuntime::emitTaskCall(
DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[5] = CGF.Builder.getInt32(0);
DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
} }
auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD, auto &&ThenCodeGen = [this, Loc, &Data, TDBase, KmpTaskTQTyRD,
NumDependencies, &TaskArgs, NumDependencies, &TaskArgs,
&DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
if (!Tied) { if (!Data.Tied) {
auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
@ -3775,22 +3765,16 @@ void CGOpenMPRuntime::emitTaskCall(
} }
} }
void CGOpenMPRuntime::emitTaskLoopCall( void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, const OMPLoopDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, llvm::Value *TaskFunction,
llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule, bool Nogroup, QualType SharedsTy, Address Shareds,
unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, const Expr *IfCond,
Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, const OMPTaskDataTy &Data) {
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits) {
if (!CGF.HaveInsertPoint()) if (!CGF.HaveInsertPoint())
return; return;
TaskDataTy Data = TaskResultTy Result =
emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction, emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
SharedsTy, Shareds, PrivateVars, PrivateCopies,
FirstprivateVars, FirstprivateCopies, FirstprivateInits);
// NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc()
// libcall. // libcall.
// Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
@ -3806,37 +3790,37 @@ void CGOpenMPRuntime::emitTaskLoopCall(
IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
LValue LBLVal = CGF.EmitLValueForField( LValue LBLVal = CGF.EmitLValueForField(
Data.TDBase, Result.TDBase,
*std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
auto *LBVar = auto *LBVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
/*IsInitializer=*/true); /*IsInitializer=*/true);
LValue UBLVal = CGF.EmitLValueForField( LValue UBLVal = CGF.EmitLValueForField(
Data.TDBase, Result.TDBase,
*std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
auto *UBVar = auto *UBVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
/*IsInitializer=*/true); /*IsInitializer=*/true);
LValue StLVal = CGF.EmitLValueForField( LValue StLVal = CGF.EmitLValueForField(
Data.TDBase, Result.TDBase,
*std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
auto *StVar = auto *StVar =
cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
/*IsInitializer=*/true); /*IsInitializer=*/true);
enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
llvm::Value *TaskArgs[] = { llvm::Value *TaskArgs[] = {
UpLoc, ThreadID, Data.NewTask, IfVal, LBLVal.getPointer(), UpLoc, ThreadID, Result.NewTask, IfVal, LBLVal.getPointer(),
UBLVal.getPointer(), CGF.EmitLoadOfScalar(StLVal, SourceLocation()), UBLVal.getPointer(), CGF.EmitLoadOfScalar(StLVal, SourceLocation()),
llvm::ConstantInt::getSigned(CGF.IntTy, Nogroup ? 1 : 0), llvm::ConstantInt::getSigned(CGF.IntTy, Data.Nogroup ? 1 : 0),
llvm::ConstantInt::getSigned( llvm::ConstantInt::getSigned(
CGF.IntTy, Schedule.getPointer() CGF.IntTy, Data.Schedule.getPointer()
? Schedule.getInt() ? NumTasks : Grainsize ? Data.Schedule.getInt() ? NumTasks : Grainsize
: NoSchedule), : NoSchedule),
Schedule.getPointer() Data.Schedule.getPointer()
? CGF.Builder.CreateIntCast(Schedule.getPointer(), CGF.Int64Ty, ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
/*isSigned=*/false) /*isSigned=*/false)
: llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};

View File

@ -87,6 +87,20 @@ public:
void operator()(CodeGenFunction &CGF) const; void operator()(CodeGenFunction &CGF) const;
}; };
struct OMPTaskDataTy final {
SmallVector<const Expr *, 4> PrivateVars;
SmallVector<const Expr *, 4> PrivateCopies;
SmallVector<const Expr *, 4> FirstprivateVars;
SmallVector<const Expr *, 4> FirstprivateCopies;
SmallVector<const Expr *, 4> FirstprivateInits;
SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4> Dependences;
llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule;
unsigned NumberOfParts = 0;
bool Tied = true;
bool Nogroup = false;
};
class CGOpenMPRuntime { class CGOpenMPRuntime {
protected: protected:
CodeGenModule &CGM; CodeGenModule &CGM;
@ -433,12 +447,12 @@ private:
/// ///
llvm::Value *getCriticalRegionLock(StringRef CriticalName); llvm::Value *getCriticalRegionLock(StringRef CriticalName);
struct TaskDataTy { struct TaskResultTy {
llvm::Value *NewTask; llvm::Value *NewTask = nullptr;
llvm::Value *TaskEntry; llvm::Value *TaskEntry = nullptr;
llvm::Value *NewTaskNewTaskTTy; llvm::Value *NewTaskNewTaskTTy = nullptr;
LValue TDBase; LValue TDBase;
RecordDecl *KmpTaskTQTyRD; RecordDecl *KmpTaskTQTyRD = nullptr;
}; };
/// Emit task region for the task directive. The task region is emitted in /// Emit task region for the task directive. The task region is emitted in
/// several steps: /// several steps:
@ -455,39 +469,17 @@ private:
/// 3. Copy a pointer to destructions function to field destructions of the /// 3. Copy a pointer to destructions function to field destructions of the
/// resulting structure kmp_task_t. /// resulting structure kmp_task_t.
/// \param D Current task directive. /// \param D Current task directive.
/// \param Tied true if the task is tied (the task is tied to the thread that
/// can suspend its task region), false - untied (the task is not tied to any
/// thread).
/// \param Final Contains either constant bool value, or llvm::Value * of i1
/// type for final clause. If the value is true, the task forces all of its
/// child tasks to become final and included tasks.
/// \param NumberOfParts Number of parts in untied tasks.
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
/// /*part_id*/, captured_struct */*__context*/); /// /*part_id*/, captured_struct */*__context*/);
/// \param SharedsTy A type which contains references the shared variables. /// \param SharedsTy A type which contains references the shared variables.
/// \param Shareds Context with the list of shared variables from the \p /// \param Shareds Context with the list of shared variables from the \p
/// TaskFunction. /// TaskFunction.
/// \param PrivateVars List of references to private variables for the task /// \param Data Additional data for task generation like tiednsee, final
/// directive. /// state, list of privates etc.
/// \param PrivateCopies List of private copies for each private variable in TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
/// \p PrivateVars. const OMPExecutableDirective &D,
/// \param FirstprivateVars List of references to private variables for the llvm::Value *TaskFunction, QualType SharedsTy,
/// task directive. Address Shareds, const OMPTaskDataTy &Data);
/// \param FirstprivateCopies List of private copies for each private variable
/// in \p FirstprivateVars.
/// \param FirstprivateInits List of references to auto generated variables
/// used for initialization of a single array element. Used if firstprivate
/// variable is of array type.
TaskDataTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
const OMPExecutableDirective &D, bool Tied,
llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
unsigned NumberOfParts, llvm::Value *TaskFunction,
QualType SharedsTy, Address Shareds,
ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits);
public: public:
explicit CGOpenMPRuntime(CodeGenModule &CGM); explicit CGOpenMPRuntime(CodeGenModule &CGM);
@ -794,13 +786,6 @@ public:
/// kmp_task_t *new_task), where new_task is a resulting structure from /// kmp_task_t *new_task), where new_task is a resulting structure from
/// previous items. /// previous items.
/// \param D Current task directive. /// \param D Current task directive.
/// \param Tied true if the task is tied (the task is tied to the thread that
/// can suspend its task region), false - untied (the task is not tied to any
/// thread).
/// \param NumberOfParts Number of parts for untied task.
/// \param Final Contains either constant bool value, or llvm::Value * of i1
/// type for final clause. If the value is true, the task forces all of its
/// child tasks to become final and included tasks.
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
/// /*part_id*/, captured_struct */*__context*/); /// /*part_id*/, captured_struct */*__context*/);
/// \param SharedsTy A type which contains references the shared variables. /// \param SharedsTy A type which contains references the shared variables.
@ -808,29 +793,13 @@ public:
/// TaskFunction. /// TaskFunction.
/// \param IfCond Not a nullptr if 'if' clause was specified, nullptr /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
/// otherwise. /// otherwise.
/// \param PrivateVars List of references to private variables for the task /// \param Data Additional data for task generation like tiednsee, final
/// directive. /// state, list of privates etc.
/// \param PrivateCopies List of private copies for each private variable in virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
/// \p PrivateVars. const OMPExecutableDirective &D,
/// \param FirstprivateVars List of references to private variables for the llvm::Value *TaskFunction, QualType SharedsTy,
/// task directive. Address Shareds, const Expr *IfCond,
/// \param FirstprivateCopies List of private copies for each private variable const OMPTaskDataTy &Data);
/// in \p FirstprivateVars.
/// \param FirstprivateInits List of references to auto generated variables
/// used for initialization of a single array element. Used if firstprivate
/// variable is of array type.
/// \param Dependences List of dependences for the 'task' construct, including
/// original expression and dependency type.
virtual void emitTaskCall(
CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final,
unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits,
ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences);
/// Emit task region for the taskloop directive. The taskloop region is /// Emit task region for the taskloop directive. The taskloop region is
/// emitted in several steps: /// emitted in several steps:
@ -852,17 +821,6 @@ public:
/// is a resulting structure from /// is a resulting structure from
/// previous items. /// previous items.
/// \param D Current task directive. /// \param D Current task directive.
/// \param Tied true if the task is tied (the task is tied to the thread that
/// can suspend its task region), false - untied (the task is not tied to any
/// thread).
/// \param Final Contains either constant bool value, or llvm::Value * of i1
/// type for final clause. If the value is true, the task forces all of its
/// child tasks to become final and included tasks.
/// \param Schedule If Pointer is nullptr, no grainsize/num_tasks clauses were
/// specified. If IntVal is false - it is for grainsize clause, true - for
/// num_tasks clause.
/// \param Nogroup true if nogroup clause was specified, false otherwise.
/// \param NumberOfParts Number of parts in untied taskloops.
/// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32 /// \param TaskFunction An LLVM function with type void (*)(i32 /*gtid*/, i32
/// /*part_id*/, captured_struct */*__context*/); /// /*part_id*/, captured_struct */*__context*/);
/// \param SharedsTy A type which contains references the shared variables. /// \param SharedsTy A type which contains references the shared variables.
@ -870,27 +828,12 @@ public:
/// TaskFunction. /// TaskFunction.
/// \param IfCond Not a nullptr if 'if' clause was specified, nullptr /// \param IfCond Not a nullptr if 'if' clause was specified, nullptr
/// otherwise. /// otherwise.
/// \param PrivateVars List of references to private variables for the task /// \param Data Additional data for task generation like tiednsee, final
/// directive. /// state, list of privates etc.
/// \param PrivateCopies List of private copies for each private variable in
/// \p PrivateVars.
/// \param FirstprivateVars List of references to private variables for the
/// task directive.
/// \param FirstprivateCopies List of private copies for each private variable
/// in \p FirstprivateVars.
/// \param FirstprivateInits List of references to auto generated variables
/// used for initialization of a single array element. Used if firstprivate
/// variable is of array type.
virtual void emitTaskLoopCall( virtual void emitTaskLoopCall(
CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, llvm::Value *TaskFunction, QualType SharedsTy, Address Shareds,
llvm::PointerIntPair<llvm::Value *, 1, bool> Schedule, bool Nogroup, const Expr *IfCond, const OMPTaskDataTy &Data);
unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy,
Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars,
ArrayRef<const Expr *> PrivateCopies,
ArrayRef<const Expr *> FirstprivateVars,
ArrayRef<const Expr *> FirstprivateCopies,
ArrayRef<const Expr *> FirstprivateInits);
/// \brief Emit code for the directive that does not require outlining. /// \brief Emit code for the directive that does not require outlining.
/// ///

View File

@ -2312,18 +2312,30 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective(
void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
const RegionCodeGenTy &BodyGen, const RegionCodeGenTy &BodyGen,
const TaskGenTy &TaskGen, const TaskGenTy &TaskGen,
bool Tied) { OMPTaskDataTy &Data) {
// Emit outlined function for task construct. // Emit outlined function for task construct.
auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
auto *I = CS->getCapturedDecl()->param_begin(); auto *I = CS->getCapturedDecl()->param_begin();
auto *PartId = std::next(I); auto *PartId = std::next(I);
auto *TaskT = std::next(I, 4); auto *TaskT = std::next(I, 4);
// Check if the task is final
if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
auto *Cond = Clause->getCondition();
bool CondConstant;
if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
Data.Final.setInt(CondConstant);
else
Data.Final.setPointer(EvaluateExprAsBool(Cond));
} else {
// By default the task is not final.
Data.Final.setInt(/*IntVal=*/false);
}
// The first function argument for tasks is a thread id, the second one is a // The first function argument for tasks is a thread id, the second one is a
// part id (0 for tied tasks, >=0 for untied task). // part id (0 for tied tasks, >=0 for untied task).
llvm::DenseSet<const VarDecl *> EmittedAsPrivate; llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
// Get list of private variables. // Get list of private variables.
OMPPrivateDataTy Data;
Data.Tied = Tied;
for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
auto IRef = C->varlist_begin(); auto IRef = C->varlist_begin();
for (auto *IInit : C->private_copies()) { for (auto *IInit : C->private_copies()) {
@ -2406,23 +2418,6 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
// Emit outlined function for task construct. // Emit outlined function for task construct.
auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
auto CapturedStruct = GenerateCapturedStmtArgument(*CS); auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
// Check if we should emit tied or untied task.
bool Tied = !S.getSingleClause<OMPUntiedClause>();
// Check if the task is final
llvm::PointerIntPair<llvm::Value *, 1, bool> Final;
if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
auto *Cond = Clause->getCondition();
bool CondConstant;
if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
Final.setInt(CondConstant);
else
Final.setPointer(EvaluateExprAsBool(Cond));
} else {
// By default the task is not final.
Final.setInt(/*IntVal=*/false);
}
auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
const Expr *IfCond = nullptr; const Expr *IfCond = nullptr;
for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
@ -2433,19 +2428,20 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
} }
} }
OMPTaskDataTy Data;
// Check if we should emit tied or untied task.
Data.Tied = !S.getSingleClause<OMPUntiedClause>();
auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) { auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
CGF.EmitStmt(CS->getCapturedStmt()); CGF.EmitStmt(CS->getCapturedStmt());
}; };
auto &&TaskGen = [&S, &Final, SharedsTy, CapturedStruct, auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn, IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
const OMPPrivateDataTy &Data) { const OMPTaskDataTy &Data) {
CGF.CGM.getOpenMPRuntime().emitTaskCall( CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getLocStart(), S, OutlinedFn,
CGF, S.getLocStart(), S, Data.Tied, Final, Data.NumberOfParts, SharedsTy, CapturedStruct, IfCond,
OutlinedFn, SharedsTy, CapturedStruct, IfCond, Data.PrivateVars, Data);
Data.PrivateCopies, Data.FirstprivateVars, Data.FirstprivateCopies,
Data.FirstprivateInits, Data.Dependences);
}; };
EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Tied); EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
} }
void CodeGenFunction::EmitOMPTaskyieldDirective( void CodeGenFunction::EmitOMPTaskyieldDirective(
@ -3345,34 +3341,21 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
break; break;
} }
} }
bool Nogroup = S.getSingleClause<OMPNogroupClause>();
OMPTaskDataTy Data;
// Check if taskloop must be emitted without taskgroup.
Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
// TODO: Check if we should emit tied or untied task. // TODO: Check if we should emit tied or untied task.
// Check if the task is final Data.Tied = true;
llvm::PointerIntPair<llvm::Value *, 1, bool> Final; // Set scheduling for taskloop
if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
auto *Cond = Clause->getCondition();
bool CondConstant;
if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
Final.setInt(CondConstant);
else
Final.setPointer(EvaluateExprAsBool(Cond));
} else {
// By default the task is not final.
Final.setInt(/*IntVal=*/false);
}
llvm::PointerIntPair<llvm::Value * /*no grainsize/num_tasks=nullptr*/, 1,
bool /*Grainsize=false, NumTasks=true*/>
Schedule;
if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) { if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) {
// grainsize clause // grainsize clause
Schedule.setInt(/*IntVal=*/false); Data.Schedule.setInt(/*IntVal=*/false);
Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize())); Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
} else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) { } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) {
// num_tasks clause // num_tasks clause
Schedule.setInt(/*IntVal=*/true); Data.Schedule.setInt(/*IntVal=*/true);
Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks())); Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
} }
auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) { auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
@ -3445,21 +3428,19 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
CGF.EmitBlock(ContBlock, true); CGF.EmitBlock(ContBlock, true);
} }
}; };
auto &&TaskGen = [&S, SharedsTy, CapturedStruct, IfCond, &Final, &Schedule, auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
Nogroup](CodeGenFunction &CGF, llvm::Value *OutlinedFn, IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn,
const OMPPrivateDataTy &Data) { const OMPTaskDataTy &Data) {
auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &) { auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &) {
OMPLoopScope PreInitScope(CGF, S); OMPLoopScope PreInitScope(CGF, S);
CGF.CGM.getOpenMPRuntime().emitTaskLoopCall( CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getLocStart(), S,
CGF, S.getLocStart(), S, Data.Tied, Final, Schedule, Nogroup, OutlinedFn, SharedsTy,
Data.NumberOfParts, OutlinedFn, SharedsTy, CapturedStruct, IfCond, CapturedStruct, IfCond, Data);
Data.PrivateVars, Data.PrivateCopies, Data.FirstprivateVars,
Data.FirstprivateCopies, Data.FirstprivateInits);
}; };
CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop, CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
CodeGen); CodeGen);
}; };
EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, /*Tied=*/true); EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data);
} }
void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {

View File

@ -87,6 +87,7 @@ class BlockFlags;
class BlockFieldFlags; class BlockFieldFlags;
class RegionCodeGenTy; class RegionCodeGenTy;
class TargetCodeGenInfo; class TargetCodeGenInfo;
struct OMPTaskDataTy;
/// The kind of evaluation to perform on values of a particular /// The kind of evaluation to perform on values of a particular
/// type. Basically, is the code in CGExprScalar, CGExprComplex, or /// type. Basically, is the code in CGExprScalar, CGExprComplex, or
@ -2346,23 +2347,13 @@ public:
/// \param D Directive (possibly) with the 'linear' clause. /// \param D Directive (possibly) with the 'linear' clause.
void EmitOMPLinearClauseInit(const OMPLoopDirective &D); void EmitOMPLinearClauseInit(const OMPLoopDirective &D);
struct OMPPrivateDataTy {
bool Tied;
unsigned NumberOfParts;
SmallVector<const Expr *, 4> PrivateVars;
SmallVector<const Expr *, 4> PrivateCopies;
SmallVector<const Expr *, 4> FirstprivateVars;
SmallVector<const Expr *, 4> FirstprivateCopies;
SmallVector<const Expr *, 4> FirstprivateInits;
SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4> Dependences;
};
typedef const llvm::function_ref<void(CodeGenFunction & /*CGF*/, typedef const llvm::function_ref<void(CodeGenFunction & /*CGF*/,
llvm::Value * /*OutlinedFn*/, llvm::Value * /*OutlinedFn*/,
const OMPPrivateDataTy & /*Data*/)> const OMPTaskDataTy & /*Data*/)>
TaskGenTy; TaskGenTy;
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
const RegionCodeGenTy &BodyGen, const RegionCodeGenTy &BodyGen,
const TaskGenTy &TaskGen, bool Tied); const TaskGenTy &TaskGen, OMPTaskDataTy &Data);
void EmitOMPParallelDirective(const OMPParallelDirective &S); void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S); void EmitOMPSimdDirective(const OMPSimdDirective &S);