Skip to content

Support for assume directive : Parse & AST modules #97535

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

Closed
wants to merge 18 commits into from

Conversation

SunilKuravinakop
Copy link
Contributor

Support for assume directive : Parse and AST modules

Sunil Kuravinakop added 7 commits July 1, 2024 03:29
  Changes to be committed:
 	modified:   clang/include/clang/Parse/Parser.h
 	modified:   clang/include/clang/Sema/Sema.h
 	modified:   clang/lib/Basic/OpenMPKinds.cpp
 	modified:   clang/lib/Parse/ParseOpenMP.cpp
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
 	modified:   llvm/include/llvm/Frontend/OpenMP/OMP.td
  Changes to be committed:
 	new file:   clang/test/OpenMP/assume_ast.cpp
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" flang:openmp clang:openmp OpenMP related changes to Clang labels Jul 3, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 3, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-flang-openmp

Author: None (SunilKuravinakop)

Changes

Support for assume directive : Parse and AST modules


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

7 Files Affected:

  • (modified) clang/include/clang/Parse/Parser.h (+2-2)
  • (modified) clang/include/clang/Sema/SemaOpenMP.h (+3)
  • (modified) clang/lib/Basic/OpenMPKinds.cpp (+3)
  • (modified) clang/lib/Parse/ParseOpenMP.cpp (+31-2)
  • (modified) clang/lib/Sema/SemaOpenMP.cpp (+65-1)
  • (added) clang/test/OpenMP/assume_ast.cpp (+43)
  • (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+4)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 6880fa4bb0b03..e9083e98e2baa 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3434,8 +3434,8 @@ class Parser : public CodeCompletionHandler {
                                      SourceLocation Loc);
 
   /// Parse 'omp [begin] assume[s]' directive.
-  void ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
-                                   SourceLocation Loc);
+  StmtResult ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
+                                         SourceLocation Loc);
 
   /// Parse 'omp end assumes' directive.
   void ParseOpenMPEndAssumesDirective(SourceLocation Loc);
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 3edf1cc7c12f2..1831d417877b5 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -106,6 +106,9 @@ class SemaOpenMP : public SemaBase {
   /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
   void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
 
+  /// Act on \p D, Associated statements of `omp assume`.
+  StmtResult ActOnFinishedStatementInOpenMPAssumeScope(Stmt *);
+
   /// Can we exit an OpenMP declare variant scope at the moment.
   bool isInOpenMPDeclareVariantScope() const {
     return !OMPDeclareVariantScopes.empty();
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 766d6a8418a6a..696a819086af1 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -760,6 +760,9 @@ void clang::getOpenMPCaptureRegions(
     case OMPD_parallel:
       CaptureRegions.push_back(OMPD_parallel);
       break;
+    case OMPD_assume:
+      CaptureRegions.push_back(OMPD_assume);
+      break;
     case OMPD_target:
       CaptureRegions.push_back(OMPD_task);
       CaptureRegions.push_back(OMPD_target);
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 326cd22ff9005..9267e8792f0bf 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1682,8 +1682,8 @@ void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
 ///     'no_openmp_routines'
 ///     'no_parallelism'
 ///
-void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
-                                         SourceLocation Loc) {
+StmtResult Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
+                                               SourceLocation Loc) {
   SmallVector<std::string, 4> Assumptions;
   bool SkippedClauses = false;
 
@@ -1759,8 +1759,34 @@ void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
     Assumptions.push_back(Assumption);
   }
 
+  StmtResult AssociatedStmt;
+
+  // Fix the scope for assume.
+  if (DKind == llvm::omp::Directive::OMPD_assume) {
+
+    if (Tok.getKind() == clang::tok::annot_pragma_openmp_end)
+      ConsumeAnyToken();
+
+    DeclarationNameInfo DirName;
+    Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
+  }
+
   Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
                                                SkippedClauses);
+
+  if (DKind == llvm::omp::Directive::OMPD_assume) {
+
+    AssociatedStmt = ParseStatement();
+    AssociatedStmt =
+        Actions.OpenMP().ActOnFinishedStatementInOpenMPAssumeScope(AssociatedStmt.get());
+
+    // End the scope for assume.
+    ParseOpenMPEndAssumesDirective(Loc);
+    Actions.OpenMP().EndOpenMPDSABlock(nullptr);
+    if (Tok.getKind() == clang::tok::annot_pragma_openmp_end)
+      ConsumeAnyToken();
+  }
+  return AssociatedStmt;
 }
 
 void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
