Skip to content

Commit 66eadbb

Browse files
authored
[OpenACC][CIR] Implement 'init' lowering for private clause vars (#151781)
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.
1 parent 147cfc8 commit 66eadbb

16 files changed

+305
-53
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -837,23 +837,43 @@ class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
837837

838838
class OpenACCPrivateClause final
839839
: public OpenACCClauseWithVarList,
840-
private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
840+
private llvm::TrailingObjects<OpenACCPrivateClause, Expr *, VarDecl *> {
841841
friend TrailingObjects;
842842

843843
OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
844-
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
844+
ArrayRef<Expr *> VarList,
845+
ArrayRef<VarDecl *> InitRecipes, SourceLocation EndLoc)
845846
: OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
846847
LParenLoc, EndLoc) {
847-
setExprs(getTrailingObjects(VarList.size()), VarList);
848+
assert(VarList.size() == InitRecipes.size());
849+
setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
850+
llvm::uninitialized_copy(InitRecipes, getTrailingObjects<VarDecl *>());
848851
}
849852

850853
public:
851854
static bool classof(const OpenACCClause *C) {
852855
return C->getClauseKind() == OpenACCClauseKind::Private;
853856
}
857+
// Gets a list of 'made up' `VarDecl` objects that can be used by codegen to
858+
// ensure that we properly initialize each of these variables.
859+
ArrayRef<VarDecl *> getInitRecipes() {
860+
return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
861+
getExprs().size()};
862+
}
863+
864+
ArrayRef<VarDecl *> getInitRecipes() const {
865+
return ArrayRef<VarDecl *>{getTrailingObjects<VarDecl *>(),
866+
getExprs().size()};
867+
}
868+
854869
static OpenACCPrivateClause *
855870
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
856-
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
871+
ArrayRef<Expr *> VarList, ArrayRef<VarDecl *> InitRecipes,
872+
SourceLocation EndLoc);
873+
874+
size_t numTrailingObjects(OverloadToken<Expr *>) const {
875+
return getExprs().size();
876+
}
857877
};
858878

859879
class OpenACCFirstPrivateClause final

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ class SemaOpenACC : public SemaBase {
241241
SourceLocation ClauseLoc,
242242
ArrayRef<const OpenACCClause *> Clauses);
243243

244+
// Creates a VarDecl with a proper default init for the purposes of a
245+
// `private` clause, so it can be used to generate a recipe later.
246+
VarDecl *CreateInitRecipe(const Expr *VarExpr);
247+
244248
public:
245249
ComputeConstructInfo &getActiveComputeConstructInfo() {
246250
return ActiveComputeConstructInfo;

clang/lib/AST/OpenACCClause.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,14 +314,17 @@ OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C,
314314
return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc);
315315
}
316316

317-
OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
318-
SourceLocation BeginLoc,
319-
SourceLocation LParenLoc,
320-
ArrayRef<Expr *> VarList,
321-
SourceLocation EndLoc) {
322-
void *Mem = C.Allocate(
323-
OpenACCPrivateClause::totalSizeToAlloc<Expr *>(VarList.size()));
324-
return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
317+
OpenACCPrivateClause *
318+
OpenACCPrivateClause::Create(const ASTContext &C, SourceLocation BeginLoc,
319+
SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
320+
ArrayRef<VarDecl *> InitRecipes,
321+
SourceLocation EndLoc) {
322+
assert(VarList.size() == InitRecipes.size());
323+
void *Mem =
324+
C.Allocate(OpenACCPrivateClause::totalSizeToAlloc<Expr *, VarDecl *>(
325+
VarList.size(), InitRecipes.size()));
326+
return new (Mem)
327+
OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, InitRecipes, EndLoc);
325328
}
326329

