[Mlir-commits] [flang] [mlir] [flang][mlir][OpenMP] Support inbranch and notinbranch clause (PR #177310)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jan 21 22:22:46 PST 2026


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

>From fd98ec81ab59204efec4f29cd092f49ee7fce0ab Mon Sep 17 00:00:00 2001
From: cchen <chichun.chen at hpe.com>
Date: Thu, 22 Jan 2026 00:02:34 -0600
Subject: [PATCH] [flang][mlir][OpenMP] Support inbranch and notinbranch clause

Support inbranch and notinbranch clause for OpenMP declare simd
directive.
---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    | 20 +++++++++
 flang/lib/Lower/OpenMP/ClauseProcessor.h      |  2 +
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  2 +
 flang/test/Lower/OpenMP/declare-simd.f90      | 29 +++++++++++-
 .../mlir/Dialect/OpenMP/OpenMPClauses.td      | 44 +++++++++++++++++++
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  3 +-
 mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp  | 13 +++---
 mlir/test/Dialect/OpenMP/invalid.mlir         |  7 +++
 mlir/test/Dialect/OpenMP/ops.mlir             | 37 ++++++++++++++++
 9 files changed, 149 insertions(+), 8 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index ec2c880437f33..bc6c6d50b88e6 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1726,6 +1726,26 @@ bool ClauseProcessor::processUniform(
       });
 }
 
