llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Zahira Ammarguellat (zahiraam)

<details>
<summary>Changes</summary>

OpenMP 6.0 classifies all loop-transforming constructs (`tile, unroll, reverse, 
interchange, stripe, fuse, split`, …) as simdizable, and only simdizable 
constructs may be encountered during execution of a simd region (`OpenMP 5.2 
[10.4]`). This patch implements that: `Clang` previously rejected these 
constructs inside a `simd` region at every OpenMP version.

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


7 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+3) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-1) 
- (modified) clang/include/clang/Basic/OpenMPKinds.h (+9) 
- (modified) clang/lib/Basic/OpenMPKinds.cpp (+15) 
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+9-4) 
- (added) clang/test/OpenMP/simd_loop_transformation_codegen.cpp (+28) 
- (added) clang/test/OpenMP/simd_loop_transformation_messages.cpp (+89) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 231587a3508d17..1d62b6c63d9751 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1260,6 +1260,9 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was 
renamed to `alpha.core.Use
   the clause was parsed but its condition was discarded without effect.
 - Fixed a crash when the loop variable or a loop bound of an OpenMP loop has a
   `_BitInt` type wider than any standard integer type. (#GH140074)
+- Loop-transforming constructs such as `tile` and `unroll` are now allowed
+  inside a `simd` region for OpenMP 6.0 or later, which classifies them as
+  simdizable.
 
 - Added support for capturing structured bindings in OpenMP regions
   (a C++20 extension; warned as an extension in C++17). Individual bindings
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cc87f556d50dcb..c436b57f9ceb61 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12368,7 +12368,8 @@ def err_omp_prohibited_region : Error<
   "; perhaps you forget to enclose 'omp %3' directive into a teams region?|"
   "; perhaps you forget to enclose 'omp %3' directive into a for, simd, for 
simd, parallel for, or parallel for simd region?}2">;
 def err_omp_prohibited_region_simd : Error<
-  "OpenMP constructs may not be nested inside a simd region%select{| except 
for ordered simd, simd, scan, or atomic directive}0">;
+  "OpenMP constructs may not be nested inside a simd region%select{| except 
for ordered simd, simd, scan, or atomic directive"
+  "| except for ordered simd, simd, scan, atomic, or loop-transforming 
directive}0">;
 def err_omp_prohibited_region_atomic : Error<
   "OpenMP constructs may not be nested inside an atomic region">;
 def err_omp_prohibited_region_order
diff --git a/clang/include/clang/Basic/OpenMPKinds.h 
b/clang/include/clang/Basic/OpenMPKinds.h
index 36c388668a455c..4515efdf663ec7 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -516,6 +516,15 @@ bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind);
 /// otherwise - false.
 bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind,
                                               const LangOptions &LangOpts);
+
+/// Checks if the specified directive is a simdizable directive, i.e. a
+/// directive that may be encountered during execution of a simd region.
+/// \param DKind Specified directive.
+/// \param LangOpts Used for getting the OpenMP version.
+/// \return true - if the above condition is met for this directive
+/// otherwise - false.
+bool isOpenMPSimdizableDirective(OpenMPDirectiveKind DKind,
+                                 const LangOptions &LangOpts);
 }
 
 template <>
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 99a2a4db4ab537..ca06fe6225328a 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -946,6 +946,21 @@ bool clang::isOpenMPOrderConcurrentNestableDirective(
   return false;
 }
 
+bool clang::isOpenMPSimdizableDirective(OpenMPDirectiveKind DKind,
+                                        const LangOptions &LangOpts) {
+  // Directives that may be encountered during execution of a simd region are:
+  // OpenMP 5.x: ordered simd, simd, scan and atomic
+  // OpenMP 6.0: above plus all loop-transformation directives
+  if (DKind == OMPD_ordered_blockassoc || DKind == OMPD_simd ||
+      DKind == OMPD_scan || DKind == OMPD_atomic)
+    return true;
+
+  if (LangOpts.OpenMP >= 60)
+    return isOpenMPLoopTransformationDirective(DKind);
+
+  return false;
+}
+
 void clang::getOpenMPCaptureRegions(
     SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
     OpenMPDirectiveKind DKind) {
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a3be416d2da24f..ad7eb8dcbebbb1 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5395,9 +5395,8 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
   }
   if (isOpenMPSimdDirective(ParentRegion) &&
       ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
-       (OMPVersion >= 50 && CurrentRegion != OMPD_ordered_blockassoc &&
-        CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
-        CurrentRegion != OMPD_scan))) {
+       (OMPVersion >= 50 &&
+        !isOpenMPSimdizableDirective(CurrentRegion, SemaRef.LangOpts)))) {
     // OpenMP [2.16, Nesting of Regions]
     // OpenMP constructs may not be nested inside a simd region.
     // OpenMP [2.8.1,simd Construct, Restrictions]
@@ -5410,10 +5409,16 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     // The only OpenMP constructs that can be encountered during execution of
     // a simd region are the atomic construct, the loop construct, the simd
     // construct and the ordered construct with the simd clause.
+    // OpenMP 5.2 [10.4, simd Construct, Restrictions]
+    // Only simdizable constructs can be encountered during execution of a
+    // simd region.
+    // OpenMP 6.0 makes all loop-transforming constructs simdizable.
     SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
                                ? diag::err_omp_prohibited_region_simd
                                : diag::warn_omp_nesting_simd)
-        << (OMPVersion >= 50 ? 1 : 0);
+        << (OMPVersion >= 60   ? 2
+            : OMPVersion >= 50 ? 1
+                               : 0);
     return CurrentRegion != OMPD_simd;
   }
   if (EnclosingConstruct == OMPD_atomic) {
diff --git a/clang/test/OpenMP/simd_loop_transformation_codegen.cpp 
b/clang/test/OpenMP/simd_loop_transformation_codegen.cpp
new file mode 100644
index 00000000000000..09f5747189c7e0
--- /dev/null
+++ b/clang/test/OpenMP/simd_loop_transformation_codegen.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fopenmp \
+// RUN:   -fopenmp-version=60 -emit-llvm -o - %s | FileCheck %s
+
+// OpenMP 6.0 allows loop-transforming constructs inside a simd region. Check
+// that the loops generated by the inner tile construct are emitted inside the
+// simd loop and that their accesses belong to the simd loop's access group.
+
+void use(int);
+
+// CHECK-LABEL: define {{.*}}void @_Z12tile_in_simdi(
+// CHECK: store i32 0, ptr %.floor_0.iv.i{{.*}}!llvm.access.group 
[[AG:![0-9]+]]
+// CHECK: store i32 {{.*}}, ptr %.tile_0.iv.i{{.*}}!llvm.access.group [[AG]]
+// CHECK: call void @_Z3usei(i32 noundef {{.*}}), !llvm.access.group [[AG]]
+// CHECK: br label %omp.inner.for.cond, !llvm.loop [[SIMD_LOOP:![0-9]+]]
+void tile_in_simd(int n) {
+#pragma omp simd
+  for (int j = 0; j < n; ++j) {
+#pragma omp tile sizes(4)
+    for (int i = 0; i < n; ++i)
+      use(i);
+  }
+}
+
+// CHECK: [[AG]] = distinct !{}
+// CHECK: [[SIMD_LOOP]] = distinct !{[[SIMD_LOOP]], [[PA:![0-9]+]],
+// CHECK-SAME: [[VE:![0-9]+]]}
+// CHECK: [[PA]] = !{!"llvm.loop.parallel_accesses", [[AG]]}
+// CHECK: [[VE]] = !{!"llvm.loop.vectorize.enable"}
diff --git a/clang/test/OpenMP/simd_loop_transformation_messages.cpp 
b/clang/test/OpenMP/simd_loop_transformation_messages.cpp
new file mode 100644
index 00000000000000..ebff3da6bf5927
--- /dev/null
+++ b/clang/test/OpenMP/simd_loop_transformation_messages.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -fopenmp-version=51 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp5x %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -fopenmp-version=52 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp5x %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -fopenmp-version=60 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp60 %s
+
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -fopenmp-version=51 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp5x %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -fopenmp-version=52 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp5x %s
+// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -fopenmp-version=60 \
+// RUN:   -triple x86_64-unknown-unknown -verify=expected,omp60 %s
+
+// OpenMP 6.0 allows simdizable constructs, which include all loop-transforming
+// constructs, to be encountered during execution of a simd region. Earlier
+// versions do not.
+
+void use(int);
+
+void tile_in_simd(int n) {
+#pragma omp simd
+  for (int j = 0; j < n; ++j) {
+    // omp5x-error@+1 {{scan, or atomic directive}}
+#pragma omp tile sizes(4)
+    for (int i = 0; i < n; ++i)
+      use(i);
+  }
+}
+
+void unroll_in_simd(int n) {
+#pragma omp simd
+  for (int j = 0; j < n; ++j) {
+    // omp5x-error@+1 {{scan, or atomic directive}}
+#pragma omp unroll partial(2)
+    for (int i = 0; i < n; ++i)
+      use(i);
+  }
+}
+
+void tile_in_for_simd(int n) {
+#pragma omp for simd
+  for (int j = 0; j < n; ++j) {
+    // omp5x-error@+1 {{scan, or atomic directive}}
+#pragma omp tile sizes(4)
+    for (int i = 0; i < n; ++i)
+      use(i);
+  }
+}
+
+// Constructs that are not simdizable are still rejected in OpenMP 6.0.
+void parallel_in_simd(int n) {
+#pragma omp simd
+  for (int j = 0; j < n; ++j) {
+    // omp5x-error@+2 {{scan, or atomic directive}}
+    // omp60-error@+1 {{atomic, or loop-transforming directive}}
+#pragma omp parallel
+    use(j);
+  }
+}
+
+#if _OPENMP >= 202411
+// Loop-transforming constructs introduced in OpenMP 6.0.
+void omp60_transformations_in_simd(int n) {
+#pragma omp simd
+  for (int j = 0; j < n; ++j) {
+#pragma omp reverse
+    for (int i = 0; i < n; ++i)
+      use(i);
+#pragma omp interchange
+    for (int i = 0; i < n; ++i)
+      for (int k = 0; k < n; ++k)
+        use(i + k);
+#pragma omp stripe sizes(4)
+    for (int i = 0; i < n; ++i)
+      use(i);
+#pragma omp fuse
+    {
+      for (int i = 0; i < n; ++i)
+        use(i);
+      for (int k = 0; k < n; ++k)
+        use(k);
+    }
+#pragma omp split counts(2, omp_fill)
+    for (int i = 0; i < n; ++i)
+      use(i);
+  }
+}
+#endif

``````````

</details>


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

Reply via email to