llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-offload

Author: Sergio Afonso (skatrak)

<details>
<summary>Changes</summary>

This patch modifies the handling of the 
`-fopenmp-assume-teams-oversubscription` and 
`-fopenmp-assume-threads-oversubscription` compiler options in Flang and the 
corresponding `omp.flags` MLIR attribute to have this information present on 
both host and target device MLIR modules. This is necessary to ensure SPMD to 
SPMD-No-Loop kernel promotion happens uniformly and no divergence between host 
and device representations of the same target region is introduced.

The identification of the kernel type in Flang lowering is updated to address 
some broken edge cases. In particular, no SPMD to SPMD-No-Loop transformation 
is performed on `target parallel do [simd]` kernels. A split `target + parallel 
loop` is now marked SPMD, which was a case missed previously, and the trip 
count on `target teams ompx_bare` kernels isn't host evaluated even if removing 
the `ompx_bare` clause would result in a valid SPMD kernel.

---

Patch is 31.59 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/206953.diff


12 Files Affected:

- (modified) clang/lib/Driver/ToolChains/Flang.cpp (+13-11) 
- (modified) flang/lib/Frontend/CompilerInvocation.cpp (+10-12) 
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+47-25) 
- (modified) flang/test/Driver/omp-driver-offload.f90 (+4-4) 
- (added) flang/test/Lower/OpenMP/target-kernel-types.f90 (+336) 
- (modified) mlir/include/mlir/Dialect/OpenMP/OpenMPOffloadUtils.h (+7-8) 
- (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+12-3) 
- (modified) 
mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp (+10-5) 
- (modified) mlir/test/Dialect/OpenMP/invalid.mlir (+22-1) 
- (modified) mlir/test/Dialect/OpenMP/ops.mlir (+13-6) 
- (modified) mlir/test/Target/LLVMIR/openmp-llvm.mlir (+7-7) 
- (modified) offload/test/offloading/fortran/target-no-loop.f90 (+1-3) 


``````````diff
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index e4aa1c9456d9a..ee67c570fb96c 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -739,6 +739,19 @@ void Flang::addOffloadOptions(Compilation &C, const 
InputInfoList &Inputs,
     }
   }
 
+  // When in OpenMP offloading mode, forward assumptions information about
+  // thread and team counts in the target device. The host needs to know about
+  // this to prevent the SPMD to SPMD-no-loop promotion being done differently
+  // for host and device on the same target region.
+  if (Args.hasFlag(options::OPT_fopenmp_assume_teams_oversubscription,
+                   options::OPT_fno_openmp_assume_teams_oversubscription,
+                   /*Default=*/false))
+    CmdArgs.push_back("-fopenmp-assume-teams-oversubscription");
+  if (Args.hasFlag(options::OPT_fopenmp_assume_threads_oversubscription,
+                   options::OPT_fno_openmp_assume_threads_oversubscription,
+                   /*Default=*/false))
+    CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");
+
   if (IsOpenMPDevice) {
     // -fopenmp-is-target-device is passed along to tell the frontend that it 
is
     // generating code for a device, so that only the relevant code is emitted.
@@ -749,17 +762,6 @@ void Flang::addOffloadOptions(Compilation &C, const 
InputInfoList &Inputs,
     if (Args.hasFlag(options::OPT_fopenmp_target_debug,
                      options::OPT_fno_openmp_target_debug, /*Default=*/false))
       CmdArgs.push_back("-fopenmp-target-debug");
-
-    // When in OpenMP offloading mode, forward assumptions information about
-    // thread and team counts in the device.
-    if (Args.hasFlag(options::OPT_fopenmp_assume_teams_oversubscription,
-                     options::OPT_fno_openmp_assume_teams_oversubscription,
-                     /*Default=*/false))
-      CmdArgs.push_back("-fopenmp-assume-teams-oversubscription");
-    if (Args.hasFlag(options::OPT_fopenmp_assume_threads_oversubscription,
-                     options::OPT_fno_openmp_assume_threads_oversubscription,
-                     /*Default=*/false))
-      CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");
     if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state))
       CmdArgs.push_back("-fopenmp-assume-no-thread-state");
     if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism))
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 003b815bef678..8e13fc9f05324 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1301,6 +1301,16 @@ static bool parseOpenMPArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
     }
   }
 