+bool ClauseProcessor::processInbranch(
+    mlir::omp::InbranchClauseOps &result) const {
+  if (findUniqueClause<omp::clause::Inbranch>()) {
+    result.inbranch =
+        mlir::UnitAttr::get(converter.getFirOpBuilder().getContext());
+    return true;
+  }
+  return false;
+}
+
+bool ClauseProcessor::processNotinbranch(
+    mlir::omp::NotinbranchClauseOps &result) const {
+  if (findUniqueClause<omp::clause::Notinbranch>()) {
+    result.notinbranch =
+        mlir::UnitAttr::get(converter.getFirOpBuilder().getContext());
+    return true;
+  }
+  return false;
+}
+
 } // namespace omp
 } // namespace lower
 } // namespace Fortran
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index 063da68fb5702..69e957ec717ec 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -169,6 +169,8 @@ class ClauseProcessor {
       mlir::omp::UseDevicePtrClauseOps &result,
       llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const;
   bool processUniform(mlir::omp::UniformClauseOps &result) const;
+  bool processInbranch(mlir::omp::InbranchClauseOps &result) const;
+  bool processNotinbranch(mlir::omp::NotinbranchClauseOps &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 eab04ab13f9fa..b9e37a0555d8a 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3849,6 +3849,8 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
   cp.processLinear(clauseOps);
   cp.processSimdlen(clauseOps);
   cp.processUniform(clauseOps);
+  cp.processInbranch(clauseOps);
+  cp.processNotinbranch(clauseOps);
 
   mlir::omp::DeclareSimdOp::create(converter.getFirOpBuilder(), loc, clauseOps);
 }
diff --git a/flang/test/Lower/OpenMP/declare-simd.f90 b/flang/test/Lower/OpenMP/declare-simd.f90
index 6ebb82d801708..59b8cc07a8f28 100644
--- a/flang/test/Lower/OpenMP/declare-simd.f90
+++ b/flang/test/Lower/OpenMP/declare-simd.f90
@@ -102,11 +102,35 @@ end subroutine declare_simd_uniform
 ! 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_inbranch()
+#ifdef OMP_60
+!$omp declare_simd inbranch
+#else
+!$omp declare simd inbranch
+#endif
+end subroutine declare_simd_inbranch
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_inbranch()
+! CHECK: omp.declare_simd inbranch{{$}}
+! CHECK: return
+
+subroutine declare_simd_notinbranch()
+#ifdef OMP_60
+!$omp declare_simd notinbranch
+#else
+!$omp declare simd notinbranch
+#endif
+end subroutine declare_simd_notinbranch
+
+! CHECK-LABEL: func.func @_QPdeclare_simd_notinbranch()
+! CHECK: omp.declare_simd notinbranch{{$}}
+! CHECK: return
+
 subroutine declare_simd_combined(x, y, n, i)
 #ifdef OMP_60
-!$omp declare_simd aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
+!$omp declare_simd inbranch aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
 #else
-!$omp declare simd aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
+!$omp declare simd inbranch aligned(x, y : 64) linear(i) simdlen(8) uniform(x, y)
 #endif
   real(8), pointer, intent(inout) :: x(:)
   real(8), pointer, intent(in)    :: y(:)
@@ -136,5 +160,6 @@ end subroutine declare_simd_combined
 ! CHECK-SAME: simdlen(8)
 ! 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: inbranch
 ! 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 3972c9aca4b12..4cc5bb19961b9 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -1556,4 +1556,48 @@ class OpenMP_UniformClauseSkip<
 
 def OpenMP_UniformClause : OpenMP_UniformClauseSkip<>;
 
+//===----------------------------------------------------------------------===//
+// V5.2: [9.8.1.1]: `inbranch` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_InbranchClauseSkip<
+    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 UnitAttr:$inbranch);
+
+  let optAssemblyFormat = [{
+    `inbranch` $inbranch
+  }];
+
+  let description = [{
+    The `inbranch` clause indicates that the generated SIMD function variant
+    is intended for use in conditional branches.
+  }];
+}
+def OpenMP_InbranchClause : OpenMP_InbranchClauseSkip<>;
+
+//===----------------------------------------------------------------------===//
+// V5.2: [9.8.1.2]: `notinbranch` clause
+//===----------------------------------------------------------------------===//
+
+class OpenMP_NotinbranchClauseSkip<
+    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 UnitAttr:$notinbranch);
+
+  let optAssemblyFormat = [{
+    `notinbranch` $notinbranch
+  }];
+
+  let description = [{
+    The `notinbranch` clause indicates that the generated SIMD function variant
+    is intended for use when not in conditional branches.
+  }];
+}
+def OpenMP_NotinbranchClause : OpenMP_NotinbranchClauseSkip<>;
+
 #endif // OPENMP_CLAUSES
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 8e48e50464532..34641b4edaa75 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2248,7 +2248,8 @@ def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
 def DeclareSimdOp
     : OpenMP_Op<"declare_simd", traits = [AttrSizedOperandSegments],
                 clauses = [OpenMP_AlignedClause, OpenMP_LinearClause,
-                           OpenMP_SimdlenClause, OpenMP_UniformClause]> {
+                           OpenMP_SimdlenClause, OpenMP_UniformClause,
+                           OpenMP_InbranchClause, OpenMP_NotinbranchClause]> {
   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 9d548c76d37da..9251802fc3ba4 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -4476,17 +4476,20 @@ LogicalResult DeclareSimdOp::verify() {
   if (!func)
     return emitOpError() << "must be nested inside a function";
 
+  if (getInbranch() && getNotinbranch())
+    return emitOpError("cannot have both 'inbranch' and 'notinbranch'");
+
   return verifyAlignedClause(*this, getAlignments(), getAlignedVars());
 }
 
 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,
-                       clauses.uniformVars);
+  DeclareSimdOp::build(
+      odsBuilder, odsState, clauses.alignedVars,
+      makeArrayAttr(ctx, clauses.alignments), clauses.linearVars,
+      clauses.linearStepVars, clauses.linearVarTypes, clauses.simdlen,
+      clauses.uniformVars, clauses.inbranch, clauses.notinbranch);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 1350c5e2ee8d2..0d9d1f1663ef9 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3143,3 +3143,10 @@ func.func @invalid_workdistribute() -> () {
 // -----
 // expected-error @+1 {{'omp.declare_simd' op must be nested inside a function}}
 omp.declare_simd
+
+// -----
+func.func @omp_declare_simd_branch() -> () {
+  // expected-error @+1 {{'omp.declare_simd' op cannot have both 'inbranch' and 'notinbranch'}}
+  omp.declare_simd inbranch notinbranch
+  return
+}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 54534cca766d9..4f61a1f3c8c57 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3425,6 +3425,41 @@ func.func @omp_declare_simd_uniform(%a: f64, %b: f64,
   return
 }
 
+// CHECK-LABEL: func.func @omp_declare_simd_inbranch
+func.func @omp_declare_simd_inbranch() -> () {
+  // CHECK:      omp.declare_simd inbranch
+  omp.declare_simd inbranch
+  return
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_notinbranch
+func.func @omp_declare_simd_notinbranch() -> () {
+  // CHECK:      omp.declare_simd notinbranch
+  omp.declare_simd notinbranch
+  return
+}
+
+// CHECK-LABEL: func.func @omp_declare_simd_multiple_clauses
+func.func @omp_declare_simd_multiple_clauses(%a: f64, %b: f64,
+                                             %p0: memref<i32>, %p1: memref<i32>,
+                                             %iv: i32, %step: i32) -> () {
+  // CHECK:      omp.declare_simd
+  // CHECK-SAME: aligned(
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
+  // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
+  // CHECK-SAME: simdlen(8)
+  // CHECK-SAME: uniform(
+  // CHECK-SAME: %{{.*}} : memref<i32>,
+  // CHECK-SAME: %{{.*}} : memref<i32>)
+  // CHECK-SAME: notinbranch
+  omp.declare_simd simdlen(8)
+    aligned(%p0 : memref<i32> -> 32 : i64,
+            %p1 : memref<i32> -> 128 : i64)
+    uniform(%p0 : memref<i32>, %p1 : memref<i32>)
+    notinbranch
+  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>,
@@ -3438,10 +3473,12 @@ func.func @omp_declare_simd_all_clauses(%a: f64, %b: f64,
   // CHECK-SAME: uniform(
   // CHECK-SAME: %{{.*}} : memref<i32>,
   // CHECK-SAME: %{{.*}} : memref<i32>)
+  // CHECK-SAME: inbranch
   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>)
+    inbranch
   return
 }



More information about the Mlir-commits mailing list