[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