|
12 | 12 |
|
13 | 13 | #include <type_traits>
|
14 | 14 |
|
| 15 | +#include "CIRGenCXXABI.h" |
15 | 16 | #include "CIRGenFunction.h"
|
16 | 17 |
|
17 | 18 | #include "clang/AST/ExprCXX.h"
|
@@ -355,6 +356,110 @@ class OpenACCClauseCIREmitter final
|
355 | 356 | }
|
356 | 357 | }
|
357 | 358 |
|
| 359 | + template <typename RecipeTy> |
| 360 | + RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef, |
| 361 | + DeclContext *dc, QualType baseType, |
| 362 | + mlir::Value mainOp) { |
| 363 | + mlir::ModuleOp mod = |
| 364 | + builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>(); |
| 365 | + |
| 366 | + std::string recipeName; |
| 367 | + { |
| 368 | + llvm::raw_string_ostream stream(recipeName); |
| 369 | + if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) { |
| 370 | + stream << "privatization_"; |
| 371 | + } else if constexpr (std::is_same_v<RecipeTy, |
| 372 | + mlir::acc::FirstprivateRecipeOp>) { |
| 373 | + stream << "firstprivatization_"; |
| 374 | + |
| 375 | + } else if constexpr (std::is_same_v<RecipeTy, |
| 376 | + mlir::acc::ReductionRecipeOp>) { |
| 377 | + stream << "reduction_"; |
| 378 | + // We don't have the reduction operation here well enough to know how to |
| 379 | + // spell this correctly (+ == 'add', etc), so when we implement |
| 380 | + // 'reduction' we have to do that here. |
| 381 | + cgf.cgm.errorNYI(varRef->getSourceRange(), |
| 382 | + "OpeNACC reduction recipe creation"); |
| 383 | + } else { |
| 384 | + static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind"); |
| 385 | + } |
| 386 | + |
| 387 | + MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext(); |
| 388 | + mc.mangleCanonicalTypeName(baseType, stream); |
| 389 | + } |
| 390 | + |
| 391 | + if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName)) |
| 392 | + return recipe; |
| 393 | + |
| 394 | + mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc()); |
| 395 | + mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc()); |
| 396 | + |
| 397 | + mlir::OpBuilder modBuilder(mod.getBodyRegion()); |
| 398 | + auto recipe = |
| 399 | + RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType()); |
| 400 | + |
| 401 | + // Magic-up a var-decl so we can use normal init/destruction operations for |
| 402 | + // a variable declaration. |
| 403 | + VarDecl &tempDecl = *VarDecl::Create( |
| 404 | + astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(), |
| 405 | + &astCtx.Idents.get("openacc.private.init"), baseType, |
| 406 | + astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto); |
| 407 | + CIRGenFunction::AutoVarEmission tempDeclEmission{ |
| 408 | + CIRGenFunction::AutoVarEmission::invalid()}; |
| 409 | + |
| 410 | + // Init section. |
| 411 | + { |
| 412 | + llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()}; |
| 413 | + llvm::SmallVector<mlir::Location> argsLocs{loc}; |
| 414 | + builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(), |
| 415 | + argsTys, argsLocs); |
| 416 | + builder.setInsertionPointToEnd(&recipe.getInitRegion().back()); |
| 417 | + |
| 418 | + if constexpr (!std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) { |
| 419 | + // We have only implemented 'init' for private, so make this NYI until |
| 420 | + // we have explicitly implemented everything. |
| 421 | + cgf.cgm.errorNYI(varRef->getSourceRange(), |
| 422 | + "OpenACC non-private recipe init"); |
| 423 | + } |
| 424 | + |
| 425 | + tempDeclEmission = |
| 426 | + cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint()); |
| 427 | + cgf.emitAutoVarInit(tempDeclEmission); |
| 428 | + |
| 429 | + mlir::acc::YieldOp::create(builder, locEnd); |
| 430 | + } |
| 431 | + |
| 432 | + // Copy section. |
| 433 | + if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp> || |
| 434 | + std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) { |
| 435 | + // TODO: OpenACC: 'private' doesn't emit this, but for the other two we |
| 436 | + // have to figure out what 'copy' means here. |
| 437 | + cgf.cgm.errorNYI(varRef->getSourceRange(), |
| 438 | + "OpenACC record type privatization copy section"); |
| 439 | + } |
| 440 | + |
| 441 | + // Destroy section (doesn't currently exist). |
| 442 | + if (tempDecl.needsDestruction(cgf.getContext())) { |
| 443 | + llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()}; |
| 444 | + llvm::SmallVector<mlir::Location> argsLocs{loc}; |
| 445 | + mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(), |
| 446 | + recipe.getDestroyRegion().end(), |
| 447 | + argsTys, argsLocs); |
| 448 | + builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back()); |
| 449 | + |
| 450 | + mlir::Type elementTy = |
| 451 | + mlir::cast<cir::PointerType>(mainOp.getType()).getPointee(); |
| 452 | + Address addr{block->getArgument(0), elementTy, |
| 453 | + cgf.getContext().getDeclAlign(&tempDecl)}; |
| 454 | + cgf.emitDestroy(addr, baseType, |
| 455 | + cgf.getDestroyer(QualType::DK_cxx_destructor)); |
| 456 | + |
| 457 | + mlir::acc::YieldOp::create(builder, locEnd); |
| 458 | + } |
| 459 | + |
| 460 | + return recipe; |
| 461 | + } |
| 462 | + |
358 | 463 | public:
|
359 | 464 | OpenACCClauseCIREmitter(OpTy &operation, CIRGen::CIRGenFunction &cgf,
|
360 | 465 | CIRGen::CIRGenBuilderTy &builder,
|
@@ -971,6 +1076,37 @@ class OpenACCClauseCIREmitter final
|
971 | 1076 | llvm_unreachable("Unknown construct kind in VisitAttachClause");
|
972 | 1077 | }
|
973 | 1078 | }
|
| 1079 | + |
| 1080 | + void VisitPrivateClause(const OpenACCPrivateClause &clause) { |
| 1081 | + if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp, |
| 1082 | + mlir::acc::LoopOp>) { |
| 1083 | + for (const Expr *var : clause.getVarList()) { |
| 1084 | + CIRGenFunction::OpenACCDataOperandInfo opInfo = |
| 1085 | + cgf.getOpenACCDataOperandInfo(var); |
| 1086 | + auto privateOp = mlir::acc::PrivateOp::create( |
| 1087 | + builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true, |
| 1088 | + /*implicit=*/false, opInfo.name, opInfo.bounds); |
| 1089 | + privateOp.setDataClause(mlir::acc::DataClause::acc_private); |
| 1090 | + |
| 1091 | + { |
| 1092 | + mlir::OpBuilder::InsertionGuard guardCase(builder); |
| 1093 | + auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>( |
| 1094 | + cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl), |
| 1095 | + opInfo.baseType, privateOp.getResult()); |
| 1096 | + // TODO: OpenACC: The dialect is going to change in the near future to |
| 1097 | + // have these be on a different operation, so when that changes, we |
| 1098 | + // probably need to change these here. |
| 1099 | + operation.addPrivatization(builder.getContext(), privateOp, recipe); |
| 1100 | + } |
| 1101 | + } |
| 1102 | + } else if constexpr (isCombinedType<OpTy>) { |
| 1103 | + // Despite this being valid on ParallelOp or SerialOp, combined type |
| 1104 | + // applies to the 'loop'. |
| 1105 | + applyToLoopOp(clause); |
| 1106 | + } else { |
| 1107 | + llvm_unreachable("Unknown construct kind in VisitPrivateClause"); |
| 1108 | + } |
| 1109 | + } |
974 | 1110 | };
|
975 | 1111 |
|
976 | 1112 | template <typename OpTy>
|
|
0 commit comments