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


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to