[Mlir-commits] [flang] [mlir] [OpenMP][Flang][MLIR] Introduce omp.declare_simd op and emit from Flang (PR #175604)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jan 14 12:00:17 PST 2026


https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/175604

>From 5783d5b394d02a7d05fe0c9e33ed9f756451682d Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Fri, 9 Jan 2026 17:48:54 -0600
Subject: [PATCH 1/3] [OpenMP][Flang][MLIR] Introduce omp.declare_simd op and
 emit from Flang

Changes:
- Adds a new `omp.declare_simd` operation to the OpenMP MLIR dialect
- Lowers Fortran `!$omp declare simd` into `omp.declare_simd` inside the
  enclosing function body

mlir to LLVMIR translation and uniform clause will be added in follow-up PRs.
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  13 +-
 flang/test/Lower/OpenMP/declare-simd.f90      | 119 ++++++++++++++++++
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  38 ++++++
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  32 +++++
 mlir/test/Dialect/OpenMP/ops.mlir             |  69 ++++++++++
 5 files changed, 269 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/declare-simd.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 4381d1e9064cf..84377c26d30f6 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3815,8 +3815,17 @@ static void
 genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
        semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
        const parser::OpenMPDeclareSimdConstruct &declareSimdConstruct) {
-  if (!semaCtx.langOptions().OpenMPSimd)
-    TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct");
+  mlir::Location loc = converter.getCurrentLocation();
+  const parser::OmpDirectiveSpecification &beginSpec = declareSimdConstruct.v;
+  List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx);
+
+  mlir::omp::DeclareSimdOperands clauseOps;
+  ClauseProcessor cp(converter, semaCtx, clauses);
+  cp.processAligned(clauseOps);
+  cp.processLinear(clauseOps);
+  cp.processSimdlen(clauseOps);
+
+  mlir::omp::DeclareSimdOp::create(converter.getFirOpBuilder(), loc, clauseOps);
 }
 
 static void genOpenMPDeclareMapperImpl(
diff --git a/flang/test/Lower/OpenMP/declare-simd.f90 b/flang/test/Lower/OpenMP/declare-simd.f90
new file mode 100644
index 0000000000000..264ac222801b9
--- /dev/null
+++ b/flang/test/Lower/OpenMP/declare-simd.f90
@@ -0,0 +1,119 @@
+! This test checks the lowering of the OpenMP `declare simd` directive with
+! different clauses (e.g. aligned, linear, simdlen). It also verifies that
+! the `omp.declare_simd` operation is emitted after the function prologue,
+! since the directive requires access to function arguments.
+
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+
+subroutine declare_simd_no_clause(x, y, n, i)
+  !$omp declare simd
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine declare_simd_no_clause
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_no_clause(
+! CHECK: %[[SCOPE_NONE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[I_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[N_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[X_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[Y_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: omp.declare_simd
+! CHECK-NOT: aligned(
+! CHECK-NOT: linear(
+! CHECK-NOT: simdlen(
+! CHECK: return
+
+subroutine declare_simd_aligned(x, y, n, i)
+  !$omp declare simd aligned(x, y : 64)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine declare_simd_aligned
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_aligned(
+! CHECK: %[[SCOPE_A:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[I_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[N_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[X_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[Y_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: omp.declare_simd
+! CHECK-SAME: aligned(%[[X_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64,
+! CHECK-SAME:         %[[Y_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64)
+! CHECK-NOT: linear(
+! CHECK-NOT: simdlen(
+! CHECK: return
+
+subroutine declare_simd_linear(x, y, n, i)
+  !$omp declare simd linear(i)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine  declare_simd_linear
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_linear(
+! CHECK: %[[SCOPE_L:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[I_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[N_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[X_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[Y_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[C1_L:.*]] = arith.constant 1 : i32
+! CHECK: omp.declare_simd
+! CHECK-NOT: aligned(
+! CHECK-SAME: linear(%[[I_L]]#0 = %[[C1_L]] : !fir.ref<i32>)
+! CHECK-SAME: {linear_var_types = [i32]}
+! CHECK-NOT: simdlen(
+! CHECK: return
+
+subroutine declare_simd_simdlen(x, y, n, i)
+  !$omp declare simd simdlen(8)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine declare_simd_simdlen
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_simdlen(
+! CHECK: %[[SCOPE_S:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[I_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[N_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[X_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[Y_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: omp.declare_simd
+! CHECK-NOT: aligned(
+! CHECK-NOT: linear(
+! CHECK-SAME: simdlen(8)
+! CHECK: return
+
+subroutine declare_simd_combined(x, y, n, i)
+    !$omp declare simd aligned(x, y : 64) linear(i) simdlen(8)
+    real(8), pointer, intent(inout) :: x(:)
+    real(8), pointer, intent(in)    :: y(:)
+    integer, intent(in) :: n, i
+
+    if (i <= n) then
+        x(i) = x(i) + y(i)
+end if
+end subroutine declare_simd_combined
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_combined(
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>{{.*}}fir.bindc_name = "x"
+! CHECK-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>{{.*}}fir.bindc_name = "y"
+! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}fir.bindc_name = "n"
+! CHECK-SAME: %{{.*}}: !fir.ref<i32>{{.*}}fir.bindc_name = "i"
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[N_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 1 {{.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 2 {{.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: %[[C1:.*]] = arith.constant 1 : i32
+
+! CHECK: omp.declare_simd
+! CHECK-SAME: aligned(%[[X_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64,
+! CHECK-SAME:         %[[Y_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64)
+! CHECK-SAME: linear(%[[I_DECL]]#0 = %[[C1]] : !fir.ref<i32>)
+! CHECK-SAME: simdlen(8)
+! CHECK-SAME: {linear_var_types = [i32]}
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index bbfe805eefe48..c77e08e1fb076 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2240,4 +2240,42 @@ def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
   let assemblyFormat = "$region attr-dict";
 }
 
+//===----------------------------------------------------------------------===//
+// declare simd Construct
+//===----------------------------------------------------------------------===//
+
+def DeclareSimdOp
+    : OpenMP_Op<"declare_simd",
+                traits = [AttrSizedOperandSegments, IsolatedFromAbove],
+                clauses = [OpenMP_AlignedClause, OpenMP_LinearClause,
+                           OpenMP_SimdlenClause]> {
+  let summary = "declare simd directive";
+  let description = [{
+    "omp.declare_simd" models the OpenMP `declare simd` directive.
+
+    This is a declarative operation (no region) intended to appear inside
+    a function body. It attaches clauses of declare simd to the enclosing
+    function.
+
+    Example:
+    ```mlir
+    func.func @add(%a: memref<16xi32>) {
+      omp.declare_simd simdlen(8) aligned(%a : memref<16xi32> -> 64 : i64)
+      ...
+    }
+    ```
+  }]#clausesDescription;
+
+  let arguments = clausesArgs;
+
+  let builders = [OpBuilder<(
+      ins CArg<"const DeclareSimdOperands &">:$clauses)>];
+
+  let assemblyFormat =
+      clausesReqAssemblyFormat#" oilist("#clausesOptAssemblyFormat#") "#"attr-"
+                               "dict";
+
+  let hasVerifier = 1;
+}
+
 #endif // OPENMP_OPS
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 103295d136dbb..f23bb659ae88e 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4458,6 +4458,38 @@ LogicalResult WorkdistributeOp::verify() {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// Declare simd [7.7]
+//===----------------------------------------------------------------------===//
+
+void DeclareSimdOp::build(OpBuilder &odsBuilder, OperationState &odsState,
+                          const DeclareSimdOperands &clauses) {
+  MLIRContext *ctx = odsBuilder.getContext();
+  DeclareSimdOp::build(odsBuilder, odsState, clauses.alignedVars,
+                       makeArrayAttr(ctx, clauses.alignments),
+                       clauses.linearVars, clauses.linearStepVars,
+                       clauses.linearVarTypes, clauses.simdlen);
+}
+
+LogicalResult DeclareSimdOp::verify() {
+  // Must be nested inside a function-like op
+  auto func = (*this)->getParentOfType<mlir::FunctionOpInterface>();
+  if (!func)
+    return emitOpError()
+           << "'omp.declare_simd' must be nested inside a function";
+
+  // omp.declare_simd must appear in the entry block of the enclosing function
+  Block &entry = func.getFunctionBody().front();
+  if (getOperation()->getBlock() != &entry)
+    return emitError()
+           << "must appear in the entry block of the enclosing function";
+
+  if (verifyAlignedClause(*this, getAlignments(), getAlignedVars()).failed())
+    return failure();
+
+  return success();
+}
+
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
 
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index ac29e20907b55..8ab2ed89e5ecc 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3367,3 +3367,72 @@ func.func @omp_target_map_clause_type_test(%arg0 : memref<?xi32>) -> () {
 
     return
 }
+
+// CHECK-LABEL: func.func @omp_declare_simd
+func.func @omp_declare_simd(%a: f64, %b: f64) -> f64 {
+  // CHECK: omp.declare_simd
+  omp.declare_simd
+  %0 = arith.addf %a, %b : f64
+  return %0 : f64
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_simdlen
+func.func @omp_declare_simd_simdlen(%a: f64, %b: f64) -> f64 {
+  // CHECK: omp.declare_simd
+  // CHECK-SAME: simdlen(8)
+  omp.declare_simd simdlen(8)
+  %0 = arith.addf %a, %b : f64
+  return %0 : f64
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_aligned
+func.func @omp_declare_simd_aligned(%a: f64, %b: f64,
+                                         %p0: memref<i32>, %p1: memref<i32>) -> f64 {
+  // CHECK:      omp.declare_simd
+  // CHECK-SAME: aligned(
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
+  omp.declare_simd aligned(%p0 : memref<i32> -> 32 : i64,
+                           %p1 : memref<i32> -> 128 : i64)
+
+  %0 = arith.addf %a, %b : f64
+  return %0 : f64
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_aligned_list_generic
+func.func @omp_declare_simd_aligned_list_generic(%arg0: f64, %arg1: f64,
+                                                 %arg2: memref<i32>, %arg3: memref<i32>) -> f64 {
+  // CHECK:      omp.declare_simd
+  // CHECK-SAME: aligned(%{{.*}} : memref<i32> -> 32 : i64, %{{.*}} : memref<i32> -> 128 : i64)
+  omp.declare_simd aligned(%arg2 : memref<i32> -> 32 : i64, %arg3 : memref<i32> -> 128 : i64)
+  %0 = arith.addf %arg0, %arg1 : f64
+  return %0 : f64
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_linear
+func.func @omp_declare_simd_linear(%a: f64, %b: f64, %iv: i32, %step: i32) -> f64 {
+  // CHECK: omp.declare_simd
+  // CHECK-SAME: linear(%{{.*}} = %{{.*}} : i32)
+  omp.declare_simd linear(%iv = %step : i32)
+  %0 = arith.addf %a, %b : f64
+  return %0 : f64
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_all_clauses
+func.func @omp_declare_simd_all_clauses(%a: f64, %b: f64,
+                                        %p0: memref<i32>, %p1: memref<i32>,
+                                        %iv: i32, %step: i32) -> f64 {
+  // CHECK:      omp.declare_simd
+  // CHECK-SAME: aligned(
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
+  // CHECK-SAME: linear(%{{.*}} = %{{.*}} : i32)
+  // CHECK-SAME: simdlen(8)
+  omp.declare_simd simdlen(8)
+    aligned(%p0 : memref<i32> -> 32 : i64,
+            %p1 : memref<i32> -> 128 : i64)
+    linear(%iv = %step : i32)
+
+  %0 = arith.addf %a, %b : f64
+  return %0 : f64
+}

>From b5ff628de45fe13bb4f8acaa7bb35849c424d2ba Mon Sep 17 00:00:00 2001
From: "Chi-Chun, Chen" <chichun.chen at hpe.com>
Date: Tue, 13 Jan 2026 14:36:00 -0600
Subject: [PATCH 2/3] Resolve feedback

- Add uniform clause to TODO test
- Fix flang declare_simd.f90 lowering test
    - Test `!$omp declare simd` for OpenMP 5.2 and 6.0
    - Test `!$omp declare_simd` for OpenMP 6.0 only (guarded by -cpp -DOMP_60)
- Fix traits in omp.declare_simd
    - remove IsolatedFromAbove
    - implement getEffects to prevent declare_simd from being remove by
      DCE
- Add invalid.mlir coverage for the DeclareSimdOp::verify
    - makes sure omp.declare_simd has parent function
    - remove unnecessary entry block check
- Remove redundancy in ops.mlir
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             |   2 +
 .../OpenMP/Todo/declare-simd-uniform.f90      |   9 ++
 flang/test/Lower/OpenMP/declare-simd.f90      | 135 ++++++++++++++----
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |   3 +-
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  23 ++-
 mlir/test/Dialect/OpenMP/invalid.mlir         |   4 +
 mlir/test/Dialect/OpenMP/ops.mlir             |  31 ++--
 7 files changed, 156 insertions(+), 51 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 84377c26d30f6..5f520635bb4c5 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3824,6 +3824,8 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
   cp.processAligned(clauseOps);
   cp.processLinear(clauseOps);
   cp.processSimdlen(clauseOps);
+  cp.processTODO<clause::Uniform>(converter.getCurrentLocation(),
+                                  llvm::omp::Directive::OMPD_declare_simd);
 
   mlir::omp::DeclareSimdOp::create(converter.getFirOpBuilder(), loc, clauseOps);
 }
diff --git a/flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90 b/flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90
new file mode 100644
index 0000000000000..1ca5dd34de2d2
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90
@@ -0,0 +1,9 @@
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: Unhandled clause UNIFORM in DECLARE SIMD construct
+subroutine declare_simd_uniform(x, y)
+    real(8), pointer, intent(inout) :: x(:)
+    real(8), pointer, intent(in)    :: y(:)
+    !$omp declare simd uniform(x, y)
+end subroutine declare_simd_uniform
+
diff --git a/flang/test/Lower/OpenMP/declare-simd.f90 b/flang/test/Lower/OpenMP/declare-simd.f90
index 264ac222801b9..222ce4af1bb7c 100644
--- a/flang/test/Lower/OpenMP/declare-simd.f90
+++ b/flang/test/Lower/OpenMP/declare-simd.f90
@@ -1,28 +1,19 @@
-! This test checks the lowering of the OpenMP `declare simd` directive with
+! This test CHECKs the lowering of the OpenMP `declare simd` directive with
 ! different clauses (e.g. aligned, linear, simdlen). It also verifies that
 ! the `omp.declare_simd` operation is emitted after the function prologue,
 ! since the directive requires access to function arguments.
 
-! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -cpp -DOMP_60 %s -o - | FileCheck %s --check-prefix=CHECK60
 
-subroutine declare_simd_no_clause(x, y, n, i)
+subroutine declare_simd_no_clause()
   !$omp declare simd
-  real(8), pointer, intent(inout) :: x(:)
-  real(8), pointer, intent(in)    :: y(:)
-  integer, intent(in) :: n, i
-  if (i <= n) x(i) = x(i) + y(i)
 end subroutine declare_simd_no_clause
 
-! CHECK-LABEL: func.func @_QPdeclare_simd_no_clause(
-! CHECK: %[[SCOPE_NONE:.*]] = fir.dummy_scope : !fir.dscope
-! CHECK: %[[I_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[N_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[X_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
-! CHECK: %[[Y_NONE:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_NONE]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK-LABEL: func.func @_QPdeclare_simd_no_clause()
 ! CHECK: omp.declare_simd
-! CHECK-NOT: aligned(
-! CHECK-NOT: linear(
-! CHECK-NOT: simdlen(
+! CHECK-NOT: {{omp\.declare_simd[[:space:]]*(aligned|linear|simdlen)\(}}
 ! CHECK: return
 
 subroutine declare_simd_aligned(x, y, n, i)
@@ -42,8 +33,7 @@ end subroutine declare_simd_aligned
 ! CHECK: omp.declare_simd
 ! CHECK-SAME: aligned(%[[X_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64,
 ! CHECK-SAME:         %[[Y_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64)
-! CHECK-NOT: linear(
-! CHECK-NOT: simdlen(
+! CHECK-NOT: {{[[:space:]]*(linear|simdlen)\(}}
 ! CHECK: return
 
 subroutine declare_simd_linear(x, y, n, i)
@@ -62,10 +52,7 @@ end subroutine  declare_simd_linear
 ! CHECK: %[[Y_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
 ! CHECK: %[[C1_L:.*]] = arith.constant 1 : i32
 ! CHECK: omp.declare_simd
-! CHECK-NOT: aligned(
-! CHECK-SAME: linear(%[[I_L]]#0 = %[[C1_L]] : !fir.ref<i32>)
-! CHECK-SAME: {linear_var_types = [i32]}
-! CHECK-NOT: simdlen(
+! CHECK-NOT: {{[[:space:]]*(aligned|simdlen)\(}}
 ! CHECK: return
 
 subroutine declare_simd_simdlen(x, y, n, i)
@@ -83,8 +70,7 @@ end subroutine declare_simd_simdlen
 ! CHECK: %[[X_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
 ! CHECK: %[[Y_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
 ! CHECK: omp.declare_simd
-! CHECK-NOT: aligned(
-! CHECK-NOT: linear(
+! CHECK-NOT: {{[[:space:]]*(aligned|linear)\(}}
 ! CHECK-SAME: simdlen(8)
 ! CHECK: return
 
@@ -96,7 +82,7 @@ subroutine declare_simd_combined(x, y, n, i)
 
     if (i <= n) then
         x(i) = x(i) + y(i)
-end if
+    end if
 end subroutine declare_simd_combined
 
 ! CHECK-LABEL: func.func @_QPdeclare_simd_combined(
@@ -117,3 +103,102 @@ end subroutine declare_simd_combined
 ! CHECK-SAME: linear(%[[I_DECL]]#0 = %[[C1]] : !fir.ref<i32>)
 ! CHECK-SAME: simdlen(8)
 ! CHECK-SAME: {linear_var_types = [i32]}
+
+#ifdef OMP_60
+
+subroutine declare_simd_60_no_clause()
+  !$omp declare_simd
+end subroutine declare_simd_60_no_clause
+
+! CHECK60-LABEL: func.func @_QPdeclare_simd_60_no_clause() {
+! CHECK60: omp.declare_simd
+
+subroutine declare_simd_aligned_60(x, y, n, i)
+  !$omp declare_simd aligned(x, y : 64)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine declare_simd_aligned_60
+
+! CHECK60-LABEL: func.func @_QPdeclare_simd_aligned_60(
+! CHECK60: %[[SCOPE_A:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK60: %[[I_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[N_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[X_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[Y_A:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_A]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: omp.declare_simd
+! CHECK60-SAME: aligned(%[[X_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64,
+! CHECK60-SAME:         %[[Y_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64)
+! CHECK60-NOT: {{[[:space:]]*(linear|simdlen)\(}}
+! CHECK60: return
+
+subroutine declare_simd_linear_60(x, y, n, i)
+  !$omp declare_simd linear(i)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine  declare_simd_linear_60
+
+! CHECK60-LABEL: func.func @_QPdeclare_simd_linear_60(
+! CHECK60: %[[SCOPE_L:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK60: %[[I_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[N_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[X_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[Y_L:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_L]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[C1_L:.*]] = arith.constant 1 : i32
+! CHECK60: omp.declare_simd
+! CHECK60-NOT: {{[[:space:]]*(aligned|simdlen)\(}}
+! CHECK60: return
+
+subroutine declare_simd_simdlen_60(x, y, n, i)
+  !$omp declare_simd simdlen(8)
+  real(8), pointer, intent(inout) :: x(:)
+  real(8), pointer, intent(in)    :: y(:)
+  integer, intent(in) :: n, i
+  if (i <= n) x(i) = x(i) + y(i)
+end subroutine declare_simd_simdlen_60
+
+! CHECK60-LABEL: func.func @_QPdeclare_simd_simdlen_60(
+! CHECK60: %[[SCOPE_S:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK60: %[[I_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[N_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[X_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 1 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[Y_S:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE_S]] arg 2 {{.*pointer.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: omp.declare_simd
+! CHECK60-NOT: {{[[:space:]]*(aligned|linear)\(}}
+! CHECK60-SAME: simdlen(8)
+! CHECK60: return
+
+subroutine declare_simd_combined_60(x, y, n, i)
+    !$omp declare_simd aligned(x, y : 64) linear(i) simdlen(8)
+    real(8), pointer, intent(inout) :: x(:)
+    real(8), pointer, intent(in)    :: y(:)
+    integer, intent(in) :: n, i
+
+    if (i <= n) then
+        x(i) = x(i) + y(i)
+    end if
+end subroutine declare_simd_combined_60
+
+! CHECK60-LABEL: func.func @_QPdeclare_simd_combined_60(
+! CHECK60-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>{{.*}}fir.bindc_name = "x"
+! CHECK60-SAME: %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>{{.*}}fir.bindc_name = "y"
+! CHECK60-SAME: %{{.*}}: !fir.ref<i32>{{.*}}fir.bindc_name = "n"
+! CHECK60-SAME: %{{.*}}: !fir.ref<i32>{{.*}}fir.bindc_name = "i"
+! CHECK60: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK60: %[[I_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 4 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[N_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 3 {{.*}} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK60: %[[X_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 1 {{.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[Y_DECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 2 {{.*}} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK60: %[[C1:.*]] = arith.constant 1 : i32
+
+! CHECK60: omp.declare_simd
+! CHECK60-SAME: aligned(%[[X_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64,
+! CHECK60-SAME:         %[[Y_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>> -> 64 : i64)
+! CHECK60-SAME: linear(%[[I_DECL]]#0 = %[[C1]] : !fir.ref<i32>)
+! CHECK60-SAME: simdlen(8)
+! CHECK60-SAME: {linear_var_types = [i32]}
+
+#endif !OMP_60
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index c77e08e1fb076..e6c35d3c1846a 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2246,7 +2246,8 @@ def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
 
 def DeclareSimdOp
     : OpenMP_Op<"declare_simd",
-                traits = [AttrSizedOperandSegments, IsolatedFromAbove],
+                traits = [AttrSizedOperandSegments,
+                          DeclareOpInterfaceMethods<MemoryEffectsOpInterface>],
                 clauses = [OpenMP_AlignedClause, OpenMP_LinearClause,
                            OpenMP_SimdlenClause]> {
   let summary = "declare simd directive";
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index f23bb659ae88e..eb0374d8fdda6 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4478,18 +4478,29 @@ LogicalResult DeclareSimdOp::verify() {
     return emitOpError()
            << "'omp.declare_simd' must be nested inside a function";
 
-  // omp.declare_simd must appear in the entry block of the enclosing function
-  Block &entry = func.getFunctionBody().front();
-  if (getOperation()->getBlock() != &entry)
-    return emitError()
-           << "must appear in the entry block of the enclosing function";
-
   if (verifyAlignedClause(*this, getAlignments(), getAlignedVars()).failed())
     return failure();
 
   return success();
 }
 
+namespace mlir {
+namespace omp {
+// A non-default resource to indicate that omp.declare_simd has side effects.
+struct DeclareSimdResource
+    : public SideEffects::Resource::Base<DeclareSimdResource> {
+  StringRef getName() final { return "omp.declare_simd.resource"; }
+};
+} // namespace omp
+} // namespace mlir
+
+void DeclareSimdOp::getEffects(
+    SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+        &effects) {
+  effects.emplace_back(MemoryEffects::Allocate::get(),
+                       DeclareSimdResource::get());
+}
+
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
 
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index af24d969064ab..9138b70ba964d 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3139,3 +3139,7 @@ func.func @invalid_workdistribute() -> () {
   }
   return
 }
+
+// -----
+// expected-error @+1 {{'omp.declare_simd' must be nested inside a function}}
+omp.declare_simd
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 8ab2ed89e5ecc..95d179247fb91 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3369,25 +3369,23 @@ func.func @omp_target_map_clause_type_test(%arg0 : memref<?xi32>) -> () {
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd
-func.func @omp_declare_simd(%a: f64, %b: f64) -> f64 {
+func.func @omp_declare_simd() -> () {
   // CHECK: omp.declare_simd
   omp.declare_simd
-  %0 = arith.addf %a, %b : f64
-  return %0 : f64
+  return
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd_simdlen
-func.func @omp_declare_simd_simdlen(%a: f64, %b: f64) -> f64 {
+func.func @omp_declare_simd_simdlen() -> () {
   // CHECK: omp.declare_simd
   // CHECK-SAME: simdlen(8)
   omp.declare_simd simdlen(8)
-  %0 = arith.addf %a, %b : f64
-  return %0 : f64
+  return
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd_aligned
 func.func @omp_declare_simd_aligned(%a: f64, %b: f64,
-                                         %p0: memref<i32>, %p1: memref<i32>) -> f64 {
+                                         %p0: memref<i32>, %p1: memref<i32>) -> () {
   // CHECK:      omp.declare_simd
   // CHECK-SAME: aligned(
   // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
@@ -3395,33 +3393,30 @@ func.func @omp_declare_simd_aligned(%a: f64, %b: f64,
   omp.declare_simd aligned(%p0 : memref<i32> -> 32 : i64,
                            %p1 : memref<i32> -> 128 : i64)
 
-  %0 = arith.addf %a, %b : f64
-  return %0 : f64
+  return
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd_aligned_list_generic
 func.func @omp_declare_simd_aligned_list_generic(%arg0: f64, %arg1: f64,
-                                                 %arg2: memref<i32>, %arg3: memref<i32>) -> f64 {
+                                                 %arg2: memref<i32>, %arg3: memref<i32>) -> () {
   // CHECK:      omp.declare_simd
   // CHECK-SAME: aligned(%{{.*}} : memref<i32> -> 32 : i64, %{{.*}} : memref<i32> -> 128 : i64)
   omp.declare_simd aligned(%arg2 : memref<i32> -> 32 : i64, %arg3 : memref<i32> -> 128 : i64)
-  %0 = arith.addf %arg0, %arg1 : f64
-  return %0 : f64
+  return
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd_linear
-func.func @omp_declare_simd_linear(%a: f64, %b: f64, %iv: i32, %step: i32) -> f64 {
+func.func @omp_declare_simd_linear(%a: f64, %b: f64, %iv: i32, %step: i32) -> () {
   // CHECK: omp.declare_simd
   // CHECK-SAME: linear(%{{.*}} = %{{.*}} : i32)
   omp.declare_simd linear(%iv = %step : i32)
-  %0 = arith.addf %a, %b : f64
-  return %0 : f64
+  return
 }
 
 // CHECK-LABEL: func.func @omp_declare_simd_all_clauses
 func.func @omp_declare_simd_all_clauses(%a: f64, %b: f64,
                                         %p0: memref<i32>, %p1: memref<i32>,
-                                        %iv: i32, %step: i32) -> f64 {
+                                        %iv: i32, %step: i32) -> () {
   // CHECK:      omp.declare_simd
   // CHECK-SAME: aligned(
   // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
@@ -3432,7 +3427,5 @@ func.func @omp_declare_simd_all_clauses(%a: f64, %b: f64,
     aligned(%p0 : memref<i32> -> 32 : i64,
             %p1 : memref<i32> -> 128 : i64)
     linear(%iv = %step : i32)
-
-  %0 = arith.addf %a, %b : f64
-  return %0 : f64
+  return
 }

>From 3a9e569f542e862ff94948c91cca26ab4459e116 Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Wed, 14 Jan 2026 13:56:37 -0600
Subject: [PATCH 3/3] Resolve feedback

- Fix check line of declare_simd.f90
- Update mlir::omp::DeclareSimdOp
---
 flang/lib/Lower/OpenMP/OpenMP.cpp             | 12 ++++++++++--
 flang/test/Lower/OpenMP/declare-simd.f90      |  5 ++---
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  5 +----
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  |  9 ---------
 4 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 5f520635bb4c5..03531919b590a 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3815,7 +3815,6 @@ static void
 genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
        semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
        const parser::OpenMPDeclareSimdConstruct &declareSimdConstruct) {
-  mlir::Location loc = converter.getCurrentLocation();
   const parser::OmpDirectiveSpecification &beginSpec = declareSimdConstruct.v;
   List<Clause> clauses = makeClauses(beginSpec.Clauses(), semaCtx);
 
@@ -3827,7 +3826,16 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
   cp.processTODO<clause::Uniform>(converter.getCurrentLocation(),
                                   llvm::omp::Directive::OMPD_declare_simd);
 
-  mlir::omp::DeclareSimdOp::create(converter.getFirOpBuilder(), loc, clauseOps);
+  fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+  mlir::Location loc = converter.getCurrentLocation();
+  auto *ctx = firOpBuilder.getContext();
+  mlir::ArrayAttr alignments;
+  if (!clauseOps.alignments.empty())
+    alignments = mlir::ArrayAttr::get(ctx, clauseOps.alignments);
+  mlir::omp::DeclareSimdOp::create(firOpBuilder, loc, clauseOps.alignedVars,
+                                   alignments, clauseOps.linearVars,
+                                   clauseOps.linearStepVars,
+                                   clauseOps.linearVarTypes, clauseOps.simdlen);
 }
 
 static void genOpenMPDeclareMapperImpl(
diff --git a/flang/test/Lower/OpenMP/declare-simd.f90 b/flang/test/Lower/OpenMP/declare-simd.f90
index 222ce4af1bb7c..81a75b6007d3d 100644
--- a/flang/test/Lower/OpenMP/declare-simd.f90
+++ b/flang/test/Lower/OpenMP/declare-simd.f90
@@ -1,4 +1,4 @@
-! This test CHECKs the lowering of the OpenMP `declare simd` directive with
+! This test checks the lowering of the OpenMP `declare simd` directive with
 ! different clauses (e.g. aligned, linear, simdlen). It also verifies that
 ! the `omp.declare_simd` operation is emitted after the function prologue,
 ! since the directive requires access to function arguments.
@@ -12,8 +12,7 @@ subroutine declare_simd_no_clause()
 end subroutine declare_simd_no_clause
 
 ! CHECK-LABEL: func.func @_QPdeclare_simd_no_clause()
-! CHECK: omp.declare_simd
-! CHECK-NOT: {{omp\.declare_simd[[:space:]]*(aligned|linear|simdlen)\(}}
+! CHECK: omp.declare_simd{{$}}
 ! CHECK: return
 
 subroutine declare_simd_aligned(x, y, n, i)
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index e6c35d3c1846a..67a54df270e1e 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2265,13 +2265,10 @@ def DeclareSimdOp
       ...
     }
     ```
-  }]#clausesDescription;
+  }] # clausesDescription;
 
   let arguments = clausesArgs;
 
-  let builders = [OpBuilder<(
-      ins CArg<"const DeclareSimdOperands &">:$clauses)>];
-
   let assemblyFormat =
       clausesReqAssemblyFormat#" oilist("#clausesOptAssemblyFormat#") "#"attr-"
                                "dict";
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index eb0374d8fdda6..fbd76b00b5a1a 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4462,15 +4462,6 @@ LogicalResult WorkdistributeOp::verify() {
 // Declare simd [7.7]
 //===----------------------------------------------------------------------===//
 
-void DeclareSimdOp::build(OpBuilder &odsBuilder, OperationState &odsState,
-                          const DeclareSimdOperands &clauses) {
-  MLIRContext *ctx = odsBuilder.getContext();
-  DeclareSimdOp::build(odsBuilder, odsState, clauses.alignedVars,
-                       makeArrayAttr(ctx, clauses.alignments),
-                       clauses.linearVars, clauses.linearStepVars,
-                       clauses.linearVarTypes, clauses.simdlen);
-}
-
 LogicalResult DeclareSimdOp::verify() {
   // Must be nested inside a function-like op
   auto func = (*this)->getParentOfType<mlir::FunctionOpInterface>();



More information about the Mlir-commits mailing list