@@ -387,6 +387,20 @@ class OpenACCClauseCIREmitter final
387387 return recipeName;
388388 }
389389
390+ void createFirstprivateRecipeCopy (
391+ mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
392+ CIRGenFunction::AutoVarEmission tempDeclEmission,
393+ mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
394+ const VarDecl *temporary) {
395+ builder.createBlock (&recipe.getCopyRegion (), recipe.getCopyRegion ().end (),
396+ {mainOp.getType (), mainOp.getType ()}, {loc, loc});
397+ builder.setInsertionPointToEnd (&recipe.getCopyRegion ().back ());
398+
399+ // TODO: OpenACC: Implement this copy to actually do something.
400+
401+ mlir::acc::YieldOp::create (builder, locEnd);
402+ }
403+
390404 // Create the 'init' section of the recipe, including the 'copy' section for
391405 // 'firstprivate'.
392406 template <typename RecipeTy>
@@ -401,12 +415,6 @@ class OpenACCClauseCIREmitter final
401415 cgf.cgm .errorNYI (exprRange, " OpenACC Reduction recipe init" );
402416 }
403417
404- if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
405- // We haven't implemented the 'init'/copy recipe for firstprivate yet, so
406- // NYI it.
407- cgf.cgm .errorNYI (exprRange, " OpenACC firstprivate recipe init" );
408- }
409-
410418 CIRGenFunction::AutoVarEmission tempDeclEmission{
411419 CIRGenFunction::AutoVarEmission::invalid ()};
412420
@@ -442,17 +450,12 @@ class OpenACCClauseCIREmitter final
442450 mlir::acc::YieldOp::create (builder, locEnd);
443451
444452 if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
445- if (!varRecipe->getInit ()) {
446- // If we don't have any initialization recipe, we failed during Sema to
447- // initialize this correctly. If we disable the
448- // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
449- // emit an error to tell us. However, emitting those errors during
450- // production is a violation of the standard, so we cannot do them.
451- cgf.cgm .errorNYI (
452- exprRange, " firstprivate copy-init recipe not properly generated" );
453- }
454-
455- cgf.cgm .errorNYI (exprRange, " firstprivate copy section generation" );
453+ // TODO: OpenACC: we should have a errorNYI call here if
454+ // !varRecipe->getInit(), but as that generation isn't currently
455+ // implemented, it ends up being too noisy. So when we implement copy-init
456+ // generation both in Sema and here, we should have a diagnostic here.
457+ createFirstprivateRecipeCopy (loc, locEnd, mainOp, tempDeclEmission,
458+ recipe, varRecipe, temporary);
456459 }
457460
458461 // Make sure we cleanup after ourselves here.
@@ -1155,6 +1158,43 @@ class OpenACCClauseCIREmitter final
11551158 llvm_unreachable (" Unknown construct kind in VisitPrivateClause" );
11561159 }
11571160 }
1161+
1162+ void VisitFirstPrivateClause (const OpenACCFirstPrivateClause &clause) {
1163+ if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp,
1164+ mlir::acc::SerialOp>) {
1165+ for (const auto [varExpr, varRecipe] :
1166+ llvm::zip_equal (clause.getVarList (), clause.getInitRecipes ())) {
1167+ CIRGenFunction::OpenACCDataOperandInfo opInfo =
1168+ cgf.getOpenACCDataOperandInfo (varExpr);
1169+ auto firstPrivateOp = mlir::acc::FirstprivateOp::create (
1170+ builder, opInfo.beginLoc , opInfo.varValue , /* structured=*/ true ,
1171+ /* implicit=*/ false , opInfo.name , opInfo.bounds );
1172+
1173+ firstPrivateOp.setDataClause (mlir::acc::DataClause::acc_firstprivate);
1174+
1175+ {
1176+ mlir::OpBuilder::InsertionGuard guardCase (builder);
1177+ auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
1178+ cgf.getContext (), varExpr, varRecipe.RecipeDecl ,
1179+ varRecipe.InitFromTemporary ,
1180+ Decl::castToDeclContext (cgf.curFuncDecl ), opInfo.baseType ,
1181+ firstPrivateOp.getResult ());
1182+
1183+ // TODO: OpenACC: The dialect is going to change in the near future to
1184+ // have these be on a different operation, so when that changes, we
1185+ // probably need to change these here.
1186+ operation.addFirstPrivatization (builder.getContext (), firstPrivateOp,
1187+ recipe);
1188+ }
1189+ }
1190+ } else if constexpr (isCombinedType<OpTy>) {
1191+ // Unlike 'private', 'firstprivate' applies to the compute op, not the
1192+ // loop op.
1193+ applyToComputeOp (clause);
1194+ } else {
1195+ llvm_unreachable (" Unknown construct kind in VisitFirstPrivateClause" );
1196+ }
1197+ }
11581198};
11591199
11601200template <typename OpTy>
0 commit comments