327330
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(

clang/lib/AST/StmtProfile.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,6 +2636,9 @@ void OpenACCClauseProfiler::VisitCollapseClause(
26362636
void OpenACCClauseProfiler::VisitPrivateClause(
26372637
const OpenACCPrivateClause &Clause) {
26382638
VisitClauseWithVarList(Clause);
2639+
2640+
for (auto *VD : Clause.getInitRecipes())
2641+
Profiler.VisitDecl(VD);
26392642
}
26402643

26412644
void OpenACCClauseProfiler::VisitFirstPrivateClause(

clang/lib/CIR/CodeGen/CIRGenOpenACC.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,15 @@ CIRGenFunction::getOpenACCDataOperandInfo(const Expr *e) {
119119

120120
if (const auto *memExpr = dyn_cast<MemberExpr>(curVarExpr))
121121
return {exprLoc, emitMemberExpr(memExpr).getPointer(), exprString,
122-
curVarExpr->getType(), std::move(bounds)};
122+
curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
123+
std::move(bounds)};
123124

124125
// Sema has made sure that only 4 types of things can get here, array
125126
// subscript, array section, member expr, or DRE to a var decl (or the
126127
// former 3 wrapping a var-decl), so we should be able to assume this is
127128
// right.
128129
const auto *dre = cast<DeclRefExpr>(curVarExpr);
129130
return {exprLoc, emitDeclRefLValue(dre).getPointer(), exprString,
130-
curVarExpr->getType(), std::move(bounds)};
131+
curVarExpr->getType().getNonReferenceType().getUnqualifiedType(),
132+
std::move(bounds)};
131133
}

clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,8 @@ class OpenACCClauseCIREmitter final
358358

359359
template <typename RecipeTy>
360360
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
361-
DeclContext *dc, QualType baseType,
362-
mlir::Value mainOp) {
361+
const VarDecl *varRecipe, DeclContext *dc,
362+
QualType baseType, mlir::Value mainOp) {
363363
mlir::ModuleOp mod =
364364
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
365365

@@ -398,12 +398,6 @@ class OpenACCClauseCIREmitter final
398398
auto recipe =
399399
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
400400

401-
// Magic-up a var-decl so we can use normal init/destruction operations for
402-
// a variable declaration.
403-
VarDecl &tempDecl = *VarDecl::Create(
404-
astCtx, dc, varRef->getBeginLoc(), varRef->getBeginLoc(),
405-
&astCtx.Idents.get("openacc.private.init"), baseType,
406-
astCtx.getTrivialTypeSourceInfo(baseType), SC_Auto);
407401
CIRGenFunction::AutoVarEmission tempDeclEmission{
408402
CIRGenFunction::AutoVarEmission::invalid()};
409403

@@ -422,9 +416,11 @@ class OpenACCClauseCIREmitter final
422416
"OpenACC non-private recipe init");
423417
}
424418

425-
tempDeclEmission =
426-
cgf.emitAutoVarAlloca(tempDecl, builder.saveInsertionPoint());
427-
cgf.emitAutoVarInit(tempDeclEmission);
419+
if (varRecipe) {
420+
tempDeclEmission =
421+
cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
422+
cgf.emitAutoVarInit(tempDeclEmission);
423+
}
428424

429425
mlir::acc::YieldOp::create(builder, locEnd);
430426
}
@@ -439,7 +435,7 @@ class OpenACCClauseCIREmitter final
439435
}
440436

