[Mlir-commits] [flang] [mlir] [mlir][OpenMP] Add memory effects of single op (PR #237929)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Nov 2 03:52:10 PST 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-openmp

Author: JRP-arm

<details>
<summary>Changes</summary>

Added a new attribute for the copyprivate clause `copyprivate_assume_bounded_recipe_effects`. Applied when the copyprivate variables are of a specific type.

Add direct memory effect tests, CSE & canonicalisation tests.
Add tests for correct application of the `copyprivate_assume_bounded_recipe_effects` attribute.
AI-Assisted-by: Codex (OpenAI)

---

Patch is 28.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/237929.diff


9 Files Affected:

- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+43-25) 
- (modified) flang/test/Lower/OpenMP/compound.f90 (+7-7) 
- (modified) flang/test/Lower/OpenMP/recipe-memory-effects.f90 (+199) 
- (modified) mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td (+15-5) 
- (modified) mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td (+6-4) 
- (modified) mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (+42-7) 
- (modified) mlir/test/Dialect/OpenMP/canonicalize.mlir (+28) 
- (modified) mlir/test/Dialect/OpenMP/cse.mlir (+21) 
- (modified) mlir/test/Dialect/OpenMP/memory-effects.mlir (+84) 


``````````diff
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 98a0a54ad2a6f2..63ebe6224bea4b 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1858,6 +1858,30 @@ struct OpWithBodyGenInfo {
   int collapseValue = 0;
 };
 
+static bool isNonDerivedNonPointer(const semantics::Symbol &sym) {
+  const auto &ultimate = sym.GetUltimate();
+  const auto *type = ultimate.GetType();
+  return type && type->AsIntrinsic() && !semantics::IsAllocatable(ultimate) &&
+         !semantics::IsPointer(ultimate);
+}
+
+static bool isNonDerivedNonPointer(const mlir::Value &variable) {
+  return !fir::isAllocatableType(variable.getType()) &&
+         !fir::isa_derived(fir::getFortranElementType(variable.getType())) &&
+         !fir::isPointerType(variable.getType());
+}
+
+static bool isNonDerivedNonPointerItem(const semantics::Symbol &sym) {
+  const auto &ultimate = sym.GetUltimate();
+  if (const auto *common =
+          ultimate.detailsIf<semantics::CommonBlockDetails>()) {
+    return llvm::all_of(common->objects(), [](const auto &member) {
+      return isNonDerivedNonPointer(*member);
+    });
+  }
+  return isNonDerivedNonPointer(ultimate);
+}
+
 /// Create the body (block) for an OpenMP Operation.
 ///
 /// \param [in]   op  - the operation the body belongs to.
@@ -1926,6 +1950,17 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info,
                     Fortran::lower::omp::isLastItemInQueue(item, queue),
                     /*useDelayedPrivatization=*/false, info.symTable);
     tempDsp->processStep1();
