[llvm-branch-commits] [flang] [mlir] [mlir][OpenMP] Pack task private variables into a heap-allocated context struct (PR #125307)
Pranav Bhandarkar via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Feb 5 14:06:12 PST 2025
================
@@ -1730,6 +1730,119 @@ buildDependData(std::optional<ArrayAttr> dependKinds, OperandRange dependVars,
}
}
+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. 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();
+
+ /// De-allocate the task context structure.
+ void freeStructPtr();
+
+ MutableArrayRef<llvm::Value *> getLLVMPrivateVars() {
+ return llvmPrivateVars;
+ }
+
+ 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;
+
+ /// LLVM values for each private variable, or null if that private variable is
+ /// not included in the task context structure
+ SmallVector<llvm::Value *> llvmPrivateVars;
+
+ /// 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 (!privOp.readsFromMold())
+ 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() {
+ if (!structPtr) {
+ assert(privateVarTypes.empty());
+ return;
+ }
+
+ // Create GEPs for each struct member and initialize llvmPrivateVars to point
+ llvmPrivateVars.clear();
+ llvmPrivateVars.reserve(privateVarTypes.size());
----------------
bhandarkar-pranav wrote:
Since we store `nullptr` for private decls that dont read from the mold argument, we might as well reserve `privateDecls.size()`
https://github.com/llvm/llvm-project/pull/125307
More information about the llvm-branch-commits
mailing list