[OpenACC][NFCI] Add AST Infrastructure for reduction recipes

This patch does the bare minimum to start setting up the reduction
recipe support, including adding a type to the AST to store it. No real
additional work is done, and a bunch of static_asserts are left around
to allow us to do this properly.
This commit is contained in:
erichkeane 2025-08-19 07:39:33 -07:00
parent 50a3368f22
commit d0dc3799b7
9 changed files with 102 additions and 20 deletions

View File

@ -1250,19 +1250,32 @@ public:
SourceLocation EndLoc);
};
// A structure to stand in for the recipe on a reduction. RecipeDecl is the
// 'main' declaration used for initializaiton, which is fixed.
struct OpenACCReductionRecipe {
VarDecl *RecipeDecl;
// TODO: OpenACC: this should eventually have the operations here too.
};
class OpenACCReductionClause final
: public OpenACCClauseWithVarList,
private llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
private llvm::TrailingObjects<OpenACCReductionClause, Expr *,
OpenACCReductionRecipe> {
friend TrailingObjects;
OpenACCReductionOperator Op;
OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator Operator,
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
ArrayRef<Expr *> VarList,
ArrayRef<OpenACCReductionRecipe> Recipes,
SourceLocation EndLoc)
: OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
LParenLoc, EndLoc),
Op(Operator) {
setExprs(getTrailingObjects(VarList.size()), VarList);
assert(VarList.size() == Recipes.size());
setExprs(getTrailingObjects<Expr *>(VarList.size()), VarList);
llvm::uninitialized_copy(Recipes, getTrailingObjects<
OpenACCReductionRecipe > ());
}
public:
@ -1270,12 +1283,26 @@ public:
return C->getClauseKind() == OpenACCClauseKind::Reduction;
}
ArrayRef<OpenACCReductionRecipe> getRecipes() {
return ArrayRef<OpenACCReductionRecipe>{
getTrailingObjects<OpenACCReductionRecipe>(), getExprs().size()};
}
ArrayRef<OpenACCReductionRecipe> getRecipes() const {
return ArrayRef<OpenACCReductionRecipe>{
getTrailingObjects<OpenACCReductionRecipe>(), getExprs().size()};
}
static OpenACCReductionClause *
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
SourceLocation EndLoc);
ArrayRef<OpenACCReductionRecipe> Recipes, SourceLocation EndLoc);
OpenACCReductionOperator getReductionOp() const { return Op; }
size_t numTrailingObjects(OverloadToken<Expr *>) const {
return getExprs().size();
}
};
class OpenACCLinkClause final

View File

@ -947,12 +947,12 @@ public:
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
// Does the checking for a 'reduction ' clause that needs to be done in
// dependent and not dependent cases.
OpenACCClause *
CheckReductionClause(ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirectiveKind,
SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator ReductionOp,
ArrayRef<Expr *> Vars, SourceLocation EndLoc);
OpenACCClause *CheckReductionClause(
ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
ArrayRef<Expr *> Vars, ArrayRef<OpenACCReductionRecipe> Recipes,
SourceLocation EndLoc);
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);

View File

@ -506,11 +506,13 @@ OpenACCDeviceTypeClause *OpenACCDeviceTypeClause::Create(
OpenACCReductionClause *OpenACCReductionClause::Create(
const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
ArrayRef<OpenACCReductionRecipe> Recipes,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCReductionClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem)
OpenACCReductionClause(BeginLoc, LParenLoc, Operator, VarList, EndLoc);
OpenACCReductionClause::totalSizeToAlloc<Expr *, OpenACCReductionRecipe>(
VarList.size(), Recipes.size()));
return new (Mem) OpenACCReductionClause(BeginLoc, LParenLoc, Operator,
VarList, Recipes, EndLoc);
}
OpenACCAutoClause *OpenACCAutoClause::Create(const ASTContext &C,

View File

@ -2748,6 +2748,14 @@ void OpenACCClauseProfiler::VisitGangClause(const OpenACCGangClause &Clause) {
void OpenACCClauseProfiler::VisitReductionClause(
const OpenACCReductionClause &Clause) {
VisitClauseWithVarList(Clause);
for (auto &Recipe : Clause.getRecipes()) {
Profiler.VisitDecl(Recipe.RecipeDecl);
// TODO: OpenACC: Make sure we remember to update this when we figure out
// what we're adding for the operation recipe, in the meantime, a static
// assert will make sure we don't add something.
static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int *));
}
}
void OpenACCClauseProfiler::VisitBindClause(const OpenACCBindClause &Clause) {

View File

@ -1774,18 +1774,27 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
}
SmallVector<Expr *> ValidVars;
SmallVector<OpenACCReductionRecipe> Recipes;
for (Expr *Var : Clause.getVarList()) {
ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),
Clause.getReductionOp(), Var);
if (Res.isUsable())
if (Res.isUsable()) {
ValidVars.push_back(Res.get());
VarDecl *InitRecipe =
SemaRef.CreateInitRecipe(OpenACCClauseKind::Reduction, Res.get())
.first;
// TODO: OpenACC: Create the reduction operation recipe here too.
Recipes.push_back({InitRecipe});
}
}
return SemaRef.CheckReductionClause(
ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,
Recipes,
Clause.getEndLoc());
}
@ -2158,7 +2167,8 @@ OpenACCClause *SemaOpenACC::CheckReductionClause(
ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
ArrayRef<Expr *> Vars, SourceLocation EndLoc) {
ArrayRef<Expr *> Vars, ArrayRef<OpenACCReductionRecipe> Recipes,
SourceLocation EndLoc) {
if (DirectiveKind == OpenACCDirectiveKind::Loop ||
isOpenACCCombinedDirectiveKind(DirectiveKind)) {
// OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
@ -2187,7 +2197,7 @@ OpenACCClause *SemaOpenACC::CheckReductionClause(
}
auto *Ret = OpenACCReductionClause::Create(
getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, EndLoc);
getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, Recipes, EndLoc);
return Ret;
}

View File

@ -12295,18 +12295,36 @@ void OpenACCClauseTransform<Derived>::VisitReductionClause(
const OpenACCReductionClause &C) {
SmallVector<Expr *> TransformedVars = VisitVarList(C.getVarList());
SmallVector<Expr *> ValidVars;
llvm::SmallVector<OpenACCReductionRecipe> Recipes;
for (Expr *Var : TransformedVars) {
for (const auto [Var, OrigRecipes] :
llvm::zip(TransformedVars, C.getRecipes())) {
ExprResult Res = Self.getSema().OpenACC().CheckReductionVar(
ParsedClause.getDirectiveKind(), C.getReductionOp(), Var);
if (Res.isUsable())
if (Res.isUsable()) {
ValidVars.push_back(Res.get());
// TODO OpenACC: When the recipe changes, make sure we get these right
// too. We probably need something similar for the operation.
static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int*));
VarDecl *InitRecipe = nullptr;
if (OrigRecipes.RecipeDecl)
InitRecipe = OrigRecipes.RecipeDecl;
else
InitRecipe =
Self.getSema()
.OpenACC()
.CreateInitRecipe(OpenACCClauseKind::Reduction, Res.get())
.first;
Recipes.push_back({InitRecipe});
}
}
NewClause = Self.getSema().OpenACC().CheckReductionClause(
ExistingClauses, ParsedClause.getDirectiveKind(),
ParsedClause.getBeginLoc(), ParsedClause.getLParenLoc(),
C.getReductionOp(), ValidVars, ParsedClause.getEndLoc());
C.getReductionOp(), ValidVars, Recipes, ParsedClause.getEndLoc());
}
template <typename Derived>

View File

@ -12996,8 +12996,16 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
SourceLocation LParenLoc = readSourceLocation();
OpenACCReductionOperator Op = readEnum<OpenACCReductionOperator>();
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
llvm::SmallVector<OpenACCReductionRecipe> RecipeList;
for (unsigned I = 0; I < VarList.size(); ++I) {
VarDecl *Recipe = readDeclAs<VarDecl>();
static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int *));
RecipeList.push_back({Recipe});
}
return OpenACCReductionClause::Create(getContext(), BeginLoc, LParenLoc, Op,
VarList, EndLoc);
VarList, RecipeList, EndLoc);
}
case OpenACCClauseKind::Seq:
return OpenACCSeqClause::Create(getContext(), BeginLoc, EndLoc);

View File

@ -8886,6 +8886,11 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeSourceLocation(RC->getLParenLoc());
writeEnum(RC->getReductionOp());
writeOpenACCVarList(RC);
for (const OpenACCReductionRecipe &R : RC->getRecipes()) {
static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int *));
AddDeclRef(R.RecipeDecl);
}
return;
}
case OpenACCClauseKind::Seq:

View File

@ -2928,6 +2928,10 @@ void OpenACCClauseEnqueue::VisitDeviceTypeClause(
void OpenACCClauseEnqueue::VisitReductionClause(
const OpenACCReductionClause &C) {
VisitVarList(C);
for (const OpenACCReductionRecipe &R : C.getRecipes()) {
static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int *));
Visitor.AddDecl(R.RecipeDecl);
}
}
void OpenACCClauseEnqueue::VisitAutoClause(const OpenACCAutoClause &C) {}
void OpenACCClauseEnqueue::VisitIndependentClause(