+
+    // TODO: omp.single still uses eager privatisation.
+    // Use clauseOps.privateVars inside genSingleOp once
+    // delayedPrivatization is turned on.
+    if (auto singleOp = llvm::dyn_cast<mlir::omp::SingleOp>(op)) {
+      const auto &privateSyms = tempDsp->getAllSymbolsToPrivatize();
+      if (llvm::all_of(privateSyms, [](const semantics::Symbol *sym) {
+            return isNonDerivedNonPointerItem(*sym);
+          }))
+        singleOp.setPrivateAssumeBoundedRecipeEffects(true);
+    }
   }
 
   if (info.dir == llvm::omp::Directive::OMPD_parallel) {
@@ -3564,30 +3599,6 @@ findEnclosingParallelOp(fir::FirOpBuilder &builder) {
   return {};
 }
 
-static bool isNonDerivedNonPointer(const semantics::Symbol &sym) {
-  const auto &ultimate = sym.GetUltimate();
-  const auto *type = ultimate.GetType();
-  return type && type->AsIntrinsic() && !semantics::IsAllocatable(ultimate) &&
-         !semantics::IsPointer(ultimate);
-}
-
-static bool isNonDerivedNonPointer(const mlir::Value &variable) {
-  return !fir::isAllocatableType(variable.getType()) &&
-         !fir::isa_derived(fir::getFortranElementType(variable.getType())) &&
-         !fir::isPointerType(variable.getType());
-}
-
-static bool isNonDerivedNonPointerItem(const semantics::Symbol &sym) {
-  const auto &ultimate = sym.GetUltimate();
-  if (const auto *common =
-          ultimate.detailsIf<semantics::CommonBlockDetails>()) {
-    return llvm::all_of(common->objects(), [](const auto &member) {
-      return isNonDerivedNonPointer(*member);
-    });
-  }
-  return isNonDerivedNonPointer(ultimate);
-}
-
 static mlir::omp::SectionsOp
 genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
               semantics::SemanticsContext &semaCtx,
@@ -3945,11 +3956,18 @@ genSingleOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   mlir::omp::SingleOperands clauseOps;
   genSingleClauses(converter, semaCtx, item->clauses, loc, clauseOps);
 
-  return genOpWithBody<mlir::omp::SingleOp>(
+  auto singleOp = genOpWithBody<mlir::omp::SingleOp>(
       OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval,
                         llvm::omp::Directive::OMPD_single)
           .setClauses(&item->clauses),
       queue, item, clauseOps);
+
+  if (llvm::all_of(clauseOps.copyprivateVars, [](mlir::Value variable) {
+        return isNonDerivedNonPointer(variable);
+      }))
+    singleOp.setCopyprivateAssumeBoundedRecipeEffects(true);
+
+  return singleOp;
 }
 
 static bool isDuplicateMappedSymbol(
diff --git a/flang/test/Lower/OpenMP/compound.f90 b/flang/test/Lower/OpenMP/compound.f90
index d61745345a6405..f06edf36244e5e 100644
--- a/flang/test/Lower/OpenMP/compound.f90
+++ b/flang/test/Lower/OpenMP/compound.f90
@@ -784,7 +784,7 @@ subroutine single_loop()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_parallel()
   implicit none
@@ -803,7 +803,7 @@ subroutine single_parallel()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_simd()
   implicit none
@@ -825,7 +825,7 @@ subroutine single_simd()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_target()
   implicit none
@@ -844,7 +844,7 @@ subroutine single_target()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_target_data()
   implicit none
@@ -864,7 +864,7 @@ subroutine single_target_data()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_task()
   implicit none
@@ -883,7 +883,7 @@ subroutine single_task()
 ! CHECK-NEXT:      }
 ! CHECK-NOT:       omp.combined
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine single_taskloop()
   implicit none
@@ -908,7 +908,7 @@ subroutine single_taskloop()
 ! CHECK:             omp.terminator
 ! CHECK-NEXT:      } {{{.*}}omp.combined{{.*}}}
 ! CHECK:           omp.terminator
-! CHECK-NEXT:    } {{{.*}}omp.combined{{.*}}}
+! CHECK-NEXT:    }{{.*}} {{{.*}}omp.combined{{.*}}}
 
 subroutine target_task()
   implicit none
diff --git a/flang/test/Lower/OpenMP/recipe-memory-effects.f90 b/flang/test/Lower/OpenMP/recipe-memory-effects.f90
index 631906ee7b45ba..1e4d748492e2ea 100644
--- a/flang/test/Lower/OpenMP/recipe-memory-effects.f90
+++ b/flang/test/Lower/OpenMP/recipe-memory-effects.f90
@@ -158,4 +158,203 @@ subroutine derived_common_private()
       z%value = x
     !$omp end sections
   end subroutine
