https://github.com/anchuraj updated 
https://github.com/llvm/llvm-project/pull/143769

>From c9b65080c1301c46b05fddc1278eaf2817963cb9 Mon Sep 17 00:00:00 2001
From: Anchu Rajendran <asudh...@amd.com>
Date: Wed, 4 Jun 2025 15:12:49 -0500
Subject: [PATCH 1/4] [flang][flang-driver] atomic control support

---
 clang/include/clang/Driver/Options.td         | 22 +++++-----
 flang/include/flang/Frontend/TargetOptions.h  |  5 +++
 .../Optimizer/Dialect/Support/FIRContext.h    | 14 +++++++
 flang/lib/Frontend/CompilerInvocation.cpp     | 12 ++++++
 flang/lib/Lower/Bridge.cpp                    |  6 +++
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  7 +++-
 .../Optimizer/Dialect/Support/FIRContext.cpp  | 40 +++++++++++++++++++
 .../Lower/OpenMP/atomic-control-options.f90   | 37 +++++++++++++++++
 .../mlir/Dialect/OpenMP/OpenMPAttrDefs.td     | 14 +++++++
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |  8 ++--
 mlir/test/Dialect/OpenMP/ops.mlir             |  9 +++++
 11 files changed, 159 insertions(+), 15 deletions(-)
 create mode 100644 flang/test/Lower/OpenMP/atomic-control-options.f90

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 152df89118a6a..7a21b4c158082 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2299,21 +2299,21 @@ def fsymbol_partition_EQ : Joined<["-"], 
"fsymbol-partition=">, Group<f_Group>,
 
 defm atomic_remote_memory : BoolFOption<"atomic-remote-memory",
   LangOpts<"AtomicRemoteMemory">, DefaultFalse,
-  PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
-  NegFlag<SetFalse, [], [ClangOption], "Assume no">,
-  BothFlags<[], [ClangOption], " atomic operations on remote memory">>;
+  PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May 
have">,
+  NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
+  BothFlags<[], [ClangOption, FlangOption], " atomic operations on remote 
memory">>;
 
 defm atomic_fine_grained_memory : BoolFOption<"atomic-fine-grained-memory",
   LangOpts<"AtomicFineGrainedMemory">, DefaultFalse,
-  PosFlag<SetTrue, [], [ClangOption, CC1Option], "May have">,
-  NegFlag<SetFalse, [], [ClangOption], "Assume no">,
-  BothFlags<[], [ClangOption], " atomic operations on fine-grained memory">>;
+  PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], "May 
have">,
+  NegFlag<SetFalse, [], [ClangOption, FlangOption], "Assume no">,
+  BothFlags<[], [ClangOption, FlangOption], " atomic operations on 
fine-grained memory">>;
 
 defm atomic_ignore_denormal_mode : BoolFOption<"atomic-ignore-denormal-mode",
   LangOpts<"AtomicIgnoreDenormalMode">, DefaultFalse,
-  PosFlag<SetTrue, [], [ClangOption, CC1Option], "Allow">,
-  NegFlag<SetFalse, [], [ClangOption], "Disallow">,
-  BothFlags<[], [ClangOption], " atomic operations to ignore denormal mode">>;
+  PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], 
"Allow">,
+  NegFlag<SetFalse, [], [ClangOption, FlangOption], "Disallow">,
+  BothFlags<[], [ClangOption, FlangOption], " atomic operations to ignore 
denormal mode">>;
 
 defm memory_profile : OptInCC1FFlag<"memory-profile", "Enable", "Disable", " 
heap memory profiling">;
 def fmemory_profile_EQ : Joined<["-"], "fmemory-profile=">,
@@ -5272,9 +5272,9 @@ defm amdgpu_precise_memory_op
                   " precise memory mode (AMDGPU only)">;
 
 def munsafe_fp_atomics : Flag<["-"], "munsafe-fp-atomics">,
-  Visibility<[ClangOption, CC1Option]>, Alias<fatomic_ignore_denormal_mode>;
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, 
Alias<fatomic_ignore_denormal_mode>;
 def mno_unsafe_fp_atomics : Flag<["-"], "mno-unsafe-fp-atomics">,
-  Visibility<[ClangOption]>, Alias<fno_atomic_ignore_denormal_mode>;
+  Visibility<[ClangOption, FlangOption]>, 
Alias<fno_atomic_ignore_denormal_mode>;
 
 def faltivec : Flag<["-"], "faltivec">, Group<f_Group>;
 def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>;
diff --git a/flang/include/flang/Frontend/TargetOptions.h 
b/flang/include/flang/Frontend/TargetOptions.h
index 002d8d158abd4..26256fd775f11 100644
--- a/flang/include/flang/Frontend/TargetOptions.h
+++ b/flang/include/flang/Frontend/TargetOptions.h
@@ -53,6 +53,11 @@ class TargetOptions {
 
   /// Print verbose assembly
   bool asmVerbose = false;
+
+  /// Atomic Control Options for AMD GPU
+  bool amdgpuIgnoreDenormalMode = false;
+  bool amdgpuRemoteMemory = false;
+  bool amdgpuFineGrainedMemory = false;
 };
 
 } // end namespace Fortran::frontend
diff --git a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h 
b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
index 2df14f83c11e1..ac563bcc402c7 100644
--- a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
+++ b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
@@ -58,10 +58,24 @@ void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
 /// Get the target CPU string from the Module or return a null reference.
 llvm::StringRef getTargetCPU(mlir::ModuleOp mod);
 
+// Setters and Getters for atomic control options
+void setAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod);
+bool getAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod);
+void setAmdgpuFineGrainedMemory(mlir::ModuleOp mod);
+bool getAmdgpuFineGrainedMemory(mlir::ModuleOp mod);
+void setAmdgpuRemoteMemory(mlir::ModuleOp mod);
+bool getAmdgpuRemoteMemory(mlir::ModuleOp mod);
+
 /// Set the tune CPU for the module. `cpu` must not be deallocated while
 /// module `mod` is still live.
 void setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
 
+// set Atomic control options for amd gpu.
+void setAmdgpuAtomicControlOptions(mlir::ModuleOp mod,
+                                   bool amdgpuIgnoreDenormalMode,
+                                   bool amdgpuNoFineGrainedMemory,
+                                   bool amdgpuNoRemoteMemory);
+
 /// Get the tune CPU string from the Module or return a null reference.
 llvm::StringRef getTuneCPU(mlir::ModuleOp mod);
 
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 15bcff254756e..044eb53e500dd 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -483,6 +483,18 @@ static void parseTargetArgs(TargetOptions &opts, 
llvm::opt::ArgList &args) {
           args.getLastArg(clang::driver::options::OPT_triple))
     opts.triple = a->getValue();
 
