Skip to content

Commit 4af249f

Browse files
authored
Add usub_cond and usub_sat operations to atomicrmw (llvm#105568)
These both perform conditional subtraction, returning the minuend and zero respectively, if the difference is negative.
1 parent 109cd11 commit 4af249f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3955
-72
lines changed

llvm/bindings/ocaml/llvm/llvm.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ module AtomicRMWBinOp = struct
300300
| FMin
301301
| UInc_Wrap
302302
| UDec_Wrap
303+
| USub_Cond
304+
| USub_Sat
303305
end
304306

305307
module ValueKind = struct

llvm/bindings/ocaml/llvm/llvm.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ module AtomicRMWBinOp : sig
335335
| FMin
336336
| UInc_Wrap
337337
| UDec_Wrap
338+
| USub_Cond
339+
| USub_Sat
338340
end
339341

340342
(** The kind of an [llvalue], the result of [classify_value v].

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,9 @@ operands.
863863
G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
864864
G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD,
865865
G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
866-
G_ATOMICRMW_FMIN
866+
G_ATOMICRMW_FMIN, G_ATOMICRMW_UINC_WRAP,
867+
G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
868+
G_ATOMICRMW_USUB_SAT
867869

868870
Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
869871
operands.

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11241,6 +11241,8 @@ operation. The operation must be one of the following keywords:
1124111241
- fmin
1124211242
- uinc_wrap
1124311243
- udec_wrap
11244+
- usub_cond
11245+
- usub_sat
1124411246

1124511247
For most of these operations, the type of '<value>' must be an integer
1124611248
type whose bit width is a power of two greater than or equal to eight
@@ -11291,6 +11293,8 @@ operation argument:
1129111293
- fmin: ``*ptr = minnum(*ptr, val)`` (match the `llvm.minnum.*`` intrinsic)
1129211294
- uinc_wrap: ``*ptr = (*ptr u>= val) ? 0 : (*ptr + 1)`` (increment value with wraparound to zero when incremented above input value)
1129311295
- udec_wrap: ``*ptr = ((*ptr == 0) || (*ptr u> val)) ? val : (*ptr - 1)`` (decrement with wraparound to input value when decremented below zero).
11296+
- usub_cond: ``*ptr = (*ptr u>= val) ? *ptr - val : *ptr`` (subtract only if no unsigned overflow).
11297+
- usub_sat: ``*ptr = (*ptr u>= val) ? *ptr - val : 0`` (subtract with unsigned clamping to zero).
1129411298

1129511299

1129611300
Example:

llvm/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ Changes to the LLVM IR
5454
the standard vector type ``<1 x i64>`` in bitcode upgrade.
5555
* Renamed ``llvm.experimental.stepvector`` intrinsic to ``llvm.stepvector``.
5656

57+
* Added ``usub_cond`` and ``usub_sat`` operations to ``atomicrmw``.
58+
5759
Changes to LLVM infrastructure
5860
------------------------------
5961

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ enum Kind {
268268
kw_fmin,
269269
kw_uinc_wrap,
270270
kw_udec_wrap,
271+
kw_usub_cond,
272+
kw_usub_sat,
271273

272274
// Instruction Opcodes (Opcode in UIntVal).
273275
kw_fneg,

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,9 @@ enum RMWOperations {
485485
RMW_FMAX = 13,
486486
RMW_FMIN = 14,
487487
RMW_UINC_WRAP = 15,
488-
RMW_UDEC_WRAP = 16
488+
RMW_UDEC_WRAP = 16,
489+
RMW_USUB_COND = 17,
490+
RMW_USUB_SAT = 18
489491
};
490492

491493
/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,41 @@ class MachineIRBuilder {
16361636
const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
16371637
MachineMemOperand &MMO);
16381638

1639+
/// Build and insert `OldValRes<def> = G_ATOMICRMW_USUB_COND Addr, Val, MMO`.
1640+
///
1641+
/// Atomically replace the value at \p Addr with the original value minus \p
1642+
/// Val if the original value is greater than or equal to \p Val, or leaves it
1643+
/// unchanged otherwise. Puts the original value from \p Addr in \p OldValRes.
1644+
///
1645+
/// \pre setBasicBlock or setMI must have been called.
1646+
/// \pre \p OldValRes must be a generic virtual register.
1647+
/// \pre \p Addr must be a generic virtual register with pointer type.
1648+
/// \pre \p OldValRes, and \p Val must be generic virtual registers of the
1649+
/// same type.
1650+
///
1651+
/// \return a MachineInstrBuilder for the newly created instruction.
1652+
MachineInstrBuilder buildAtomicRMWUSubCond(const DstOp &OldValRes,
1653+
const SrcOp &Addr,
1654+
const SrcOp &Val,
1655+
MachineMemOperand &MMO);
1656+
1657+
/// Build and insert `OldValRes<def> = G_ATOMICRMW_USUB_SAT Addr, Val, MMO`.
1658+
///
1659+
/// Atomically replace the value at \p Addr with the original value minus \p
1660+
/// Val, with clamping to zero if the unsigned subtraction would overflow.
1661+
/// Puts the original value from \p Addr in \p OldValRes.
1662+
///
1663+
/// \pre setBasicBlock or setMI must have been called.
1664+
/// \pre \p OldValRes must be a generic virtual register.
1665+
/// \pre \p Addr must be a generic virtual register with pointer type.
1666+
/// \pre \p OldValRes, and \p Val must be generic virtual registers of the
1667+
/// same type.
1668+
///
1669+
/// \return a MachineInstrBuilder for the newly created instruction.
1670+
MachineInstrBuilder buildAtomicRMWUSubSat(const DstOp &OldValRes,
1671+
const SrcOp &Addr, const SrcOp &Val,
1672+
MachineMemOperand &MMO);
1673+
16391674
/// Build and insert `G_FENCE Ordering, Scope`.
16401675
MachineInstrBuilder buildFence(unsigned Ordering, unsigned Scope);
16411676

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,8 @@ enum NodeType {
13451345
ATOMIC_LOAD_FMIN,
13461346
ATOMIC_LOAD_UINC_WRAP,
13471347
ATOMIC_LOAD_UDEC_WRAP,
1348+
ATOMIC_LOAD_USUB_COND,
1349+
ATOMIC_LOAD_USUB_SAT,
13481350

13491351
/// Masked load and store - consecutive vector load and store operations
13501352
/// with additional mask operand that prevents memory accesses to the

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,8 @@ class MemSDNode : public SDNode {
14841484
case ISD::ATOMIC_LOAD_FMIN:
14851485
case ISD::ATOMIC_LOAD_UINC_WRAP:
14861486
case ISD::ATOMIC_LOAD_UDEC_WRAP:
1487+
case ISD::ATOMIC_LOAD_USUB_COND:
1488+
case ISD::ATOMIC_LOAD_USUB_SAT:
14871489
case ISD::ATOMIC_LOAD:
14881490
case ISD::ATOMIC_STORE:
14891491
case ISD::MLOAD:
@@ -1550,27 +1552,29 @@ class AtomicSDNode : public MemSDNode {
15501552

15511553
// Methods to support isa and dyn_cast
15521554
static bool classof(const SDNode *N) {
1553-
return N->getOpcode() == ISD::ATOMIC_CMP_SWAP ||
1555+
return N->getOpcode() == ISD::ATOMIC_CMP_SWAP ||
15541556
N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS ||
1555-
N->getOpcode() == ISD::ATOMIC_SWAP ||
1556-
N->getOpcode() == ISD::ATOMIC_LOAD_ADD ||
1557-
N->getOpcode() == ISD::ATOMIC_LOAD_SUB ||
1558-
N->getOpcode() == ISD::ATOMIC_LOAD_AND ||
1559-
N->getOpcode() == ISD::ATOMIC_LOAD_CLR ||
1560-
N->getOpcode() == ISD::ATOMIC_LOAD_OR ||
1561-
N->getOpcode() == ISD::ATOMIC_LOAD_XOR ||
1562-
N->getOpcode() == ISD::ATOMIC_LOAD_NAND ||
1563-
N->getOpcode() == ISD::ATOMIC_LOAD_MIN ||
1564-
N->getOpcode() == ISD::ATOMIC_LOAD_MAX ||
1565-
N->getOpcode() == ISD::ATOMIC_LOAD_UMIN ||
1566-
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
1567-
N->getOpcode() == ISD::ATOMIC_LOAD_FADD ||
1568-
N->getOpcode() == ISD::ATOMIC_LOAD_FSUB ||
1569-
N->getOpcode() == ISD::ATOMIC_LOAD_FMAX ||
1570-
N->getOpcode() == ISD::ATOMIC_LOAD_FMIN ||
1557+
N->getOpcode() == ISD::ATOMIC_SWAP ||
1558+
N->getOpcode() == ISD::ATOMIC_LOAD_ADD ||
1559+
N->getOpcode() == ISD::ATOMIC_LOAD_SUB ||
1560+
N->getOpcode() == ISD::ATOMIC_LOAD_AND ||
1561+
N->getOpcode() == ISD::ATOMIC_LOAD_CLR ||
1562+
N->getOpcode() == ISD::ATOMIC_LOAD_OR ||
1563+
N->getOpcode() == ISD::ATOMIC_LOAD_XOR ||
1564+
N->getOpcode() == ISD::ATOMIC_LOAD_NAND ||
1565+
N->getOpcode() == ISD::ATOMIC_LOAD_MIN ||
1566+
N->getOpcode() == ISD::ATOMIC_LOAD_MAX ||
1567+
N->getOpcode() == ISD::ATOMIC_LOAD_UMIN ||
1568+
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
1569+
N->getOpcode() == ISD::ATOMIC_LOAD_FADD ||
1570+
N->getOpcode() == ISD::ATOMIC_LOAD_FSUB ||
1571+
N->getOpcode() == ISD::ATOMIC_LOAD_FMAX ||
1572+
N->getOpcode() == ISD::ATOMIC_LOAD_FMIN ||
15711573
N->getOpcode() == ISD::ATOMIC_LOAD_UINC_WRAP ||
15721574
N->getOpcode() == ISD::ATOMIC_LOAD_UDEC_WRAP ||
1573-
N->getOpcode() == ISD::ATOMIC_LOAD ||
1575+
N->getOpcode() == ISD::ATOMIC_LOAD_USUB_COND ||
1576+
N->getOpcode() == ISD::ATOMIC_LOAD_USUB_SAT ||
1577+
N->getOpcode() == ISD::ATOMIC_LOAD ||
15741578
N->getOpcode() == ISD::ATOMIC_STORE;
15751579
}
15761580
};

0 commit comments

Comments
 (0)