[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