+
+  ! Eager privatisation emits the privatisation recipe inside the single
+  ! region, preventing getEffects() from providing its memory effects.
+  ! Make sure these are emitted so recursive analyis records their memory
+  ! effects.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPsingle_eager_firstprivate(
+  ! CHECK: %[[ORIGINAL:.*]] = fir.alloca i32
+  ! CHECK: %[[ORIGINAL_DECL:.*]]:2 = hlfir.declare %[[ORIGINAL]]
+  ! CHECK: omp.parallel {
+  ! CHECK-NEXT: omp.single {
+  ! CHECK-NEXT: %[[PRIVATE:.*]] = fir.alloca i32
+  ! CHECK-NEXT: %[[PRIVATE_DECL:.*]]:2 = hlfir.declare %[[PRIVATE]]
+  ! CHECK-NEXT: %[[INITIAL:.*]] = fir.load %[[ORIGINAL_DECL]]#0 : !fir.ref<i32>
+  ! CHECK-NEXT: hlfir.assign %[[INITIAL]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref<i32>
+  ! CHECK-NEXT: %[[VALUE:.*]] = fir.load %[[PRIVATE_DECL]]#0 : !fir.ref<i32>
+  ! CHECK-NEXT: %[[ONE:.*]] = arith.constant 1 : i32
+  ! CHECK-NEXT: %[[UPDATED:.*]] = arith.addi %[[VALUE]], %[[ONE]] : i32
+  ! CHECK-NEXT: hlfir.assign %[[UPDATED]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref<i32>
+  ! CHECK-NEXT: omp.terminator
+  ! CHECK-NEXT: } <copyprivate_assume_bounded_recipe_effects, private_assume_bounded_recipe_effects>
+  ! CHECK-NEXT: omp.terminator
+  ! CHECK-NEXT: }
+  ! CHECK-NEXT: %[[AFTER:.*]] = fir.load %[[ORIGINAL_DECL]]#0 : !fir.ref<i32>
+  ! CHECK-NEXT: hlfir.assign %[[AFTER]] to %{{.*}} : i32, !fir.ref<i32>
+  ! CHECK-NEXT: return
+  subroutine single_eager_firstprivate(result)
+    integer :: result, x
+    x = 10
+    !$omp parallel shared(x)
+      !$omp single firstprivate(x)
+        x = x + 1
+      !$omp end single
+    !$omp end parallel
+    result = x
+  end subroutine
+
+  ! Eager single privatization maps COMMON members rather than the block.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPsingle_intrinsic_common_private(
+  ! CHECK: omp.single {
+  ! CHECK: } <copyprivate_assume_bounded_recipe_effects, private_assume_bounded_recipe_effects>
+  ! CHECK: return
+  subroutine single_intrinsic_common_private()
+    integer :: x
+    real :: y
+    common /single_private_block/ x, y
+    !$omp single private(/single_private_block/)
+      x = 1
+      y = 1.0
+    !$omp end single
+  end subroutine
+
+  ! Firstprivate COMMON blocks must also be checked member by member.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPsingle_intrinsic_common_firstprivate(
+  ! CHECK: omp.single {
+  ! CHECK: } <copyprivate_assume_bounded_recipe_effects, private_assume_bounded_recipe_effects>
+  ! CHECK: return
+  subroutine single_intrinsic_common_firstprivate()
+    integer :: x
+    real :: y
+    common /single_firstprivate_block/ x, y
+    !$omp single firstprivate(/single_firstprivate_block/)
+      x = x + 1
+      y = y + 1.0
+    !$omp end single
+  end subroutine
+
+  ! One derived member prevents the assumption for the entire COMMON block.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPsingle_derived_common_private(
+  ! CHECK: omp.single {
+  ! CHECK-NOT: private_assume_bounded_recipe_effects
+  ! CHECK: } <copyprivate_assume_bounded_recipe_effects>
+  ! CHECK: return
+  subroutine single_derived_common_private()
+    integer :: x
+    type(record) :: z
+    common /single_derived_block/ x, z
+    !$omp single private(/single_derived_block/)
+      x = 1
+      z%value = x
+    !$omp end single
+  end subroutine
+
+  ! Direct intrinsic scalars and fixed-size arrays have bounded copy functions.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPintrinsic_copyprivate(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine intrinsic_copyprivate()
+    integer :: i, a(4)
+    real :: r
+    complex :: c
+    logical :: l
+    character(8) :: s
+    !$omp parallel private(i, a, r, c, l, s)
+      !$omp single
+      !$omp end single copyprivate(i, a, r, c, l, s)
+    !$omp end parallel
+  end subroutine
+
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPno_copyprivate(
+  ! CHECK: omp.single {
+  ! CHECK: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine no_copyprivate()
+    !$omp single
+    !$omp end single
+  end subroutine
+
+  ! Copyprivate and private make independent assumptions.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPbounded_copyprivate_derived_private(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine bounded_copyprivate_derived_private()
+    type record
+      integer :: value
+    end type
+    type(record) :: z
+    integer :: i
+    !$omp parallel private(i)
+      !$omp single private(z)
+      !$omp end single copyprivate(i)
+    !$omp end parallel
+  end subroutine
+
+  ! One derived item prevents the assumption for the entire copyprivate clause.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPderived_copyprivate_bounded_private(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK-NOT: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: } <private_assume_bounded_recipe_effects>
+  ! CHECK: return
+  subroutine derived_copyprivate_bounded_private()
+    type record
+      integer :: value
+    end type
+    type(record) :: z
+    integer :: i, p
+    !$omp parallel private(i, z)
+      !$omp single private(p)
+      !$omp end single copyprivate(i, z)
+    !$omp end parallel
+  end subroutine
+
+  ! Allocatable copies may allocate, free, and access pointee storage.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPallocatable_scalar_copyprivate(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK-NOT: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine allocatable_scalar_copyprivate()
+    integer, allocatable :: a
+    !$omp parallel private(a)
+      !$omp single
+      !$omp end single copyprivate(a)
+    !$omp end parallel
+  end subroutine
+
+  ! Allocatables may access pointees of the copyprivate variable, violating the
+  ! copyprivate_assume_bounded_recipe_effects attribute contract.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPallocatable_array_copyprivate(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK-NOT: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine allocatable_array_copyprivate()
+    integer, allocatable :: a(:)
+    !$omp parallel private(a)
+      !$omp single
+      !$omp end single copyprivate(a)
+    !$omp end parallel
+  end subroutine
+
+  ! Pointer variables may access pointees of the copyprivate variable, violating
+  ! the copyprivate_assume_bounded_recipe_effects attribute contract.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPpointer_copyprivate(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK-NOT: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine pointer_copyprivate()
+    integer, pointer :: p, a(:)
+    !$omp parallel private(p, a)
+      !$omp single
+      !$omp end single copyprivate(p, a)
+    !$omp end parallel
+  end subroutine
+
+  ! Check the members of a threadprivate COMMON block.
+  ! CHECK-LABEL: func.func @_QMrecipe_memory_effectsPintrinsic_common_copyprivate(
+  ! CHECK: omp.single copyprivate(
+  ! CHECK: copyprivate_assume_bounded_recipe_effects
+  ! CHECK: return
+  subroutine intrinsic_common_copyprivate()
+    integer :: i
+    real :: r
+    common /intrinsic_copy_block/ i, r
+    !$omp threadprivate(/intrinsic_copy_block/)
+    !$omp parallel
+      !$omp single
+      !$omp end single copyprivate(/intrinsic_copy_block/)
+    !$omp end parallel
+  end subroutine
 end module
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index ab6e7178c9f2e9..eddd4fde2cd6bd 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -241,13 +241,16 @@ def OpenMP_CollapseClause : OpenMP_CollapseClauseSkip<>;
 
 class OpenMP_CopyprivateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
-    bit description = false, bit extraClassDeclaration = false
+    bit description = false, bit extraClassDeclaration = false,
+    bit boundedRecipeEffects = false
   > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
                     extraClassDeclaration> {
-  let arguments = (ins
+  let arguments = !con((ins
     Variadic<OpenMP_PointerLikeType>:$copyprivate_vars,
     OptionalAttr<SymbolRefArrayAttr>:$copyprivate_syms
-  );
+  ), !if(boundedRecipeEffects, (ins
+    UnitAttr:$copyprivate_assume_bounded_recipe_effects
+  ), (ins)));
 
   let optAssemblyFormat = [{
     `copyprivate` `(`
@@ -259,6 +262,15 @@ class OpenMP_CopyprivateClauseSkip<
     If `copyprivate` variables and functions are specified, then each thread
     variable is updated with the variable value of the thread that executed
     the single region, using the specified copy functions.
+
+    The optional `copyprivate_assume_bounded_recipe_effects` unit attribute
+    asserts that referenced copyprivatisation recipes may only read or write
+    `copyprivate` variables associated with the clause.
+    These effects apply only to storage directly designated by the `copyprivate`
+    variables. Recipes may not access other storage, including globals or
+    pointees reached by loading pointers from these variables. Without the
+    attribute, referenced copy functions are assumed to have arbitrary memory
+    effects.
   }];
 }
 
@@ -1515,7 +1527,6 @@ def OpenMP_PriorityClause : OpenMP_PriorityClauseSkip<>;
 class OpenMP_PrivateClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false,
-    // Only sections currently consumes the recipe-effect assumption.
     bit boundedRecipeEffects = false
   > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
                     extraClassDeclaration> {
@@ -1584,7 +1595,6 @@ def OpenMP_ProcBindClause : OpenMP_ProcBindClauseSkip<>;
 class OpenMP_ReductionClauseSkip<
     bit traits = false, bit arguments = false, bit assemblyFormat = false,
     bit description = false, bit extraClassDeclaration = false,
-    // Only sections currently consumes the recipe-effect assumption.
     bit boundedRecipeEffects = false
   > : OpenMP_Clause<traits, arguments, assemblyFormat, description,
                     extraClassDeclaration> {
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index d08b27b90ede5c..021ed0ce7d35e8 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -370,10 +370,12 @@ def SectionsOp : OpenMP_Op<"sections", traits = [
 //===----------------------------------------------------------------------===//
 
 def SingleOp : OpenMP_Op<"single", traits = [
-    AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>
+    AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>,
+    DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, RecursiveMemoryEffects
   ], clauses = [
-    OpenMP_AllocateClause, OpenMP_CopyprivateClause, OpenMP_NowaitClause,
-    OpenMP_PrivateClause
+    OpenMP_AllocateClause,
+    OpenMP_CopyprivateClauseSkip<boundedRecipeEffects = true>, OpenMP_NowaitClause,
+    OpenMP_PrivateClauseSkip<boundedRecipeEffects = true>
   ], singleRegion = true> {
   let summary = "single directive";
   let description = [{
@@ -390,7 +392,7 @@ def SingleOp : OpenMP_Op<"single", traits = [
 
   let assemblyFormat = clausesAssemblyFormat # [{
     custom<PrivateRegion>($region, $private_vars, type($private_vars),
-        $private_syms, $private_needs_barrier) attr-dict
+        $private_syms, $private_needs_barrier) prop-dict attr-dict
   }];
 
   let hasVerifier = 1;
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 1c869ad04bbcf6..7e2d94e8f74c0b 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -3594,13 +3594,15 @@ void SingleOp::build(OpBuilder &builder, OperationState &state,
                      const SingleOperands &clauses) {
   MLIRContext *ctx = builder.getContext();
   // TODO Store clauses in op: privateVars, privateSyms, privateNeedsBarrier
-  SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
-                  makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
-                  makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
-                  clauses.copyprivateVars,
-                  makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait,
-                  /*private_vars=*/{}, /*private_syms=*/nullptr,
-                  /*private_needs_barrier=*/nullptr);
+  SingleOp::build(
+      builder, state, clauses.allocateVars, clauses.allocatorVars,
+      makeDenseI64ArrayAttr(ctx, clauses.allocateAlignments),
+      makeDenseI64ArrayAttr(ctx, clauses.allocatePrivateIndices),
+      clauses.copyprivateVars, makeArrayAttr(ctx, clauses.copyprivateSyms),
+      /*copyprivate_assume_bounded_recipe_effects=*/nullptr, clauses.nowait,
+      /*private_vars=*/{}, /*private_syms=*/nullptr,
+      /*private_needs_barrier=*/nullptr,
+      /*private_assume_bounded_recipe_effects=*/nullptr);
 }
 
 LogicalResult SingleOp::verify() {
@@ -3614,6 +3616,39 @@ LogicalResult SingleOp::verify() {
                                   getCopyprivateSyms());
 }
 
+void SingleOp::getEffects(
+    llvm::SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+        &effects) {
+  // The presence of the nowait cl...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/237929


More information about the Mlir-commits mailing list