https://github.com/erichkeane created 
https://github.com/llvm/llvm-project/pull/162573

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.

>From 8d4b3d657f2c249738797320b227daafaed66e34 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Wed, 8 Oct 2025 16:40:50 -0700
Subject: [PATCH] [OpenACC][NFC] AST changes for Reduction combiner

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.
---
 clang/include/clang/AST/OpenACCClause.h | 24 +++++++++++++++++++++---
 clang/lib/AST/StmtProfile.cpp           | 11 ++++++++++-
 clang/lib/Sema/SemaOpenACC.cpp          |  2 +-
 clang/lib/Serialization/ASTReader.cpp   | 17 +++++++++++++++--
 clang/lib/Serialization/ASTWriter.cpp   | 11 ++++++++++-
 5 files changed, 57 insertions(+), 8 deletions(-)

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;
   }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to