+  if (llvm::Triple(opts.triple).isAMDGPU()) {
+    opts.amdgpuIgnoreDenormalMode = args.hasFlag(
+        clang::driver::options::OPT_fatomic_ignore_denormal_mode,
+        clang::driver::options::OPT_fno_atomic_ignore_denormal_mode, false);
+    opts.amdgpuFineGrainedMemory = args.hasFlag(
+        clang::driver::options::OPT_fatomic_fine_grained_memory,
+        clang::driver::options::OPT_fno_atomic_fine_grained_memory, false);
+    opts.amdgpuRemoteMemory = args.hasFlag(
+        clang::driver::options::OPT_fatomic_remote_memory,
+        clang::driver::options::OPT_fno_atomic_remote_memory, false);
+  }
+
   if (const llvm::opt::Arg *a =
           args.getLastArg(clang::driver::options::OPT_target_cpu))
     opts.cpu = a->getValue();
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 5ff8101dba097..dd8aa96b34057 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -6644,6 +6644,12 @@ Fortran::lower::LoweringBridge::LoweringBridge(
   fir::setKindMapping(*module, kindMap);
   fir::setTargetCPU(*module, targetMachine.getTargetCPU());
   fir::setTuneCPU(*module, targetOpts.cpuToTuneFor);
+  if (targetOpts.amdgpuIgnoreDenormalMode)
+    fir::setAmdgpuIgnoreDenormalMode(*module);
+  if (targetOpts.amdgpuFineGrainedMemory)
+    fir::setAmdgpuFineGrainedMemory(*module);
+  if (targetOpts.amdgpuRemoteMemory)
+    fir::setAmdgpuRemoteMemory(*module);
   fir::setTargetFeatures(*module, targetMachine.getTargetFeatureString());
   fir::support::setMLIRDataLayout(*module, targetMachine.createDataLayout());
   fir::setIdent(*module, Fortran::common::getFlangFullVersion());
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp 
b/flang/lib/Lower/OpenMP/OpenMP.cpp
index c13fa471978db..de9d81e6d9a6d 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2850,9 +2850,14 @@ genAtomicUpdate(lower::AbstractConverter &converter, 
mlir::Location loc,
     }
   }
 
+  mlir::ModuleOp module = builder.getModule();
+  mlir::omp::AtomicControlAttr atomicControlAttr = 
mlir::omp::AtomicControlAttr::get(
+      builder.getContext(), fir::getAmdgpuIgnoreDenormalMode(module),
+      fir::getAmdgpuFineGrainedMemory(module),
+      fir::getAmdgpuRemoteMemory(module));
   builder.restoreInsertionPoint(atomicAt);
   auto updateOp =
-      builder.create<mlir::omp::AtomicUpdateOp>(loc, atomAddr, hint, memOrder);
+      builder.create<mlir::omp::AtomicUpdateOp>(loc, atomAddr, 
atomicControlAttr, hint, memOrder);
 
   mlir::Region &region = updateOp->getRegion(0);
   mlir::Block *block = builder.createBlock(&region, {}, {atomType}, {loc});
diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp 
b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
index 01c0be66d1ecc..b961793dbdfd5 100644
--- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
@@ -88,6 +88,46 @@ void fir::setTuneCPU(mlir::ModuleOp mod, llvm::StringRef 
cpu) {
   mod->setAttr(tuneCpuName, mlir::StringAttr::get(ctx, cpu));
 }
 