+  if (args.hasFlag(clang::options::OPT_fopenmp_assume_teams_oversubscription,
+                   
clang::options::OPT_fno_openmp_assume_teams_oversubscription,
+                   /*Default=*/false))
+    res.getLangOpts().OpenMPTeamSubscription = true;
+  if (args.hasFlag(
+          clang::options::OPT_fopenmp_assume_threads_oversubscription,
+          clang::options::OPT_fno_openmp_assume_threads_oversubscription,
+          /*Default=*/false))
+    res.getLangOpts().OpenMPThreadSubscription = true;
+
   if (args.hasArg(clang::options::OPT_fopenmp_force_usm)) {
     res.getLangOpts().OpenMPForceUSM = 1;
   }
@@ -1317,24 +1327,12 @@ static bool parseOpenMPArgs(CompilerInvocation &res, 
llvm::opt::ArgList &args,
             << res.getLangOpts().OMPHostIRFile;
     }
 
-    if (args.hasFlag(
-            clang::options::OPT_fopenmp_assume_teams_oversubscription,
-            clang::options::OPT_fno_openmp_assume_teams_oversubscription,
-            /*Default=*/false))
-      res.getLangOpts().OpenMPTeamSubscription = true;
-
     if (args.hasArg(clang::options::OPT_fopenmp_assume_no_thread_state))
       res.getLangOpts().OpenMPNoThreadState = 1;
 
     if (args.hasArg(clang::options::OPT_fopenmp_assume_no_nested_parallelism))
       res.getLangOpts().OpenMPNoNestedParallelism = 1;
 
