================ @@ -1730,6 +1730,126 @@ buildDependData(std::optional<ArrayAttr> dependKinds, OperandRange dependVars, } } +static bool privatizerReadsSourceVariable(omp::PrivateClauseOp &priv) { + if (priv.getDataSharingType() == omp::DataSharingClauseType::FirstPrivate) + return true; + + Region &initRegion = priv.getInitRegion(); + if (initRegion.empty()) + return false; + + BlockArgument sourceVariable = priv.getInitMoldArg(); + if (!sourceVariable) + return false; + return !sourceVariable.use_empty(); +} + +namespace { +/// TaskContextStructManager takes care of creating and freeing a structure +/// containing information needed by the task body to execute. +class TaskContextStructManager { +public: + TaskContextStructManager(llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation, + MutableArrayRef<omp::PrivateClauseOp> privateDecls) + : builder{builder}, moduleTranslation{moduleTranslation}, + privateDecls{privateDecls} {} + + /// Creates a heap allocated struct containing space for each private + /// variable. Returns nullptr if there are is no struct needed. Invariant: + /// privateVarTypes, privateDecls, and the elements of the structure should + /// all have the same order (although privateDecls which do not read from the + /// mold argument are skipped). + void generateTaskContextStruct(); + + /// Create GEPs to access each member of the structure representing a private + /// variable, adding them to llvmPrivateVars. Null values are added where + /// private decls were skipped so that the ordering continues to match the + /// private decls. + void createGEPsToPrivateVars(SmallVectorImpl<llvm::Value *> &llvmPrivateVars); + + /// De-allocate the task context structure. + void freeStructPtr(); + + llvm::Value *getStructPtr() { return structPtr; } + +private: + llvm::IRBuilderBase &builder; + LLVM::ModuleTranslation &moduleTranslation; + MutableArrayRef<omp::PrivateClauseOp> privateDecls; + + /// The type of each member of the structure, in order. + SmallVector<llvm::Type *> privateVarTypes; + + /// A pointer to the structure containing context for this task. + llvm::Value *structPtr = nullptr; + /// The type of the structure + llvm::Type *structTy = nullptr; +}; +} // namespace + +void TaskContextStructManager::generateTaskContextStruct() { + if (privateDecls.empty()) + return; + privateVarTypes.reserve(privateDecls.size()); + + for (omp::PrivateClauseOp &privOp : privateDecls) { + // Skip private variables which can safely be allocated and initialised + // inside of the task + if (!privatizerReadsSourceVariable(privOp)) + continue; + Type mlirType = privOp.getType(); + privateVarTypes.push_back(moduleTranslation.convertType(mlirType)); + } + + structTy = llvm::StructType::get(moduleTranslation.getLLVMContext(), + privateVarTypes); + + llvm::DataLayout dataLayout = + builder.GetInsertBlock()->getModule()->getDataLayout(); + llvm::Type *intPtrTy = builder.getIntPtrTy(dataLayout); + llvm::Constant *allocSize = llvm::ConstantExpr::getSizeOf(structTy); + + // Heap allocate the structure + structPtr = builder.CreateMalloc(intPtrTy, structTy, allocSize, + /*ArraySize=*/nullptr, /*MallocF=*/nullptr, + "omp.task.context_ptr"); +} + +void TaskContextStructManager::createGEPsToPrivateVars( + SmallVectorImpl<llvm::Value *> &llvmPrivateVars) { + if (!structPtr) { + assert(privateVarTypes.empty()); + return; + } + + // Create GEPs for each struct member and initialize llvmPrivateVars to point ---------------- bhandarkar-pranav wrote:
Comment incomplete, perhaps? https://github.com/llvm/llvm-project/pull/125307 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits