Skip to content

Conversation

erichkeane
Copy link
Collaborator

This is the first patch of a handful to get the reduction combiner recipe lowering properly. THIS patch is NFC as it doesn't actually change anything except the structure of the AST.

For each 'combiner' recipe we need a 'LHS' 'RHS' and expression to represent the operation.

Each var-reference can have 1 or more combiners.

IF it is a plain scalar, or a struct with the proper operator, or an array of either of those, there will be 1.

HOWEVER, aggregates without the proper operator are supposed to be broken down and done from their elements (which can only be scalars). In this case, we will represent 1 'combiner' recipe per field-decl.

This patch only puts the infrastructure in place to do so, future patches wll do the work to fill this in.

This is the first patch of a handful to get the reduction combiner recipe lowering properly. THIS patch is NFC as it doesn't actually change anything except the structure of the AST. For each 'combiner' recipe we need a 'LHS' 'RHS' and expression to represent the operation. Each var-reference can have 1 or more combiners. IF it is a plain scalar, or a struct with the proper operator, or an array of either of those, there will be 1. HOWEVER, aggregates without the proper operator are supposed to be broken down and done from their elements (which can only be scalars). In this case, we will represent 1 'combiner' recipe per field-decl. This patch only puts the infrastructure in place to do so, future patches wll do the work to fill this in.
@erichkeane erichkeane requested review from mmha and andykaylor October 8, 2025 23:44
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Oct 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Erich Keane (erichkeane)

Changes

This is the first patch of a handful to get the reduction combiner recipe lowering properly. THIS patch is NFC as it doesn't actually change anything except the structure of the AST.

For each 'combiner' recipe we need a 'LHS' 'RHS' and expression to represent the operation.

Each var-reference can have 1 or more combiners.

IF it is a plain scalar, or a struct with the proper operator, or an array of either of those, there will be 1.

HOWEVER, aggregates without the proper operator are supposed to be broken down and done from their elements (which can only be scalars). In this case, we will represent 1 'combiner' recipe per field-decl.

This patch only puts the infrastructure in place to do so, future patches wll do the work to fill this in.


Full diff: https://github.com/llvm/llvm-project/pull/162573.diff

5 Files Affected:

  • (modified) clang/include/clang/AST/OpenACCClause.h (+21-3)
  • (modified) clang/lib/AST/StmtProfile.cpp (+10-1)
  • (modified) clang/lib/Sema/SemaOpenACC.cpp (+1-1)
  • (modified) clang/lib/Serialization/ASTReader.cpp (+15-2)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (+10-1)
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h index 58ba8d91f1277..79cffeb4dade9 100644 --- a/clang/include/clang/AST/OpenACCClause.h +++ b/clang/include/clang/AST/OpenACCClause.h @@ -1280,13 +1280,31 @@ class OpenACCCreateClause final // 'main' declaration used for initializaiton, which is fixed. struct OpenACCReductionRecipe { VarDecl *AllocaDecl; - // TODO: OpenACC: this should eventually have the operations here too. - OpenACCReductionRecipe(VarDecl *A) : AllocaDecl(A) {} + // A combiner recipe is represented by an operation expression. However, in + // order to generate these properly, we have to make up a LHS and a RHS + // expression for the purposes of generation. + struct CombinerRecipe { + VarDecl *LHS; + VarDecl *RHS; + Expr *Op; + }; + + // Contains a collection of the recipe elements we need for the combiner: + // -For Scalars, there will be 1 element, just the combiner for that scalar. + // -For a struct with a valid operator, this will be 1 element, just that + // call. + // -For a struct without the operator, this will be 1 element per field, which + // should be the combiner for that element. + // -For an array of any of the above, it will be the above for the element. + llvm::SmallVector<CombinerRecipe, 1> CombinerRecipes; + + OpenACCReductionRecipe(VarDecl *A, llvm::ArrayRef<CombinerRecipe> Combiners) + : AllocaDecl(A), CombinerRecipes(Combiners) {} bool isSet() const { return AllocaDecl; } static OpenACCReductionRecipe Empty() { - return OpenACCReductionRecipe(/*AllocaDecl=*/nullptr); + return OpenACCReductionRecipe(/*AllocaDecl=*/nullptr, {}); } }; diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index f3b5478222488..3cd033e73800f 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2769,10 +2769,19 @@ void OpenACCClauseProfiler::VisitReductionClause( for (auto &Recipe : Clause.getRecipes()) { Profiler.VisitDecl(Recipe.AllocaDecl); + // 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 *)); + static_assert(sizeof(OpenACCReductionRecipe::CombinerRecipe) == + 3 * sizeof(int *)); + for (auto &CombinerRecipe : Recipe.CombinerRecipes) { + if (CombinerRecipe.Op) { + Profiler.VisitDecl(CombinerRecipe.LHS); + Profiler.VisitDecl(CombinerRecipe.RHS); + Profiler.VisitStmt(CombinerRecipe.Op); + } + } } } diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 8471f02f323d6..4824b5a3082a4 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -2946,5 +2946,5 @@ OpenACCReductionRecipe SemaOpenACC::CreateReductionInitRecipe( AllocaDecl->setInit(Init.get()); AllocaDecl->setInitStyle(VarDecl::CallInit); } - return OpenACCReductionRecipe(AllocaDecl); + return OpenACCReductionRecipe(AllocaDecl, {}); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 6acf79acea111..868f0cc8b1da7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -13009,9 +13009,22 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() { llvm::SmallVector<OpenACCReductionRecipe> RecipeList; for (unsigned I = 0; I < VarList.size(); ++I) { - static_assert(sizeof(OpenACCReductionRecipe) == sizeof(int *)); VarDecl *Recipe = readDeclAs<VarDecl>(); - RecipeList.push_back({Recipe}); + + static_assert(sizeof(OpenACCReductionRecipe::CombinerRecipe) == + 3 * sizeof(int *)); + + llvm::SmallVector<OpenACCReductionRecipe::CombinerRecipe> Combiners; + unsigned NumCombiners = readInt(); + for (unsigned I = 0; I < NumCombiners; ++I) { + VarDecl *LHS = readDeclAs<VarDecl>(); + VarDecl *RHS = readDeclAs<VarDecl>(); + Expr *Op = readExpr(); + + Combiners.push_back({LHS, RHS, Op}); + } + + RecipeList.push_back({Recipe, Combiners}); } return OpenACCReductionClause::Create(getContext(), BeginLoc, LParenLoc, Op, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 09b1e58ef220c..82ccde84de37d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -8925,8 +8925,17 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeOpenACCVarList(RC); for (const OpenACCReductionRecipe &R : RC->getRecipes()) { - static_assert(sizeof(OpenACCReductionRecipe) == 1 * sizeof(int *)); AddDeclRef(R.AllocaDecl); + + static_assert(sizeof(OpenACCReductionRecipe::CombinerRecipe) == + 3 * sizeof(int *)); + writeUInt32(R.CombinerRecipes.size()); + + for (auto &CombinerRecipe : R.CombinerRecipes) { + AddDeclRef(CombinerRecipe.LHS); + AddDeclRef(CombinerRecipe.RHS); + AddStmt(CombinerRecipe.Op); + } } return; } 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
2 participants