Skip to content

Adding parsing support for omp loop, target loop directives #93517

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

Merged
merged 2 commits into from
Jun 21, 2024

Conversation

anchuraj
Copy link
Contributor

Change adds parsing support for omp loop, omp target loop, omp target parallel loop and omp target teams loop.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp flang:semantics flang:parser clang:openmp OpenMP related changes to Clang labels May 28, 2024
@llvmbot
Copy link
Member

llvmbot commented May 28, 2024

@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-flang-semantics

Author: Anchu Rajendran S (anchuraj)

Changes

Change adds parsing support for omp loop, omp target loop, omp target parallel loop and omp target teams loop.


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

7 Files Affected:

  • (modified) flang/include/flang/Semantics/openmp-directive-sets.h (+1)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+7)
  • (modified) flang/lib/Parser/unparse.cpp (+12)
  • (modified) flang/lib/Semantics/resolve-directives.cpp (+4)
  • (added) flang/test/Lower/OpenMP/Todo/loop-directive.f90 (+15)
  • (added) flang/test/Parser/OpenMP/target-loop-unparse.f90 (+53)
  • (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+29)
diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h
index da66e0eda3216..8eb736bb098fe 100644
--- a/flang/include/flang/Semantics/openmp-directive-sets.h
+++ b/flang/include/flang/Semantics/openmp-directive-sets.h
@@ -242,6 +242,7 @@ static const OmpDirectiveSet loopConstructSet{
     Directive::OMPD_parallel_master_taskloop,
     Directive::OMPD_parallel_master_taskloop_simd,
     Directive::OMPD_simd,
+    Directive::OMPD_target_loop,
     Directive::OMPD_target_parallel_do,
     Directive::OMPD_target_parallel_do_simd,
     Directive::OMPD_target_parallel_loop,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index e67dbcca30e7d..cc6b7b2c60913 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -378,6 +378,7 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
     "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
     "DO" >> pure(llvm::omp::Directive::OMPD_do),
+    "LOOP" >> pure(llvm::omp::Directive::OMPD_loop),
     "MASKED TASKLOOP SIMD" >>
         pure(llvm::omp::Directive::OMPD_masked_taskloop_simd),
     "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop),
@@ -388,9 +389,13 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "PARALLEL MASKED TASKLOOP" >>
         pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop),
     "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
+    "TARGET LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_loop),
     "TARGET PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
     "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
+    "TARGET PARALLEL LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_parallel_loop),
     "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
     "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::
@@ -401,6 +406,8 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
         pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
     "TARGET TEAMS DISTRIBUTE" >>
         pure(llvm::omp::Directive::OMPD_target_teams_distribute),
