[Mlir-commits] [mlir] [OpenMP] Enable simd in non-reduction composite constructs (PR #146097)

Kajetan Puchalski llvmlistbot at llvm.org
Tue Jul 8 05:39:36 PDT 2025


https://github.com/mrkajetanp updated https://github.com/llvm/llvm-project/pull/146097

>From 019a8a8ec981f0223de499a0b3206ed20c5115eb Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at arm.com>
Date: Fri, 27 Jun 2025 15:38:40 +0000
Subject: [PATCH 1/4] [OpenMP] Enable simd in non-reduction composite
 constructs

Despite currently being ignored with a warning, simd as a leaf in
composite constructs behaves as expected when the construct does not
contain a reduction. Enable it for those non-reduction constructs.

Signed-off-by: Kajetan Puchalski <kajetan.puchalski at arm.com>
---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |  7 ++--
 .../LLVMIR/openmp-parallel-do-simd.mlir       | 30 +++++++++++++++++
 ...nmp-teams-distribute-parallel-do-simd.mlir | 33 +++++++++++++++++++
 mlir/test/Target/LLVMIR/openmp-todo.mlir      | 14 --------
 4 files changed, 65 insertions(+), 19 deletions(-)
 create mode 100644 mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
 create mode 100644 mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir

diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 7a517fb86d1ff..165fb6a455966 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2852,11 +2852,8 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
   llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
   auto simdOp = cast<omp::SimdOp>(opInst);
 
-  // TODO: Replace this with proper composite translation support.
-  // Currently, simd information on composite constructs is ignored, so e.g.
-  // 'do/for simd' will be treated the same as a standalone 'do/for'. This is
-  // allowed by the spec, since it's equivalent to using a SIMD length of 1.
-  if (simdOp.isComposite()) {
+  // TODO: Replace this once simd + reduction is properly supported
+  if (simdOp.isComposite() && simdOp.getReductionByref().has_value()) {
     if (failed(convertIgnoredWrapper(simdOp, moduleTranslation)))
       return failure();
 
diff --git a/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir b/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
new file mode 100644
index 0000000000000..9ea0ff590144f
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
@@ -0,0 +1,30 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Check that omp.simd as a leaf of a composite construct still generates
+// the appropriate loop vectorization attribute.
+
+// CHECK-LABEL: define internal void @test_parallel_do_simd..omp_par
+// CHECK: ![[VAL:.*]] = !{!"llvm.loop.vectorize.enable", i1 true}
+
+llvm.func @test_parallel_do_simd() {
+  %0 = llvm.mlir.constant(1 : i64) : i64
+  %1 = llvm.alloca %0 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
+  %2 = llvm.mlir.constant(1000 : i32) : i32
+  %3 = llvm.mlir.constant(1 : i32) : i32
+  %4 = llvm.mlir.constant(1 : i64) : i64
+  omp.parallel {
+    %5 = llvm.mlir.constant(1 : i64) : i64
+    %6 = llvm.alloca %5 x i32 {bindc_name = "i", pinned} : (i64) -> !llvm.ptr
+    %7 = llvm.mlir.constant(1 : i64) : i64
+    omp.wsloop {
+      omp.simd {
+        omp.loop_nest (%arg0) : i32 = (%3) to (%2) inclusive step (%3) {
+          llvm.store %arg0, %6 : i32, !llvm.ptr
+          omp.yield
+        }
+      } {omp.composite}
+    } {omp.composite}
+    omp.terminator
+  }
+  llvm.return
+}
diff --git a/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir b/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir
new file mode 100644
index 0000000000000..108a99cf7c40f
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir
@@ -0,0 +1,33 @@
+// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
+
+// Check that omp.simd as a leaf of a composite construct still generates
+// the appropriate loop vectorization attribute.
+
+// CHECK-LABEL: define internal void @test_teams_distribute_parallel_do_simd..omp_par
+// CHECK: ![[VAL:.*]] = !{!"llvm.loop.vectorize.enable", i1 true}
+
+omp.private {type = private} @_QFEi_private_i32 : i32
+llvm.func @test_teams_distribute_parallel_do_simd() {
+  %0 = llvm.mlir.constant(1 : i64) : i64
+  %1 = llvm.alloca %0 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr
+  %2 = llvm.mlir.constant(1000 : i32) : i32
+  %3 = llvm.mlir.constant(1 : i32) : i32
+  %4 = llvm.mlir.constant(1 : i64) : i64
+  omp.teams {
+    omp.parallel {
+      omp.distribute {
+        omp.wsloop {
+          omp.simd private(@_QFEi_private_i32 %1 -> %arg0 : !llvm.ptr) {
+            omp.loop_nest (%arg1) : i32 = (%3) to (%2) inclusive step (%3) {
+              llvm.store %arg1, %arg0 : i32, !llvm.ptr
+              omp.yield
+            }
+          } {omp.composite}
+        } {omp.composite}
+      } {omp.composite}
+      omp.terminator
+    } {omp.composite}
+    omp.terminator
+  }
+  llvm.return
+}
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 29725a02c075a..2fa4470bb8300 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -26,20 +26,6 @@ llvm.func @atomic_hint(%v : !llvm.ptr, %x : !llvm.ptr, %expr : i32) {
 
 // -----
 
-llvm.func @do_simd(%lb : i32, %ub : i32, %step : i32) {
-  omp.wsloop {
-    // expected-warning at below {{simd information on composite construct discarded}}
-    omp.simd {
-      omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
-        omp.yield
-      }
-    } {omp.composite}
-  } {omp.composite}
-  llvm.return
-}
-
-// -----
-
 llvm.func @distribute_allocate(%lb : i32, %ub : i32, %step : i32, %x : !llvm.ptr) {
   // expected-error at below {{not yet implemented: Unhandled clause allocate in omp.distribute operation}}
   // expected-error at below {{LLVM Translation failed for operation: omp.distribute}}

>From a16bf8a83d42b5911a2714d8a31c32f21c8a658a Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at arm.com>
Date: Mon, 30 Jun 2025 12:41:56 +0000
Subject: [PATCH 2/4] Expand tests

---
 .../LLVMIR/openmp-parallel-do-simd.mlir       | 10 +++++++++-
 ...nmp-teams-distribute-parallel-do-simd.mlir | 20 ++++++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir b/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
index 9ea0ff590144f..bfa57b85245ca 100644
--- a/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-parallel-do-simd.mlir
@@ -4,7 +4,15 @@
 // the appropriate loop vectorization attribute.
 
 // CHECK-LABEL: define internal void @test_parallel_do_simd..omp_par
-// CHECK: ![[VAL:.*]] = !{!"llvm.loop.vectorize.enable", i1 true}
+// CHECK: omp.par.entry:
+// CHECK: omp.par.region:
+// CHECK: omp_loop.header:
+// CHECK: omp_loop.inc:
+// CHECK-NEXT:   %omp_loop.next = add nuw i32 %omp_loop.iv, 1
+// CHECK-NEXT:   br label %omp_loop.header, !llvm.loop ![[LOOP_ATTR:.*]]
+// CHECK: ![[LOOP_ATTR]] = distinct !{![[LOOP_ATTR]], ![[LPAR:.*]], ![[LVEC:.*]]}
+// CHECK: ![[LPAR]] = !{!"llvm.loop.parallel_accesses", ![[PAR_ACC:.*]]}
+// CHECK: ![[LVEC]] = !{!"llvm.loop.vectorize.enable", i1 true}
 
 llvm.func @test_parallel_do_simd() {
   %0 = llvm.mlir.constant(1 : i64) : i64
diff --git a/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir b/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir
index 108a99cf7c40f..4d766cc1ac4f4 100644
--- a/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-teams-distribute-parallel-do-simd.mlir
@@ -3,8 +3,26 @@
 // Check that omp.simd as a leaf of a composite construct still generates
 // the appropriate loop vectorization attribute.
 
+// CHECK-LABEL: define internal void @test_teams_distribute_parallel_do_simd..omp_par.2
+// CHECK: teams.body:
+// CHECK: omp.teams.region:
+
+// CHECK-LABEL: define internal void @test_teams_distribute_parallel_do_simd..omp_par.1
+// CHECK: omp.par.entry:
+// CHECK: omp.par.region:
+// CHECK: distribute.exit:
+
 // CHECK-LABEL: define internal void @test_teams_distribute_parallel_do_simd..omp_par
-// CHECK: ![[VAL:.*]] = !{!"llvm.loop.vectorize.enable", i1 true}
+// CHECK: distribute.body:
+// CHECK: omp.distribute.region:
+// CHECK: omp_loop.header:
+// CHECK: omp_loop.inc:
+// CHECK-NEXT:   %omp_loop.next = add nuw i32 %omp_loop.iv, 1
+// CHECK-NEXT:   br label %omp_loop.header, !llvm.loop ![[LOOP_ATTR:.*]]
+
+// CHECK: ![[LOOP_ATTR]] = distinct !{![[LOOP_ATTR]], ![[LPAR:.*]], ![[LVEC:.*]]}
+// CHECK: ![[LPAR]] = !{!"llvm.loop.parallel_accesses", ![[PAR_ACC:.*]]}
+// CHECK: ![[LVEC]] = !{!"llvm.loop.vectorize.enable", i1 true}
 
 omp.private {type = private} @_QFEi_private_i32 : i32
 llvm.func @test_teams_distribute_parallel_do_simd() {

>From 31de8abe8637bad19bedebaed3f731d457520d93 Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at arm.com>
Date: Tue, 1 Jul 2025 12:58:20 +0000
Subject: [PATCH 3/4] Ignore simd with if clause

---
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      |  6 ++-
 mlir/test/Target/LLVMIR/openmp-todo.mlir      | 40 +++++++++++++++++++
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 165fb6a455966..4ea96703ec0df 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -2852,8 +2852,10 @@ convertOmpSimd(Operation &opInst, llvm::IRBuilderBase &builder,
   llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
   auto simdOp = cast<omp::SimdOp>(opInst);
 
-  // TODO: Replace this once simd + reduction is properly supported
-  if (simdOp.isComposite() && simdOp.getReductionByref().has_value()) {
+  // Ignore simd in composite constructs with unsupported clauses
+  // TODO: Replace this once simd + clause combinations are properly supported
+  if (simdOp.isComposite() &&
+      (simdOp.getReductionByref().has_value() || simdOp.getIfExpr())) {
     if (failed(convertIgnoredWrapper(simdOp, moduleTranslation)))
       return failure();
 
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 2fa4470bb8300..0e8d64ec0daad 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -489,3 +489,43 @@ llvm.func @wsloop_order(%lb : i32, %ub : i32, %step : i32) {
   }
   llvm.return
 }
+
+// -----
+
+llvm.func @do_simd_if(%1 : !llvm.ptr, %5 : i32, %4 : i32, %6 : i1) {
+  omp.wsloop {
+    // expected-warning at below {{simd information on composite construct discarded}}
+    omp.simd if(%6) {
+      omp.loop_nest (%arg0) : i32 = (%5) to (%4) inclusive step (%5) {
+        llvm.store %arg0, %1 : i32, !llvm.ptr
+        omp.yield
+      }
+    } {omp.composite}
+  } {omp.composite}
+  llvm.return
+}
+
+// -----
+
+omp.declare_reduction @add_reduction_i32 : i32 init {
+^bb0(%arg0: i32):
+  %0 = llvm.mlir.constant(0 : i32) : i32
+  omp.yield(%0 : i32)
+} combiner {
+^bb0(%arg0: i32, %arg1: i32):
+  %0 = llvm.add %arg0, %arg1 : i32
+  omp.yield(%0 : i32)
+}
+llvm.func @simd_reduction(%1 : !llvm.ptr, %3 : !llvm.ptr, %6 : i32, %7 : i32) {
+  omp.wsloop reduction(@add_reduction_i32 %3 -> %arg0 : !llvm.ptr) {
+    // expected-warning at below {{simd information on composite construct discarded}}
+    omp.simd reduction(@add_reduction_i32 %arg0 -> %arg1 : !llvm.ptr) {
+      omp.loop_nest (%arg2) : i32 = (%7) to (%6) inclusive step (%7) {
+        llvm.store %arg2, %1 : i32, !llvm.ptr
+        %12 = llvm.load %arg1 : !llvm.ptr -> i32
+        omp.yield
+      }
+    } {omp.composite}
+  } {omp.composite}
+  llvm.return
+}

>From 6ca4af1f934afe961ae880839a07032232f0cba9 Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at tuta.io>
Date: Wed, 2 Jul 2025 13:36:39 +0100
Subject: [PATCH 4/4] Update test

Co-authored-by: Sergio Afonso <safonsof at amd.com>
---
 mlir/test/Target/LLVMIR/openmp-todo.mlir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 0e8d64ec0daad..e2c32b254c200 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -516,7 +516,7 @@ omp.declare_reduction @add_reduction_i32 : i32 init {
   %0 = llvm.add %arg0, %arg1 : i32
   omp.yield(%0 : i32)
 }
-llvm.func @simd_reduction(%1 : !llvm.ptr, %3 : !llvm.ptr, %6 : i32, %7 : i32) {
+llvm.func @do_simd_reduction(%1 : !llvm.ptr, %3 : !llvm.ptr, %6 : i32, %7 : i32) {
   omp.wsloop reduction(@add_reduction_i32 %3 -> %arg0 : !llvm.ptr) {
     // expected-warning at below {{simd information on composite construct discarded}}
     omp.simd reduction(@add_reduction_i32 %arg0 -> %arg1 : !llvm.ptr) {



More information about the Mlir-commits mailing list