+static constexpr const char *amdgpuIgnoreDenormalModeName =
+    "fir.amdgpu.ignore.denormal.mode";
+void fir::setAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod) {
+  auto *ctx = mod.getContext();
+  mod->setAttr(amdgpuIgnoreDenormalModeName, mlir::UnitAttr::get(ctx));
+}
+
+bool fir::getAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod) {
+  if (auto attr =
+          mod->getAttrOfType<mlir::UnitAttr>(amdgpuIgnoreDenormalModeName))
+    return true;
+  return false;
+}
+
+static constexpr const char *amdgpuFineGrainedMemoryName =
+    "fir.amdgpu.fine.grained.memory";
+void fir::setAmdgpuFineGrainedMemory(mlir::ModuleOp mod) {
+  auto *ctx = mod.getContext();
+  mod->setAttr(amdgpuFineGrainedMemoryName, mlir::UnitAttr::get(ctx));
+}
+
+bool fir::getAmdgpuFineGrainedMemory(mlir::ModuleOp mod) {
+  if (auto attr =
+          mod->getAttrOfType<mlir::UnitAttr>(amdgpuFineGrainedMemoryName))
+    return true;
+  return false;
+}
+static constexpr const char *amdgpuRemoteMemoryName =
+    "fir.amdgpu.remote.memory";
+void fir::setAmdgpuRemoteMemory(mlir::ModuleOp mod) {
+  auto *ctx = mod.getContext();
+  mod->setAttr(amdgpuRemoteMemoryName, mlir::UnitAttr::get(ctx));
+}
+
+bool fir::getAmdgpuRemoteMemory(mlir::ModuleOp mod) {
+  if (auto attr = mod->getAttrOfType<mlir::UnitAttr>(amdgpuRemoteMemoryName))
+    return true;
+  return false;
+}
+
 llvm::StringRef fir::getTuneCPU(mlir::ModuleOp mod) {
   if (auto attr = mod->getAttrOfType<mlir::StringAttr>(tuneCpuName))
     return attr.getValue();
diff --git a/flang/test/Lower/OpenMP/atomic-control-options.f90 
b/flang/test/Lower/OpenMP/atomic-control-options.f90
new file mode 100644
index 0000000000000..1eb0f617f365e
--- /dev/null
+++ b/flang/test/Lower/OpenMP/atomic-control-options.f90
@@ -0,0 +1,37 @@
+! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -munsafe-fp-atomics %s -o - | FileCheck 
-check-prefix=UNSAFE-FP-ATOMICS %s
+! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-ignore-denormal-mode %s -o - | FileCheck 
-check-prefix=IGNORE-DENORMAL %s
+! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-fine-grained-memory %s -o - | FileCheck 
-check-prefix=FINE-GRAINED-MEMORY %s
+! RUN: %flang_fc1 -emit-hlfir -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-remote-memory %s -o - | FileCheck 
-check-prefix=REMOTE-MEMORY %s
+program test
+    implicit none
+    integer :: A, B, threads
+    threads = 128
+    A = 0
+    B = 0
+    !UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !UNSAFE-FP-ATOMICS: } {atomic_control = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true>}
+    !IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !IGNORE-DENORMAL: } {atomic_control = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true>}
+    !FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !FINE-GRAINED-MEMORY: } {atomic_control = 
#omp.atomic_control<amdgpu_fine_grained_memory = true>}
+    !REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !REMOTE-MEMORY: } {atomic_control = 
#omp.atomic_control<amdgpu_remote_memory = true>}
+    !$omp target parallel num_threads(threads)
+    !$omp atomic
+    A =  A + 1
+    !$omp end target parallel
+    !UNSAFE-FP-ATOMICS: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !UNSAFE-FP-ATOMICS: } {atomic_control = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true>}
+    !IGNORE-DENORMAL: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !IGNORE-DENORMAL: } {atomic_control = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true>}
+    !FINE-GRAINED-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !FINE-GRAINED-MEMORY: } {atomic_control = 
#omp.atomic_control<amdgpu_fine_grained_memory = true>}
+    !REMOTE-MEMORY: omp.atomic.update %{{.*}} : !fir.ref<i32> {
+    !REMOTE-MEMORY: } {atomic_control = 
#omp.atomic_control<amdgpu_remote_memory = true>}
+    !$omp target parallel num_threads(threads)
+    !$omp atomic capture
+        A = A + B
+        B = A
+    !$omp end atomic
+    !$omp end target parallel
+end program test
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
index 704d0b2220e8a..84887dfd2c6f9 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
@@ -54,6 +54,20 @@ def FlagsAttr : OpenMP_Attr<"Flags", "flags"> {
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
+//===----------------------------------------------------------------------===//
+// AtomicControlAttr
+//===----------------------------------------------------------------------===//
+
+// Runtime library flags attribute that holds information for lowering to LLVM.
+def AtomicControlAttr : OpenMP_Attr<"AtomicControl", "atomic_control"> {
+  let parameters =
+      (ins DefaultValuedParameter<"bool", 
"false">:$amdgpu_ignore_denormal_mode,
+          DefaultValuedParameter<"bool", "false">:$amdgpu_fine_grained_memory,
+          DefaultValuedParameter<"bool", "false">:$amdgpu_remote_memory);
+
+  let assemblyFormat = "`<` struct(params) `>`";
+}
+
 
//===----------------------------------------------------------------------===//
 // TaskDependArrayAttr
 
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 036c6a6e350a8..d7d14e96233ae 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1543,9 +1543,11 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = 
[
     operations.
   }] # clausesDescription;
 
-  let arguments = !con((ins Arg<OpenMP_PointerLikeType,
-                                "Address of variable to be updated",
-                                [MemRead, MemWrite]>:$x), clausesArgs);
+  let arguments = !con(
+      (ins Arg<OpenMP_PointerLikeType,
+               "Address of variable to be updated", [MemRead, MemWrite]>:$x,
+          OptionalAttr<AtomicControlAttr>:$atomic_control),
+      clausesArgs);
 
   // Override region definition.
   let regions = (region SizedRegion<1>:$region);
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir 
b/mlir/test/Dialect/OpenMP/ops.mlir
index 47cfc5278a5d0..e377b7aab3e43 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1562,6 +1562,15 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
     omp.yield(%newval : i32)
   }
 
+  // CHECK: omp.atomic.update %[[X]] : memref<i32> {
+  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
+  // CHECK-NEXT:   omp.yield(%{{.+}} : i32)
+  // CHECK-NEXT: } {atomic_control_attr = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true, 
amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
+  omp.atomic.update %x : memref<i32> {
+  ^bb0(%xval:i32):
+    omp.yield(%const:i32)
+  } {atomic_control_attr = #omp.atomic_control<amdgpu_ignore_denormal_mode = 
true, amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
+
   return
 }
 

>From 52c04c75cbb4a2e5ce31665740d0ff98b7aa715e Mon Sep 17 00:00:00 2001
From: Anchu Rajendran <asudh...@amd.com>
Date: Wed, 11 Jun 2025 13:58:07 -0500
Subject: [PATCH 2/4] R2: Making Atomic control non-optional

---
 mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td |   2 +-
 .../OpenMPToLLVM/convert-to-llvmir.mlir       |   2 +-
 mlir/test/Dialect/OpenMP/canonicalize.mlir    |  10 +-
 mlir/test/Dialect/OpenMP/invalid.mlir         |  46 +++----
 mlir/test/Dialect/OpenMP/ops.mlir             | 127 +++++++++---------
 .../Target/LLVMIR/openmp-llvm-invalid.mlir    |   8 +-
 mlir/test/Target/LLVMIR/openmp-llvm.mlir      |  98 +++++++-------
 .../openmp-target-nesting-in-host-ops.mlir    |   2 +-
 mlir/test/Target/LLVMIR/openmp-todo.mlir      |   2 +-
 9 files changed, 148 insertions(+), 149 deletions(-)

diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index d7d14e96233ae..d821f7f943218 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1546,7 +1546,7 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update", traits = [
   let arguments = !con(
       (ins Arg<OpenMP_PointerLikeType,
                "Address of variable to be updated", [MemRead, MemWrite]>:$x,
-          OptionalAttr<AtomicControlAttr>:$atomic_control),
+          AtomicControlAttr:$atomic_control),
       clausesArgs);
 
   // Override region definition.
diff --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir 
b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
index d69de998346b5..0b2445d0a0d18 100644
--- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
+++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
@@ -133,7 +133,7 @@ func.func @atomic_update() {
     %1 = arith.constant 1 : i32
     %2 = arith.addi %arg0, %1  : i32
     omp.yield(%2 : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 llvm.mlir.global internal @_QFsEc() : i32 {
diff --git a/mlir/test/Dialect/OpenMP/canonicalize.mlir 
b/mlir/test/Dialect/OpenMP/canonicalize.mlir
index de6c931ecc5fd..2492010c4d3c7 100644
--- a/mlir/test/Dialect/OpenMP/canonicalize.mlir
+++ b/mlir/test/Dialect/OpenMP/canonicalize.mlir
@@ -4,7 +4,7 @@ func.func @update_no_op(%x : memref<i32>) {
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval : i32):
     omp.yield(%xval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -17,7 +17,7 @@ func.func @update_write_op(%x : memref<i32>, %value: i32) {
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval : i32):
     omp.yield(%value : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -33,7 +33,7 @@ func.func @update_normal(%x : memref<i32>, %value: i32) {
   ^bb0(%xval : i32):
     %newval = arith.addi %xval, %value : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -50,7 +50,7 @@ func.func @update_unnecessary_computations(%x: memref<i32>) {
   ^bb0(%xval: i32):
     %newval = arith.addi %xval, %c0 : i32
     omp.yield(%newval: i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -65,7 +65,7 @@ func.func @update_unnecessary_computations(%x: memref<i32>) {
   ^bb0(%xval: i32):
     %newval = arith.muli %xval, %c0 : i32
     omp.yield(%newval: i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir 
b/mlir/test/Dialect/OpenMP/invalid.mlir
index 060b3cd2455a0..afc3830286f30 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -1007,7 +1007,7 @@ func.func @omp_atomic_update1(%x: memref<i32>, %expr: 
f32) {
   ^bb0(%xval: f32):
     %newval = llvm.fadd %xval, %expr : f32
     omp.yield (%newval : f32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1020,7 +1020,7 @@ func.func @omp_atomic_update2(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.terminator
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1032,7 +1032,7 @@ func.func @omp_atomic_update3(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1044,7 +1044,7 @@ func.func @omp_atomic_update4(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1056,7 +1056,7 @@ func.func @omp_atomic_update5(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1068,7 +1068,7 @@ func.func @omp_atomic_update6(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval, %expr : i32, i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1080,7 +1080,7 @@ func.func @omp_atomic_update7(%x: memref<i32>, %expr: 
i32, %y: f32) {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%y: f32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1092,7 +1092,7 @@ func.func @omp_atomic_update8(%x: memref<i32>, %expr: 
i32) {
   ^bb0(%xval: i32, %tmp: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1104,7 +1104,7 @@ func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) 
{
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1116,7 +1116,7 @@ func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) 
{
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1128,7 +1128,7 @@ func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) 
{
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield (%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
@@ -1164,12 +1164,12 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.update %x : memref<i32> {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.terminator
   }
   return
@@ -1197,7 +1197,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.terminator
   }
   return
@@ -1212,7 +1212,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.write %x = %expr : memref<i32>, i32
     omp.terminator
   }
@@ -1240,7 +1240,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %y: 
memref<i32>, %v: memref<i32>,
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %y : memref<i32>, memref<i32>, i32
     omp.terminator
   }
@@ -1256,7 +1256,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %y: 
memref<i32>, %v: memref<i32>,
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield (%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.terminator
   }
 }
@@ -1281,7 +1281,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   return
@@ -1296,7 +1296,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   return
@@ -1311,7 +1311,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   return
@@ -1326,7 +1326,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   return
@@ -1341,7 +1341,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   return
@@ -1356,7 +1356,7 @@ func.func @omp_atomic_capture(%x: memref<i32>, %v: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32>, memref<i32>, 
i32
   }
   return
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir 
b/mlir/test/Dialect/OpenMP/ops.mlir
index e377b7aab3e43..5aa7befb2dc26 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1371,7 +1371,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
   // CHECK-NEXT: (%[[XVAL:.*]]: i1):
   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1
@@ -1380,57 +1380,57 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i1):
     %newval = llvm.and %xval, %exprBool : i1
     omp.yield(%newval : i1)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   // CHECK: omp.atomic.update %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32
   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval: i32):
     %newval = llvm.shl %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   // CHECK: omp.atomic.update %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.intr.smax(%[[XVAL]], %[[EXPR]]) : 
(i32, i32) -> i32
   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval: i32):
     %newval = llvm.intr.smax(%xval, %expr) : (i32, i32) -> i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
   // CHECK-NEXT: (%[[XVAL:.*]]: i1):
   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : 
i1
   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i1)
-  // }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   omp.atomic.update %xBool : memref<i1> {
   ^bb0(%xval: i1):
     %newval = llvm.icmp "eq" %xval, %exprBool : i1
     omp.yield(%newval : i1)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update %[[X]] : memref<i32> {
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   omp.yield(%[[XVAL]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval:i32):
     omp.yield(%xval:i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update %[[X]] : memref<i32> {
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   omp.yield(%{{.+}} : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   %const = arith.constant 42 : i32
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval:i32):
     omp.yield(%const:i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1440,7 +1440,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1450,7 +1450,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1460,7 +1460,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1470,7 +1470,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1480,7 +1480,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : 
memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1490,7 +1490,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : 
memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1500,7 +1500,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : 
memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1510,7 +1510,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1520,7 +1520,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update memory_order(seq_cst) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1530,7 +1530,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update memory_order(release) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1540,7 +1540,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update memory_order(relaxed) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1550,7 +1550,7 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update hint(uncontended, speculative) 
memory_order(seq_cst) %[[X]] : memref<i32>
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
@@ -1560,17 +1560,16 @@ func.func @omp_atomic_update(%x : memref<i32>, %expr : 
i32, %xBool : memref<i1>,
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   // CHECK: omp.atomic.update %[[X]] : memref<i32> {
   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   omp.yield(%{{.+}} : i32)
-  // CHECK-NEXT: } {atomic_control_attr = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true, 
amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
+  // CHECK-NEXT: } {atomic_control = 
#omp.atomic_control<amdgpu_ignore_denormal_mode = true, 
amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
   omp.atomic.update %x : memref<i32> {
   ^bb0(%xval:i32):
     omp.yield(%const:i32)
-  } {atomic_control_attr = #omp.atomic_control<amdgpu_ignore_denormal_mode = 
true, amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
-
+  } {atomic_control = #omp.atomic_control<amdgpu_ignore_denormal_mode = true, 
amdgpu_fine_grained_memory = true, amdgpu_remote_memory = true>}
   return
 }
 
@@ -1582,7 +1581,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture{
@@ -1590,7 +1589,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
   // CHECK: omp.atomic.capture {
@@ -1599,7 +1598,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: }
   omp.atomic.capture{
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
@@ -1607,7 +1606,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
   // CHECK: omp.atomic.capture {
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
@@ -1623,7 +1622,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(none) {
@@ -1631,7 +1630,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1640,7 +1639,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(uncontended) {
@@ -1648,7 +1647,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1657,7 +1656,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(contended) {
@@ -1665,7 +1664,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1674,7 +1673,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(nonspeculative) {
@@ -1682,7 +1681,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1691,7 +1690,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(speculative) {
@@ -1699,7 +1698,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1708,7 +1707,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(uncontended, nonspeculative) {
@@ -1716,7 +1715,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1725,7 +1724,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(contended, nonspeculative) {
@@ -1733,7 +1732,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1742,7 +1741,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(uncontended, speculative) {
@@ -1750,7 +1749,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1759,7 +1758,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(contended, speculative) {
@@ -1767,7 +1766,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1776,7 +1775,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture memory_order(seq_cst) {
@@ -1784,7 +1783,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1793,7 +1792,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture memory_order(acq_rel) {
@@ -1801,7 +1800,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1810,7 +1809,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture memory_order(acquire) {
@@ -1818,7 +1817,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1827,7 +1826,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture memory_order(release) {
@@ -1835,7 +1834,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1844,7 +1843,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture memory_order(relaxed) {
@@ -1852,7 +1851,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -1861,7 +1860,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
   // CHECK-NEXT: (%[[xval:.*]]: i32):
   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, 
i32
   // CHECK-NEXT: }
   omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) {
@@ -1869,7 +1868,7 @@ func.func @omp_atomic_capture(%v: memref<i32>, %x: 
memref<i32>, %expr: i32) {
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
   }
 
@@ -2653,14 +2652,14 @@ func.func @opaque_pointers_atomic_rwu(%v: !llvm.ptr, 
%x: !llvm.ptr) {
   // CHECK: omp.atomic.update %[[x]] : !llvm.ptr {
   // CHECK-NEXT: ^{{[[:alnum:]]+}}(%[[XVAL:.*]]: i32):
   // CHECK-NEXT:   omp.yield(%[[XVAL]] : i32)
-  // CHECK-NEXT: }
+  // CHECK-NEXT: } {atomic_control = #omp.atomic_control<>}
   omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   %val = llvm.load %x : !llvm.ptr -> i32
   omp.atomic.write %v = %val : !llvm.ptr, i32
   omp.atomic.update %x : !llvm.ptr {
     ^bb0(%xval: i32):
       omp.yield(%xval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   return
 }
 
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm-invalid.mlir 
b/mlir/test/Target/LLVMIR/openmp-llvm-invalid.mlir
index 41bc5c4ba525f..00f53864b5fa7 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm-invalid.mlir
@@ -9,7 +9,7 @@ llvm.func @omp_atomic_update_multiple_step_update(%x: 
!llvm.ptr, %expr: i32) {
     %t2 = llvm.sdiv %t1, %expr : i32
     %newval = llvm.add %xval, %t2 : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -24,7 +24,7 @@ llvm.func @omp_atomic_update_multiple_step_update(%x: 
!llvm.ptr, %expr: i32) {
   ^bb0(%xval: i32):
     %newval = llvm.mul %expr, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -41,7 +41,7 @@ llvm.func @omp_atomic_update_multiple_step_update(%x: 
!llvm.ptr, %v: !llvm.ptr,
     ^bb0(%xval: i32):
       %newval = llvm.mul %expr, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
   llvm.return
 }
@@ -59,7 +59,7 @@ llvm.func @omp_atomic_update_multiple_step_update(%x: 
!llvm.ptr, %v: !llvm.ptr,
       %t2 = llvm.sdiv %t1, %expr : i32
       %newval = llvm.add %xval, %t2 : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
   llvm.return
 }
diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir 
b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
index 32f0ba5b105ff..ab7f756bf95f9 100644
--- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir
@@ -1462,13 +1462,13 @@ llvm.func @omp_atomic_update(%x:!llvm.ptr, %expr: i32, 
%xbool: !llvm.ptr, %exprb
   ^bb0(%xval: i32):
     %newval = llvm.mul %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   // CHECK: atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
   omp.atomic.update %x : !llvm.ptr {
   ^bb0(%xval: i32):
     %newval = llvm.add %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -1563,7 +1563,7 @@ llvm.func @_QPomp_atomic_update_complex() {
       %15 = llvm.insertvalue %12, %14[0] : !llvm.struct<(f32, f32)>
       %16 = llvm.insertvalue %13, %15[1] : !llvm.struct<(f32, f32)>
       omp.yield(%16 : !llvm.struct<(f32, f32)>)
-    }
+    } {atomic_control = #omp.atomic_control<>}
    llvm.return
 }
 
@@ -1623,7 +1623,7 @@ llvm.func @_QPomp_atomic_capture_complex() {
         %19 = llvm.insertvalue %16, %18[0] : !llvm.struct<(f32, f32)>
         %20 = llvm.insertvalue %17, %19[1] : !llvm.struct<(f32, f32)>
         omp.yield(%20 : !llvm.struct<(f32, f32)>)
-      }
+      } {atomic_control = #omp.atomic_control<>}
       omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>
     }
     llvm.return
@@ -1665,7 +1665,7 @@ llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, 
%expr: i32) {
   ^bb0(%xval: i32):
     %newval = llvm.shl %expr, %xval : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -1683,7 +1683,7 @@ llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, 
%expr: i32) {
   ^bb0(%xval: i32):
     %newval = llvm.shl %xval, %expr : i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -1701,7 +1701,7 @@ llvm.func @omp_atomic_update_intrinsic(%x:!llvm.ptr, 
%expr: i32) {
   ^bb0(%xval: i32):
     %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   // CHECK: %[[t1:.*]] = call i32 @llvm.umax.i32(i32 %[[x_old:.*]], i32 
%[[expr]])
   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
@@ -1710,7 +1710,7 @@ llvm.func @omp_atomic_update_intrinsic(%x:!llvm.ptr, 
%expr: i32) {
   ^bb0(%xval: i32):
     %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
     omp.yield(%newval : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -1732,7 +1732,7 @@ llvm.func @atomic_update_cmpxchg(%arg0: !llvm.ptr, %arg1: 
!llvm.ptr) {
     %2 = llvm.fadd %1, %0 : f32
     %3 = llvm.fptosi %2 : f32 to i32
     omp.yield(%3 : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
   llvm.return
 }
 
@@ -1751,7 +1751,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1763,7 +1763,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.sub %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1775,7 +1775,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.and %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1787,7 +1787,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.or %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1799,7 +1799,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.xor %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1814,7 +1814,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.mul %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1829,7 +1829,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.sdiv %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1844,7 +1844,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.udiv %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1859,7 +1859,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.shl %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1874,7 +1874,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.lshr %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1889,7 +1889,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = llvm.ashr %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1904,7 +1904,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1919,7 +1919,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1934,7 +1934,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1949,7 +1949,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
   }
 
@@ -1964,7 +1964,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: f32):
       %newval = llvm.fadd %xval, %exprf : f32
       omp.yield(%newval : f32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
   }
 
@@ -1979,7 +1979,7 @@ llvm.func @omp_atomic_capture_prefix_update(
     ^bb0(%xval: f32):
       %newval = llvm.fsub %xval, %exprf : f32
       omp.yield(%newval : f32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
   }
 
@@ -2001,7 +2001,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw sub ptr %[[x]], i32 %[[expr]] monotonic
@@ -2012,7 +2012,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.sub %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw and ptr %[[x]], i32 %[[expr]] monotonic
@@ -2023,7 +2023,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.and %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw or ptr %[[x]], i32 %[[expr]] monotonic
@@ -2034,7 +2034,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.or %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw xor ptr %[[x]], i32 %[[expr]] monotonic
@@ -2045,7 +2045,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.xor %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2060,7 +2060,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.mul %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2075,7 +2075,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.sdiv %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2090,7 +2090,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.udiv %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2105,7 +2105,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.shl %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2120,7 +2120,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.lshr %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2135,7 +2135,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = llvm.ashr %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2150,7 +2150,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2165,7 +2165,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2180,7 +2180,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2195,7 +2195,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: i32):
       %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2211,7 +2211,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: f32):
       %newval = llvm.fadd %xval, %exprf : f32
       omp.yield(%newval : f32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[xval:.*]] = phi i32
@@ -2227,7 +2227,7 @@ llvm.func @omp_atomic_capture_postfix_update(
     ^bb0(%xval: f32):
       %newval = llvm.fsub %xval, %exprf : f32
       omp.yield(%newval : f32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   llvm.return
@@ -2265,7 +2265,7 @@ llvm.func @omp_atomic_capture_misc(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acquire
@@ -2276,7 +2276,7 @@ llvm.func @omp_atomic_capture_misc(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] release
@@ -2287,7 +2287,7 @@ llvm.func @omp_atomic_capture_misc(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
@@ -2298,7 +2298,7 @@ llvm.func @omp_atomic_capture_misc(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acq_rel
@@ -2309,7 +2309,7 @@ llvm.func @omp_atomic_capture_misc(
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
 
   llvm.return
@@ -3055,7 +3055,7 @@ llvm.func @omp_opaque_pointers(%arg0 : !llvm.ptr, %arg1: 
!llvm.ptr, %expr: i32)
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
   }
   llvm.return
 }
diff --git a/mlir/test/Target/LLVMIR/openmp-target-nesting-in-host-ops.mlir 
b/mlir/test/Target/LLVMIR/openmp-target-nesting-in-host-ops.mlir
index cbf273b887bc7..a9a4ffd533136 100644
--- a/mlir/test/Target/LLVMIR/openmp-target-nesting-in-host-ops.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-target-nesting-in-host-ops.mlir
@@ -110,7 +110,7 @@ module attributes {dlti.dl_spec = 
#dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
     ^bb0(%xval: i32):
       %newval = llvm.add %xval, %expr : i32
       omp.yield(%newval : i32)
-    }
+    } {atomic_control = #omp.atomic_control<>}
 
     llvm.return
   }
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir 
b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 97608ca3b4df1..2f294658edb3d 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -19,7 +19,7 @@ llvm.func @atomic_hint(%v : !llvm.ptr, %x : !llvm.ptr, %expr 
: i32) {
   ^bb0(%arg0: i32):
     %result = llvm.add %arg0, %expr : i32
     omp.yield(%result : i32)
-  }
+  } {atomic_control = #omp.atomic_control<>}
 
   llvm.return
 }

>From 26d8e6403840655c013752f527ce08914f372bc1 Mon Sep 17 00:00:00 2001
From: Anchu Rajendran <asudh...@amd.com>
Date: Wed, 11 Jun 2025 14:11:02 -0500
Subject: [PATCH 3/4] R3: Addressing review comments

---
 flang/include/flang/Frontend/TargetOptions.h              | 2 +-
 .../include/flang/Optimizer/Dialect/Support/FIRContext.h  | 4 ++--
 flang/lib/Optimizer/Dialect/Support/FIRContext.cpp        | 8 +++-----
 mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td        | 3 ++-
 4 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/flang/include/flang/Frontend/TargetOptions.h 
b/flang/include/flang/Frontend/TargetOptions.h
index 26256fd775f11..dd29b4e3e8b08 100644
--- a/flang/include/flang/Frontend/TargetOptions.h
+++ b/flang/include/flang/Frontend/TargetOptions.h
@@ -54,7 +54,7 @@ class TargetOptions {
   /// Print verbose assembly
   bool asmVerbose = false;
 
-  /// Atomic Control Options for AMD GPU
+  /// Atomic control options for AMD gpu
   bool amdgpuIgnoreDenormalMode = false;
   bool amdgpuRemoteMemory = false;
   bool amdgpuFineGrainedMemory = false;
diff --git a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h 
b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
index ac563bcc402c7..ac5fd33874db8 100644
--- a/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
+++ b/flang/include/flang/Optimizer/Dialect/Support/FIRContext.h
@@ -58,7 +58,7 @@ void setTargetCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
 /// Get the target CPU string from the Module or return a null reference.
 llvm::StringRef getTargetCPU(mlir::ModuleOp mod);
 
-// Setters and Getters for atomic control options
+// Setters and getters for atomic control options.
 void setAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod);
 bool getAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod);
 void setAmdgpuFineGrainedMemory(mlir::ModuleOp mod);
@@ -70,7 +70,7 @@ bool getAmdgpuRemoteMemory(mlir::ModuleOp mod);
 /// module `mod` is still live.
 void setTuneCPU(mlir::ModuleOp mod, llvm::StringRef cpu);
 
-// set Atomic control options for amd gpu.
+// set atomic control options for AMD gpu.
 void setAmdgpuAtomicControlOptions(mlir::ModuleOp mod,
                                    bool amdgpuIgnoreDenormalMode,
                                    bool amdgpuNoFineGrainedMemory,
diff --git a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp 
b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
index b961793dbdfd5..e2c915b2dea67 100644
--- a/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Dialect/Support/FIRContext.cpp
@@ -96,8 +96,7 @@ void fir::setAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod) {
 }
 
 bool fir::getAmdgpuIgnoreDenormalMode(mlir::ModuleOp mod) {
-  if (auto attr =
-          mod->getAttrOfType<mlir::UnitAttr>(amdgpuIgnoreDenormalModeName))
+  if (mod->hasAttrOfType<mlir::UnitAttr>(amdgpuIgnoreDenormalModeName))
     return true;
   return false;
 }
@@ -110,8 +109,7 @@ void fir::setAmdgpuFineGrainedMemory(mlir::ModuleOp mod) {
 }
 
 bool fir::getAmdgpuFineGrainedMemory(mlir::ModuleOp mod) {
-  if (auto attr =
-          mod->getAttrOfType<mlir::UnitAttr>(amdgpuFineGrainedMemoryName))
+  if (mod->hasAttrOfType<mlir::UnitAttr>(amdgpuFineGrainedMemoryName))
     return true;
   return false;
 }
@@ -123,7 +121,7 @@ void fir::setAmdgpuRemoteMemory(mlir::ModuleOp mod) {
 }
 
 bool fir::getAmdgpuRemoteMemory(mlir::ModuleOp mod) {
-  if (auto attr = mod->getAttrOfType<mlir::UnitAttr>(amdgpuRemoteMemoryName))
+  if (mod->hasAttrOfType<mlir::UnitAttr>(amdgpuRemoteMemoryName))
     return true;
   return false;
 }
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
index 84887dfd2c6f9..1707099860114 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPAttrDefs.td
@@ -58,7 +58,8 @@ def FlagsAttr : OpenMP_Attr<"Flags", "flags"> {
 // AtomicControlAttr
 
//===----------------------------------------------------------------------===//
 
-// Runtime library flags attribute that holds information for lowering to LLVM.
+// Atomic control attributes holds information about architectural
+// characteristics that are required for lowering of atomic operations.
 def AtomicControlAttr : OpenMP_Attr<"AtomicControl", "atomic_control"> {
   let parameters =
       (ins DefaultValuedParameter<"bool", 
"false">:$amdgpu_ignore_denormal_mode,

>From d0d8e44da5f8465653b8f087c0f11d5678a05fb9 Mon Sep 17 00:00:00 2001
From: Anchu Rajendran <asudh...@amd.com>
Date: Wed, 11 Jun 2025 13:24:46 -0500
Subject: [PATCH 4/4] backend changes

---
 flang/test/Driver/atomic-control-options.f90  | 19 ++++++++++++++
 .../llvm/Frontend/OpenMP/OMPIRBuilder.h       | 11 +++++---
 llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp     | 25 ++++++++++++++-----
 .../OpenMP/OpenMPToLLVMIRTranslation.cpp      | 20 +++++++++++++--
 4 files changed, 64 insertions(+), 11 deletions(-)
 create mode 100644 flang/test/Driver/atomic-control-options.f90

diff --git a/flang/test/Driver/atomic-control-options.f90 
b/flang/test/Driver/atomic-control-options.f90
new file mode 100644
index 0000000000000..5cbecde6c521e
--- /dev/null
+++ b/flang/test/Driver/atomic-control-options.f90
@@ -0,0 +1,19 @@
+! RUN: %flang_fc1 -emit-llvm -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -munsafe-fp-atomics %s -o -|FileCheck 
-check-prefix=UNSAFE-FP-ATOMICS %s
+! RUN: %flang_fc1 -emit-llvm -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-ignore-denormal-mode %s -o -|FileCheck 
-check-prefix=IGNORE-DENORMAL-MODE %s
+! RUN: %flang_fc1 -emit-llvm -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-fine-grained-memory %s -o -|FileCheck 
-check-prefix=FINE-GRAINED-MEMORY %s
+! RUN: %flang_fc1 -emit-llvm -triple amdgcn-amd-amdhsa -fopenmp 
-fopenmp-is-device -fatomic-remote-memory %s -o -|FileCheck 
-check-prefix=REMOTE-MEMORY %s
+program test
+    implicit none
+    integer :: A, threads
+    threads = 128
+    A = 0
+    !$omp target parallel num_threads(threads)
+    !$omp atomic
+    A =  A + 1
+    !$omp end target parallel
+end program test
+
+!UNSAFE-FP-ATOMICS: %{{.*}} = atomicrmw add ptr {{.*}}, i32 1 monotonic, align 
4, !amdgpu.ignore.denormal.mode !{{.*}}, !amdgpu.no.fine.grained.memory 
!{{.*}}, !amdgpu.no.remote.memory !{{.*}}
+!IGNORE-DENORMAL-MODE: %{{.*}} = atomicrmw add ptr {{.*}}, i32 1 monotonic, 
align 4, !amdgpu.ignore.denormal.mode !{{.*}}, !amdgpu.no.fine.grained.memory 
!{{.*}}, !amdgpu.no.remote.memory !{{.*}}
+!FINE-GRAINED-MEMORY: %{{.*}} = atomicrmw add ptr {{.*}}, i32 1 monotonic, 
align 4, !amdgpu.no.remote.memory !{{.*}}
+!REMOTE-MEMORY: %{{.*}} = atomicrmw add ptr {{.*}}, i32 1 monotonic, align 4, 
!amdgpu.no.fine.grained.memory !{{.*}}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h 
b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index e4b1241151e9d..0887719b42f79 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -3278,7 +3278,8 @@ class OpenMPIRBuilder {
   emitAtomicUpdate(InsertPointTy AllocaIP, Value *X, Type *XElemTy, Value 
*Expr,
                    AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp,
                    AtomicUpdateCallbackTy &UpdateOp, bool VolatileX,
-                   bool IsXBinopExpr);
+                   bool IsXBinopExpr, bool IsAmdgpuIgnoreDenormalMode,
+                   bool IsAmdgpuNoFineGrainedMemory, bool 
IsAmdgpuNoRemoteMemory);
 
   /// Emit the binary op. described by \p RMWOp, using \p Src1 and \p Src2 .
   ///
@@ -3349,7 +3350,9 @@ class OpenMPIRBuilder {
   LLVM_ABI InsertPointOrErrorTy createAtomicUpdate(
       const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X,
       Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp,
-      AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr);
+      AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr,
+      bool IsAmdgpuIgnoreDenormalMode = false,
+      bool IsAmdgpuNoFineGrainedMemory = false, bool IsAmdgpuNoRemoteMemory = 
false);
 
   /// Emit atomic update for constructs: --- Only Scalar data types
   /// V = X; X = X BinOp Expr ,
@@ -3384,7 +3387,9 @@ class OpenMPIRBuilder {
       const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X,
       AtomicOpValue &V, Value *Expr, AtomicOrdering AO,
       AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp,
-      bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr);
+      bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr,
+      bool IsAmdgpuIgnoreDenormalMode = false,
+      bool IsAmdgpuNoFineGrainedMemory = false, bool IsAmdgpuNoRemoteMemory = 
false);
 
   /// Emit atomic compare for constructs: --- Only scalar data types
   /// cond-expr-stmt:
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp 
b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index ca3d8438654dc..ecc3c620312cb 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -8761,7 +8761,8 @@ OpenMPIRBuilder::createAtomicWrite(const 
LocationDescription &Loc,
 OpenMPIRBuilder::InsertPointOrErrorTy OpenMPIRBuilder::createAtomicUpdate(
     const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X,
     Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp,
-    AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr) {
+    AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr, bool 
IsAmdgpuIgnoreDenormalMode,
+    bool IsNoFineGrainedMemory, bool IsNoRemoteMemory) {
   assert(!isConflictIP(Loc.IP, AllocaIP) && "IPs must not be ambiguous");
   if (!updateToLocation(Loc))
     return Loc.IP;
@@ -8781,7 +8782,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy 
OpenMPIRBuilder::createAtomicUpdate(
 
   Expected<std::pair<Value *, Value *>> AtomicResult =
       emitAtomicUpdate(AllocaIP, X.Var, X.ElemTy, Expr, AO, RMWOp, UpdateOp,
-                       X.IsVolatile, IsXBinopExpr);
+                       X.IsVolatile, IsXBinopExpr, IsAmdgpuIgnoreDenormalMode, 
IsNoFineGrainedMemory, IsNoRemoteMemory);
   if (!AtomicResult)
     return AtomicResult.takeError();
   checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Update);
@@ -8828,7 +8829,8 @@ Value *OpenMPIRBuilder::emitRMWOpAsInstruction(Value 
*Src1, Value *Src2,
 Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
     InsertPointTy AllocaIP, Value *X, Type *XElemTy, Value *Expr,
     AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp,
-    AtomicUpdateCallbackTy &UpdateOp, bool VolatileX, bool IsXBinopExpr) {
+    AtomicUpdateCallbackTy &UpdateOp, bool VolatileX, bool IsXBinopExpr, bool 
IsAmdgpuIgnoreDenormalMode,
+    bool IsAmdgpuNoFineGrainedMemory, bool IsAmdgpuNoRemoteMemory) {
   // TODO: handle the case where XElemTy is not byte-sized or not a power of 2
   // or a complex datatype.
   bool emitRMWOp = false;
@@ -8851,7 +8853,17 @@ Expected<std::pair<Value *, Value *>> 
OpenMPIRBuilder::emitAtomicUpdate(
 
   std::pair<Value *, Value *> Res;
   if (emitRMWOp) {
-    Res.first = Builder.CreateAtomicRMW(RMWOp, X, Expr, llvm::MaybeAlign(), 
AO);
+    AtomicRMWInst *atomicRMWInst = Builder.CreateAtomicRMW(RMWOp, X, Expr, 
llvm::MaybeAlign(), AO);
+    if(IsAmdgpuIgnoreDenormalMode)
+      atomicRMWInst->setMetadata("amdgpu.ignore.denormal.mode",
+                         llvm::MDNode::get(Builder.getContext(), {}));
+    if(IsAmdgpuNoFineGrainedMemory)
+      atomicRMWInst->setMetadata("amdgpu.no.fine.grained.memory",
+                         llvm::MDNode::get(Builder.getContext(), {}));
+    if(IsAmdgpuNoRemoteMemory)
+      atomicRMWInst->setMetadata("amdgpu.no.remote.memory",
+                         llvm::MDNode::get(Builder.getContext(), {}));
+    Res.first = atomicRMWInst;
     // not needed except in case of postfix captures. Generate anyway for
     // consistency with the else part. Will be removed with any DCE pass.
     // AtomicRMWInst::Xchg does not have a coressponding instruction.
@@ -8983,7 +8995,8 @@ OpenMPIRBuilder::InsertPointOrErrorTy 
OpenMPIRBuilder::createAtomicCapture(
     const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X,
     AtomicOpValue &V, Value *Expr, AtomicOrdering AO,
     AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp,
-    bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr) {
+    bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr, bool 
IsAmdgpuIgnoreDenormalMode,
+    bool IsAmdgpuNoFineGrainedMemory, bool IsAmdgpuNoRemoteMemory) {
   if (!updateToLocation(Loc))
     return Loc.IP;
 
@@ -9004,7 +9017,7 @@ OpenMPIRBuilder::InsertPointOrErrorTy 
OpenMPIRBuilder::createAtomicCapture(
   AtomicRMWInst::BinOp AtomicOp = (UpdateExpr ? RMWOp : AtomicRMWInst::Xchg);
   Expected<std::pair<Value *, Value *>> AtomicResult =
       emitAtomicUpdate(AllocaIP, X.Var, X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
-                       X.IsVolatile, IsXBinopExpr);
+                       X.IsVolatile, IsXBinopExpr, IsAmdgpuIgnoreDenormalMode, 
IsAmdgpuNoFineGrainedMemory, IsAmdgpuNoRemoteMemory);
   if (!AtomicResult)
     return AtomicResult.takeError();
   Value *CapturedVal =
diff --git 
a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp 
b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 6bccc1d6f5d30..5e9cd26c8f99b 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -3166,13 +3166,18 @@ convertOmpAtomicUpdate(omp::AtomicUpdateOp &opInst,
     return moduleTranslation.lookupValue(yieldop.getResults()[0]);
   };
 
+  mlir::omp::AtomicControlAttr atomicControlAttr = 
opInst.getAtomicControlAttr();
+  bool isAmdgpuIgnoreDenormalMode = 
atomicControlAttr.getAmdgpuIgnoreDenormalMode();
+  bool isAmdgpuNoFineGrainedMemory = 
!atomicControlAttr.getAmdgpuFineGrainedMemory();
+  bool isAmdgpuNoRemoteMemory = !atomicControlAttr.getAmdgpuRemoteMemory(); 
   // Handle ambiguous alloca, if any.
   auto allocaIP = findAllocaInsertPoint(builder, moduleTranslation);
   llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
       ompBuilder->createAtomicUpdate(ompLoc, allocaIP, llvmAtomicX, llvmExpr,
                                      atomicOrdering, binop, updateFn,
-                                     isXBinopExpr);
+                                     isXBinopExpr, isAmdgpuIgnoreDenormalMode, 
isAmdgpuNoFineGrainedMemory, isAmdgpuNoRemoteMemory);
+                                    
 
   if (failed(handleError(afterIP, *opInst)))
     return failure();
@@ -3194,6 +3199,7 @@ convertOmpAtomicCapture(omp::AtomicCaptureOp 
atomicCaptureOp,
   llvm::AtomicRMWInst::BinOp binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
 
   omp::AtomicUpdateOp atomicUpdateOp = atomicCaptureOp.getAtomicUpdateOp();
+
   omp::AtomicWriteOp atomicWriteOp = atomicCaptureOp.getAtomicWriteOp();
 
   assert((atomicUpdateOp || atomicWriteOp) &&
@@ -3261,13 +3267,23 @@ convertOmpAtomicCapture(omp::AtomicCaptureOp 
atomicCaptureOp,
     return moduleTranslation.lookupValue(yieldop.getResults()[0]);
   };
 
+  bool isAmdgpuIgnoreDenormalMode = false;
+  bool isAmdgpuNoFineGrainedMemory = true;
+  bool isAmdgpuNoRemoteMemory = true;
+  if(atomicUpdateOp) {
+    mlir::omp::AtomicControlAttr atomicControlAttr = 
atomicUpdateOp.getAtomicControlAttr();
+    isAmdgpuIgnoreDenormalMode = 
atomicControlAttr.getAmdgpuIgnoreDenormalMode();
+    isAmdgpuNoFineGrainedMemory = 
!atomicControlAttr.getAmdgpuFineGrainedMemory();
+    isAmdgpuNoRemoteMemory = !atomicControlAttr.getAmdgpuRemoteMemory(); 
+  }
   // Handle ambiguous alloca, if any.
   auto allocaIP = findAllocaInsertPoint(builder, moduleTranslation);
   llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
   llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
       ompBuilder->createAtomicCapture(
           ompLoc, allocaIP, llvmAtomicX, llvmAtomicV, llvmExpr, atomicOrdering,
-          binop, updateFn, atomicUpdateOp, isPostfixUpdate, isXBinopExpr);
+          binop, updateFn, atomicUpdateOp, isPostfixUpdate,
+          isXBinopExpr, isAmdgpuIgnoreDenormalMode, 
isAmdgpuNoFineGrainedMemory, isAmdgpuNoRemoteMemory);
 
   if (failed(handleError(afterIP, *atomicCaptureOp)))
     return failure();

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to