-
Notifications
You must be signed in to change notification settings - Fork 15k
[OpenACC][NFCI] Split recipe generation into its own class #157160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The recipe generation was dependent on the clause kind, which meant we had all of the recipe generation duplicated in each of clauses. This patch copy/pastes all of them into their own type to do recipe generation, which should reduce clang's size. Additionally, we've moved it off into its own file, which should make readability/organization improvements.
A quick refactor, no need to review. |
@llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) ChangesThe recipe generation was dependent on the clause kind, which meant we had all of the recipe generation duplicated in each of clauses. This patch copy/pastes all of them into their own type to do recipe generation, which should reduce clang's size. Additionally, we've moved it off into its own file, which should make readability/organization improvements. Patch is 31.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/157160.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 0022befa3b562..9959cf6c15792 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,299 +357,6 @@ class OpenACCClauseCIREmitter final
}
}
- template <typename RecipeTy>
- std::string getRecipeName(SourceRange loc, QualType baseType,
- OpenACCReductionOperator reductionOp) {
- 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_";
- // Values here are a little weird (for bitwise and/or is 'i' prefix, and
- // logical ops with 'l'), but are chosen to be the same as the MLIR
- // dialect names as well as to match the Flang versions of these.
- switch (reductionOp) {
- case OpenACCReductionOperator::Addition:
- stream << "add_";
- break;
- case OpenACCReductionOperator::Multiplication:
- stream << "mul_";
- break;
- case OpenACCReductionOperator::Max:
- stream << "max_";
- break;
- case OpenACCReductionOperator::Min:
- stream << "min_";
- break;
- case OpenACCReductionOperator::BitwiseAnd:
- stream << "iand_";
- break;
- case OpenACCReductionOperator::BitwiseOr:
- stream << "ior_";
- break;
- case OpenACCReductionOperator::BitwiseXOr:
- stream << "xor_";
- break;
- case OpenACCReductionOperator::And:
- stream << "land_";
- break;
- case OpenACCReductionOperator::Or:
- stream << "lor_";
- break;
- case OpenACCReductionOperator::Invalid:
- llvm_unreachable("invalid reduction operator");
- }
- } 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());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- 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'. Note that this function is not 'insertion point' clean, in
- // that it alters the insertion point to be inside of the 'destroy' section of
- // the recipe, but doesn't restore it aftewards.
- 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?");
-
- 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).
- mlir::Block *block = builder.createBlock(&recipe.getInitRegion(),
- recipe.getInitRegion().end(),
- {mainOp.getType()}, {loc});
- builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- 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 (cgf.getContext().getLangOpts().CPlusPlus &&
- !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);
- } else if constexpr (std::is_same_v<RecipeTy,
- mlir::acc::ReductionRecipeOp>) {
- // Unlike Private, the recipe here is always required as it has to do
- // init, not just 'default' init.
- if (!varRecipe->getInit())
- cgf.cgm.errorNYI(exprRange, "reduction 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);
- }
- }
-
- // This function generates the 'combiner' section for a reduction recipe. Note
- // that this function is not 'insertion point' clean, in that it alters the
- // insertion point to be inside of the 'combiner' section of the recipe, but
- // doesn't restore it aftewards.
- void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd,
- mlir::Value mainOp,
- mlir::acc::ReductionRecipeOp recipe) {
- mlir::Block *block = builder.createBlock(
- &recipe.getCombinerRegion(), recipe.getCombinerRegion().end(),
- {mainOp.getType(), mainOp.getType()}, {loc, loc});
- builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- mlir::BlockArgument lhsArg = block->getArgument(0);
-
- mlir::acc::YieldOp::create(builder, locEnd, lhsArg);
- }
-
- // This function generates the 'destroy' section for a recipe. Note
- // that this function is not 'insertion point' clean, in that it alters the
- // insertion point to be inside of the 'destroy' section of the recipe, but
- // doesn't restore it aftewards.
- 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(), mainOp.getType()}, {loc, loc});
- builder.setInsertionPointToEnd(&destroyRegion.back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- mlir::Type elementTy =
- mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
- // The destroy region has a signature of "original item, privatized item".
- // So the 2nd item is the one that needs destroying, the former is just for
- // reference and we don't really have a need for it at the moment.
- Address addr{block->getArgument(1), elementTy, alignment};
- cgf.emitDestroy(addr, baseType,
- cgf.getDestroyer(QualType::DK_cxx_destructor));
-
- mlir::acc::YieldOp::create(builder, locEnd);
- }
-
- mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op) {
- switch (op) {
- case OpenACCReductionOperator::Addition:
- return mlir::acc::ReductionOperator::AccAdd;
- case OpenACCReductionOperator::Multiplication:
- return mlir::acc::ReductionOperator::AccMul;
- case OpenACCReductionOperator::Max:
- return mlir::acc::ReductionOperator::AccMax;
- case OpenACCReductionOperator::Min:
- return mlir::acc::ReductionOperator::AccMin;
- case OpenACCReductionOperator::BitwiseAnd:
- return mlir::acc::ReductionOperator::AccIand;
- case OpenACCReductionOperator::BitwiseOr:
- return mlir::acc::ReductionOperator::AccIor;
- case OpenACCReductionOperator::BitwiseXOr:
- return mlir::acc::ReductionOperator::AccXor;
- case OpenACCReductionOperator::And:
- return mlir::acc::ReductionOperator::AccLand;
- case OpenACCReductionOperator::Or:
- return mlir::acc::ReductionOperator::AccLor;
- case OpenACCReductionOperator::Invalid:
- llvm_unreachable("invalid reduction operator");
- }
-
- llvm_unreachable("invalid reduction operator");
- }
-
- template <typename RecipeTy>
- RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- const VarDecl *varRecipe, const VarDecl *temporary,
- OpenACCReductionOperator reductionOp,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
-
- if (baseType->isPointerType() ||
- (baseType->isArrayType() && !baseType->isConstantArrayType())) {
- // It is clear that the use of pointers/VLAs in a recipe are not properly
- // generated/don't do what they are supposed to do. In the case where we
- // have 'bounds', we can actually figure out what we want to
- // initialize/copy/destroy/compare/etc, but we haven't figured out how
- // that looks yet, both between the IR and generation code. For now, we
- // will do an NYI error no it.
- cgf.cgm.errorNYI(
- varRef->getSourceRange(),
- "OpenACC recipe generation for pointer/non-constant arrays");
- }
-
- mlir::ModuleOp mod = builder.getBlock()
- ->getParent()
- ->template getParentOfType<mlir::ModuleOp>();
-
- std::string recipeName = getRecipeName<RecipeTy>(varRef->getSourceRange(),
- baseType, reductionOp);
- 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());
- RecipeTy recipe;
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType(),
- convertReductionOp(reductionOp));
- } else {
- recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- }
-
- createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp, recipe,
- varRecipe, temporary);
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- createReductionRecipeCombiner(loc, locEnd, mainOp, recipe);
- }
-
- 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,
@@ -1287,11 +995,13 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl, /*temporary=*/nullptr,
- OpenACCReductionOperator::Invalid,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- privateOp.getResult());
+ 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.
@@ -1329,11 +1039,15 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl,
- varRecipe.InitFromTemporary, OpenACCReductionOperator::Invalid,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- firstPrivateOp.getResult());
+ 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
@@ -1373,11 +1087,13 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::ReductionRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl,
- /*temporary=*/nullptr, clause.getReductionOp(),
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- reductionOp.getResult());
+ 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);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
new file mode 100644
index 0000000000000..102fd890e5579
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
@@ -0,0 +1,323 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Emit OpenACC clause recipes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeBase.h"
+#include "clang/Basic/OpenACCKinds.h"
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+
+namespace clang::CIRGen {
+template <typename RecipeTy> class OpenACCRecipeBuilder {
+ CIRGen::CIRGenFunction &cgf;
+ CIRGen::CIRGenBuilderTy &builder;
+
+ mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op) {
+ switch (op) {
+ case OpenACCReductionOperator::Addition:
+ return mlir::acc::ReductionOperator::AccAdd;
+ case OpenACCReductionOperator::Multiplication:
+ return mlir::acc::ReductionOperator::AccMul;
+ case OpenACCReductionOperator::Max:
+ return mlir::acc::ReductionOperator::AccMax;
+ case OpenACCReductionOperator::Min:
+ return mlir::acc::ReductionOperator::AccMin;
+ case OpenACCReductionOperator::BitwiseAnd:
+ return mlir::acc::ReductionOperator::AccIand;
+ case OpenACCReductionOperator::BitwiseOr:
+ return mlir::acc::ReductionOperator::AccIor;
+ case OpenACCReductionOperator::BitwiseXOr:
+ return mlir::acc::ReductionOperator::AccXor;
+ case OpenACCReductionOperator::And:
+ return mlir::acc::ReductionOperator::AccLand;
+ case OpenACCReductionOperator::Or:
+ return mlir::acc::ReductionOperator::AccLor;
+ case OpenACCReductionOperator::Invalid:
+ llvm_unreachable("invalid reduction operator");
+ }
+
+ llvm_unreachable("invalid reduction operator");
+ }
+
+ std::string getRecipeName(SourceRange loc, QualType baseType,
+ OpenACCReductionOperator reductionOp) {
+ 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>) {
+ s...
[truncated]
|
@llvm/pr-subscribers-clangir Author: Erich Keane (erichkeane) ChangesThe recipe generation was dependent on the clause kind, which meant we had all of the recipe generation duplicated in each of clauses. This patch copy/pastes all of them into their own type to do recipe generation, which should reduce clang's size. Additionally, we've moved it off into its own file, which should make readability/organization improvements. Patch is 31.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/157160.diff 2 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 0022befa3b562..9959cf6c15792 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,299 +357,6 @@ class OpenACCClauseCIREmitter final
}
}
- template <typename RecipeTy>
- std::string getRecipeName(SourceRange loc, QualType baseType,
- OpenACCReductionOperator reductionOp) {
- 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_";
- // Values here are a little weird (for bitwise and/or is 'i' prefix, and
- // logical ops with 'l'), but are chosen to be the same as the MLIR
- // dialect names as well as to match the Flang versions of these.
- switch (reductionOp) {
- case OpenACCReductionOperator::Addition:
- stream << "add_";
- break;
- case OpenACCReductionOperator::Multiplication:
- stream << "mul_";
- break;
- case OpenACCReductionOperator::Max:
- stream << "max_";
- break;
- case OpenACCReductionOperator::Min:
- stream << "min_";
- break;
- case OpenACCReductionOperator::BitwiseAnd:
- stream << "iand_";
- break;
- case OpenACCReductionOperator::BitwiseOr:
- stream << "ior_";
- break;
- case OpenACCReductionOperator::BitwiseXOr:
- stream << "xor_";
- break;
- case OpenACCReductionOperator::And:
- stream << "land_";
- break;
- case OpenACCReductionOperator::Or:
- stream << "lor_";
- break;
- case OpenACCReductionOperator::Invalid:
- llvm_unreachable("invalid reduction operator");
- }
- } 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());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- 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'. Note that this function is not 'insertion point' clean, in
- // that it alters the insertion point to be inside of the 'destroy' section of
- // the recipe, but doesn't restore it aftewards.
- 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?");
-
- 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).
- mlir::Block *block = builder.createBlock(&recipe.getInitRegion(),
- recipe.getInitRegion().end(),
- {mainOp.getType()}, {loc});
- builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- 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 (cgf.getContext().getLangOpts().CPlusPlus &&
- !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);
- } else if constexpr (std::is_same_v<RecipeTy,
- mlir::acc::ReductionRecipeOp>) {
- // Unlike Private, the recipe here is always required as it has to do
- // init, not just 'default' init.
- if (!varRecipe->getInit())
- cgf.cgm.errorNYI(exprRange, "reduction 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);
- }
- }
-
- // This function generates the 'combiner' section for a reduction recipe. Note
- // that this function is not 'insertion point' clean, in that it alters the
- // insertion point to be inside of the 'combiner' section of the recipe, but
- // doesn't restore it aftewards.
- void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd,
- mlir::Value mainOp,
- mlir::acc::ReductionRecipeOp recipe) {
- mlir::Block *block = builder.createBlock(
- &recipe.getCombinerRegion(), recipe.getCombinerRegion().end(),
- {mainOp.getType(), mainOp.getType()}, {loc, loc});
- builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- mlir::BlockArgument lhsArg = block->getArgument(0);
-
- mlir::acc::YieldOp::create(builder, locEnd, lhsArg);
- }
-
- // This function generates the 'destroy' section for a recipe. Note
- // that this function is not 'insertion point' clean, in that it alters the
- // insertion point to be inside of the 'destroy' section of the recipe, but
- // doesn't restore it aftewards.
- 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(), mainOp.getType()}, {loc, loc});
- builder.setInsertionPointToEnd(&destroyRegion.back());
- CIRGenFunction::LexicalScope ls(cgf, loc, block);
-
- mlir::Type elementTy =
- mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
- // The destroy region has a signature of "original item, privatized item".
- // So the 2nd item is the one that needs destroying, the former is just for
- // reference and we don't really have a need for it at the moment.
- Address addr{block->getArgument(1), elementTy, alignment};
- cgf.emitDestroy(addr, baseType,
- cgf.getDestroyer(QualType::DK_cxx_destructor));
-
- mlir::acc::YieldOp::create(builder, locEnd);
- }
-
- mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op) {
- switch (op) {
- case OpenACCReductionOperator::Addition:
- return mlir::acc::ReductionOperator::AccAdd;
- case OpenACCReductionOperator::Multiplication:
- return mlir::acc::ReductionOperator::AccMul;
- case OpenACCReductionOperator::Max:
- return mlir::acc::ReductionOperator::AccMax;
- case OpenACCReductionOperator::Min:
- return mlir::acc::ReductionOperator::AccMin;
- case OpenACCReductionOperator::BitwiseAnd:
- return mlir::acc::ReductionOperator::AccIand;
- case OpenACCReductionOperator::BitwiseOr:
- return mlir::acc::ReductionOperator::AccIor;
- case OpenACCReductionOperator::BitwiseXOr:
- return mlir::acc::ReductionOperator::AccXor;
- case OpenACCReductionOperator::And:
- return mlir::acc::ReductionOperator::AccLand;
- case OpenACCReductionOperator::Or:
- return mlir::acc::ReductionOperator::AccLor;
- case OpenACCReductionOperator::Invalid:
- llvm_unreachable("invalid reduction operator");
- }
-
- llvm_unreachable("invalid reduction operator");
- }
-
- template <typename RecipeTy>
- RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- const VarDecl *varRecipe, const VarDecl *temporary,
- OpenACCReductionOperator reductionOp,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
-
- if (baseType->isPointerType() ||
- (baseType->isArrayType() && !baseType->isConstantArrayType())) {
- // It is clear that the use of pointers/VLAs in a recipe are not properly
- // generated/don't do what they are supposed to do. In the case where we
- // have 'bounds', we can actually figure out what we want to
- // initialize/copy/destroy/compare/etc, but we haven't figured out how
- // that looks yet, both between the IR and generation code. For now, we
- // will do an NYI error no it.
- cgf.cgm.errorNYI(
- varRef->getSourceRange(),
- "OpenACC recipe generation for pointer/non-constant arrays");
- }
-
- mlir::ModuleOp mod = builder.getBlock()
- ->getParent()
- ->template getParentOfType<mlir::ModuleOp>();
-
- std::string recipeName = getRecipeName<RecipeTy>(varRef->getSourceRange(),
- baseType, reductionOp);
- 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());
- RecipeTy recipe;
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType(),
- convertReductionOp(reductionOp));
- } else {
- recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- }
-
- createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp, recipe,
- varRecipe, temporary);
-
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- createReductionRecipeCombiner(loc, locEnd, mainOp, recipe);
- }
-
- 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,
@@ -1287,11 +995,13 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl, /*temporary=*/nullptr,
- OpenACCReductionOperator::Invalid,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- privateOp.getResult());
+ 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.
@@ -1329,11 +1039,15 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl,
- varRecipe.InitFromTemporary, OpenACCReductionOperator::Invalid,
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- firstPrivateOp.getResult());
+ 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
@@ -1373,11 +1087,13 @@ class OpenACCClauseCIREmitter final
allocaDecl->setInit(varRecipe.InitExpr);
allocaDecl->setInitStyle(VarDecl::CallInit);
- auto recipe = getOrCreateRecipe<mlir::acc::ReductionRecipeOp>(
- cgf.getContext(), varExpr, allocaDecl,
- /*temporary=*/nullptr, clause.getReductionOp(),
- Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
- reductionOp.getResult());
+ 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);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
new file mode 100644
index 0000000000000..102fd890e5579
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCRecipe.h
@@ -0,0 +1,323 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Emit OpenACC clause recipes as CIR code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeBase.h"
+#include "clang/Basic/OpenACCKinds.h"
+
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+
+namespace clang::CIRGen {
+template <typename RecipeTy> class OpenACCRecipeBuilder {
+ CIRGen::CIRGenFunction &cgf;
+ CIRGen::CIRGenBuilderTy &builder;
+
+ mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op) {
+ switch (op) {
+ case OpenACCReductionOperator::Addition:
+ return mlir::acc::ReductionOperator::AccAdd;
+ case OpenACCReductionOperator::Multiplication:
+ return mlir::acc::ReductionOperator::AccMul;
+ case OpenACCReductionOperator::Max:
+ return mlir::acc::ReductionOperator::AccMax;
+ case OpenACCReductionOperator::Min:
+ return mlir::acc::ReductionOperator::AccMin;
+ case OpenACCReductionOperator::BitwiseAnd:
+ return mlir::acc::ReductionOperator::AccIand;
+ case OpenACCReductionOperator::BitwiseOr:
+ return mlir::acc::ReductionOperator::AccIor;
+ case OpenACCReductionOperator::BitwiseXOr:
+ return mlir::acc::ReductionOperator::AccXor;
+ case OpenACCReductionOperator::And:
+ return mlir::acc::ReductionOperator::AccLand;
+ case OpenACCReductionOperator::Or:
+ return mlir::acc::ReductionOperator::AccLor;
+ case OpenACCReductionOperator::Invalid:
+ llvm_unreachable("invalid reduction operator");
+ }
+
+ llvm_unreachable("invalid reduction operator");
+ }
+
+ std::string getRecipeName(SourceRange loc, QualType baseType,
+ OpenACCReductionOperator reductionOp) {
+ 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>) {
+ s...
[truncated]
|
The recipe generation was dependent on the clause kind, which meant we had all of the recipe generation duplicated in each of clauses. This patch copy/pastes all of them into their own type to do recipe generation, which should reduce clang's size.
Additionally, we've moved it off into its own file, which should make readability/organization improvements.