-    if (args.hasFlag(
-            clang::options::OPT_fopenmp_assume_threads_oversubscription,
-            clang::options::OPT_fno_openmp_assume_threads_oversubscription,
-            /*Default=*/false))
-      res.getLangOpts().OpenMPThreadSubscription = true;
-
     if ((args.hasArg(clang::options::OPT_fopenmp_target_debug) ||
          args.hasArg(clang::options::OPT_fopenmp_target_debug_EQ))) {
       res.getLangOpts().OpenMPTargetDebug =
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp 
b/flang/lib/Lower/OpenMP/OpenMP.cpp
index ea8c279962508..d630d825062b7 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -304,17 +304,17 @@ class HostEvalInfo {
 ///
 /// The main entry point visit() will call visitDirective() for the OpenMP
 /// directive associated to the initial given evaluation based on whether it is
-/// part of the initialDirectives() set. A nested OpenMP evaluation might
-/// optionally be also visited by the pattern recursively if it meets all of 
the
-/// following conditions:
+/// part of the initial set of directives of interest. A nested OpenMP
+/// evaluation might optionally be also visited by the pattern recursively if 
it
+/// meets all of the following conditions:
 ///   - It is the only nested evaluation, apart from an optional END statement
 ///     associated to the same directive.
 ///   - The OpenMP directive is part of the directive set returned by the
 ///     `visitDirective` call for the parent.
 ///
-/// Subclasses define the expected pattern by implementing the
-/// initialDirectives() and visitDirective() methods, and users are expected to
-/// use visit() to trigger the complete pattern visit.
+/// Subclasses define the expected pattern by implementing the initialize() and
+/// visitDirective() methods, and users are expected to use visit() to trigger
+/// the complete pattern visit.
 class DirectivePatternVisitor {
 public:
   DirectivePatternVisitor(semantics::SemanticsContext &semaCtx)
@@ -323,13 +323,14 @@ class DirectivePatternVisitor {
 
   /// Run the pattern from the given evaluation.
   void visit(lower::pft::Evaluation &eval) {
-    directivesOfInterest = initialDirectives();
+    directivesOfInterest = initialize();
     visitEval(eval);
   }
 
 protected:
-  /// Returns the set of directives of interest at the beginning of the 
pattern.
-  virtual OmpDirectiveSet initialDirectives() const = 0;
+  /// Initializes the visitor and returns the set of initial directives of
+  /// interest to be matched the beginning of the pattern.
+  virtual OmpDirectiveSet initialize() = 0;
 
   /// Visits a single directive and, based on it, returns the set of other
   /// directives of interest that would be part of the pattern if nested 
inside.
@@ -419,11 +420,12 @@ class TargetSPMDVisitor : public DirectivePatternVisitor {
   virtual ~TargetSPMDVisitor() = default;
 
 protected:
-  virtual OmpDirectiveSet initialDirectives() const override {
+  virtual OmpDirectiveSet initialize() override {
+    teamsVisited = false;
     return llvm::omp::allTargetSet;
   }
 
-  virtual OmpDirectiveSet visitDirective(lower::pft::Evaluation &,
+  virtual OmpDirectiveSet visitDirective(lower::pft::Evaluation &eval,
                                          llvm::omp::Directive dir) override {
     using namespace llvm::omp;
 
@@ -440,7 +442,12 @@ class TargetSPMDVisitor : public DirectivePatternVisitor {
     case OMPD_target:
       return topTeamsSet | topParallelSet;
     case OMPD_target_teams:
+      // The 'bare' kernel type prevents the SPMD pattern from matching.
+      if (hasOmpxBareClause(eval))
+        return {};
+      [[fallthrough]];
     case OMPD_teams:
+      teamsVisited = true;
       return topDistributeSet | topLoopSet;
     case OMPD_target_parallel:
     case OMPD_parallel:
@@ -449,6 +456,19 @@ class TargetSPMDVisitor : public DirectivePatternVisitor {
       return {};
     }
   }
+
+  bool hasOmpxBareClause(lower::pft::Evaluation &eval) {
+    List<lower::omp::Clause> clauses;
+    extractClauses(eval, clauses);
+
+    return llvm::find_if(clauses, [](const Clause &clause) {
+             return std::holds_alternative<clause::OmpxBare>(clause.u);
+           }) != clauses.end();
+  }
+
+protected:
+  /// Whether a `teams` construct has been visited by visitDirective().
+  bool teamsVisited;
 };
 
 /// Populates the given HostEvalInfo structure after processing clauses for
@@ -628,20 +648,31 @@ class KernelTypeVisitor : protected TargetSPMDVisitor {
     case OMPD_target_teams_distribute_parallel_do:
     case OMPD_target_teams_distribute_parallel_do_simd:
     case OMPD_target_teams_loop:
-    case OMPD_target_parallel_do:
-    case OMPD_target_parallel_do_simd:
-    case OMPD_target_parallel_loop:
     case OMPD_teams_distribute_parallel_do:
     case OMPD_teams_distribute_parallel_do_simd:
     case OMPD_teams_loop:
     case OMPD_distribute_parallel_do:
     case OMPD_distribute_parallel_do_simd:
-    case OMPD_loop:
+      execMode = canPromoteSPMDToNoLoop(eval)
+                     ? mlir::omp::TargetExecMode::spmd_no_loop
+                     : mlir::omp::TargetExecMode::spmd;
+      return {};
+    case OMPD_target_parallel_do:
+    case OMPD_target_parallel_do_simd:
+    case OMPD_target_parallel_loop:
     case OMPD_parallel_do:
     case OMPD_parallel_do_simd:
+    case OMPD_parallel_loop:
     case OMPD_do:
     case OMPD_do_simd:
-      execMode = canPromoteSPMDToNoLoop(eval)
+      // SPMD kernels without a `teams` construct cannot be promoted to no-loop
+      // mode.
+      execMode = mlir::omp::TargetExecMode::spmd;
+      return {};
+    case OMPD_loop:
+      // Prevent `target parallel loop` or equivalent nests to be promoted to
+      // no-loop mode.
+      execMode = teamsVisited && canPromoteSPMDToNoLoop(eval)
                      ? mlir::omp::TargetExecMode::spmd_no_loop
                      : mlir::omp::TargetExecMode::spmd;
       return {};
@@ -674,15 +705,6 @@ class KernelTypeVisitor : protected TargetSPMDVisitor {
            }) == clauses.end();
   }
 
-  bool hasOmpxBareClause(lower::pft::Evaluation &eval) {
-    List<lower::omp::Clause> clauses;
-    extractClauses(eval, clauses);
-
-    return llvm::find_if(clauses, [](const Clause &clause) {
-             return std::holds_alternative<clause::OmpxBare>(clause.u);
-           }) != clauses.end();
-  }
-
 private:
   mlir::ModuleOp moduleOp;
   mlir::omp::TargetExecMode execMode;
diff --git a/flang/test/Driver/omp-driver-offload.f90 
b/flang/test/Driver/omp-driver-offload.f90
index 1d1d4f6f1dd4b..fc9bbd7f968cb 100644
--- a/flang/test/Driver/omp-driver-offload.f90
+++ b/flang/test/Driver/omp-driver-offload.f90
@@ -77,7 +77,7 @@
 ! RUN: -fopenmp-targets=nvptx64-nvidia-cuda \
 ! RUN: -fopenmp-assume-threads-oversubscription -nogpulib \
 ! RUN: | FileCheck %s --check-prefixes=CHECK-THREADS-OVS
-! CHECK-THREADS-OVS: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-is-target-device" "-fopenmp-assume-threads-oversubscription" 
{{.*}}.f90"
+! CHECK-THREADS-OVS: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-assume-threads-oversubscription" "-fopenmp-is-target-device" 
{{.*}}.f90"
 
 ! RUN: %flang -### %s -o %t 2>&1 \
 ! RUN: -fopenmp --offload-arch=gfx90a \
@@ -89,7 +89,7 @@
 ! RUN: -fopenmp-targets=nvptx64-nvidia-cuda \
 ! RUN: -fopenmp-assume-teams-oversubscription -nogpulib \
 ! RUN: | FileCheck %s --check-prefixes=CHECK-TEAMS-OVS
-! CHECK-TEAMS-OVS: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-is-target-device" "-fopenmp-assume-teams-oversubscription" {{.*}}.f90"
+! CHECK-TEAMS-OVS: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-assume-teams-oversubscription" "-fopenmp-is-target-device" {{.*}}.f90"
 
 ! RUN: %flang -### %s -o %t 2>&1 \
 ! RUN: -fopenmp --offload-arch=gfx90a \
@@ -153,8 +153,8 @@
 ! RUN: -fopenmp-assume-teams-oversubscription 
-fopenmp-assume-no-nested-parallelism \
 ! RUN: -fopenmp-assume-no-thread-state -nogpulib \
 ! RUN: | FileCheck %s --check-prefixes=CHECK-RTL-ALL
-! CHECK-RTL-ALL: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-is-target-device" "-fopenmp-target-debug" 
"-fopenmp-assume-teams-oversubscription"
-! CHECK-RTL-ALL: "-fopenmp-assume-threads-oversubscription" 
"-fopenmp-assume-no-thread-state" "-fopenmp-assume-no-nested-parallelism"
+! CHECK-RTL-ALL: "{{[^"]*}}flang{{[^"]*}}" "-fc1" {{.*}} "-fopenmp" {{.*}} 
"-fopenmp-assume-teams-oversubscription" 
"-fopenmp-assume-threads-oversubscription"
+! CHECK-RTL-ALL: "-fopenmp-is-target-device" "-fopenmp-target-debug" 
"-fopenmp-assume-no-thread-state" "-fopenmp-assume-no-nested-parallelism"
 ! CHECK-RTL-ALL: {{.*}}.f90"
 
 ! RUN: %flang -### %s -o %t 2>&1 \
diff --git a/flang/test/Lower/OpenMP/target-kernel-types.f90 
b/flang/test/Lower/OpenMP/target-kernel-types.f90
new file mode 100644
index 0000000000000..50d715ea61486
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-kernel-types.f90
@@ -0,0 +1,336 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-assume-teams-oversubscription 
-fopenmp-assume-threads-oversubscription -o - %s | FileCheck %s
+
+! 
------------------------------------------------------------------------------
+! GENERIC KERNELS
+! 
------------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @{{.*}}generic
+subroutine generic(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i, j
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target
+    call foo()
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target teams
+    call foo()
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target teams distribute
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target teams distribute
+  do i = 1, n
+    !$omp parallel do
+    do j = 1, n
+      call foo()
+    end do
+  end do
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target teams
+  !$omp parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(generic)
+  !$omp target teams
+  !$omp parallel
+  !$omp loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end parallel
+  !$omp end target teams
+end subroutine
+
+! 
------------------------------------------------------------------------------
+! BARE KERNELS
+! 
------------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @{{.*}}bare
+subroutine bare(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(bare)
+  !$omp target teams ompx_bare num_teams(1) thread_limit(1)
+    call foo()
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(bare)
+  !$omp target teams ompx_bare num_teams(1) thread_limit(1)
+  !$omp distribute parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(bare)
+  !$omp target teams ompx_bare num_teams(1) thread_limit(1)
+  !$omp distribute parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(bare)
+  !$omp target teams ompx_bare num_teams(1) thread_limit(1)
+  !$omp loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+end subroutine
+
+! 
------------------------------------------------------------------------------
+! SPMD KERNELS PROMOTABLE TO NO-LOOP MODE
+! 
------------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @{{.*}}target_teams_distribute_parallel_do_simd
+subroutine target_teams_distribute_parallel_do_simd(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target teams distribute parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams distribute parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target teams
+  !$omp distribute parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams
+  !$omp distribute parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end teams
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @{{.*}}target_teams_distribute_parallel_do
+subroutine target_teams_distribute_parallel_do(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target teams distribute parallel do
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams distribute parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target teams
+  !$omp distribute parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams
+  !$omp distribute parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end teams
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @{{.*}}target_teams_loop
+subroutine target_teams_loop(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target teams loop
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  !$omp target teams
+  !$omp loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target teams
+
+  ! CHECK: omp.target kernel_type(spmd_no_loop)
+  !$omp target
+  !$omp teams
+  !$omp loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end teams
+  !$omp end target
+end subroutine
+
+! 
------------------------------------------------------------------------------
+! SPMD KERNELS NOT PROMOTABLE TO NO-LOOP MODE
+! 
------------------------------------------------------------------------------
+
+! CHECK-LABEL: func.func @{{.*}}target_parallel_do_simd
+subroutine target_parallel_do_simd(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target
+  !$omp parallel do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel
+  !$omp do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target parallel
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target
+  !$omp parallel
+  !$omp do simd
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @{{.*}}target_parallel_do
+subroutine target_parallel_do(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel do
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target
+  !$omp parallel do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel
+  !$omp do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target parallel
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target
+  !$omp parallel
+  !$omp do
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end parallel
+  !$omp end target
+end subroutine
+
+! CHECK-LABEL: func.func @{{.*}}target_parallel_loop
+subroutine target_parallel_loop(n)
+  implicit none
+  integer, intent(in) :: n
+  integer :: i
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel loop
+  do i = 1, n
+    call foo()
+  end do
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target
+  !$omp parallel loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target
+
+  ! CHECK: omp.target kernel_type(spmd)
+  !$omp target parallel
+  !$omp loop
+  do i = 1, n
+    call foo()
+  end do
+  !$omp end target parallel
+...
[truncated]

``````````

</details>


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

Reply via email to