441437
// Destroy section (doesn't currently exist).
442-
if (tempDecl.needsDestruction(cgf.getContext())) {
438+
if (varRecipe && varRecipe->needsDestruction(cgf.getContext())) {
443439
llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
444440
llvm::SmallVector<mlir::Location> argsLocs{loc};
445441
mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(),
@@ -450,7 +446,7 @@ class OpenACCClauseCIREmitter final
450446
mlir::Type elementTy =
451447
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
452448
Address addr{block->getArgument(0), elementTy,
453-
cgf.getContext().getDeclAlign(&tempDecl)};
449+
cgf.getContext().getDeclAlign(varRecipe)};
454450
cgf.emitDestroy(addr, baseType,
455451
cgf.getDestroyer(QualType::DK_cxx_destructor));
456452

@@ -1080,9 +1076,10 @@ class OpenACCClauseCIREmitter final
10801076
void VisitPrivateClause(const OpenACCPrivateClause &clause) {
10811077
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
10821078
mlir::acc::LoopOp>) {
1083-
for (const Expr *var : clause.getVarList()) {
1079+
for (const auto [varExpr, varRecipe] :
1080+
llvm::zip_equal(clause.getVarList(), clause.getInitRecipes())) {
10841081
CIRGenFunction::OpenACCDataOperandInfo opInfo =
1085-
cgf.getOpenACCDataOperandInfo(var);
1082+
cgf.getOpenACCDataOperandInfo(varExpr);
10861083
auto privateOp = mlir::acc::PrivateOp::create(
10871084
builder, opInfo.beginLoc, opInfo.varValue, /*structured=*/true,
10881085
/*implicit=*/false, opInfo.name, opInfo.bounds);
@@ -1091,8 +1088,9 @@ class OpenACCClauseCIREmitter final
10911088
{
10921089
mlir::OpBuilder::InsertionGuard guardCase(builder);
10931090
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
1094-
cgf.getContext(), var, Decl::castToDeclContext(cgf.curFuncDecl),
1095-
opInfo.baseType, privateOp.getResult());
1091+
cgf.getContext(), varExpr, varRecipe,
1092+
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
1093+
privateOp.getResult());
10961094
// TODO: OpenACC: The dialect is going to change in the near future to
10971095
// have these be on a different operation, so when that changes, we
10981096
// probably need to change these here.

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "clang/Basic/DiagnosticSema.h"
1818
#include "clang/Basic/OpenACCKinds.h"
1919
#include "clang/Basic/SourceManager.h"
20+
#include "clang/Sema/Initialization.h"
2021
#include "clang/Sema/Scope.h"
2122
#include "clang/Sema/Sema.h"
2223
#include "llvm/ADT/StringExtras.h"
@@ -2552,3 +2553,50 @@ ExprResult
25522553
SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
25532554
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
25542555
}
2556+
2557+
VarDecl *SemaOpenACC::CreateInitRecipe(const Expr *VarExpr) {
2558+
// Strip off any array subscripts/array section exprs to get to the type of
2559+
// the variable.
2560+
while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {
2561+
if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr))
2562+
VarExpr = AS->getBase()->IgnoreParenImpCasts();
2563+
else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr))
2564+
VarExpr = Sub->getBase()->IgnoreParenImpCasts();
2565+
}
2566+
2567+
// If for some reason the expression is invalid, or this is dependent, just
2568+
// fill in with nullptr. We'll count on TreeTransform to make this if
2569+
// necessary.
2570+
if (!VarExpr || VarExpr->getType()->isDependentType())
2571+
return nullptr;
2572+
2573+
QualType VarTy =
2574+
VarExpr->getType().getNonReferenceType().getUnqualifiedType();
2575+
2576+
VarDecl *Recipe = VarDecl::Create(
2577+
getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2578+
VarExpr->getBeginLoc(),
2579+
&getASTContext().Idents.get("openacc.private.init"), VarTy,
2580+
getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
2581+
2582+
ExprResult Init;
2583+
2584+
{
2585+
// Trap errors so we don't get weird ones here. If we can't init, we'll just
2586+
// swallow the errors.
2587+
Sema::TentativeAnalysisScope Trap{SemaRef};
2588+
InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);
2589+
InitializationKind Kind =
2590+
InitializationKind::CreateDefault(Recipe->getLocation());
2591+
2592+
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2593+
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2594+
}
2595+
2596+
if (Init.get()) {
2597+
Recipe->setInit(Init.get());
2598+
Recipe->setInitStyle(VarDecl::CallInit);
2599+
}
2600+
2601+
return Recipe;
2602+
}

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -795,9 +795,15 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
795795
// really isn't anything to do here. GCC does some duplicate-finding, though
796796
// it isn't apparent in the standard where this is justified.
797797

798-
return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
799-
Clause.getLParenLoc(),
800-
Clause.getVarList(), Clause.getEndLoc());
798+
llvm::SmallVector<VarDecl *> InitRecipes;
799+
800+
// Assemble the recipes list.
801+
for (const Expr *VarExpr : Clause.getVarList())
802+
InitRecipes.push_back(SemaRef.CreateInitRecipe(VarExpr));
803+
804+
return OpenACCPrivateClause::Create(
805+
Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
806+
InitRecipes, Clause.getEndLoc());
801807
}
802808

