[llvm] [SystemZ] TableGen-erate node descriptions (PR #168113)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 17 11:38:47 PST 2025
================
@@ -441,55 +614,117 @@ def z_atomic_loadw_max : AtomicWOp<"ATOMIC_LOADW_MAX">;
def z_atomic_loadw_umin : AtomicWOp<"ATOMIC_LOADW_UMIN">;
def z_atomic_loadw_umax : AtomicWOp<"ATOMIC_LOADW_UMAX">;
+// Atomic compare-and-swap returning CC value.
+// Val, CC, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap)
def z_atomic_cmp_swap : SDNode<"SystemZISD::ATOMIC_CMP_SWAP",
SDT_ZAtomicCmpSwap,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad,
SDNPMemOperand]>;
+
+// A wrapper around the inner loop of an ATOMIC_CMP_SWAP.
+//
+// Operand 0: the address of the containing 32-bit-aligned field
+// Operand 1: the compare value, in the low bits of an i32
+// Operand 2: the swap value, in the low bits of an i32
+// Operand 3: how many bits to rotate the i32 left to bring the first
+// operand into the high bits
+// Operand 4: the negative of operand 2, for rotating the other way
+// Operand 5: the width of the field in bits (8 or 16)
def z_atomic_cmp_swapw : SDNode<"SystemZISD::ATOMIC_CMP_SWAPW",
SDT_ZAtomicCmpSwapW,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad,
SDNPMemOperand]>;
+// 128-bit atomic load.
+// Val, OUTCHAIN = ATOMIC_LOAD_128(INCHAIN, ptr)
def z_atomic_load_128 : SDNode<"SystemZISD::ATOMIC_LOAD_128",
SDT_ZAtomicLoad128,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+
+// 128-bit atomic store.
+// OUTCHAIN = ATOMIC_STORE_128(INCHAIN, val, ptr)
def z_atomic_store_128 : SDNode<"SystemZISD::ATOMIC_STORE_128",
SDT_ZAtomicStore128,
[SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+
+// 128-bit atomic compare-and-swap.
+// Val, CC, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap)
def z_atomic_cmp_swap_128 : SDNode<"SystemZISD::ATOMIC_CMP_SWAP_128",
SDT_ZAtomicCmpSwap128,
[SDNPHasChain, SDNPMayStore, SDNPMayLoad,
SDNPMemOperand]>;
+// Use a series of MVCs to copy bytes from one memory location to another.
+// The operands are:
+// - the target address
+// - the source address
+// - the constant length
+//
+// This isn't a memory opcode because we'd need to attach two
+// MachineMemOperands rather than one.
----------------
s-barannikov wrote:
In both the old in the new schemes memory opcodes are those for which `isTargetMemoryOpcode()` returns true. The difference is that in the new scheme the default implementation of this function uses TableGen-erated tables, while the old scheme required C++ code. For historical reasons, most targets grouped all memory opcodes between `FIRST_MEMORY_OPCODE`/`LAST_MEMORY_OPCODE` enum members and the function checked if an opcode falls in this range. The new scheme checks if the node has `SDNPMemOperand` property instead.
So you don't (and didn't) have to do anything special to avoid MVC being considered a memory opcode. It is the opposite: if you need an opcode to be considered a memory opcode, you need to either put it between `FIRST_MEMORY_OPCODE`/`LAST_MEMORY_OPCODE` (old scheme) or add `SDNPMemOperand` property (new scheme).
Should I remove the comment still?
---
I'm not sure that two memory operands is something unsupported though, might be worth checking.
https://github.com/llvm/llvm-project/pull/168113
More information about the llvm-commits
mailing list