Skip to content

Commit a979787

Browse files
jthackrayGeorgeARM
authored andcommitted
Reland [llvm] Add support for llvm IR atomicrmw fminimum/fmaximum instructions (llvm#137701)
This patch adds support for LLVM IR atomicrmw `fmaximum` and `fminimum` instructions. These mirror the `llvm.maximum.*` and `llvm.minimum.*` instructions, but are atomic and use IEEE754 2019 handling for NaNs, which is different to `fmax` and `fmin`. See: https://llvm.org/docs/LangRef.html#llvm-minimum-intrinsic for more details. Future changes will allow this LLVM IR to be lowered to specialised assembler instructions on suitable targets, such as AArch64.
1 parent bda396c commit a979787

File tree

38 files changed

+679
-73
lines changed

38 files changed

+679
-73
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,8 @@ operands.
922922
G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX,
923923
G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD,
924924
G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX,
925-
G_ATOMICRMW_FMIN, G_ATOMICRMW_UINC_WRAP,
925+
G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAXIMUM,
926+
G_ATOMICRMW_FMINIMUM, G_ATOMICRMW_UINC_WRAP,
926927
G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND,
927928
G_ATOMICRMW_USUB_SAT
928929

llvm/docs/LangRef.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11597,6 +11597,8 @@ operation. The operation must be one of the following keywords:
1159711597
- fsub
1159811598
- fmax
1159911599
- fmin
11600+
- fmaximum
11601+
- fminimum
1160011602
- uinc_wrap
1160111603
- udec_wrap
1160211604
- usub_cond
@@ -11606,7 +11608,7 @@ For most of these operations, the type of '<value>' must be an integer
1160611608
type whose bit width is a power of two greater than or equal to eight
1160711609
and less than or equal to a target-specific size limit. For xchg, this
1160811610
may also be a floating point or a pointer type with the same size constraints
11609-
as integers. For fadd/fsub/fmax/fmin, this must be a floating-point
11611+
as integers. For fadd/fsub/fmax/fmin/fmaximum/fminimum, this must be a floating-point
1161011612
or fixed vector of floating-point type. The type of the '``<pointer>``'
1161111613
operand must be a pointer to that type. If the ``atomicrmw`` is marked
1161211614
as ``volatile``, then the optimizer is not allowed to modify the
@@ -11647,8 +11649,10 @@ operation argument:
1164711649
- umin: ``*ptr = *ptr < val ? *ptr : val`` (using an unsigned comparison)
1164811650
- fadd: ``*ptr = *ptr + val`` (using floating point arithmetic)
1164911651
- fsub: ``*ptr = *ptr - val`` (using floating point arithmetic)
11650-
- fmax: ``*ptr = maxnum(*ptr, val)`` (match the `llvm.maxnum.*`` intrinsic)
11651-
- fmin: ``*ptr = minnum(*ptr, val)`` (match the `llvm.minnum.*`` intrinsic)
11652+
- fmax: ``*ptr = maxnum(*ptr, val)`` (match the `llvm.maxnum.*` intrinsic)
11653+
- fmin: ``*ptr = minnum(*ptr, val)`` (match the `llvm.minnum.*` intrinsic)
11654+
- fmaximum: ``*ptr = maximum(*ptr, val)`` (match the `llvm.maximum.*` intrinsic)
11655+
- fminimum: ``*ptr = minimum(*ptr, val)`` (match the `llvm.minimum.*` intrinsic)
1165211656
- uinc_wrap: ``*ptr = (*ptr u>= val) ? 0 : (*ptr + 1)`` (increment value with wraparound to zero when incremented above input value)
1165311657
- udec_wrap: ``*ptr = ((*ptr == 0) || (*ptr u> val)) ? val : (*ptr - 1)`` (decrement with wraparound to input value when decremented below zero).
1165411658
- usub_cond: ``*ptr = (*ptr u>= val) ? *ptr - val : *ptr`` (subtract only if no unsigned overflow).

llvm/docs/ReleaseNotes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ Changes to LLVM infrastructure
7373
themselves (i.e., the `TargetIntrinsicInfo` class).
7474
* Fix Microsoft demangling of string literals to be stricter
7575
(#GH129970))
76+
* Added the support for ``fmaximum`` and ``fminimum`` in ``atomicrmw`` instruction. The
77+
comparison is expected to match the behavior of ``llvm.maximum.*`` and
78+
``llvm.minimum.*`` respectively.
7679

7780
Changes to building LLVM
7881
------------------------

llvm/include/llvm-c/Core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,12 @@ typedef enum {
393393
LLVMAtomicRMWBinOpUSubCond, /**<Subtracts the value only if no unsigned
394394
overflow */
395395
LLVMAtomicRMWBinOpUSubSat, /**<Subtracts the value, clamping to zero */
396+
LLVMAtomicRMWBinOpFMaximum, /**< Sets the value if it's greater than the
397+
original using an floating point comparison and
398+
return the old one */
399+
LLVMAtomicRMWBinOpFMinimum, /**< Sets the value if it's smaller than the
400+
original using an floating point comparison and
401+
return the old one */
396402
} LLVMAtomicRMWBinOp;
397403

398404
typedef enum {

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ enum Kind {
276276
kw_umin,
277277
kw_fmax,
278278
kw_fmin,
279+
kw_fmaximum,
280+
kw_fminimum,
279281
kw_uinc_wrap,
280282
kw_udec_wrap,
281283
kw_usub_cond,

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,9 @@ enum RMWOperations {
504504
RMW_UINC_WRAP = 15,
505505
RMW_UDEC_WRAP = 16,
506506
RMW_USUB_COND = 17,
507-
RMW_USUB_SAT = 18
507+
RMW_USUB_SAT = 18,
508+
RMW_FMAXIMUM = 19,
509+
RMW_FMINIMUM = 20,
508510
};
509511

510512
/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,42 @@ class MachineIRBuilder {
16631663
const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
16641664
MachineMemOperand &MMO);
16651665

1666+
/// Build and insert `OldValRes<def> = G_ATOMICRMW_FMAXIMUM Addr, Val, MMO`.
1667+
///
1668+
/// Atomically replace the value at \p Addr with the floating point maximum of
1669+
/// \p Val and the original value. Puts the original value from \p Addr in \p
1670+
/// OldValRes.
1671+
///
1672+
/// \pre setBasicBlock or setMI must have been called.
1673+
/// \pre \p OldValRes must be a generic virtual register.
1674+
/// \pre \p Addr must be a generic virtual register with pointer type.
1675+
/// \pre \p OldValRes, and \p Val must be generic virtual registers of the
1676+
/// same type.
1677+
///
1678+
/// \return a MachineInstrBuilder for the newly created instruction.
1679+
MachineInstrBuilder buildAtomicRMWFMaximum(const DstOp &OldValRes,
1680+
const SrcOp &Addr,
1681+
const SrcOp &Val,
1682+
MachineMemOperand &MMO);
1683+
1684+
/// Build and insert `OldValRes<def> = G_ATOMICRMW_FMINIMUM Addr, Val, MMO`.
1685+
///
1686+
/// Atomically replace the value at \p Addr with the floating point minimum of
1687+
/// \p Val and the original value. Puts the original value from \p Addr in \p
1688+
/// OldValRes.
1689+
///
1690+
/// \pre setBasicBlock or setMI must have been called.
1691+
/// \pre \p OldValRes must be a generic virtual register.
1692+
/// \pre \p Addr must be a generic virtual register with pointer type.
1693+
/// \pre \p OldValRes, and \p Val must be generic virtual registers of the
1694+
/// same type.
1695+
///
1696+
/// \return a MachineInstrBuilder for the newly created instruction.
1697+
MachineInstrBuilder buildAtomicRMWFMinimum(const DstOp &OldValRes,
1698+
const SrcOp &Addr,
1699+
const SrcOp &Val,
1700+
MachineMemOperand &MMO);
1701+
16661702
/// Build and insert `OldValRes<def> = G_ATOMICRMW_USUB_COND Addr, Val, MMO`.
16671703
///
16681704
/// Atomically replace the value at \p Addr with the original value minus \p

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,8 @@ enum NodeType {
13671367
ATOMIC_LOAD_FSUB,
13681368
ATOMIC_LOAD_FMAX,
13691369
ATOMIC_LOAD_FMIN,
1370+
ATOMIC_LOAD_FMAXIMUM,
1371+
ATOMIC_LOAD_FMINIMUM,
13701372
ATOMIC_LOAD_UINC_WRAP,
13711373
ATOMIC_LOAD_UDEC_WRAP,
13721374
ATOMIC_LOAD_USUB_COND,

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,8 @@ class MemSDNode : public SDNode {
15171517
case ISD::ATOMIC_LOAD_FSUB:
15181518
case ISD::ATOMIC_LOAD_FMAX:
15191519
case ISD::ATOMIC_LOAD_FMIN:
1520+
case ISD::ATOMIC_LOAD_FMAXIMUM:
1521+
case ISD::ATOMIC_LOAD_FMINIMUM:
15201522
case ISD::ATOMIC_LOAD_UINC_WRAP:
15211523
case ISD::ATOMIC_LOAD_UDEC_WRAP:
15221524
case ISD::ATOMIC_LOAD_USUB_COND:
@@ -1603,6 +1605,8 @@ class AtomicSDNode : public MemSDNode {
16031605
N->getOpcode() == ISD::ATOMIC_LOAD_FSUB ||
16041606
N->getOpcode() == ISD::ATOMIC_LOAD_FMAX ||
16051607
N->getOpcode() == ISD::ATOMIC_LOAD_FMIN ||
1608+
N->getOpcode() == ISD::ATOMIC_LOAD_FMAXIMUM ||
1609+
N->getOpcode() == ISD::ATOMIC_LOAD_FMINIMUM ||
16061610
N->getOpcode() == ISD::ATOMIC_LOAD_UINC_WRAP ||
16071611
N->getOpcode() == ISD::ATOMIC_LOAD_UDEC_WRAP ||
16081612
N->getOpcode() == ISD::ATOMIC_LOAD_USUB_COND ||

llvm/include/llvm/IR/Instructions.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,14 @@ class AtomicRMWInst : public Instruction {
751751
/// \p minnum matches the behavior of \p llvm.minnum.*.
752752
FMin,
753753

754+
/// *p = maximum(old, v)
755+
/// \p maximum matches the behavior of \p llvm.maximum.*.
756+
FMaximum,
757+
758+
/// *p = minimum(old, v)
759+
/// \p minimum matches the behavior of \p llvm.minimum.*.
760+
FMinimum,
761+
754762
/// Increment one up to a maximum value.
755763
/// *p = (old u>= v) ? 0 : (old + 1)
756764
UIncWrap,
@@ -812,6 +820,8 @@ class AtomicRMWInst : public Instruction {
812820
case AtomicRMWInst::FSub:
813821
case AtomicRMWInst::FMax:
814822
case AtomicRMWInst::FMin:
823+
case AtomicRMWInst::FMaximum:
824+
case AtomicRMWInst::FMinimum:
815825
return true;
816826
default:
817827
return false;

0 commit comments

Comments
 (0)