================ @@ -1794,37 +1909,118 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder, moduleTranslation, allocaIP); // Allocate and initialize private variables - // TODO: package private variables up in a structure builder.SetInsertPoint(initBlock->getTerminator()); - for (auto [privDecl, mlirPrivVar, blockArg] : - llvm::zip_equal(privateDecls, mlirPrivateVars, privateBlockArgs)) { - llvm::Type *llvmAllocType = - moduleTranslation.convertType(privDecl.getType()); - // Allocations: - builder.SetInsertPoint(allocaIP.getBlock()->getTerminator()); - llvm::Value *llvmPrivateVar = builder.CreateAlloca( - llvmAllocType, /*ArraySize=*/nullptr, "omp.private.alloc"); + // Create task variable structure + taskStructMgr.generateTaskContextStruct(); + // GEPs so that we can initialize the variables. Don't use these GEPs inside + // of the body otherwise it will be the GEP not the struct which is fowarded + // to the outlined function. GEPs forwarded in this way are passed in a + // stack-allocated (by OpenMPIRBuilder) structure which is not safe for tasks + // which may not be executed until after the current stack frame goes out of + // scope. + taskStructMgr.createGEPsToPrivateVars(); + + for (auto [privDecl, mlirPrivVar, blockArg, llvmPrivateVarAlloc] : + llvm::zip_equal(privateDecls, mlirPrivateVars, privateBlockArgs, + taskStructMgr.getLLVMPrivateVarGEPs())) { + if (!privDecl.readsFromMold()) + // to be handled inside the task + continue; + assert(llvmPrivateVarAlloc && + "reads from mold so shouldn't have been skipped"); - auto err = + llvm::Expected<llvm::Value *> privateVarOrErr = initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar, - blockArg, llvmPrivateVar, llvmPrivateVars, initBlock); - if (err) + blockArg, llvmPrivateVarAlloc, initBlock); + if (auto err = privateVarOrErr.takeError()) return handleError(std::move(err), *taskOp.getOperation()); + + llvm::IRBuilderBase::InsertPointGuard guard(builder); + builder.SetInsertPoint(builder.GetInsertBlock()->getTerminator()); + + // TODO: this is a bit of a hack for Fortran character boxes. + // Character boxes are passed by value into the init region and then the + // initialized character box is yielded by value. Here we need to store the + // yielded value into the private allocation, and load the private + // allocation to match the type expected by region block arguments. + if ((privateVarOrErr.get() != llvmPrivateVarAlloc) && + !mlir::isa<LLVM::LLVMPointerType>(blockArg.getType())) { + builder.CreateStore(privateVarOrErr.get(), llvmPrivateVarAlloc); + // Load it so we have the value pointed to by the GEP + llvmPrivateVarAlloc = builder.CreateLoad(privateVarOrErr.get()->getType(), + llvmPrivateVarAlloc); + } + assert(llvmPrivateVarAlloc->getType() == + moduleTranslation.convertType(blockArg.getType())); + + // Mapping blockArg -> llvmPrivateVarAlloc is done inside the body callback + // so that OpenMPIRBuilder doesn't try to pass each GEP address through a + // stack allocated structure. } // firstprivate copy region if (failed(initFirstPrivateVars(builder, moduleTranslation, mlirPrivateVars, - llvmPrivateVars, privateDecls, copyBlock))) + taskStructMgr.getLLVMPrivateVarGEPs(), + privateDecls, copyBlock))) return llvm::failure(); // Set up for call to createTask() builder.SetInsertPoint(taskStartBlock); auto bodyCB = [&](InsertPointTy allocaIP, InsertPointTy codegenIP) -> llvm::Error { + // Save the alloca insertion point on ModuleTranslation stack for use in + // nested regions. + LLVM::ModuleTranslation::SaveStack<OpenMPAllocaStackFrame> frame( + moduleTranslation, allocaIP); + // translate the body of the task: builder.restoreIP(codegenIP); + + llvm::BasicBlock *privInitBlock = nullptr; + for (auto [blockArg, privDecl, mlirPrivVar] : + llvm::zip_equal(privateBlockArgs, privateDecls, mlirPrivateVars)) { + if (privDecl.readsFromMold()) + // This is handled before the task executes + continue; + + auto codegenInsertionPt = builder.saveIP(); + llvm::Type *llvmAllocType = + moduleTranslation.convertType(privDecl.getType()); + builder.SetInsertPoint(allocaIP.getBlock()->getTerminator()); + llvm::Value *llvmPrivateVar = builder.CreateAlloca( + llvmAllocType, /*ArraySize=*/nullptr, "omp.private.alloc"); + + llvm::Expected<llvm::Value *> privateVarOrError = + initPrivateVar(builder, moduleTranslation, privDecl, mlirPrivVar, + blockArg, llvmPrivateVar, privInitBlock); + if (auto err = privateVarOrError.takeError()) + return err; ---------------- tblah wrote:
Thanks. Fixed in [459d2d5](https://github.com/llvm/llvm-project/pull/125307/commits/459d2d5ea7f803cc6553b7d9007283281263f1fe) 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