[Mlir-commits] [flang] [mlir] [flang][mlir][OpenMP] Add support for uniform clause in declare simd (PR #176046)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jan 16 14:21:55 PST 2026
https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/176046
>From f548f1511113b372bc16c6e41b67a816e0e8d372 Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Wed, 14 Jan 2026 16:14:24 -0600
Subject: [PATCH 1/2] [flang][mlir][OpenMP] Add support for uniform clause in
declare simd
Define OpenMP uniform clause in mlir and emit it from flang.
---
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 10 +++++
flang/lib/Lower/OpenMP/ClauseProcessor.h | 1 +
flang/lib/Lower/OpenMP/OpenMP.cpp | 2 +-
.../OpenMP/Todo/declare-simd-uniform.f90 | 9 -----
flang/test/Lower/OpenMP/declare-simd.f90 | 38 +++++++++++++++++--
.../mlir/Dialect/OpenMP/OpenMPClauses.td | 24 ++++++++++++
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 2 +-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 32 +++++++++++++++-
mlir/test/Dialect/OpenMP/ops.mlir | 17 +++++++++
9 files changed, 120 insertions(+), 15 deletions(-)
delete mode 100644 flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 2f531efaf09aa..ec2c880437f33 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1716,6 +1716,16 @@ bool ClauseProcessor::processUseDevicePtr(
return clauseFound;
}
+bool ClauseProcessor::processUniform(
+ mlir::omp::UniformClauseOps &result) const {
+ return findRepeatableClause<omp::clause::Uniform>(
+ [&](const omp::clause::Uniform &clause, const parser::CharBlock &) {
+ const auto &objects = clause.v;
+ if (!objects.empty())
+ genObjectList(objects, converter, result.uniformVars);
+ });
+}
+
} // namespace omp
} // namespace lower
} // namespace Fortran
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index a04cd4b79dd24..063da68fb5702 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -168,6 +168,7 @@ class ClauseProcessor {
lower::StatementContext &stmtCtx,
mlir::omp::UseDevicePtrClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;
+ bool processUniform(mlir::omp::UniformClauseOps &result) const;
// Call this method for these clauses that should be supported but are not
// implemented yet. It triggers a compilation error if any of the given
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 0764693f748a5..dc7207383147a 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3848,7 +3848,7 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
cp.processAligned(clauseOps);
cp.processLinear(clauseOps);
cp.processSimdlen(clauseOps);
- cp.processTODO<clause::Uniform>(loc, llvm::omp::Directive::OMPD_declare_simd);
+ cp.processUniform(clauseOps);
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
deleted file mode 100644
index 1ca5dd34de2d2..0000000000000
--- a/flang/test/Lower/OpenMP/Todo/declare-simd-uniform.f90
+++ /dev/null
@@ -1,9 +0,0 @@
-! 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 240d0f0d58305..6ebb82d801708 100644
--- a/flang/test/Lower/OpenMP/declare-simd.f90
+++ b/flang/test/Lower/OpenMP/declare-simd.f90
@@ -73,11 +73,40 @@ end subroutine declare_simd_simdlen
! CHECK: omp.declare_simd{{.*}}simdlen(8){{$}}
! CHECK-NEXT: return
+subroutine declare_simd_uniform(x, y, n, i)
+#ifdef OMP_60
+!$omp declare_simd uniform(x, y)
+#else
+!$omp declare simd uniform(x, y)
+#endif
+
+ 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_uniform
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_uniform(
+! CHECK-SAME: fir.bindc_name = "x"
+! CHECK-SAME: fir.bindc_name = "y"
+! CHECK-SAME: fir.bindc_name = "n"
+! CHECK-SAME: fir.bindc_name = "i"
+! CHECK: %[[SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[IDECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 4
+! CHECK: %[[NDECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 3
+! CHECK: %[[XDECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 1
+! CHECK: %[[YDECL:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[SCOPE]] arg 2
+! CHECK: omp.declare_simd uniform(%[[XDECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>, %[[YDECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK: return
+
subroutine declare_simd_combined(x, y, n, i)
#ifdef OMP_60
-!$omp declare_simd aligned(x, y : 64) linear(i) simdlen(8)
+!$omp declare_simd aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
#else
-!$omp declare simd aligned(x, y : 64) linear(i) simdlen(8)
+!$omp declare simd aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
#endif
real(8), pointer, intent(inout) :: x(:)
real(8), pointer, intent(in) :: y(:)
@@ -105,4 +134,7 @@ end subroutine declare_simd_combined
! 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]}
+! CHECK-SAME: uniform(%[[X_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>,
+! CHECK-SAME: %[[Y_DECL]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf64>>>>)
+! CHECK-SAME: {linear_var_types = [i32]}{{$}}
+! CHECK: return
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 05e2ee4e5632b..3972c9aca4b12 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1532,4 +1532,28 @@ class OpenMP_UseDevicePtrClauseSkip<
def OpenMP_UseDevicePtrClause : OpenMP_UseDevicePtrClauseSkip<>;
+//===----------------------------------------------------------------------===//
+// V5.2: [5.10] `uniform` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_UniformClauseSkip<
+ bit traits = false, bit arguments = false, bit assemblyFormat = false,
+ bit description = false, bit extraClassDeclaration = false>
+ : OpenMP_Clause<traits, arguments, assemblyFormat, description,
+ extraClassDeclaration> {
+ let arguments = (ins Variadic<OpenMP_PointerLikeType>:$uniform_vars);
+
+ let optAssemblyFormat = [{
+ `uniform` `(` custom<UniformClause>($uniform_vars, type($uniform_vars)) `)`
+ }];
+
+ let description = [{
+ The `uniform` clause declares one or more arguments to have an invariant
+ value for all concurrent invocations of the function in the execution of
+ a single SIMD loop.
+ }];
+}
+
+def OpenMP_UniformClause : OpenMP_UniformClauseSkip<>;
+
#endif // OPENMP_CLAUSES
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index d4e8cecda2601..8e48e50464532 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2248,7 +2248,7 @@ def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
def DeclareSimdOp
: OpenMP_Op<"declare_simd", traits = [AttrSizedOperandSegments],
clauses = [OpenMP_AlignedClause, OpenMP_LinearClause,
- OpenMP_SimdlenClause]> {
+ OpenMP_SimdlenClause, OpenMP_UniformClause]> {
let summary = "declare simd directive";
let description = [{
"omp.declare_simd" models the OpenMP `declare simd` directive.
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index cf25fc53e0238..d43c93d88a881 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4485,7 +4485,37 @@ void DeclareSimdOp::build(OpBuilder &odsBuilder, OperationState &odsState,
DeclareSimdOp::build(odsBuilder, odsState, clauses.alignedVars,
makeArrayAttr(ctx, clauses.alignments),
clauses.linearVars, clauses.linearStepVars,
- clauses.linearVarTypes, clauses.simdlen);
+ clauses.linearVarTypes, clauses.simdlen,
+ clauses.uniformVars);
+}
+
+//===----------------------------------------------------------------------===//
+// Parser and printer for Uniform Clause
+//===----------------------------------------------------------------------===//
+
+/// uniform ::= `uniform` `(` uniform-list `)`
+/// uniform-list := uniform-val (`,` uniform-val)*
+/// uniform-val := ssa-id `:` type
+static ParseResult
+parseUniformClause(OpAsmParser &parser,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &uniformVars,
+ SmallVectorImpl<Type> &uniformTypes) {
+ return parser.parseCommaSeparatedList([&]() -> mlir::ParseResult {
+ if (parser.parseOperand(uniformVars.emplace_back()) ||
+ parser.parseColonType(uniformTypes.emplace_back()))
+ return mlir::failure();
+ return mlir::success();
+ });
+}
+
+/// Print Uniform Clauses
+static void printUniformClause(OpAsmPrinter &p, Operation *op,
+ ValueRange uniformVars, TypeRange uniformTypes) {
+ for (unsigned i = 0; i < uniformVars.size(); ++i) {
+ if (i != 0)
+ p << ", ";
+ p << uniformVars[i] << " : " << uniformTypes[i];
+ }
}
#define GET_ATTRDEF_CLASSES
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 902d962138fc9..d57029a086f41 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3414,6 +3414,19 @@ func.func @omp_declare_simd_linear(%a: f64, %b: f64, %iv: i32, %step: i32) -> ()
return
}
+// CHECK-LABEL: func.func @omp_declare_simd_uniform
+func.func @omp_declare_simd_uniform(%a: f64, %b: f64,
+ %p0: memref<i32>, %p1: memref<i32>) -> f64 {
+ // CHECK: omp.declare_simd
+ // CHECK-SAME: uniform(
+ // CHECK-SAME: %{{.*}} : memref<i32>,
+ // CHECK-SAME: %{{.*}} : memref<i32>)
+ omp.declare_simd uniform(%p0 : memref<i32>, %p1 : memref<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>,
@@ -3424,9 +3437,13 @@ func.func @omp_declare_simd_all_clauses(%a: f64, %b: f64,
// CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
// CHECK-SAME: linear(%{{.*}} = %{{.*}} : i32)
// CHECK-SAME: simdlen(8)
+ // CHECK-SAME: uniform(
+ // CHECK-SAME: %{{.*}} : memref<i32>,
+ // CHECK-SAME: %{{.*}} : memref<i32>)
omp.declare_simd simdlen(8)
aligned(%p0 : memref<i32> -> 32 : i64,
%p1 : memref<i32> -> 128 : i64)
linear(%iv = %step : i32)
+ uniform(%p0 : memref<i32>, %p1 : memref<i32>)
return
}
>From b8ea484b68d883c27e37ac1b1dad4350b01a6d7b Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Fri, 16 Jan 2026 16:01:07 -0600
Subject: [PATCH 2/2] Add semantic check for uniform clause
Add semantic check to verify that parameters in uniform clause are
dummy arguments of the enclosing procedure.
---
flang/lib/Semantics/check-omp-structure.cpp | 32 +++++++++++++++++++
.../Semantics/OpenMP/declare-simd-uniform.f90 | 15 ++++++++-
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 23871ca04bccb..9072f5a642267 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1446,6 +1446,38 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) {
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);
+ const Scope &containingScope = context_.FindScope(dirName.source);
+ const Scope &progUnitScope = GetProgramUnitContaining(containingScope);
+
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ llvm::omp::Clause id{clause.Id()};
+ if (id != llvm::omp::Clause::OMPC_uniform) {
+ continue;
+ }
+ const auto *u = std::get_if<parser::OmpClause::Uniform>(&clause.u);
+ if (!u) {
+ continue;
+ }
+ for (const parser::Name &name : u->v) {
+ const Symbol *sym{name.symbol};
+ if (!sym) {
+ context_.Say(name.source,
+ "Variable '%s' in UNIFORM clause must be a dummy argument of the "
+ "enclosing procedure"_err_en_US,
+ name.ToString());
+ continue;
+ }
+
+ if (!IsDummy(*sym) ||
+ &GetProgramUnitContaining(sym->owner()) != &progUnitScope) {
+ context_.Say(name.source,
+ "Variable '%s' in UNIFORM clause must be a dummy argument of the "
+ "enclosing procedure"_err_en_US,
+ name.ToString());
+ }
+ }
+ }
+
const parser::OmpArgumentList &args{x.v.Arguments()};
if (args.v.empty()) {
return;
diff --git a/flang/test/Semantics/OpenMP/declare-simd-uniform.f90 b/flang/test/Semantics/OpenMP/declare-simd-uniform.f90
index 8d986300cd750..f729773cdd2e2 100644
--- a/flang/test/Semantics/OpenMP/declare-simd-uniform.f90
+++ b/flang/test/Semantics/OpenMP/declare-simd-uniform.f90
@@ -1,4 +1,4 @@
-! RUN: %python %S/../test_errors.py %s %flang -fopenmp
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -cpp -DNEGATIVE
! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s
! Test declare simd with uniform clause
@@ -20,3 +20,16 @@ function add2(a,b,i,fact,alc) result(c)
! CHECK-NEXT: c size=8 offset=40: ObjectEntity funcResult type: REAL(8)
! CHECK-NEXT: fact (OmpUniform) size=8 offset=32: ObjectEntity dummy type: REAL(8)
! CHECK-NEXT: i size=4 offset=0: ObjectEntity dummy type: INTEGER(4)
+
+#ifdef NEGATIVE
+
+function bad_uniform(a,b,i) result(c)
+ double precision :: a(*), b(*), c
+ integer :: i
+ double precision :: local
+ !ERROR: Variable 'local' in UNIFORM clause must be a dummy argument of the enclosing procedure
+ !$omp declare simd(bad_uniform) uniform(a,local)
+ c = a(i) + b(i) + local
+end function
+
+#endif
More information about the Mlir-commits
mailing list