summaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp257
1 files changed, 73 insertions, 184 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 4ad15e6922dd..9959cf6c1579 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -14,6 +14,7 @@
#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
+#include "CIRGenOpenACCRecipe.h"
#include "clang/AST/ExprCXX.h"
@@ -356,181 +357,6 @@ class OpenACCClauseCIREmitter final
}
}
- template <typename RecipeTy>
- std::string getRecipeName(SourceRange loc, QualType baseType) {
- std::string recipeName;
- {
- llvm::raw_string_ostream stream(recipeName);
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
- stream << "privatization_";
- } else if constexpr (std::is_same_v<RecipeTy,
- mlir::acc::FirstprivateRecipeOp>) {
- stream << "firstprivatization_";
-
- } else if constexpr (std::is_same_v<RecipeTy,
- mlir::acc::ReductionRecipeOp>) {
- stream << "reduction_";
- // TODO: OpenACC: once we have this part implemented, we can remove the
- // SourceRange `loc` variable from this function. We don't have the
- // reduction operation here well enough to know how to spell this
- // correctly (+ == 'add', etc), so when we implement 'reduction' we have
- // to do that here.
- cgf.cgm.errorNYI(loc, "OpenACC reduction recipe name creation");
- } else {
- static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
- }
-
- MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
- mc.mangleCanonicalTypeName(baseType, stream);
- }
- return recipeName;
- }
-
- void createFirstprivateRecipeCopy(
- mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
- CIRGenFunction::AutoVarEmission tempDeclEmission,
- mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
- const VarDecl *temporary) {
- mlir::Block *block = builder.createBlock(
- &recipe.getCopyRegion(), recipe.getCopyRegion().end(),
- {mainOp.getType(), mainOp.getType()}, {loc, loc});
- builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
-
- mlir::BlockArgument fromArg = block->getArgument(0);
- mlir::BlockArgument toArg = block->getArgument(1);
-
- mlir::Type elementTy =
- mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
-
- // Set the address of the emission to be the argument, so that we initialize
- // that instead of the variable in the other block.
- tempDeclEmission.setAllocatedAddress(
- Address{toArg, elementTy, cgf.getContext().getDeclAlign(varRecipe)});
- tempDeclEmission.EmittedAsOffload = true;
-
- CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, temporary};
- cgf.setAddrOfLocalVar(
- temporary,
- Address{fromArg, elementTy, cgf.getContext().getDeclAlign(varRecipe)});
-
- cgf.emitAutoVarInit(tempDeclEmission);
- mlir::acc::YieldOp::create(builder, locEnd);
- }
-
- // Create the 'init' section of the recipe, including the 'copy' section for
- // 'firstprivate'.
- template <typename RecipeTy>
- void createRecipeInitCopy(mlir::Location loc, mlir::Location locEnd,
- SourceRange exprRange, mlir::Value mainOp,
- RecipeTy recipe, const VarDecl *varRecipe,
- const VarDecl *temporary) {
- assert(varRecipe && "Required recipe variable not set?");
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- // We haven't implemented the 'init' recipe for Reduction yet, so NYI
- // it.
- cgf.cgm.errorNYI(exprRange, "OpenACC Reduction recipe init");
- }
-
- CIRGenFunction::AutoVarEmission tempDeclEmission{
- CIRGenFunction::AutoVarEmission::invalid()};
- CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, varRecipe};
-
- // Do the 'init' section of the recipe IR, which does an alloca, then the
- // initialization (except for firstprivate).
- builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
- {mainOp.getType()}, {loc});
- builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
- tempDeclEmission =
- cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
-
- // 'firstprivate' doesn't do its initialization in the 'init' section,
- // instead does it in the 'copy' section. SO only do init here.
- // 'reduction' appears to use it too (rather than a 'copy' section), so
- // we probably have to do it here too, but we can do that when we get to
- // reduction implementation.
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
- // We are OK with no init for builtins, arrays of builtins, or pointers,
- // else we should NYI so we know to go look for these.
- if (!varRecipe->getType()
- ->getPointeeOrArrayElementType()
- ->isBuiltinType() &&
- !varRecipe->getType()->isPointerType() && !varRecipe->getInit()) {
- // If we don't have any initialization recipe, we failed during Sema to
- // initialize this correctly. If we disable the
- // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
- // emit an error to tell us. However, emitting those errors during
- // production is a violation of the standard, so we cannot do them.
- cgf.cgm.errorNYI(exprRange, "private default-init recipe");
- }
- cgf.emitAutoVarInit(tempDeclEmission);
- }
-
- mlir::acc::YieldOp::create(builder, locEnd);
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
- if (!varRecipe->getInit()) {
- // If we don't have any initialization recipe, we failed during Sema to
- // initialize this correctly. If we disable the
- // Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
- // emit an error to tell us. However, emitting those errors during
- // production is a violation of the standard, so we cannot do them.
- cgf.cgm.errorNYI(
- exprRange, "firstprivate copy-init recipe not properly generated");
- }
-
- createFirstprivateRecipeCopy(loc, locEnd, mainOp, tempDeclEmission,
- recipe, varRecipe, temporary);
- }
- }
-
- void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
- mlir::Value mainOp, CharUnits alignment,
- QualType baseType,
- mlir::Region &destroyRegion) {
- mlir::Block *block = builder.createBlock(
- &destroyRegion, destroyRegion.end(), {mainOp.getType()}, {loc});
- builder.setInsertionPointToEnd(&destroyRegion.back());
-
- mlir::Type elementTy =
- mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
- Address addr{block->getArgument(0), elementTy, alignment};
- cgf.emitDestroy(addr, baseType,
- cgf.getDestroyer(QualType::DK_cxx_destructor));
-
- mlir::acc::YieldOp::create(builder, locEnd);
- }
-
- template <typename RecipeTy>
- RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- const VarDecl *varRecipe, const VarDecl *temporary,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
- mlir::ModuleOp mod =
- builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
-
- std::string recipeName =
- getRecipeName<RecipeTy>(varRef->getSourceRange(), baseType);
- if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
- return recipe;
-
- mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
- mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
-
- mlir::OpBuilder modBuilder(mod.getBodyRegion());
- auto recipe =
- RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
-
- createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp, recipe,
- varRecipe, temporary);
-
- if (varRecipe && varRecipe->needsDestruction(cgf.getContext()))
- createRecipeDestroySection(loc, locEnd, mainOp,
- cgf.getContext().getDeclAlign(varRecipe),
- baseType, recipe.getDestroyRegion());
- return recipe;
- }
-
public:
OpenACCClauseCIREmitter(OpTy &operation, CIRGen::CIRGenFunction &cgf,
CIRGen::CIRGenBuilderTy &builder,
@@ -1162,10 +988,20 @@ public:
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
- auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), varExpr, varRecipe, /*temporary=*/nullptr,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- privateOp.getResult());
+ // TODO: OpenACC: At the moment this is a bit of a hacky way of doing
+ // this, and won't work when we get to bounds/etc. Do this for now to
+ // limit the scope of this refactor.
+ VarDecl *allocaDecl = varRecipe.AllocaDecl;
+ allocaDecl->setInit(varRecipe.InitExpr);
+ allocaDecl->setInitStyle(VarDecl::CallInit);
+
+ auto recipe =
+ OpenACCRecipeBuilder<mlir::acc::PrivateRecipeOp>(cgf, builder)
+ .getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
+ /*temporary=*/nullptr,
+ OpenACCReductionOperator::Invalid,
+ Decl::castToDeclContext(cgf.curFuncDecl),
+ opInfo.baseType, privateOp.getResult());
// TODO: OpenACC: The dialect is going to change in the near future to
// have these be on a different operation, so when that changes, we
// probably need to change these here.
@@ -1196,11 +1032,22 @@ public:
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
- auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
- cgf.getContext(), varExpr, varRecipe.RecipeDecl,
- varRecipe.InitFromTemporary,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- firstPrivateOp.getResult());
+ // TODO: OpenACC: At the moment this is a bit of a hacky way of doing
+ // this, and won't work when we get to bounds/etc. Do this for now to
+ // limit the scope of this refactor.
+ VarDecl *allocaDecl = varRecipe.AllocaDecl;
+ allocaDecl->setInit(varRecipe.InitExpr);
+ allocaDecl->setInitStyle(VarDecl::CallInit);
+
+ auto recipe =
+ OpenACCRecipeBuilder<mlir::acc::FirstprivateRecipeOp>(cgf,
+ builder)
+ .getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
+ varRecipe.InitFromTemporary,
+ OpenACCReductionOperator::Invalid,
+ Decl::castToDeclContext(cgf.curFuncDecl),
+ opInfo.baseType,
+ firstPrivateOp.getResult());
// TODO: OpenACC: The dialect is going to change in the near future to
// have these be on a different operation, so when that changes, we
@@ -1217,6 +1064,48 @@ public:
llvm_unreachable("Unknown construct kind in VisitFirstPrivateClause");
}
}
+
+ void VisitReductionClause(const OpenACCReductionClause &clause) {
+ if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
+ mlir::acc::LoopOp>) {
+ for (const auto [varExpr, varRecipe] :
+ llvm::zip_equal(clause.getVarList(), clause.getRecipes())) {
+ CIRGenFunction::OpenACCDataOperandInfo opInfo =
+ cgf.getOpenACCDataOperandInfo(varExpr);
+
+ auto reductionOp = mlir::acc::ReductionOp::create(
+ builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
+ /*implicit=*/false, opInfo.name, opInfo.bounds);
+ reductionOp.setDataClause(mlir::acc::DataClause::acc_reduction);
+
+ {
+ mlir::OpBuilder::InsertionGuard guardCase(builder);
+ // TODO: OpenACC: At the moment this is a bit of a hacky way of doing
+ // this, and won't work when we get to bounds/etc. Do this for now to
+ // limit the scope of this refactor.
+ VarDecl *allocaDecl = varRecipe.AllocaDecl;
+ allocaDecl->setInit(varRecipe.InitExpr);
+ allocaDecl->setInitStyle(VarDecl::CallInit);
+
+ auto recipe =
+ OpenACCRecipeBuilder<mlir::acc::ReductionRecipeOp>(cgf, builder)
+ .getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
+ /*temporary=*/nullptr,
+ clause.getReductionOp(),
+ Decl::castToDeclContext(cgf.curFuncDecl),
+ opInfo.baseType, reductionOp.getResult());
+
+ operation.addReduction(builder.getContext(), reductionOp, recipe);
+ }
+ }
+ } else if constexpr (isCombinedType<OpTy>) {
+ // Despite this being valid on ParallelOp or SerialOp, combined type
+ // applies to the 'loop'.
+ applyToLoopOp(clause);
+ } else {
+ llvm_unreachable("Unknown construct kind in VisitReductionClause");
+ }
+ }
};
template <typename OpTy>