803809
OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(

clang/lib/Sema/TreeTransform.h

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11740,20 +11740,26 @@ class OpenACCClauseTransform final
1174011740
SemaOpenACC::OpenACCParsedClause &ParsedClause;
1174111741
OpenACCClause *NewClause = nullptr;
1174211742

11743+
ExprResult VisitVar(Expr *VarRef) {
11744+
ExprResult Res = Self.TransformExpr(VarRef);
11745+
11746+
if (!Res.isUsable())
11747+
return Res;
11748+
11749+
Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
11750+
ParsedClause.getClauseKind(),
11751+
Res.get());
11752+
11753+
return Res;
11754+
}
11755+
1174311756
llvm::SmallVector<Expr *> VisitVarList(ArrayRef<Expr *> VarList) {
1174411757
llvm::SmallVector<Expr *> InstantiatedVarList;
1174511758
for (Expr *CurVar : VarList) {
11746-
ExprResult Res = Self.TransformExpr(CurVar);
11747-
11748-
if (!Res.isUsable())
11749-
continue;
11759+
ExprResult VarRef = VisitVar(CurVar);
1175011760

11751-
Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getDirectiveKind(),
11752-
ParsedClause.getClauseKind(),
11753-
Res.get());
11754-
11755-
if (Res.isUsable())
11756-
InstantiatedVarList.push_back(Res.get());
11761+
if (VarRef.isUsable())
11762+
InstantiatedVarList.push_back(VarRef.get());
1175711763
}
1175811764

1175911765
return InstantiatedVarList;
@@ -11880,12 +11886,31 @@ void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
1188011886
template <typename Derived>
1188111887
void OpenACCClauseTransform<Derived>::VisitPrivateClause(
1188211888
const OpenACCPrivateClause &C) {
11883-
ParsedClause.setVarListDetails(VisitVarList(C.getVarList()),
11889+
llvm::SmallVector<Expr *> InstantiatedVarList;
11890+
llvm::SmallVector<VarDecl *> InitRecipes;
11891+
11892+
for (const auto [RefExpr, InitRecipe] :
11893+
llvm::zip(C.getVarList(), C.getInitRecipes())) {
11894+
ExprResult VarRef = VisitVar(RefExpr);
11895+
11896+
if (VarRef.isUsable()) {
11897+
InstantiatedVarList.push_back(VarRef.get());
11898+
11899+
// We only have to create a new one if it is dependent, and Sema won't
11900+
// make one of these unless the type is non-dependent.
11901+
if (InitRecipe)
11902+
InitRecipes.push_back(InitRecipe);
11903+
else
11904+
InitRecipes.push_back(
11905+
Self.getSema().OpenACC().CreateInitRecipe(VarRef.get()));
11906+
}
11907+
}
11908+
ParsedClause.setVarListDetails(InstantiatedVarList,
1188411909
OpenACCModifierKind::Invalid);
1188511910

1188611911
NewClause = OpenACCPrivateClause::Create(
1188711912
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
11888-
ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
11913+
ParsedClause.getLParenLoc(), ParsedClause.getVarList(), InitRecipes,
1188911914
ParsedClause.getEndLoc());
1189011915
}
1189111916

clang/lib/Serialization/ASTReader.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12854,8 +12854,13 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
1285412854
case OpenACCClauseKind::Private: {
1285512855
SourceLocation LParenLoc = readSourceLocation();
1285612856
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
12857+
12858+
llvm::SmallVector<VarDecl *> RecipeList;
12859+
for (unsigned I = 0; I < VarList.size(); ++I)
12860+
RecipeList.push_back(readDeclAs<VarDecl>());
12861+
1285712862
return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
12858-
VarList, EndLoc);
12863+
VarList, RecipeList, EndLoc);
1285912864
}
1286012865
case OpenACCClauseKind::Host: {
1286112866
SourceLocation LParenLoc = readSourceLocation();

0 commit comments

Comments
 (0)