[clang] 15d7a95 - [CIR] Refactor recipe init generation, cleanup after init (#153610)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 15 06:41:45 PDT 2025
Author: Erich Keane
Date: 2025-08-15T06:41:42-07:00
New Revision: 15d7a95ea990214f77d9d99df8c2fc53799e5161
URL: https://github.com/llvm/llvm-project/commit/15d7a95ea990214f77d9d99df8c2fc53799e5161
DIFF: https://github.com/llvm/llvm-project/commit/15d7a95ea990214f77d9d99df8c2fc53799e5161.diff
LOG: [CIR] Refactor recipe init generation, cleanup after init (#153610)
In preperation of the firstprivate implementation, this separates out
some functions to make it easier to read.
Additionally, it cleans up the VarDecl->alloca relationship, which will
prevent issues if we have to re-use the same vardecl for a future
generated recipe (and causes concerns in firstprivate later).
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenFunction.h
clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index c3e77c99cca35..9a887ec047f86 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -518,6 +518,13 @@ class CIRGenFunction : public CIRGenTypeCache {
symbolTable.insert(vd, addr.getPointer());
}
+ /// Removes a declaration from the address-relationship. This is a function
+ /// that shouldn't need to be used except in cases where we're adding/removing
+ /// things that aren't part of the language-semantics AST.
+ void removeAddrOfLocalVar(const clang::VarDecl *vd) {
+ localDeclMap.erase(vd);
+ }
+
bool shouldNullCheckClassCastValue(const CastExpr *ce);
RValue convertTempToRValue(Address addr, clang::QualType type,
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index bb9054a68b5c7..9194b522114bc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -357,15 +357,11 @@ class OpenACCClauseCIREmitter final
}
template <typename RecipeTy>
- RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- const VarDecl *varRecipe, DeclContext *dc,
- QualType baseType, mlir::Value mainOp) {
- mlir::ModuleOp mod =
- builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
-
+ 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,
@@ -375,11 +371,12 @@ class OpenACCClauseCIREmitter final
} else if constexpr (std::is_same_v<RecipeTy,
mlir::acc::ReductionRecipeOp>) {
stream << "reduction_";
- // 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(varRef->getSourceRange(),
- "OpeNACC reduction recipe creation");
+ // 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");
}
@@ -387,72 +384,125 @@ class OpenACCClauseCIREmitter final
MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
mc.mangleCanonicalTypeName(baseType, stream);
}
+ return recipeName;
+ }
- 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());
+ // 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");
+ }
- mlir::OpBuilder modBuilder(mod.getBodyRegion());
- auto recipe =
- RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
+ if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
+ // We haven't implemented the 'init'/copy recipe for firstprivate yet, so
+ // NYI it.
+ cgf.cgm.errorNYI(exprRange, "OpenACC firstprivate recipe init");
+ }
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
- // Init section.
- {
- llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
- llvm::SmallVector<mlir::Location> argsLocs{loc};
- builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
- argsTys, argsLocs);
- builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
-
- if constexpr (!std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
- // We have only implemented 'init' for private, so make this NYI until
- // we have explicitly implemented everything.
- cgf.cgm.errorNYI(varRef->getSourceRange(),
- "OpenACC non-private recipe init");
+ // 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);
+ }
- if (varRecipe) {
- tempDeclEmission =
- cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
- 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");
}
- mlir::acc::YieldOp::create(builder, locEnd);
+ cgf.cgm.errorNYI(exprRange, "firstprivate copy section generation");
}
- // Copy section.
- if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp> ||
- std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
- // TODO: OpenACC: 'private' doesn't emit this, but for the other two we
- // have to figure out what 'copy' means here.
- cgf.cgm.errorNYI(varRef->getSourceRange(),
- "OpenACC record type privatization copy section");
- }
+ // Make sure we cleanup after ourselves here.
+ cgf.removeAddrOfLocalVar(varRecipe);
+ }
- // Destroy section (doesn't currently exist).
- if (varRecipe && varRecipe->needsDestruction(cgf.getContext())) {
- llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
- llvm::SmallVector<mlir::Location> argsLocs{loc};
- mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(),
- recipe.getDestroyRegion().end(),
- argsTys, argsLocs);
- builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back());
-
- mlir::Type elementTy =
- mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
- Address addr{block->getArgument(0), elementTy,
- cgf.getContext().getDeclAlign(varRecipe)};
- cgf.emitDestroy(addr, baseType,
- cgf.getDestroyer(QualType::DK_cxx_destructor));
-
- mlir::acc::YieldOp::create(builder, locEnd);
- }
+ 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;
}
@@ -1088,7 +1138,7 @@ class OpenACCClauseCIREmitter final
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), varExpr, varRecipe,
+ cgf.getContext(), varExpr, varRecipe, /*temporary=*/nullptr,
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
privateOp.getResult());
// TODO: OpenACC: The dialect is going to change in the near future to
More information about the cfe-commits
mailing list