-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[OpenACC][CIR] Implement 'init' lowering for private clause vars #151781
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
Previously, llvm#151360 implemented 'private' clause lowering, but didn't properly initialize the variables. This patch adds that behavior to make sure we correctly get the constructor or other init called.
@llvm/pr-subscribers-clangir Author: Erich Keane (erichkeane) ChangesPreviously, #151360 implemented 'private' clause lowering, but didn't properly initialize the variables. This patch adds that behavior to make sure we correctly get the constructor or other init called. Patch is 32.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/151781.diff 16 Files Affected:
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index 71ad24a427105..32a06bc84ad20 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -837,23 +837,43 @@ class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
class OpenACCPrivateClause final
: public OpenACCClauseWithVarList,
- private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
+ private llvm::TrailingObjects<OpenACCPrivateClause, Expr *, VarDecl *> {
friend TrailingObjects;
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
LParenLoc, EndLoc) {
- setExprs(getTrailingObjects(VarList.size()), VarList);
+ assert(VarList.size() == InitRecipes.size());
+ setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
+ llvm::uninitialized_copy(InitRecipes, getTrailingObjects<VarDecl *>());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Private;
}
+ // Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
+ // ensure that we properly initialize each of these variables.
+ ArrayRef<VarDecl *> getInitRecipes() {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
+ ArrayRef<VarDecl *> getInitRecipes() const {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
static OpenACCPrivateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+ ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc);
+
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return getExprs().size();
+ }
};
class OpenACCFirstPrivateClause final
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index b7e7f5d97bcef..f51045d26e23b 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -241,6 +241,10 @@ class SemaOpenACC : public SemaBase {
SourceLocation ClauseLoc,
ArrayRef<const OpenACCClause *> Clauses);
+ // Creates a VarDecl with a proper default init for the purposes of a
+ // `private` clause, so it can be used to generate a recipe later.
+ VarDecl *CreateInitRecipe(const Expr *VarExpr);
+
public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 60ec10a986e5e..f21e645697656 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -314,14 +314,17 @@ OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C,
return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc);
}
-OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
- SourceLocation BeginLoc,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(
- OpenACCPrivateClause::totalSizeToAlloc<Expr *>(VarList.size()));
- return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
+OpenACCPrivateClause *
+OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc) {
+ assert(VarList.size() == InitRecipes.size());
+ void *Mem =
+ C.Allocate(OpenACCPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>(
+ VarList.size(), InitRecipes.size()));
+ return new (Mem)
+ OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, InitRecipes, EndLoc);
}
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c61450e19f1b6..57834ca4a89ca 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2636,6 +2636,9 @@ void OpenACCClauseProfiler::VisitCollapseClause(
void OpenACCClauseProfiler::VisitPrivateClause(
const OpenACCPrivateClause &Clause) {
VisitClauseWithVarList(Clause);
+
+ for (auto *VD : Clause.getInitRecipes())
+ Profiler.VisitDecl(VD);
}
void OpenACCClauseProfiler::VisitFirstPrivateClause(
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
index 32095cb687e88..907cb5fa11401 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
@@ -119,7 +119,8 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
// Sema has made sure that only 4 types of things can get here, array
// subscript, array section, member expr, or DRE to a var decl (or the
@@ -127,5 +128,6 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 5a6e66550c0bd..bb9054a68b5c7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -358,8 +358,8 @@ class OpenACCClauseCIREmitter final
template <typename RecipeTy>
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
+ const VarDecl *varRecipe, DeclContext *dc,
+ QualType baseType, mlir::Value mainOp) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
@@ -398,12 +398,6 @@ class OpenACCClauseCIREmitter final
auto recipe =
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- // Magic-up a var-decl so we can use normal init/destruction operations for
- // a variable declaration.
- VarDecl &tempDecl = *VarDecl::Create(
- astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
- &astCtx.Idents.get("openacc.private.init"), baseType,
- astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
@@ -422,9 +416,11 @@ class OpenACCClauseCIREmitter final
"OpenACC non-private recipe init");
}
- tempDeclEmission =
- cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
- cgf.emitAutoVarInit(tempDeclEmission);
+ if (varRecipe) {
+ tempDeclEmission =
+ cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
+ cgf.emitAutoVarInit(tempDeclEmission);
+ }
mlir::acc::YieldOp::create(builder, locEnd);
}
@@ -439,7 +435,7 @@ class OpenACCClauseCIREmitter final
}
// Destroy section (doesn't currently exist).
- if (tempDecl.needsDestruction(cgf.getContext())) {
+ 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(),
@@ -450,7 +446,7 @@ class OpenACCClauseCIREmitter final
mlir::Type elementTy =
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
Address addr{block->getArgument(0), elementTy,
- cgf.getContext().getDeclAlign(&tempDecl)};
+ cgf.getContext().getDeclAlign(varRecipe)};
cgf.emitDestroy(addr, baseType,
cgf.getDestroyer(QualType::DK_cxx_destructor));
@@ -1080,9 +1076,10 @@ class OpenACCClauseCIREmitter final
void VisitPrivateClause(const OpenACCPrivateClause &clause) {
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
mlir::acc::LoopOp>) {
- for (const Expr *var : clause.getVarList()) {
+ for (const auto [varExpr, varRecipe] :
+ llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
CIRGenFunction::OpenACCDataOperandInfo opInfo =
- cgf.getOpenACCDataOperandInfo(var);
+ cgf.getOpenACCDataOperandInfo(varExpr);
auto privateOp = mlir::acc::PrivateOp::create(
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
/*implicit=*/false, opInfo.name, opInfo.bounds);
@@ -1091,8 +1088,9 @@ class OpenACCClauseCIREmitter final
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
- opInfo.baseType, privateOp.getResult());
+ cgf.getContext(), varExpr, varRecipe,
+ 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.
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 8bfea623103e4..8f32817aec48f 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -17,6 +17,7 @@
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/StringExtras.h"
@@ -2552,3 +2553,50 @@ ExprResult
SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
}
+
+VarDecl *SemaOpenACC::CreateInitRecipe(const Expr *VarExpr) {
+ // Strip off any array subscripts/array section exprs to get to the type of
+ // the variable.
+ while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {
+ if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr))
+ VarExpr = AS->getBase()->IgnoreParenImpCasts();
+ else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr))
+ VarExpr = Sub->getBase()->IgnoreParenImpCasts();
+ }
+
+ // If for some reason the expression is invalid, or this is dependent, just
+ // fill in with nullptr. We'll count on TreeTransform to make this if
+ // necessary.
+ if (!VarExpr || VarExpr->getType()->isDependentType())
+ return nullptr;
+
+ QualType VarTy =
+ VarExpr->getType().getNonReferenceType().getUnqualifiedType();
+
+ VarDecl *Recipe = VarDecl::Create(
+ getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
+ VarExpr->getBeginLoc(),
+ &getASTContext().Idents.get("openacc.private.init"), VarTy,
+ getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
+
+ ExprResult Init;
+
+ {
+ // Trap errors so we don't get weird ones here. If we can't init, we'll just
+ // swallow the errors.
+ Sema::TentativeAnalysisScope Trap{SemaRef};
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);
+ InitializationKind Kind =
+ InitializationKind::CreateDefault(Recipe->getLocation());
+
+ InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
+ Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
+ }
+
+ if (Init.get()) {
+ Recipe->setInit(Init.get());
+ Recipe->setInitStyle(VarDecl::CallInit);
+ }
+
+ return Recipe;
+}
diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp
index b54a0124e9495..9f1a6177b945c 100644
--- a/clang/lib/Sema/SemaOpenACCClause.cpp
+++ b/clang/lib/Sema/SemaOpenACCClause.cpp
@@ -795,9 +795,15 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
// really isn't anything to do here. GCC does some duplicate-finding, though
// it isn't apparent in the standard where this is justified.
- return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
- Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ // Assemble the recipes list.
+ for (const Expr *VarExpr : Clause.getVarList())
+ InitRecipes.push_back(SemaRef.CreateInitRecipe(VarExpr));
+
+ return OpenACCPrivateClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ InitRecipes, Clause.getEndLoc());
}
OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c7428d1a02345..7c9755f301552 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -11730,20 +11730,26 @@ class OpenACCClauseTransform final
SemaOpenACC::OpenACCParsedClause &ParsedClause;
OpenACCClause *NewClause = nullptr;
+ ExprResult VisitVar(Expr *VarRef) {
+ ExprResult Res = Self.TransformExpr(VarRef);
+
+ if (!Res.isUsable())
+ return Res;
+
+ Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
+ ParsedClause.getClauseKind(),
+ Res.get());
+
+ return Res;
+ }
+
llvm::SmallVector<Expr *> VisitVarList(ArrayRef<Expr *> VarList) {
llvm::SmallVector<Expr *> InstantiatedVarList;
for (Expr *CurVar : VarList) {
- ExprResult Res = Self.TransformExpr(CurVar);
-
- if (!Res.isUsable())
- continue;
+ ExprResult VarRef = VisitVar(CurVar);
- Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
- ParsedClause.getClauseKind(),
- Res.get());
-
- if (Res.isUsable())
- InstantiatedVarList.push_back(Res.get());
+ if (VarRef.isUsable())
+ InstantiatedVarList.push_back(VarRef.get());
}
return InstantiatedVarList;
@@ -11870,12 +11876,31 @@ void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitPrivateClause(
const OpenACCPrivateClause &C) {
- ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
+ llvm::SmallVector<Expr *> InstantiatedVarList;
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ for (const auto [RefExpr, InitRecipe] :
+ llvm::zip(C.getVarList(), C.getInitRecipes())) {
+ ExprResult VarRef = VisitVar(RefExpr);
+
+ if (VarRef.isUsable()) {
+ InstantiatedVarList.push_back(VarRef.get());
+
+ // We only have to create a new one if it is dependent, and Sema won't
+ // make one of these unless the type is non-dependent.
+ if (InitRecipe)
+ InitRecipes.push_back(InitRecipe);
+ else
+ InitRecipes.push_back(
+ Self.getSema().OpenACC().CreateInitRecipe(VarRef.get()));
+ }
+ }
+ ParsedClause.setVarListDetails(InstantiatedVarList,
OpenACCModifierKind::Invalid);
NewClause = OpenACCPrivateClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
- ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(), InitRecipes,
ParsedClause.getEndLoc());
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 682d26394c0d5..753b25fb7dade 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12851,8 +12851,13 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
case OpenACCClauseKind::Private: {
SourceLocation LParenLoc = readSourceLocation();
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
+
+ llvm::SmallVector<VarDecl *> RecipeList;
+ for (unsigned I = 0; I < VarList.size(); ++I)
+ RecipeList.push_back(readDeclAs<VarDecl>());
+
return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
- VarList, EndLoc);
+ VarList, RecipeList, EndLoc);
}
case OpenACCClauseKind::Host: {
SourceLocation LParenLoc = readSourceLocation();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a6957e54b66f1..7c637c0d00369 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8738,6 +8738,9 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
const auto *PC = cast<OpenACCPrivateClause>(C);
writeSourceLocation(PC->getLParenLoc());
writeOpenACCVarList(PC);
+
+ for (VarDecl *VD : PC->getInitRecipes())
+ AddDeclRef(VD);
return;
}
case OpenACCClauseKind::Host: {
diff --git a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
index 3306c55b4a8e7..0b58bae9239b2 100644
--- a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
+++ b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
@@ -43,7 +43,24 @@ struct HasDtor {
//
// CHECK-NEXT: acc.private.recipe @privatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
-// CHECK-NEXT: cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
+// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init", init]
+// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<5> : !u64i
+// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ALLOCA]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[LAST_ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_NonDefaultCtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, ["__array_idx"]
+// CHECK-NEXT: cir.store %[[ARRPTR]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.do {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[ELEM_LOAD]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
+// CHECK-NEXT: %[[ONE_CONST:.*]] = cir.const #cir.int<1> : !u64i
+// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_NonDefaultCtor>, %[[ONE_CONST]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.yield
+// CHECK-NEXT: } while {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_Non...
[truncated]
|
@llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) ChangesPreviously, #151360 implemented 'private' clause lowering, but didn't properly initialize the variables. This patch adds that behavior to make sure we correctly get the constructor or other init called. Patch is 32.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/151781.diff 16 Files Affected:
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index 71ad24a427105..32a06bc84ad20 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -837,23 +837,43 @@ class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
class OpenACCPrivateClause final
: public OpenACCClauseWithVarList,
- private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
+ private llvm::TrailingObjects<OpenACCPrivateClause, Expr *, VarDecl *> {
friend TrailingObjects;
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
LParenLoc, EndLoc) {
- setExprs(getTrailingObjects(VarList.size()), VarList);
+ assert(VarList.size() == InitRecipes.size());
+ setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
+ llvm::uninitialized_copy(InitRecipes, getTrailingObjects<VarDecl *>());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Private;
}
+ // Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
+ // ensure that we properly initialize each of these variables.
+ ArrayRef<VarDecl *> getInitRecipes() {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
+ ArrayRef<VarDecl *> getInitRecipes() const {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
static OpenACCPrivateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+ ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc);
+
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return getExprs().size();
+ }
};
class OpenACCFirstPrivateClause final
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index b7e7f5d97bcef..f51045d26e23b 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -241,6 +241,10 @@ class SemaOpenACC : public SemaBase {
SourceLocation ClauseLoc,
ArrayRef<const OpenACCClause *> Clauses);
+ // Creates a VarDecl with a proper default init for the purposes of a
+ // `private` clause, so it can be used to generate a recipe later.
+ VarDecl *CreateInitRecipe(const Expr *VarExpr);
+
public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 60ec10a986e5e..f21e645697656 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -314,14 +314,17 @@ OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C,
return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc);
}
-OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
- SourceLocation BeginLoc,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(
- OpenACCPrivateClause::totalSizeToAlloc<Expr *>(VarList.size()));
- return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
+OpenACCPrivateClause *
+OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc) {
+ assert(VarList.size() == InitRecipes.size());
+ void *Mem =
+ C.Allocate(OpenACCPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>(
+ VarList.size(), InitRecipes.size()));
+ return new (Mem)
+ OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, InitRecipes, EndLoc);
}
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c61450e19f1b6..57834ca4a89ca 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2636,6 +2636,9 @@ void OpenACCClauseProfiler::VisitCollapseClause(
void OpenACCClauseProfiler::VisitPrivateClause(
const OpenACCPrivateClause &Clause) {
VisitClauseWithVarList(Clause);
+
+ for (auto *VD : Clause.getInitRecipes())
+ Profiler.VisitDecl(VD);
}
void OpenACCClauseProfiler::VisitFirstPrivateClause(
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
index 32095cb687e88..907cb5fa11401 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
@@ -119,7 +119,8 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
// Sema has made sure that only 4 types of things can get here, array
// subscript, array section, member expr, or DRE to a var decl (or the
@@ -127,5 +128,6 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 5a6e66550c0bd..bb9054a68b5c7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -358,8 +358,8 @@ class OpenACCClauseCIREmitter final
template <typename RecipeTy>
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
+ const VarDecl *varRecipe, DeclContext *dc,
+ QualType baseType, mlir::Value mainOp) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
@@ -398,12 +398,6 @@ class OpenACCClauseCIREmitter final
auto recipe =
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- // Magic-up a var-decl so we can use normal init/destruction operations for
- // a variable declaration.
- VarDecl &tempDecl = *VarDecl::Create(
- astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
- &astCtx.Idents.get("openacc.private.init"), baseType,
- astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
@@ -422,9 +416,11 @@ class OpenACCClauseCIREmitter final
"OpenACC non-private recipe init");
}
- tempDeclEmission =
- cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
- cgf.emitAutoVarInit(tempDeclEmission);
+ if (varRecipe) {
+ tempDeclEmission =
+ cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
+ cgf.emitAutoVarInit(tempDeclEmission);
+ }
mlir::acc::YieldOp::create(builder, locEnd);
}
@@ -439,7 +435,7 @@ class OpenACCClauseCIREmitter final
}
// Destroy section (doesn't currently exist).
- if (tempDecl.needsDestruction(cgf.getContext())) {
+ 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(),
@@ -450,7 +446,7 @@ class OpenACCClauseCIREmitter final
mlir::Type elementTy =
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
Address addr{block->getArgument(0), elementTy,
- cgf.getContext().getDeclAlign(&tempDecl)};
+ cgf.getContext().getDeclAlign(varRecipe)};
cgf.emitDestroy(addr, baseType,
cgf.getDestroyer(QualType::DK_cxx_destructor));
@@ -1080,9 +1076,10 @@ class OpenACCClauseCIREmitter final
void VisitPrivateClause(const OpenACCPrivateClause &clause) {
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
mlir::acc::LoopOp>) {
- for (const Expr *var : clause.getVarList()) {
+ for (const auto [varExpr, varRecipe] :
+ llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
CIRGenFunction::OpenACCDataOperandInfo opInfo =
- cgf.getOpenACCDataOperandInfo(var);
+ cgf.getOpenACCDataOperandInfo(varExpr);
auto privateOp = mlir::acc::PrivateOp::create(
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
/*implicit=*/false, opInfo.name, opInfo.bounds);
@@ -1091,8 +1088,9 @@ class OpenACCClauseCIREmitter final
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
- opInfo.baseType, privateOp.getResult());
+ cgf.getContext(), varExpr, varRecipe,
+ 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.
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 8bfea623103e4..8f32817aec48f 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -17,6 +17,7 @@
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/StringExtras.h"
@@ -2552,3 +2553,50 @@ ExprResult
SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
}
+
+VarDecl *SemaOpenACC::CreateInitRecipe(const Expr *VarExpr) {
+ // Strip off any array subscripts/array section exprs to get to the type of
+ // the variable.
+ while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {
+ if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr))
+ VarExpr = AS->getBase()->IgnoreParenImpCasts();
+ else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr))
+ VarExpr = Sub->getBase()->IgnoreParenImpCasts();
+ }
+
+ // If for some reason the expression is invalid, or this is dependent, just
+ // fill in with nullptr. We'll count on TreeTransform to make this if
+ // necessary.
+ if (!VarExpr || VarExpr->getType()->isDependentType())
+ return nullptr;
+
+ QualType VarTy =
+ VarExpr->getType().getNonReferenceType().getUnqualifiedType();
+
+ VarDecl *Recipe = VarDecl::Create(
+ getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
+ VarExpr->getBeginLoc(),
+ &getASTContext().Idents.get("openacc.private.init"), VarTy,
+ getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
+
+ ExprResult Init;
+
+ {
+ // Trap errors so we don't get weird ones here. If we can't init, we'll just
+ // swallow the errors.
+ Sema::TentativeAnalysisScope Trap{SemaRef};
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);
+ InitializationKind Kind =
+ InitializationKind::CreateDefault(Recipe->getLocation());
+
+ InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
+ Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
+ }
+
+ if (Init.get()) {
+ Recipe->setInit(Init.get());
+ Recipe->setInitStyle(VarDecl::CallInit);
+ }
+
+ return Recipe;
+}
diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp
index b54a0124e9495..9f1a6177b945c 100644
--- a/clang/lib/Sema/SemaOpenACCClause.cpp
+++ b/clang/lib/Sema/SemaOpenACCClause.cpp
@@ -795,9 +795,15 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
// really isn't anything to do here. GCC does some duplicate-finding, though
// it isn't apparent in the standard where this is justified.
- return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
- Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ // Assemble the recipes list.
+ for (const Expr *VarExpr : Clause.getVarList())
+ InitRecipes.push_back(SemaRef.CreateInitRecipe(VarExpr));
+
+ return OpenACCPrivateClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ InitRecipes, Clause.getEndLoc());
}
OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c7428d1a02345..7c9755f301552 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -11730,20 +11730,26 @@ class OpenACCClauseTransform final
SemaOpenACC::OpenACCParsedClause &ParsedClause;
OpenACCClause *NewClause = nullptr;
+ ExprResult VisitVar(Expr *VarRef) {
+ ExprResult Res = Self.TransformExpr(VarRef);
+
+ if (!Res.isUsable())
+ return Res;
+
+ Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
+ ParsedClause.getClauseKind(),
+ Res.get());
+
+ return Res;
+ }
+
llvm::SmallVector<Expr *> VisitVarList(ArrayRef<Expr *> VarList) {
llvm::SmallVector<Expr *> InstantiatedVarList;
for (Expr *CurVar : VarList) {
- ExprResult Res = Self.TransformExpr(CurVar);
-
- if (!Res.isUsable())
- continue;
+ ExprResult VarRef = VisitVar(CurVar);
- Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
- ParsedClause.getClauseKind(),
- Res.get());
-
- if (Res.isUsable())
- InstantiatedVarList.push_back(Res.get());
+ if (VarRef.isUsable())
+ InstantiatedVarList.push_back(VarRef.get());
}
return InstantiatedVarList;
@@ -11870,12 +11876,31 @@ void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitPrivateClause(
const OpenACCPrivateClause &C) {
- ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
+ llvm::SmallVector<Expr *> InstantiatedVarList;
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ for (const auto [RefExpr, InitRecipe] :
+ llvm::zip(C.getVarList(), C.getInitRecipes())) {
+ ExprResult VarRef = VisitVar(RefExpr);
+
+ if (VarRef.isUsable()) {
+ InstantiatedVarList.push_back(VarRef.get());
+
+ // We only have to create a new one if it is dependent, and Sema won't
+ // make one of these unless the type is non-dependent.
+ if (InitRecipe)
+ InitRecipes.push_back(InitRecipe);
+ else
+ InitRecipes.push_back(
+ Self.getSema().OpenACC().CreateInitRecipe(VarRef.get()));
+ }
+ }
+ ParsedClause.setVarListDetails(InstantiatedVarList,
OpenACCModifierKind::Invalid);
NewClause = OpenACCPrivateClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
- ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(), InitRecipes,
ParsedClause.getEndLoc());
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 682d26394c0d5..753b25fb7dade 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12851,8 +12851,13 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
case OpenACCClauseKind::Private: {
SourceLocation LParenLoc = readSourceLocation();
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
+
+ llvm::SmallVector<VarDecl *> RecipeList;
+ for (unsigned I = 0; I < VarList.size(); ++I)
+ RecipeList.push_back(readDeclAs<VarDecl>());
+
return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
- VarList, EndLoc);
+ VarList, RecipeList, EndLoc);
}
case OpenACCClauseKind::Host: {
SourceLocation LParenLoc = readSourceLocation();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a6957e54b66f1..7c637c0d00369 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8738,6 +8738,9 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
const auto *PC = cast<OpenACCPrivateClause>(C);
writeSourceLocation(PC->getLParenLoc());
writeOpenACCVarList(PC);
+
+ for (VarDecl *VD : PC->getInitRecipes())
+ AddDeclRef(VD);
return;
}
case OpenACCClauseKind::Host: {
diff --git a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
index 3306c55b4a8e7..0b58bae9239b2 100644
--- a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
+++ b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
@@ -43,7 +43,24 @@ struct HasDtor {
//
// CHECK-NEXT: acc.private.recipe @privatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
-// CHECK-NEXT: cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
+// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init", init]
+// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<5> : !u64i
+// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ALLOCA]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[LAST_ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_NonDefaultCtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, ["__array_idx"]
+// CHECK-NEXT: cir.store %[[ARRPTR]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.do {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[ELEM_LOAD]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
+// CHECK-NEXT: %[[ONE_CONST:.*]] = cir.const #cir.int<1> : !u64i
+// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_NonDefaultCtor>, %[[ONE_CONST]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.yield
+// CHECK-NEXT: } while {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_Non...
[truncated]
|
@llvm/pr-subscribers-clang-modules Author: Erich Keane (erichkeane) ChangesPreviously, #151360 implemented 'private' clause lowering, but didn't properly initialize the variables. This patch adds that behavior to make sure we correctly get the constructor or other init called. Patch is 32.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/151781.diff 16 Files Affected:
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index 71ad24a427105..32a06bc84ad20 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -837,23 +837,43 @@ class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
class OpenACCPrivateClause final
: public OpenACCClauseWithVarList,
- private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
+ private llvm::TrailingObjects<OpenACCPrivateClause, Expr *, VarDecl *> {
friend TrailingObjects;
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes, SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
LParenLoc, EndLoc) {
- setExprs(getTrailingObjects(VarList.size()), VarList);
+ assert(VarList.size() == InitRecipes.size());
+ setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
+ llvm::uninitialized_copy(InitRecipes, getTrailingObjects<VarDecl *>());
}
public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Private;
}
+ // Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
+ // ensure that we properly initialize each of these variables.
+ ArrayRef<VarDecl *> getInitRecipes() {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
+ ArrayRef<VarDecl *> getInitRecipes() const {
+ return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
+ getExprs().size()};
+ }
+
static OpenACCPrivateClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+ ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc);
+
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return getExprs().size();
+ }
};
class OpenACCFirstPrivateClause final
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index b7e7f5d97bcef..f51045d26e23b 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -241,6 +241,10 @@ class SemaOpenACC : public SemaBase {
SourceLocation ClauseLoc,
ArrayRef<const OpenACCClause *> Clauses);
+ // Creates a VarDecl with a proper default init for the purposes of a
+ // `private` clause, so it can be used to generate a recipe later.
+ VarDecl *CreateInitRecipe(const Expr *VarExpr);
+
public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 60ec10a986e5e..f21e645697656 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -314,14 +314,17 @@ OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C,
return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc);
}
-OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
- SourceLocation BeginLoc,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> VarList,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(
- OpenACCPrivateClause::totalSizeToAlloc<Expr *>(VarList.size()));
- return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
+OpenACCPrivateClause *
+OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
+ ArrayRef<VarDecl *> InitRecipes,
+ SourceLocation EndLoc) {
+ assert(VarList.size() == InitRecipes.size());
+ void *Mem =
+ C.Allocate(OpenACCPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>(
+ VarList.size(), InitRecipes.size()));
+ return new (Mem)
+ OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, InitRecipes, EndLoc);
}
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index c61450e19f1b6..57834ca4a89ca 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2636,6 +2636,9 @@ void OpenACCClauseProfiler::VisitCollapseClause(
void OpenACCClauseProfiler::VisitPrivateClause(
const OpenACCPrivateClause &Clause) {
VisitClauseWithVarList(Clause);
+
+ for (auto *VD : Clause.getInitRecipes())
+ Profiler.VisitDecl(VD);
}
void OpenACCClauseProfiler::VisitFirstPrivateClause(
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
index 32095cb687e88..907cb5fa11401 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp
@@ -119,7 +119,8 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
// Sema has made sure that only 4 types of things can get here, array
// subscript, array section, member expr, or DRE to a var decl (or the
@@ -127,5 +128,6 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
- curVarExpr->getType(), std::move(bounds)};
+ curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
+ std::move(bounds)};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
index 5a6e66550c0bd..bb9054a68b5c7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
@@ -358,8 +358,8 @@ class OpenACCClauseCIREmitter final
template <typename RecipeTy>
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
- DeclContext *dc, QualType baseType,
- mlir::Value mainOp) {
+ const VarDecl *varRecipe, DeclContext *dc,
+ QualType baseType, mlir::Value mainOp) {
mlir::ModuleOp mod =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
@@ -398,12 +398,6 @@ class OpenACCClauseCIREmitter final
auto recipe =
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
- // Magic-up a var-decl so we can use normal init/destruction operations for
- // a variable declaration.
- VarDecl &tempDecl = *VarDecl::Create(
- astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
- &astCtx.Idents.get("openacc.private.init"), baseType,
- astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
CIRGenFunction::AutoVarEmission tempDeclEmission{
CIRGenFunction::AutoVarEmission::invalid()};
@@ -422,9 +416,11 @@ class OpenACCClauseCIREmitter final
"OpenACC non-private recipe init");
}
- tempDeclEmission =
- cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
- cgf.emitAutoVarInit(tempDeclEmission);
+ if (varRecipe) {
+ tempDeclEmission =
+ cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
+ cgf.emitAutoVarInit(tempDeclEmission);
+ }
mlir::acc::YieldOp::create(builder, locEnd);
}
@@ -439,7 +435,7 @@ class OpenACCClauseCIREmitter final
}
// Destroy section (doesn't currently exist).
- if (tempDecl.needsDestruction(cgf.getContext())) {
+ 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(),
@@ -450,7 +446,7 @@ class OpenACCClauseCIREmitter final
mlir::Type elementTy =
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
Address addr{block->getArgument(0), elementTy,
- cgf.getContext().getDeclAlign(&tempDecl)};
+ cgf.getContext().getDeclAlign(varRecipe)};
cgf.emitDestroy(addr, baseType,
cgf.getDestroyer(QualType::DK_cxx_destructor));
@@ -1080,9 +1076,10 @@ class OpenACCClauseCIREmitter final
void VisitPrivateClause(const OpenACCPrivateClause &clause) {
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
mlir::acc::LoopOp>) {
- for (const Expr *var : clause.getVarList()) {
+ for (const auto [varExpr, varRecipe] :
+ llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
CIRGenFunction::OpenACCDataOperandInfo opInfo =
- cgf.getOpenACCDataOperandInfo(var);
+ cgf.getOpenACCDataOperandInfo(varExpr);
auto privateOp = mlir::acc::PrivateOp::create(
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
/*implicit=*/false, opInfo.name, opInfo.bounds);
@@ -1091,8 +1088,9 @@ class OpenACCClauseCIREmitter final
{
mlir::OpBuilder::InsertionGuard guardCase(builder);
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
- cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
- opInfo.baseType, privateOp.getResult());
+ cgf.getContext(), varExpr, varRecipe,
+ 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.
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 8bfea623103e4..8f32817aec48f 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -17,6 +17,7 @@
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/StringExtras.h"
@@ -2552,3 +2553,50 @@ ExprResult
SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
}
+
+VarDecl *SemaOpenACC::CreateInitRecipe(const Expr *VarExpr) {
+ // Strip off any array subscripts/array section exprs to get to the type of
+ // the variable.
+ while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {
+ if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr))
+ VarExpr = AS->getBase()->IgnoreParenImpCasts();
+ else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr))
+ VarExpr = Sub->getBase()->IgnoreParenImpCasts();
+ }
+
+ // If for some reason the expression is invalid, or this is dependent, just
+ // fill in with nullptr. We'll count on TreeTransform to make this if
+ // necessary.
+ if (!VarExpr || VarExpr->getType()->isDependentType())
+ return nullptr;
+
+ QualType VarTy =
+ VarExpr->getType().getNonReferenceType().getUnqualifiedType();
+
+ VarDecl *Recipe = VarDecl::Create(
+ getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
+ VarExpr->getBeginLoc(),
+ &getASTContext().Idents.get("openacc.private.init"), VarTy,
+ getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
+
+ ExprResult Init;
+
+ {
+ // Trap errors so we don't get weird ones here. If we can't init, we'll just
+ // swallow the errors.
+ Sema::TentativeAnalysisScope Trap{SemaRef};
+ InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);
+ InitializationKind Kind =
+ InitializationKind::CreateDefault(Recipe->getLocation());
+
+ InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
+ Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
+ }
+
+ if (Init.get()) {
+ Recipe->setInit(Init.get());
+ Recipe->setInitStyle(VarDecl::CallInit);
+ }
+
+ return Recipe;
+}
diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp
index b54a0124e9495..9f1a6177b945c 100644
--- a/clang/lib/Sema/SemaOpenACCClause.cpp
+++ b/clang/lib/Sema/SemaOpenACCClause.cpp
@@ -795,9 +795,15 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
// really isn't anything to do here. GCC does some duplicate-finding, though
// it isn't apparent in the standard where this is justified.
- return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
- Clause.getLParenLoc(),
- Clause.getVarList(), Clause.getEndLoc());
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ // Assemble the recipes list.
+ for (const Expr *VarExpr : Clause.getVarList())
+ InitRecipes.push_back(SemaRef.CreateInitRecipe(VarExpr));
+
+ return OpenACCPrivateClause::Create(
+ Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
+ InitRecipes, Clause.getEndLoc());
}
OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c7428d1a02345..7c9755f301552 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -11730,20 +11730,26 @@ class OpenACCClauseTransform final
SemaOpenACC::OpenACCParsedClause &ParsedClause;
OpenACCClause *NewClause = nullptr;
+ ExprResult VisitVar(Expr *VarRef) {
+ ExprResult Res = Self.TransformExpr(VarRef);
+
+ if (!Res.isUsable())
+ return Res;
+
+ Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
+ ParsedClause.getClauseKind(),
+ Res.get());
+
+ return Res;
+ }
+
llvm::SmallVector<Expr *> VisitVarList(ArrayRef<Expr *> VarList) {
llvm::SmallVector<Expr *> InstantiatedVarList;
for (Expr *CurVar : VarList) {
- ExprResult Res = Self.TransformExpr(CurVar);
-
- if (!Res.isUsable())
- continue;
+ ExprResult VarRef = VisitVar(CurVar);
- Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
- ParsedClause.getClauseKind(),
- Res.get());
-
- if (Res.isUsable())
- InstantiatedVarList.push_back(Res.get());
+ if (VarRef.isUsable())
+ InstantiatedVarList.push_back(VarRef.get());
}
return InstantiatedVarList;
@@ -11870,12 +11876,31 @@ void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitPrivateClause(
const OpenACCPrivateClause &C) {
- ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
+ llvm::SmallVector<Expr *> InstantiatedVarList;
+ llvm::SmallVector<VarDecl *> InitRecipes;
+
+ for (const auto [RefExpr, InitRecipe] :
+ llvm::zip(C.getVarList(), C.getInitRecipes())) {
+ ExprResult VarRef = VisitVar(RefExpr);
+
+ if (VarRef.isUsable()) {
+ InstantiatedVarList.push_back(VarRef.get());
+
+ // We only have to create a new one if it is dependent, and Sema won't
+ // make one of these unless the type is non-dependent.
+ if (InitRecipe)
+ InitRecipes.push_back(InitRecipe);
+ else
+ InitRecipes.push_back(
+ Self.getSema().OpenACC().CreateInitRecipe(VarRef.get()));
+ }
+ }
+ ParsedClause.setVarListDetails(InstantiatedVarList,
OpenACCModifierKind::Invalid);
NewClause = OpenACCPrivateClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
- ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+ ParsedClause.getLParenLoc(), ParsedClause.getVarList(), InitRecipes,
ParsedClause.getEndLoc());
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 682d26394c0d5..753b25fb7dade 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12851,8 +12851,13 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
case OpenACCClauseKind::Private: {
SourceLocation LParenLoc = readSourceLocation();
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
+
+ llvm::SmallVector<VarDecl *> RecipeList;
+ for (unsigned I = 0; I < VarList.size(); ++I)
+ RecipeList.push_back(readDeclAs<VarDecl>());
+
return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
- VarList, EndLoc);
+ VarList, RecipeList, EndLoc);
}
case OpenACCClauseKind::Host: {
SourceLocation LParenLoc = readSourceLocation();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a6957e54b66f1..7c637c0d00369 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8738,6 +8738,9 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
const auto *PC = cast<OpenACCPrivateClause>(C);
writeSourceLocation(PC->getLParenLoc());
writeOpenACCVarList(PC);
+
+ for (VarDecl *VD : PC->getInitRecipes())
+ AddDeclRef(VD);
return;
}
case OpenACCClauseKind::Host: {
diff --git a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
index 3306c55b4a8e7..0b58bae9239b2 100644
--- a/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
+++ b/clang/test/CIR/CodeGenOpenACC/combined-private-clause.cpp
@@ -43,7 +43,24 @@ struct HasDtor {
//
// CHECK-NEXT: acc.private.recipe @privatization__ZTSA5_14NonDefaultCtor : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> init {
// CHECK-NEXT: ^bb0(%[[ARG:.*]]: !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>> {{.*}}):
-// CHECK-NEXT: cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init"]
+// CHECK-NEXT: %[[ALLOCA:.*]] = cir.alloca !cir.array<!rec_NonDefaultCtor x 5>, !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>, ["openacc.private.init", init]
+// CHECK-NEXT: %[[LAST_IDX:.*]] = cir.const #cir.int<5> : !u64i
+// CHECK-NEXT: %[[ARRPTR:.*]] = cir.cast(array_to_ptrdecay, %[[ALLOCA]] : !cir.ptr<!cir.array<!rec_NonDefaultCtor x 5>>), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[LAST_ELEM:.*]] = cir.ptr_stride(%[[ARRPTR]] : !cir.ptr<!rec_NonDefaultCtor>, %[[LAST_IDX]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: %[[ITR:.*]] = cir.alloca !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, ["__array_idx"]
+// CHECK-NEXT: cir.store %[[ARRPTR]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.do {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>, !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.call @_ZN14NonDefaultCtorC1Ev(%[[ELEM_LOAD]]) : (!cir.ptr<!rec_NonDefaultCtor>) -> ()
+// CHECK-NEXT: %[[ONE_CONST:.*]] = cir.const #cir.int<1> : !u64i
+// CHECK-NEXT: %[[ELEM:.*]] = cir.ptr_stride(%[[ELEM_LOAD]] : !cir.ptr<!rec_NonDefaultCtor>, %[[ONE_CONST]] : !u64i), !cir.ptr<!rec_NonDefaultCtor>
+// CHECK-NEXT: cir.store %[[ELEM]], %[[ITR]] : !cir.ptr<!rec_NonDefaultCtor>, !cir.ptr<!cir.ptr<!rec_NonDefaultCtor>>
+// CHECK-NEXT: cir.yield
+// CHECK-NEXT: } while {
+// CHECK-NEXT: %[[ELEM_LOAD:.*]] = cir.load %[[ITR]] : !cir.ptr<!cir.ptr<!rec_Non...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - Thank you!
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/21194 Here is the relevant piece of the build log for the reference
|
Previously, #151360 implemented 'private' clause lowering, but didn't properly initialize the variables. This patch adds that behavior to make sure we correctly get the constructor or other init called.