@@ -2885,6 +2911,9 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
     }
     break;
   }
+  case OMPD_assume:
+    Directive = ParseOpenMPAssumesDirective(DKind, ConsumeToken());
+    break;
   case OMPD_declare_target: {
     SourceLocation DTLoc = ConsumeAnyToken();
     bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 86666f064f35d..043559c052d57 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3536,7 +3536,8 @@ void SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
 
   auto *AA =
       OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
-  if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
+  if (DKind == llvm::omp::Directive::OMPD_begin_assumes ||
+      DKind == llvm::omp::Directive::OMPD_assume) {
     OMPAssumeScoped.push_back(AA);
     return;
   }
@@ -7323,6 +7324,69 @@ void SemaOpenMP::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
     FD->addAttr(AA);
 }
 
+class OMPAssumeStmtVisitor : public StmtVisitor<OMPAssumeStmtVisitor> {
+  SmallVector<OMPAssumeAttr *, 4> *OMPAssumeScoped;
+
+public:
+  OMPAssumeStmtVisitor(SmallVector<OMPAssumeAttr *, 4> *OMPAssumeScoped) {
+    this->OMPAssumeScoped = OMPAssumeScoped;
+  }
+
+  void VisitCapturedStmt(CapturedStmt *CS) {
+    // To find the CaptureDecl for the CaptureStmt
+    CapturedDecl *CD = CS->getCapturedDecl();
+    if (CD) {
+      for (OMPAssumeAttr *AA : *OMPAssumeScoped)
+        CD->addAttr(AA);
+    }
+  }
+
+  void VisitCompoundStmt(CompoundStmt *CS) {
+    // Handle CompoundStmt
+    // Visit each statement in the CompoundStmt
+    for (Stmt *SubStmt : CS->body()) {
+      if (Expr *CE = dyn_cast<Expr>(SubStmt)) {
+        // If the statement is a Expr, process it
+        VisitExpr(CE);
+      }
+    }
+  }
+
+  void VisitExpr(Expr *CE) {
+    // Handle all Expr
+    for (auto *Child : CE->children()) {
+      Visit(Child);
+    }
+  }
+
+  void Visit(Stmt *S) {
+    const char *CName = S->getStmtClassName();
+    if ((strstr(CName, "OMP") != NULL) &&
+        (strstr(CName, "Directive") != NULL)) {
+      for (Stmt *Child : S->children()) {
+        auto *CS = dyn_cast<CapturedStmt>(Child);
+        if (CS)
+          VisitCapturedStmt(CS);
+        else
+          StmtVisitor<OMPAssumeStmtVisitor>::Visit(Child);
+      }
+    } else {
+      StmtVisitor<OMPAssumeStmtVisitor>::Visit(S);
+    }
+  }
+};
+
+StmtResult
+SemaOpenMP::ActOnFinishedStatementInOpenMPAssumeScope(Stmt *AssociatedStmt) {
+
+  if (AssociatedStmt) {
+    // Add the AssumeAttr to the Directive associated with the Assume Directive.
+    OMPAssumeStmtVisitor Visitor(&OMPAssumeScoped);
+    Visitor.Visit(AssociatedStmt);
+  }
+  return AssociatedStmt;
+}
+
 SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
     : TI(&TI), NameSuffix(TI.getMangledName()) {}
 