+    "TARGET TEAMS LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_teams_loop),
     "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
     "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
     "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index bdd968b19a43f..8131d336b5eb9 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2194,6 +2194,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_do_simd:
       Word("DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_loop:
+      Word("LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_masked_taskloop_simd:
       Word("MASKED TASKLOOP SIMD");
       break;
@@ -2215,12 +2218,18 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_simd:
       Word("SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_loop:
+      Word("TARGET LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_parallel_do:
       Word("TARGET PARALLEL DO ");
       break;
     case llvm::omp::Directive::OMPD_target_parallel_do_simd:
       Word("TARGET PARALLEL DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_parallel_loop:
+      Word("TARGET PARALLEL LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_teams_distribute:
       Word("TARGET TEAMS DISTRIBUTE ");
       break;
@@ -2233,6 +2242,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
       Word("TARGET TEAMS DISTRIBUTE SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_teams_loop:
+      Word("TARGET TEAMS LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_simd:
       Word("TARGET SIMD ");
       break;
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index dbc531372c3f4..789e0f089fe6a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1602,6 +1602,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_distribute_simd:
   case llvm::omp::Directive::OMPD_do:
   case llvm::omp::Directive::OMPD_do_simd:
+  case llvm::omp::Directive::OMPD_loop:
   case llvm::omp::Directive::OMPD_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_masked_taskloop:
   case llvm::omp::Directive::OMPD_parallel_do:
@@ -1609,12 +1610,15 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop:
   case llvm::omp::Directive::OMPD_simd:
+  case llvm::omp::Directive::OMPD_target_loop:
   case llvm::omp::Directive::OMPD_target_parallel_do:
   case llvm::omp::Directive::OMPD_target_parallel_do_simd:
+  case llvm::omp::Directive::OMPD_target_parallel_loop:
   case llvm::omp::Directive::OMPD_target_teams_distribute:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
   case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
+  case llvm::omp::Directive::OMPD_target_teams_loop:
   case llvm::omp::Directive::OMPD_target_simd:
   case llvm::omp::Directive::OMPD_taskloop:
   case llvm::omp::Directive::OMPD_taskloop_simd:
diff --git a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
new file mode 100644
index 0000000000000..f1aea70458aa6
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
@@ -0,0 +1,15 @@
+! This test checks lowering of OpenMP loop Directive.
+
+! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: Unhandled directive loop
+subroutine test_loop()
+  integer :: i, j = 1
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
diff --git a/flang/test/Parser/OpenMP/target-loop-unparse.f90 b/flang/test/Parser/OpenMP/target-loop-unparse.f90
new file mode 100644
index 0000000000000..3ee2fcef075a3
--- /dev/null
+++ b/flang/test/Parser/OpenMP/target-loop-unparse.f90
@@ -0,0 +1,53 @@
+
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+! Check for parsing of loop directive
+
+subroutine test_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = loop
+  !CHECK: !$omp loop
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
+subroutine test_target_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target loop
+  !CHECK: !$omp target loop
+  !$omp target loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target loop
+end subroutine
+
+subroutine test_target_teams_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams loop
+  !CHECK: !$omp target teams loop
+  !$omp target teams loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target teams loop
+end subroutine
+
+subroutine test_target_parallel_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel loop
+  !CHECK: !$omp target parallel loop
+  !$omp target parallel loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target parallel loop
+end subroutine
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e91169e8da1aa..e4c7df5f11208 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -2232,6 +2232,35 @@ def OMP_teams_loop : Directive<"teams loop"> {
   ];
   let leafConstructs = [OMP_Teams, OMP_loop];
 }
+def OMP_target_loop : Directive<"target loop"> {
+  let allowedClauses = [
+    VersionedClause<OMPC_Allocate>,
+    VersionedClause<OMPC_Depend>,
+    VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_IsDevicePtr>,
+    VersionedClause<OMPC_HasDeviceAddr, 51>,
+    VersionedClause<OMPC_LastPrivate>,
+    VersionedClause<OMPC_Map>,
+    VersionedClause<OMPC_Private>,
+    VersionedClause<OMPC_Reduction>,
+    VersionedClause<OMPC_UsesAllocators, 50>,
+    VersionedClause<OMPC_OMPX_Attribute>,
+    VersionedClause<OMPC_InReduction, 50>,
+
+  ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_Bind, 50>,
+    VersionedClause<OMPC_Collapse>,
+    VersionedClause<OMPC_Order>,
+    VersionedClause<OMPC_ThreadLimit>,
+    VersionedClause<OMPC_OMPX_DynCGroupMem>,
+    VersionedClause<OMPC_If>,
+    VersionedClause<OMPC_Device>,
+    VersionedClause<OMPC_DefaultMap>,
+    VersionedClause<OMPC_NoWait>,
+  ];
+  let leafConstructs = [OMP_Target, OMP_loop];
+}
 def OMP_target_teams_loop : Directive<"target teams loop"> {
   let allowedClauses = [
     VersionedClause<OMPC_If>,

@llvmbot
Copy link
Member

llvmbot commented May 28, 2024

@llvm/pr-subscribers-flang-parser

Author: Anchu Rajendran S (anchuraj)

Changes

Change adds parsing support for omp loop, omp target loop, omp target parallel loop and omp target teams loop.


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

7 Files Affected:

  • (modified) flang/include/flang/Semantics/openmp-directive-sets.h (+1)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+7)
  • (modified) flang/lib/Parser/unparse.cpp (+12)
  • (modified) flang/lib/Semantics/resolve-directives.cpp (+4)
  • (added) flang/test/Lower/OpenMP/Todo/loop-directive.f90 (+15)
  • (added) flang/test/Parser/OpenMP/target-loop-unparse.f90 (+53)
  • (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+29)
diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h
index da66e0eda3216..8eb736bb098fe 100644
--- a/flang/include/flang/Semantics/openmp-directive-sets.h
+++ b/flang/include/flang/Semantics/openmp-directive-sets.h
@@ -242,6 +242,7 @@ static const OmpDirectiveSet loopConstructSet{
     Directive::OMPD_parallel_master_taskloop,
     Directive::OMPD_parallel_master_taskloop_simd,
     Directive::OMPD_simd,
+    Directive::OMPD_target_loop,
     Directive::OMPD_target_parallel_do,
     Directive::OMPD_target_parallel_do_simd,
     Directive::OMPD_target_parallel_loop,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index e67dbcca30e7d..cc6b7b2c60913 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -378,6 +378,7 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
     "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
     "DO" >> pure(llvm::omp::Directive::OMPD_do),
+    "LOOP" >> pure(llvm::omp::Directive::OMPD_loop),
     "MASKED TASKLOOP SIMD" >>
         pure(llvm::omp::Directive::OMPD_masked_taskloop_simd),
     "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop),
@@ -388,9 +389,13 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "PARALLEL MASKED TASKLOOP" >>
         pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop),
     "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
+    "TARGET LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_loop),
     "TARGET PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
     "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
+    "TARGET PARALLEL LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_parallel_loop),
     "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
     "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::
@@ -401,6 +406,8 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
         pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
     "TARGET TEAMS DISTRIBUTE" >>
         pure(llvm::omp::Directive::OMPD_target_teams_distribute),
+    "TARGET TEAMS LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_teams_loop),
     "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
     "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
     "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index bdd968b19a43f..8131d336b5eb9 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2194,6 +2194,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_do_simd:
       Word("DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_loop:
+      Word("LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_masked_taskloop_simd:
       Word("MASKED TASKLOOP SIMD");
       break;
@@ -2215,12 +2218,18 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_simd:
       Word("SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_loop:
+      Word("TARGET LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_parallel_do:
       Word("TARGET PARALLEL DO ");
       break;
     case llvm::omp::Directive::OMPD_target_parallel_do_simd:
       Word("TARGET PARALLEL DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_parallel_loop:
+      Word("TARGET PARALLEL LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_teams_distribute:
       Word("TARGET TEAMS DISTRIBUTE ");
       break;
@@ -2233,6 +2242,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
       Word("TARGET TEAMS DISTRIBUTE SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_teams_loop:
+      Word("TARGET TEAMS LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_simd:
       Word("TARGET SIMD ");
       break;
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index dbc531372c3f4..789e0f089fe6a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1602,6 +1602,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_distribute_simd:
   case llvm::omp::Directive::OMPD_do:
   case llvm::omp::Directive::OMPD_do_simd:
+  case llvm::omp::Directive::OMPD_loop:
   case llvm::omp::Directive::OMPD_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_masked_taskloop:
   case llvm::omp::Directive::OMPD_parallel_do:
@@ -1609,12 +1610,15 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop:
   case llvm::omp::Directive::OMPD_simd:
+  case llvm::omp::Directive::OMPD_target_loop:
   case llvm::omp::Directive::OMPD_target_parallel_do:
   case llvm::omp::Directive::OMPD_target_parallel_do_simd:
+  case llvm::omp::Directive::OMPD_target_parallel_loop:
   case llvm::omp::Directive::OMPD_target_teams_distribute:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
   case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
+  case llvm::omp::Directive::OMPD_target_teams_loop:
   case llvm::omp::Directive::OMPD_target_simd:
   case llvm::omp::Directive::OMPD_taskloop:
   case llvm::omp::Directive::OMPD_taskloop_simd:
diff --git a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
new file mode 100644
index 0000000000000..f1aea70458aa6
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
@@ -0,0 +1,15 @@
+! This test checks lowering of OpenMP loop Directive.
+
+! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: Unhandled directive loop
+subroutine test_loop()
+  integer :: i, j = 1
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
diff --git a/flang/test/Parser/OpenMP/target-loop-unparse.f90 b/flang/test/Parser/OpenMP/target-loop-unparse.f90
new file mode 100644
index 0000000000000..3ee2fcef075a3
--- /dev/null
+++ b/flang/test/Parser/OpenMP/target-loop-unparse.f90
@@ -0,0 +1,53 @@
+
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+! Check for parsing of loop directive
+
+subroutine test_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = loop
+  !CHECK: !$omp loop
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
+subroutine test_target_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target loop
+  !CHECK: !$omp target loop
+  !$omp target loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target loop
+end subroutine
+
+subroutine test_target_teams_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams loop
+  !CHECK: !$omp target teams loop
+  !$omp target teams loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target teams loop
+end subroutine
+
+subroutine test_target_parallel_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel loop
+  !CHECK: !$omp target parallel loop
+  !$omp target parallel loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target parallel loop
+end subroutine
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e91169e8da1aa..e4c7df5f11208 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -2232,6 +2232,35 @@ def OMP_teams_loop : Directive<"teams loop"> {
   ];
   let leafConstructs = [OMP_Teams, OMP_loop];
 }
+def OMP_target_loop : Directive<"target loop"> {
+  let allowedClauses = [
+    VersionedClause<OMPC_Allocate>,
+    VersionedClause<OMPC_Depend>,
+    VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_IsDevicePtr>,
+    VersionedClause<OMPC_HasDeviceAddr, 51>,
+    VersionedClause<OMPC_LastPrivate>,
+    VersionedClause<OMPC_Map>,
+    VersionedClause<OMPC_Private>,
+    VersionedClause<OMPC_Reduction>,
+    VersionedClause<OMPC_UsesAllocators, 50>,
+    VersionedClause<OMPC_OMPX_Attribute>,
+    VersionedClause<OMPC_InReduction, 50>,
+
+  ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_Bind, 50>,
+    VersionedClause<OMPC_Collapse>,
+    VersionedClause<OMPC_Order>,
+    VersionedClause<OMPC_ThreadLimit>,
+    VersionedClause<OMPC_OMPX_DynCGroupMem>,
+    VersionedClause<OMPC_If>,
+    VersionedClause<OMPC_Device>,
+    VersionedClause<OMPC_DefaultMap>,
+    VersionedClause<OMPC_NoWait>,
+  ];
+  let leafConstructs = [OMP_Target, OMP_loop];
+}
 def OMP_target_teams_loop : Directive<"target teams loop"> {
   let allowedClauses = [
     VersionedClause<OMPC_If>,

@llvmbot
Copy link
Member

llvmbot commented May 28, 2024

@llvm/pr-subscribers-flang-openmp

Author: Anchu Rajendran S (anchuraj)

Changes

Change adds parsing support for omp loop, omp target loop, omp target parallel loop and omp target teams loop.


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

7 Files Affected:

  • (modified) flang/include/flang/Semantics/openmp-directive-sets.h (+1)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+7)
  • (modified) flang/lib/Parser/unparse.cpp (+12)
  • (modified) flang/lib/Semantics/resolve-directives.cpp (+4)
  • (added) flang/test/Lower/OpenMP/Todo/loop-directive.f90 (+15)
  • (added) flang/test/Parser/OpenMP/target-loop-unparse.f90 (+53)
  • (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+29)
diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h
index da66e0eda3216..8eb736bb098fe 100644
--- a/flang/include/flang/Semantics/openmp-directive-sets.h
+++ b/flang/include/flang/Semantics/openmp-directive-sets.h
@@ -242,6 +242,7 @@ static const OmpDirectiveSet loopConstructSet{
     Directive::OMPD_parallel_master_taskloop,
     Directive::OMPD_parallel_master_taskloop_simd,
     Directive::OMPD_simd,
+    Directive::OMPD_target_loop,
     Directive::OMPD_target_parallel_do,
     Directive::OMPD_target_parallel_do_simd,
     Directive::OMPD_target_parallel_loop,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index e67dbcca30e7d..cc6b7b2c60913 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -378,6 +378,7 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "DISTRIBUTE" >> pure(llvm::omp::Directive::OMPD_distribute),
     "DO SIMD" >> pure(llvm::omp::Directive::OMPD_do_simd),
     "DO" >> pure(llvm::omp::Directive::OMPD_do),
+    "LOOP" >> pure(llvm::omp::Directive::OMPD_loop),
     "MASKED TASKLOOP SIMD" >>
         pure(llvm::omp::Directive::OMPD_masked_taskloop_simd),
     "MASKED TASKLOOP" >> pure(llvm::omp::Directive::OMPD_masked_taskloop),
@@ -388,9 +389,13 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
     "PARALLEL MASKED TASKLOOP" >>
         pure(llvm::omp::Directive::OMPD_parallel_masked_taskloop),
     "SIMD" >> pure(llvm::omp::Directive::OMPD_simd),
+    "TARGET LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_loop),
     "TARGET PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::OMPD_target_parallel_do_simd),
     "TARGET PARALLEL DO" >> pure(llvm::omp::Directive::OMPD_target_parallel_do),
+    "TARGET PARALLEL LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_parallel_loop),
     "TARGET SIMD" >> pure(llvm::omp::Directive::OMPD_target_simd),
     "TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
         pure(llvm::omp::Directive::
@@ -401,6 +406,8 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
         pure(llvm::omp::Directive::OMPD_target_teams_distribute_simd),
     "TARGET TEAMS DISTRIBUTE" >>
         pure(llvm::omp::Directive::OMPD_target_teams_distribute),
+    "TARGET TEAMS LOOP" >>
+        pure(llvm::omp::Directive::OMPD_target_teams_loop),
     "TASKLOOP SIMD" >> pure(llvm::omp::Directive::OMPD_taskloop_simd),
     "TASKLOOP" >> pure(llvm::omp::Directive::OMPD_taskloop),
     "TEAMS DISTRIBUTE PARALLEL DO SIMD" >>
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index bdd968b19a43f..8131d336b5eb9 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2194,6 +2194,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_do_simd:
       Word("DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_loop:
+      Word("LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_masked_taskloop_simd:
       Word("MASKED TASKLOOP SIMD");
       break;
@@ -2215,12 +2218,18 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_simd:
       Word("SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_loop:
+      Word("TARGET LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_parallel_do:
       Word("TARGET PARALLEL DO ");
       break;
     case llvm::omp::Directive::OMPD_target_parallel_do_simd:
       Word("TARGET PARALLEL DO SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_parallel_loop:
+      Word("TARGET PARALLEL LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_teams_distribute:
       Word("TARGET TEAMS DISTRIBUTE ");
       break;
@@ -2233,6 +2242,9 @@ class UnparseVisitor {
     case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
       Word("TARGET TEAMS DISTRIBUTE SIMD ");
       break;
+    case llvm::omp::Directive::OMPD_target_teams_loop:
+      Word("TARGET TEAMS LOOP ");
+      break;
     case llvm::omp::Directive::OMPD_target_simd:
       Word("TARGET SIMD ");
       break;
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index dbc531372c3f4..789e0f089fe6a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1602,6 +1602,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_distribute_simd:
   case llvm::omp::Directive::OMPD_do:
   case llvm::omp::Directive::OMPD_do_simd:
+  case llvm::omp::Directive::OMPD_loop:
   case llvm::omp::Directive::OMPD_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_masked_taskloop:
   case llvm::omp::Directive::OMPD_parallel_do:
@@ -1609,12 +1610,15 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop_simd:
   case llvm::omp::Directive::OMPD_parallel_masked_taskloop:
   case llvm::omp::Directive::OMPD_simd:
+  case llvm::omp::Directive::OMPD_target_loop:
   case llvm::omp::Directive::OMPD_target_parallel_do:
   case llvm::omp::Directive::OMPD_target_parallel_do_simd:
+  case llvm::omp::Directive::OMPD_target_parallel_loop:
   case llvm::omp::Directive::OMPD_target_teams_distribute:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
   case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
   case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
+  case llvm::omp::Directive::OMPD_target_teams_loop:
   case llvm::omp::Directive::OMPD_target_simd:
   case llvm::omp::Directive::OMPD_taskloop:
   case llvm::omp::Directive::OMPD_taskloop_simd:
diff --git a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
new file mode 100644
index 0000000000000..f1aea70458aa6
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/loop-directive.f90
@@ -0,0 +1,15 @@
+! This test checks lowering of OpenMP loop Directive.
+
+! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: Unhandled directive loop
+subroutine test_loop()
+  integer :: i, j = 1
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
diff --git a/flang/test/Parser/OpenMP/target-loop-unparse.f90 b/flang/test/Parser/OpenMP/target-loop-unparse.f90
new file mode 100644
index 0000000000000..3ee2fcef075a3
--- /dev/null
+++ b/flang/test/Parser/OpenMP/target-loop-unparse.f90
@@ -0,0 +1,53 @@
+
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+! Check for parsing of loop directive
+
+subroutine test_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = loop
+  !CHECK: !$omp loop
+  !$omp loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end loop
+end subroutine
+
+subroutine test_target_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target loop
+  !CHECK: !$omp target loop
+  !$omp target loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target loop
+end subroutine
+
+subroutine test_target_teams_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target teams loop
+  !CHECK: !$omp target teams loop
+  !$omp target teams loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target teams loop
+end subroutine
+
+subroutine test_target_parallel_loop
+  integer :: i, j = 1
+  !PARSE-TREE: OmpBeginLoopDirective
+  !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = target parallel loop
+  !CHECK: !$omp target parallel loop
+  !$omp target parallel loop
+  do i=1,10
+   j = j + 1
+  end do
+  !$omp end target parallel loop
+end subroutine
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e91169e8da1aa..e4c7df5f11208 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -2232,6 +2232,35 @@ def OMP_teams_loop : Directive<"teams loop"> {
   ];
   let leafConstructs = [OMP_Teams, OMP_loop];
 }
+def OMP_target_loop : Directive<"target loop"> {
+  let allowedClauses = [
+    VersionedClause<OMPC_Allocate>,
+    VersionedClause<OMPC_Depend>,
+    VersionedClause<OMPC_FirstPrivate>,
+    VersionedClause<OMPC_IsDevicePtr>,
+    VersionedClause<OMPC_HasDeviceAddr, 51>,
+    VersionedClause<OMPC_LastPrivate>,
+    VersionedClause<OMPC_Map>,
+    VersionedClause<OMPC_Private>,
+    VersionedClause<OMPC_Reduction>,
+    VersionedClause<OMPC_UsesAllocators, 50>,
+    VersionedClause<OMPC_OMPX_Attribute>,
+    VersionedClause<OMPC_InReduction, 50>,
+
+  ];
+  let allowedOnceClauses = [
+    VersionedClause<OMPC_Bind, 50>,
+    VersionedClause<OMPC_Collapse>,
+    VersionedClause<OMPC_Order>,
+    VersionedClause<OMPC_ThreadLimit>,
+    VersionedClause<OMPC_OMPX_DynCGroupMem>,
+    VersionedClause<OMPC_If>,
+    VersionedClause<OMPC_Device>,
+    VersionedClause<OMPC_DefaultMap>,
+    VersionedClause<OMPC_NoWait>,
+  ];
+  let leafConstructs = [OMP_Target, OMP_loop];
+}
 def OMP_target_teams_loop : Directive<"target teams loop"> {
   let allowedClauses = [
     VersionedClause<OMPC_If>,

@anchuraj anchuraj force-pushed the loop-parse-support branch from 4f6bd12 to 04401b7 Compare May 28, 2024 09:41
@llvm llvm deleted a comment from github-actions bot May 28, 2024
@anchuraj anchuraj requested a review from mjklemm May 28, 2024 09:46
@dpalermo dpalermo requested a review from ergawy May 28, 2024 13:09
Copy link
Member

@ergawy ergawy left a comment

Choose a reason for hiding this comment

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

Thanks @anchuraj! Just a question/clarification about target loop.

@@ -2232,6 +2232,35 @@ def OMP_teams_loop : Directive<"teams loop"> {
];
let leafConstructs = [OMP_Teams, OMP_loop];
}
def OMP_target_loop : Directive<"target loop"> {
Copy link
Member

Choose a reason for hiding this comment

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

AFAIK, target loop is a non-standard construct, right? Where did we get the allowed clauses from? What target loop map to in the standard?

cc @mjklemm

Copy link

@anchur anchur Jun 5, 2024

Choose a reason for hiding this comment

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

That is true. I copied the clauses from target and loop constructs (as that is the way specified for most complex constructs in ref card of openmp) .

@mjklemm
Copy link
Contributor

mjklemm commented May 29, 2024

Yes, target loop is non-conforming. But some vendor implementations support it and it will be coming with OpenMP 6.0. So, we should accept it. If people like, we may want to emit a warning it a non-conforming feature is being used and is being mapped to target teams loop.

@ergawy
Copy link
Member

ergawy commented May 31, 2024

Yes, target loop is non-conforming. But some vendor implementations support it and it will be coming with OpenMP 6.0. So, we should accept it. If people like, we may want to emit a warning it a non-conforming feature is being used and is being mapped to target teams loop.

@anchuraj sorry for the late review, yesterday was a public holiday.

I was more concerned about the list of allowed clauses and allowed once clauses. There are small differences between the 2 lists for target teams loop and target loop (for example if is in allowedClauses for target teams loop while in allowedOnceClauses for target loop). Maybe we just copy and paste the list from target teams loop or share them somehow.

@anchur
Copy link

anchur commented Jun 5, 2024

Yes, target loop is non-conforming. But some vendor implementations support it and it will be coming with OpenMP 6.0. So, we should accept it. If people like, we may want to emit a warning it a non-conforming feature is being used and is being mapped to target teams loop.

@mjklemm makes sense. I will add that

@anchur
Copy link

anchur commented Jun 5, 2024

Yes, target loop is non-conforming. But some vendor implementations support it and it will be coming with OpenMP 6.0. So, we should accept it. If people like, we may want to emit a warning it a non-conforming feature is being used and is being mapped to target teams loop.

@anchuraj sorry for the late review, yesterday was a public holiday.

I was more concerned about the list of allowed clauses and allowed once clauses. There are small differences between the 2 lists for target teams loop and target loop (for example if is in allowedClauses for target teams loop while in allowedOnceClauses for target loop). Maybe we just copy and paste the list from target teams loop or share them somehow.

This part is confusing for me as well. For target construct it is specified in allowed once clause. I think it makes more sense to include it in allowed once as semantics of multiple if conditions included in a construct may be ambiguous. The following is from standard. I followed the same structure as specified in target and loop directives

Restrictions
20 Restrictions to the if clause are as follows:
21 � At most one if clause can be specified that applies to the semantics of any construct or
22 constituent construct of a directive-specification.

@anchur
Copy link

anchur commented Jun 5, 2024

Thank you @mjklemm and @ergawy for reviewing my PR. I was on vacation and sorry for the late response. Please let me know if there are other concerns.

VersionedClause<OMPC_Reduction>,
VersionedClause<OMPC_UsesAllocators, 50>,
VersionedClause<OMPC_OMPX_Attribute>,
VersionedClause<OMPC_InReduction, 50>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Are InReduction and Allocate coming in due to the target construct? loop does not support these on its own.

Copy link

Choose a reason for hiding this comment

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

Yes, allocate, defaultmap, depend, device, firstprivate, has_device_addr, if, in_reduction, is_device_ptr, map, nowait, private, thread_limit, uses_allocators are clauses of target

@skatrak
Copy link
Member

skatrak commented Jun 5, 2024

I was more concerned about the list of allowed clauses and allowed once clauses. There are small differences between the 2 lists for target teams loop and target loop (for example if is in allowedClauses for target teams loop while in allowedOnceClauses for target loop). Maybe we just copy and paste the list from target teams loop or share them somehow.

This part is confusing for me as well. For target construct it is specified in allowed once clause. I think it makes more sense to include it in allowed once as semantics of multiple if conditions included in a construct may be ambiguous.

I agree with you. It seems like the IF clause should be allowed once in all 3 cases: target, target loop and target teams loop. If target teams loop didn't do this already it seems like it's a bug because, as you pointed out, we can't have multiple IF clauses for the same construct, and in that combined construct only one of the leaves (target) can accept the clause.

@anchuraj anchuraj requested review from mjklemm and anchur June 19, 2024 05:39
Copy link
Contributor

@mjklemm mjklemm left a comment

Choose a reason for hiding this comment

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

LGTM

@anchuraj anchuraj force-pushed the loop-parse-support branch from c36ef48 to 152b1ea Compare June 20, 2024 08:28
@anchuraj anchuraj merged commit 826bde5 into llvm:main Jun 21, 2024
7 checks passed
@anchuraj anchuraj deleted the loop-parse-support branch June 21, 2024 04:11
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
Change adds parsing support for omp loop, omp target loop, omp target
parallel loop and omp target teams loop.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:openmp OpenMP related changes to Clang flang:fir-hlfir flang:openmp flang:parser flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants