[llvm] [SPIRV] Lower uinc/udec_wrap to OpAtomicIIncrement/Decrement (PR #207766)

Marcos Maronas via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 09:01:39 PDT 2026


https://github.com/maarquitos14 created https://github.com/llvm/llvm-project/pull/207766

None

>From 0e54d19e61f0cfcf6270f0ababe7a6fd9ca479ba Mon Sep 17 00:00:00 2001
From: Marcos Maronas <mmaronas at amd.com>
Date: Mon, 6 Jul 2026 10:50:30 -0500
Subject: [PATCH] [SPIRV] Lower uinc/udec_wrap to OpAtomicIIncrement/Decrement

---
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   |  3 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 42 +++++++++++++
 llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp  |  3 +-
 .../atomicrmw-uinc-udec-wrap-orderings.ll     | 63 +++++++++++++++++++
 .../SPIRV/atomicrmw-uinc-udec-wrap-scopes.ll  | 56 +++++++++++++++++
 .../atomicrmw-uinc-udec-wrap-storage-class.ll | 49 +++++++++++++++
 .../CodeGen/SPIRV/atomicrmw-uinc-udec-wrap.ll | 44 +++----------
 7 files changed, 223 insertions(+), 37 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-orderings.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-scopes.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-storage-class.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index 64c61d9f6a0c8..74a46cb7d3ae7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -676,10 +676,9 @@ SPIRVTargetLowering::shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const {
   case AtomicRMWInst::FSub:
   case AtomicRMWInst::FMin:
   case AtomicRMWInst::FMax:
-    return AtomicExpansionKind::None;
   case AtomicRMWInst::UIncWrap:
   case AtomicRMWInst::UDecWrap:
-    return AtomicExpansionKind::CmpXChg;
+    return AtomicExpansionKind::None;
   default:
     return TargetLowering::shouldExpandAtomicRMWInIR(RMW);
   }
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 274a3265f7115..f2bb316d7c1a7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -180,6 +180,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
   bool selectInterlockedOp(Register ResVReg, SPIRVTypeInst ResType,
                            MachineInstr &I, unsigned Opcode) const;
 
+  bool selectAtomicIncDec(Register ResVReg, SPIRVTypeInst ResType,
+                          MachineInstr &I, unsigned NewOpcode) const;
+
   bool selectAtomicCmpXchg(Register ResVReg, SPIRVTypeInst ResType,
                            MachineInstr &I) const;
 
@@ -1392,6 +1395,11 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
   case TargetOpcode::G_ATOMICRMW_FMAX:
     return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicFMaxEXT);
 
+  case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
+    return selectAtomicIncDec(ResVReg, ResType, I, SPIRV::OpAtomicIIncrement);
+  case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
+    return selectAtomicIncDec(ResVReg, ResType, I, SPIRV::OpAtomicIDecrement);
+
   case TargetOpcode::G_FENCE:
     return selectFence(I);
 
@@ -2455,6 +2463,40 @@ bool SPIRVInstructionSelector::selectAtomicRMW(Register ResVReg,
   return true;
 }
 
+bool SPIRVInstructionSelector::selectAtomicIncDec(Register ResVReg,
+                                                  SPIRVTypeInst ResType,
+                                                  MachineInstr &I,
+                                                  unsigned NewOpcode) const {
+  assert(I.hasOneMemOperand());
+  const MachineMemOperand *MemOp = *I.memoperands_begin();
+  uint32_t Scope = static_cast<uint32_t>(getMemScope(
+      GR.CurMF->getFunction().getContext(), MemOp->getSyncScopeID()));
+  Register ScopeReg = buildI32Constant(Scope, I);
+
+  Register Ptr = I.getOperand(1).getReg();
+  uint32_t ScSem = static_cast<uint32_t>(
+      getMemSemanticsForStorageClass(GR.getPointerStorageClass(Ptr)));
+  AtomicOrdering AO = MemOp->getSuccessOrdering();
+  uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO)) | ScSem;
+  Register MemSemReg = buildI32Constant(MemSem, I);
+
+  Register WrapReg = I.getOperand(2).getReg();
+
+  BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(NewOpcode))
+      .addDef(ResVReg)
+      .addUse(GR.getSPIRVTypeID(ResType))
+      .addUse(Ptr)
+      .addUse(ScopeReg)
+      .addUse(MemSemReg)
+      .constrainAllUses(TII, TRI, RBI);
+
+  BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
+      .addUse(ResVReg)
+      .addImm(static_cast<uint32_t>(SPIRV::Decoration::MaxByteOffsetId))
+      .addUse(WrapReg);
+  return true;
+}
+
 bool SPIRVInstructionSelector::selectInterlockedOp(Register ResVReg,
                                                    SPIRVTypeInst ResType,
                                                    MachineInstr &I,
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index b39806b5848e1..20e11df885c4c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -441,7 +441,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
   getActionDefinitionsBuilder({G_ATOMICRMW_OR, G_ATOMICRMW_ADD, G_ATOMICRMW_AND,
                                G_ATOMICRMW_MAX, G_ATOMICRMW_MIN,
                                G_ATOMICRMW_SUB, G_ATOMICRMW_XOR,
-                               G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN})
+                               G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN,
+                               G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP})
       .legalForCartesianProduct(allIntScalars, allPtrs);
 
   getActionDefinitionsBuilder(
diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-orderings.ll b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-orderings.ll
new file mode 100644
index 0000000000000..9b49b186e796a
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-orderings.ll
@@ -0,0 +1,63 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Check that atomicrmw uinc_wrap/udec_wrap correctly encode memory
+; orderings.
+; CrossWorkgroupMemory = 0x200 = 512
+; Monotonic (Relaxed) = 0x000 -> with CrossWorkgroup: 512
+; Acquire              = 0x002 -> with CrossWorkgroup: 514
+; Release              = 0x004 -> with CrossWorkgroup: 516
+; AcquireRelease       = 0x008 -> with CrossWorkgroup: 520
+; SequentiallyConsistent = 0x010 -> with CrossWorkgroup: 528
+
+; CHECK-DAG: %[[#Int:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Scope:]] = OpConstantNull %[[#Int]]
+; CHECK-DAG: %[[#MemSem_Monotonic:]] = OpConstant %[[#Int]] 512
+; CHECK-DAG: %[[#MemSem_Acquire:]] = OpConstant %[[#Int]] 514
+; CHECK-DAG: %[[#MemSem_Release:]] = OpConstant %[[#Int]] 516
+; CHECK-DAG: %[[#MemSem_AcqRel:]] = OpConstant %[[#Int]] 520
+; CHECK-DAG: %[[#MemSem_SeqCst:]] = OpConstant %[[#Int]] 528
+
+ at ui = common dso_local addrspace(1) global i32 0, align 4
+
+define dso_local spir_func void @uinc_wrap_orderings() {
+entry:
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Monotonic]]
+  %0 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 monotonic
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Acquire]]
+  %1 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 acquire
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Release]]
+  %2 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 release
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_AcqRel]]
+  %3 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 acq_rel
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_SeqCst]]
+  %4 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 seq_cst
+
+  ret void
+}
+
+define dso_local spir_func void @udec_wrap_orderings() {
+entry:
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Monotonic]]
+  %0 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 monotonic
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Acquire]]
+  %1 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 acquire
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_Release]]
+  %2 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 release
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_AcqRel]]
+  %3 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 acq_rel
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope]] %[[#MemSem_SeqCst]]
+  %4 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 seq_cst
+
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-scopes.ll b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-scopes.ll
new file mode 100644
index 0000000000000..df3211fb9c820
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-scopes.ll
@@ -0,0 +1,56 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Check that atomicrmw uinc_wrap/udec_wrap correctly encode scopes. 
+
+; CHECK-DAG: %[[#Int:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#Scope_CrossDevice:]] = OpConstantNull %[[#Int]]
+; CHECK-DAG: %[[#Scope_Device:]] = OpConstant %[[#Int]] 1{{$}}
+; CHECK-DAG: %[[#Scope_Workgroup:]] = OpConstant %[[#Int]] 2{{$}}
+; CHECK-DAG: %[[#Scope_Subgroup:]] = OpConstant %[[#Int]] 3{{$}}
+; CHECK-DAG: %[[#Scope_Invocation:]] = OpConstant %[[#Int]] 4{{$}}
+; CHECK-DAG: %[[#MemSem_SeqCst:]] = OpConstant %[[#Int]] 528{{$}}
+
+ at ui = common dso_local addrspace(1) global i32 0, align 4
+
+define dso_local spir_func void @uinc_wrap_scopes() {
+entry:
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope_CrossDevice]] %[[#MemSem_SeqCst]]
+  %0 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 seq_cst
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Device]] %[[#MemSem_SeqCst]]
+  %1 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 syncscope("device") seq_cst
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Workgroup]] %[[#MemSem_SeqCst]]
+  %2 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 syncscope("workgroup") seq_cst
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Subgroup]] %[[#MemSem_SeqCst]]
+  %3 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 syncscope("subgroup") seq_cst
+
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Invocation]] %[[#MemSem_SeqCst]]
+  %4 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 syncscope("singlethread") seq_cst
+
+  ret void
+}
+
+define dso_local spir_func void @udec_wrap_scopes() {
+entry:
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope_CrossDevice]] %[[#MemSem_SeqCst]]
+  %0 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 seq_cst
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Device]] %[[#MemSem_SeqCst]]
+  %1 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 syncscope("device") seq_cst
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Workgroup]] %[[#MemSem_SeqCst]]
+  %2 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 syncscope("workgroup") seq_cst
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Subgroup]] %[[#MemSem_SeqCst]]
+  %3 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 syncscope("subgroup") seq_cst
+
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %[[#Scope_Invocation]] %[[#MemSem_SeqCst]]
+  %4 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 syncscope("singlethread") seq_cst
+
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-storage-class.ll b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-storage-class.ll
new file mode 100644
index 0000000000000..3d66131c4ea63
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap-storage-class.ll
@@ -0,0 +1,49 @@
+; Verify that atomicrmw uinc_wrap/udec_wrap correctly encode the
+; storage-class semantics bit for different address spaces.
+
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; Check that atomicrmw uinc_wrap/udec_wrap correctly encode scopes. 
+; CrossWorkgroupMemory = 0x200 = 512
+; WorkgroupMemory      = 0x100 = 256
+; AcquireRelease       = 0x008 =   8
+;   -> with CrossWorkgroup: 520
+;   -> with Workgroup:      264
+
+; CHECK-DAG: %[[#Int:]] = OpTypeInt 32 0
+; CHECK-DAG: %[[#MemSem_AcqRel_CW:]] = OpConstant %[[#Int]] 520
+; CHECK-DAG: %[[#MemSem_AcqRel_WG:]] = OpConstant %[[#Int]] 264
+
+ at g_cw = common dso_local addrspace(1) global i32 0, align 4
+ at g_wg = common dso_local addrspace(3) global i32 0, align 4
+
+define dso_local spir_func void @uinc_wrap_crossworkgroup() {
+entry:
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %{{[0-9]+}} %[[#MemSem_AcqRel_CW]]
+  %0 = atomicrmw uinc_wrap ptr addrspace(1) @g_cw, i32 1 acq_rel
+  ret void
+}
+
+define dso_local spir_func void @uinc_wrap_workgroup() {
+entry:
+  ; CHECK: OpAtomicIIncrement %[[#Int]] %{{[0-9]+}} %{{[0-9]+}} %[[#MemSem_AcqRel_WG]]
+  %0 = atomicrmw uinc_wrap ptr addrspace(3) @g_wg, i32 1 acq_rel
+  ret void
+}
+
+define dso_local spir_func void @udec_wrap_crossworkgroup() {
+entry:
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %{{[0-9]+}} %[[#MemSem_AcqRel_CW]]
+  %0 = atomicrmw udec_wrap ptr addrspace(1) @g_cw, i32 1 acq_rel
+  ret void
+}
+
+define dso_local spir_func void @udec_wrap_workgroup() {
+entry:
+  ; CHECK: OpAtomicIDecrement %[[#Int]] %{{[0-9]+}} %{{[0-9]+}} %[[#MemSem_AcqRel_WG]]
+  %0 = atomicrmw udec_wrap ptr addrspace(3) @g_wg, i32 1 acq_rel
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap.ll b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap.ll
index 23f8ae6939e86..adaa602180b6f 100644
--- a/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap.ll
+++ b/llvm/test/CodeGen/SPIRV/atomicrmw-uinc-udec-wrap.ll
@@ -1,55 +1,31 @@
+; Verify that atomicrmw uinc_wrap/udec_wrap lower to OpAtomicIIncrement/
+; OpAtomicIDecrement with a MaxByteOffsetId decoration carrying the wrap
+; operand, rather than being expanded to a CmpXChg loop.
+
 ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 ; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
 ; CHECK-DAG: %[[#Int:]] = OpTypeInt 32 0
-; CHECK-DAG: %[[#Bool:]] = OpTypeBool
 ; CHECK-DAG: %[[#PointerType:]] = OpTypePointer CrossWorkgroup %[[#Int]]
-; CHECK-DAG: %[[#MemSem_SequentiallyConsistent:]] = OpConstant %[[#Int]] 528
-; CHECK-DAG: %[[#Value:]] = OpConstant %[[#Int]] 42
-; CHECK-DAG: %[[#One:]] = OpConstant %[[#Int]] 1
+; CHECK-DAG: %[[#MemSem_SeqCst:]] = OpConstant %[[#Int]] 528
 ; CHECK-DAG: %[[#Scope_CrossDevice:]] = OpConstantNull %[[#Int]]
 ; CHECK-DAG: %[[#Pointer:]] = OpVariable %[[#PointerType]] CrossWorkgroup
 
- at ui = common dso_local addrspace(1) global i32 0, align 4
+; CHECK-DAG: OpDecorate %[[#Inc:]] MaxByteOffsetId %[[#WrapVal:]]
+; CHECK-DAG: OpDecorate %[[#Dec:]] MaxByteOffsetId %[[#WrapVal2:]]
 
-; CHECK:      %[[#Load:]] = OpLoad %[[#Int]] %[[#Pointer]] Aligned 4
-; CHECK:      OpBranch %[[#Loop:]]
-; CHECK:      %[[#Loop]] = OpLabel
-; CHECK:      %[[#Phi:]] = OpPhi %[[#Int]] %[[#Load]] %[[#Entry:]] %[[#PhiNext:]] %[[#Loop]]
-; CHECK:      %[[#Add:]] = OpIAdd %[[#Int]] %[[#Phi]] %[[#One]]
-; CHECK:      %[[#GE:]] = OpUGreaterThanEqual %[[#Bool]] %[[#Phi]] %[[#Value]]
-; CHECK:      %[[#Select:]] = OpSelect %[[#Int]] %[[#GE]] %[[#Scope_CrossDevice]] %[[#Add]]
-; CHECK:      %[[#CmpXChg:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr:]] %[[#Scope_CrossDevice]]
-; CHECK-SAME: %[[#MemSem_SequentiallyConsistent]] %[[#MemSem_SequentiallyConsistent]] %[[#Select]] %[[#Phi]]
-; CHECK:      %[[#Cond:]] = OpCompositeExtract %[[#Bool]] %[[#CmpXChgComposite:]] 1
-; CHECK:      %[[#PhiNext]] = OpCompositeExtract %[[#Int]] %[[#CmpXChgComposite]] 0
-; CHECK:      OpBranchConditional %[[#Cond]] %[[#Exit:]] %[[#Loop]]
-; CHECK:      %[[#Exit]] = OpLabel
+ at ui = common dso_local addrspace(1) global i32 0, align 4
 
+; CHECK: %[[#Inc]] = OpAtomicIIncrement %[[#Int]] %[[#Pointer]] %[[#Scope_CrossDevice]] %[[#MemSem_SeqCst]]
 define dso_local spir_func void @atomicrmw_uinc_wrap() local_unnamed_addr {
 entry:
   %0 = atomicrmw uinc_wrap ptr addrspace(1) @ui, i32 42 seq_cst
   ret void
 }
 
-; CHECK:      %[[#Load:]] = OpLoad %[[#Int]] %[[#Pointer]] Aligned 4
-; CHECK:      OpBranch %[[#Loop:]]
-; CHECK:      %[[#Loop]] = OpLabel
-; CHECK:      %[[#Phi:]] = OpPhi %[[#Int]] %[[#Load]] %[[#Entry:]] %[[#PhiNext:]] %[[#Loop]]
-; CHECK:      %[[#Sub:]] = OpISub %[[#Int]] %[[#Phi]] %[[#One]]
-; CHECK:      %[[#Equal:]] = OpIEqual %[[#Bool]] %[[#Phi]] %[[#Scope_CrossDevice]]
-; CHECK:      %[[#GT:]] = OpUGreaterThan %[[#Bool]] %[[#Phi]] %[[#Value]]
-; CHECK:      %[[#Or:]] = OpLogicalOr %[[#Bool]] %[[#Equal]] %[[#GT]]
-; CHECK:      %[[#Select:]] = OpSelect %[[#Int]] %[[#Or]] %[[#Value]] %[[#Sub]]
-; CHECK:      %[[#CmpXChg:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr:]] %[[#Scope_CrossDevice]] 
-; CHECK-SAME: %[[#MemSem_SequentiallyConsistent]] %[[#MemSem_SequentiallyConsistent]] %[[#Select]] %[[#Phi]]
-; CHECK:      %[[#Cond:]] = OpCompositeExtract %[[#Bool]] %[[#CmpXChgComposite:]] 1
-; CHECK:      %[[#PhiNext]] = OpCompositeExtract %[[#Int]] %[[#CmpXChgComposite]] 0
-; CHECK:      OpBranchConditional %[[#Cond]] %[[#Exit:]] %[[#Loop]]
-; CHECK:      %[[#Exit]] = OpLabel
-
+; CHECK: %[[#Dec]] = OpAtomicIDecrement %[[#Int]] %[[#Pointer]] %[[#Scope_CrossDevice]] %[[#MemSem_SeqCst]]
 define dso_local spir_func void @atomicrmw_udec_wrap() local_unnamed_addr {
 entry:
   %0 = atomicrmw udec_wrap ptr addrspace(1) @ui, i32 42 seq_cst



More information about the llvm-commits mailing list