diff --git a/clang/test/OpenMP/assume_ast.cpp b/clang/test/OpenMP/assume_ast.cpp
new file mode 100644
index 0000000000000..9f63ac87391a5
--- /dev/null
+++ b/clang/test/OpenMP/assume_ast.cpp
@@ -0,0 +1,43 @@
+// Check no warnings/errors
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+// Check AST and unparsing
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -ast-dump  %s | FileCheck %s --check-prefix=DUMP
+
+// Check same results after serialization round-trip
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -emit-pch -o %t %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
+
+#ifndef HEADER
+#define HEADER
+
+#define N 12
+int A[N];
+int B[N];
+
+
+// DUMP-LABEL:  FunctionDecl {{.*}} main
+int
+main() {
+
+  for (int i = 0; i < N; ++i) {
+    A[i] = 0;
+  }
+
+
+  // assume is for the "simd" region
+  // DUMP:      OMPSimdDirective
+  // DUMP-NEXT:   CapturedStmt
+  // DUMP-NEXT:   CapturedDecl
+  #pragma omp assume no_openmp
+  #pragma omp simd
+  for (int i = 0; i < N; ++i){
+    A[i] += B[i];
+  }
+  // DUMP:  OMPAssumeAttr {{.*}} "omp_no_openmp"
+
+  return 0;
+}
+
+#endif
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 005c678302b27..aac86bc8d7bc4 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -502,6 +502,10 @@ def OMP_Allocators : Directive<"allocators"> {
   let association = AS_Block;
   let category = CA_Executable;
 }
+def OMP_Assume : Directive<"assume"> {
+  let association = AS_None;
+  let category = CA_Informational;
+}
 def OMP_Assumes : Directive<"assumes"> {
   let association = AS_None;
   let category = CA_Informational;

Copy link

github-actions bot commented Jul 3, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

  Changes to be committed:
 	modified:   clang/lib/Parse/ParseOpenMP.cpp
@chichunchen chichunchen requested a review from alexey-bataev July 3, 2024 15:29
@@ -760,6 +760,9 @@ void clang::getOpenMPCaptureRegions(
case OMPD_parallel:
CaptureRegions.push_back(OMPD_parallel);
break;
case OMPD_assume:
CaptureRegions.push_back(OMPD_assume);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assume ends up with a simple assume intrinsic, right? Most probably non need to emit captured function, so it should be OMPD_unknown

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have corrected this. Thank you.

@@ -1759,8 +1759,35 @@ void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
Assumptions.push_back(Assumption);
}

StmtResult AssociatedStmt;

// Fix the scope for assume.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with the scope?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error was in the wording in the comment. I have corrected it to "Begin marking the scope for assume."

Comment on lines 7384 to 7385
OMPAssumeStmtVisitor Visitor(&OMPAssumeScoped);
Visitor.Visit(AssociatedStmt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need to do this?

Copy link
Contributor Author

@SunilKuravinakop SunilKuravinakop Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the code which ensures that :
-OMPAssumeAttr with the accompanying clauses of assume
is added to the statement associated with the assume directive. The test case attached with this upload checks for the OMPAssumeAttr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need the visitor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the example is :

// assume is for the "simd" region
 #pragma omp assume no_openmp
 #pragma omp simd
 for (int i = 0; i < N; ++i){
   A[i] += B[i];
 }

then in -ast-dump for:

    |-OMPSimdDirective 0x15cc6a0 <line:22:3, col:19>
    |  `-CapturedStmt 0x15b0d98 <line:23:3, line:25:3>
    |    `-CapturedDecl 0x15b0960 <<invalid sloc>> <invalid sloc>
    |     |
    |     |-OMPAssumeAttr 0x15b07b0 <line:21:15> "omp_no_openmp"

needs to be added. Also, according to the spec :
The scope of the assume directive is the code executed in the corresponding region or in any region that is nested in the corresponding region.
Is there a better way to add this other than having
OMPAssumeStmtVisitor::VisitCapturedStmt( )

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it is not enough to mark just the outer region? The fact that it is applied to nested regions can be hanf]dled in the codegen

1) assume ends up with a simple assume intrinsic, right? Most probably non need to emit captured function, so it should be OMPD_unknown
2) "Fix the scope for assume" reworded to "Begin marking the scope for assume."
 	modified:   clang/lib/Basic/OpenMPKinds.cpp
 	modified:   clang/lib/Parse/ParseOpenMP.cpp
 	modified:   clang/test/OpenMP/assume_ast.cpp
Comment on lines 1765 to 1773
if (DKind == llvm::omp::Directive::OMPD_assume) {

if (Tok.getKind() == clang::tok::annot_pragma_openmp_end)
ConsumeAnyToken();

DeclarationNameInfo DirName;
Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
Loc);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introduce RAAI class for this and use it instead

Comment on lines 7384 to 7385
OMPAssumeStmtVisitor Visitor(&OMPAssumeScoped);
Visitor.Visit(AssociatedStmt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it is not enough to mark just the outer region? The fact that it is applied to nested regions can be hanf]dled in the codegen

@cor3ntin
Copy link
Contributor

Can we get a more specific title for this PR? thanks!

Comment on lines 763 to 765
case OMPD_assume:
CaptureRegions.push_back(OMPD_unknown);
break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't push OMPD_unknown here, instead add OMPD_assume to the directives at lines 790+.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please add OMPD_assume to isOpenMPCapturingDirective.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? We usually add OMPD_unknown to the directives that do nit require outlining to a standalone function, here should be the same behavior.

Copy link
Contributor

@kparzysz kparzysz Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what happens with the directives at lines 790+ (before these changes). We don't want to be adding OMPD_unknown as we go, because it can end up intermingled with other directives (in case of combined directives). I understand that OMPD_assume may be standalone, but we should treat it the same as the combinable ones for consistency.
Edit: typo OMPD_assumes -> OMPD_assume.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may affect codegen + may add some memory overhead

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final output from this (global) function will be the same, so it shouldn't affect codegen.

@SunilKuravinakop SunilKuravinakop changed the title Assume Support for assume directive : Parse & AST modules Jul 10, 2024
Sunil Kuravinakop added 2 commits July 15, 2024 13:17
2) returning OMPD_assume in clang/lib/Basic/OpenMPKinds.cpp.

  Changes to be committed:
 	modified:   clang/include/clang/Parse/Parser.h
 	modified:   clang/lib/Basic/OpenMPKinds.cpp
 	modified:   clang/lib/Parse/ParseOpenMP.cpp
@SunilKuravinakop
Copy link
Contributor Author

In clang/lib/Sema/SemaOpenMP.cpp I have retained the marking of the inner regions of the associated statements with AssumeAttr. This will make the work in Codegen easier.

@@ -488,6 +488,49 @@ class Parser : public CodeCompletionHandler {
/// a statement expression and builds a suitable expression statement.
StmtResult handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx);

class AssumeParseAssociatedStmtRAII {
Parser *parent;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Parser *parent;
Parser &Parent;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I am creating instance of AssumeParseAssociatedStmtRAII in Parser::ParseOpenMPAssumesDirective() I have to store Parent as a pointer. The creation of the instance is done as :
AssumeParseAssociatedStmtRAII AssumeParseAssocRAII(this, Loc, DKind);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass it as *this

Comment on lines 496 to 498
AssumeParseAssociatedStmtRAII(Parser *parent, SourceLocation Loc,
OpenMPDirectiveKind DKind)
: parent(parent), DKind(DKind) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AssumeParseAssociatedStmtRAII(Parser *parent, SourceLocation Loc,
OpenMPDirectiveKind DKind)
: parent(parent), DKind(DKind) {
AssumeParseAssociatedStmtRAII(Parser &Parent, SourceLocation Loc,
OpenMPDirectiveKind DKind)
: Parent(Parent), DKind(DKind) {

Sunil Kuravinakop added 4 commits July 15, 2024 15:03
 	modified:   clang/include/clang/Parse/Parser.h
2) Changing "Parent" to "&Parent".

 	modified:   clang/include/clang/Parse/Parser.h
 	modified:   clang/lib/Parse/ParseOpenMP.cpp
@alexey-bataev
Copy link
Member

In clang/lib/Sema/SemaOpenMP.cpp I have retained the marking of the inner regions of the associated statements with AssumeAttr. This will make the work in Codegen easier.

How it will make the codegen easier? It is better to try to avoid post-building attribute assignment, if possible. If possible to add attribute on the region build, better to do it.

Sunil Kuravinakop and others added 3 commits July 17, 2024 06:57
executed in the corresponding region or in any region that is nested in the
corresponding region". Moving the marking of the nested regions into
Codegen. Marking the outer Associated Statement provides sufficient
information.

  Changes to be committed:
 	modified:   clang/lib/Sema/SemaOpenMP.cpp
@SunilKuravinakop
Copy link
Contributor Author

Changes to omp assume was done by Julian Brown from AMD on August 5th, #92731
git log:

commit a42e515e3a9f3bb4e44389c097b89104d95b9b29
Author: Julian Brown <julian.brown@amd.com>
Date:   Mon Aug 5 12:37:07 2024 +0100

Hence closing this pull request.

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:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category flang:openmp
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants