[llvm] [IR] Introduce reduce.fminimumnum and reduce.fmaximumnum intrinsics (PR #196062)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 06:45:51 PDT 2026
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/196062
>From 71ec76999f26e44df99e8d75dc302b12cc65dbb4 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 6 May 2026 14:53:11 +0200
Subject: [PATCH] [IR] Introduce reduce.fminimumnum and reduce.fmaximumnum
intrinsics
These are the same as the other FP min/max reductions, but using
minimumnum/maximumnum as the underlying reduction operation.
TODO: Tests.
---
llvm/docs/LangRef.rst | 56 +++++++++++++++++++
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 2 +
llvm/include/llvm/CodeGen/ISDOpcodes.h | 3 +
llvm/include/llvm/IR/Intrinsics.td | 6 ++
.../include/llvm/Target/TargetSelectionDAG.td | 4 ++
llvm/lib/Analysis/ValueTracking.cpp | 4 +-
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 5 +-
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 10 +++-
.../SelectionDAG/LegalizeFloatTypes.cpp | 8 ++-
.../SelectionDAG/LegalizeVectorOps.cpp | 6 ++
.../SelectionDAG/LegalizeVectorTypes.cpp | 6 ++
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 4 ++
.../SelectionDAG/SelectionDAGBuilder.cpp | 8 +++
.../SelectionDAG/SelectionDAGDumper.cpp | 2 +
llvm/lib/CodeGen/TargetLoweringBase.cpp | 1 +
llvm/lib/Transforms/Utils/LoopUtils.cpp | 12 +++-
.../minimumnum-maximumnum-reductions.ll | 8 +--
17 files changed, 134 insertions(+), 11 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 5640eec987133..491bd12b1ef9e 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -21471,6 +21471,62 @@ Arguments:
""""""""""
The argument to this intrinsic must be a vector of floating-point values.
+.. _int_vector_reduce_fmaximumnum:
+
+'``llvm.vector.reduce.fmaximumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+This is an overloaded intrinsic.
+
+::
+
+ declare float @llvm.vector.reduce.fmaximumnum.v4f32(<4 x float> %a)
+ declare double @llvm.vector.reduce.fmaximumnum.v2f64(<2 x double> %a)
+
+Overview:
+"""""""""
+
+The '``llvm.vector.reduce.fmaximumnum.*``' intrinsics do a floating-point
+``MAX`` reduction of a vector, returning the result as a scalar. The return type
+matches the element-type of the vector input.
+
+This instruction has the same comparison and ``nsz`` semantics as the
+'``llvm.maximumnum.*``' intrinsic.
+
+Arguments:
+""""""""""
+The argument to this intrinsic must be a vector of floating-point values.
+
+.. _int_vector_reduce_fminimumnum:
+
+'``llvm.vector.reduce.fminimumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+This is an overloaded intrinsic.
+
+::
+
+ declare float @llvm.vector.reduce.fminimumnum.v4f32(<4 x float> %a)
+ declare double @llvm.vector.reduce.fminimumnum.v2f64(<2 x double> %a)
+
+Overview:
+"""""""""
+
+The '``llvm.vector.reduce.fminimumnum.*``' intrinsics do a floating-point
+``MIN`` reduction of a vector, returning the result as a scalar. The return type
+matches the element-type of the vector input.
+
+This instruction has the same comparison and ``nsz`` semantics as the
+'``llvm.minimumnum.*``' intrinsic.
+
+Arguments:
+""""""""""
+The argument to this intrinsic must be a vector of floating-point values.
+
Vector Partial Reduction Intrinsics
-----------------------------------
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 55163eb1976bf..232120ac0883d 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -2074,6 +2074,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::vector_reduce_fmin:
case Intrinsic::vector_reduce_fmaximum:
case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fmaximumnum:
+ case Intrinsic::vector_reduce_fminimumnum:
case Intrinsic::vector_reduce_umax:
case Intrinsic::vector_reduce_umin: {
IntrinsicCostAttributes Attrs(IID, RetTy, Args[0]->getType(), FMF, I, 1);
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 224855e02f21d..8bd2d0cb82778 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1526,6 +1526,9 @@ enum NodeType {
/// llvm.minimum and llvm.maximum semantics.
VECREDUCE_FMAXIMUM,
VECREDUCE_FMINIMUM,
+ /// Reduction using FMINIMUMNUM/FMAXIMUMNUM.
+ VECREDUCE_FMAXIMUMNUM,
+ VECREDUCE_FMINIMUMNUM,
/// Integer reductions may have a result type larger than the vector element
/// type. However, the reduction is performed using the vector element type
/// and the value in the top bits is unspecified.
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 007882c492b4c..3ee8ba0d334a5 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -2916,6 +2916,12 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]
def int_vector_reduce_fmaximum: DefaultAttrsIntrinsic<
[LLVMVectorElementType<0>],
[llvm_any_vector_float_ty]>;
+ def int_vector_reduce_fminimumnum : DefaultAttrsIntrinsic<
+ [LLVMVectorElementType<0>],
+ [llvm_any_vector_float_ty]>;
+ def int_vector_reduce_fmaximumnum : DefaultAttrsIntrinsic<
+ [LLVMVectorElementType<0>],
+ [llvm_any_vector_float_ty]>;
}
//===------ Matrix intrinsics ---------------------------------------------===//
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 5b9c95d5659e2..816168c03bb0f 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -563,6 +563,10 @@ def vecreduce_fmin : SDNode<"ISD::VECREDUCE_FMIN", SDTFPVecReduce>;
def vecreduce_fmax : SDNode<"ISD::VECREDUCE_FMAX", SDTFPVecReduce>;
def vecreduce_fminimum : SDNode<"ISD::VECREDUCE_FMINIMUM", SDTFPVecReduce>;
def vecreduce_fmaximum : SDNode<"ISD::VECREDUCE_FMAXIMUM", SDTFPVecReduce>;
+def vecreduce_fminimumnum : SDNode<"ISD::VECREDUCE_FMINIMUMNUM",
+ SDTFPVecReduce>;
+def vecreduce_fmaximumnum : SDNode<"ISD::VECREDUCE_FMAXIMUMNUM",
+ SDTFPVecReduce>;
def partial_reduce_umla : SDNode<"ISD::PARTIAL_REDUCE_UMLA",
SDTPartialReduceMLA>;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5cbf9f628867f..7909adf1d1672 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5381,7 +5381,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
case Intrinsic::vector_reduce_fmax:
case Intrinsic::vector_reduce_fmin:
case Intrinsic::vector_reduce_fmaximum:
- case Intrinsic::vector_reduce_fminimum: {
+ case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fmaximumnum:
+ case Intrinsic::vector_reduce_fminimumnum: {
// reduce min/max will choose an element from one of the vector elements,
// so we can infer and class information that is common to all elements.
Known = computeKnownFPClass(II->getArgOperand(0), II->getFastMathFlags(),
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e04e9578a3232..8cfbac82219c7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2108,7 +2108,9 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
- case ISD::VECREDUCE_FMINIMUM: return visitVECREDUCE(N);
+ case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM: return visitVECREDUCE(N);
#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
#include "llvm/IR/VPIntrinsics.def"
return visitVPOp(N);
@@ -20601,6 +20603,7 @@ SDValue DAGCombiner::visitFMinMax(SDNode *N) {
}
// There are no VECREDUCE variants of FMINIMUMNUM or FMAXIMUMNUM
+ // FIXME: There are now.
if (Opc == ISD::FMINIMUMNUM || Opc == ISD::FMAXIMUMNUM)
return SDValue();
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 65b8212755e6e..c8f7725dfed8e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1254,6 +1254,8 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
case ISD::IS_FPCLASS:
Action = TLI.getOperationAction(
Node->getOpcode(), Node->getOperand(0).getValueType());
@@ -4642,6 +4644,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
Results.push_back(TLI.expandVecReduce(Node, DAG));
break;
case ISD::VP_CTTZ_ELTS:
@@ -5503,7 +5507,9 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
Node->getOpcode() == ISD::VECREDUCE_FMAX ||
Node->getOpcode() == ISD::VECREDUCE_FMIN ||
Node->getOpcode() == ISD::VECREDUCE_FMAXIMUM ||
- Node->getOpcode() == ISD::VECREDUCE_FMINIMUM) {
+ Node->getOpcode() == ISD::VECREDUCE_FMINIMUM ||
+ Node->getOpcode() == ISD::VECREDUCE_FMAXIMUMNUM ||
+ Node->getOpcode() == ISD::VECREDUCE_FMINIMUMNUM) {
OVT = Node->getOperand(0).getSimpleValueType();
}
if (Node->getOpcode() == ISD::ATOMIC_STORE ||
@@ -6308,6 +6314,8 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
case ISD::VP_REDUCE_FMAX:
case ISD::VP_REDUCE_FMIN:
case ISD::VP_REDUCE_FMAXIMUM:
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 25cc420c42482..4af35075adc0e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -176,7 +176,11 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMAXIMUM:
- case ISD::VECREDUCE_FMINIMUM: R = SoftenFloatRes_VECREDUCE(N); break;
+ case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
+ R = SoftenFloatRes_VECREDUCE(N);
+ break;
case ISD::VECREDUCE_SEQ_FADD:
case ISD::VECREDUCE_SEQ_FMUL: R = SoftenFloatRes_VECREDUCE_SEQ(N); break;
// clang-format on
@@ -2780,6 +2784,8 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
R = SoftPromoteHalfRes_VECREDUCE(N);
break;
case ISD::VECREDUCE_SEQ_FADD:
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index f4cb60736ef7a..19da4341a3d7f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -522,8 +522,10 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
case ISD::VECREDUCE_FADD:
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMAXIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
case ISD::VECREDUCE_FMUL:
case ISD::CTTZ_ELTS:
case ISD::CTTZ_ELTS_ZERO_POISON:
@@ -790,8 +792,10 @@ void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
return;
case ISD::VECREDUCE_FMAX:
case ISD::VECREDUCE_FMAXIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
PromoteFloatVECREDUCE(Node, Results, /*NonArithmetic=*/true);
return;
case ISD::VECTOR_COMPRESS:
@@ -1317,6 +1321,8 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
Results.push_back(TLI.expandVecReduce(Node, DAG));
return;
case ISD::PARTIAL_REDUCE_UMLA:
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 97aa765642ea7..f9c8e7469bc1b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -962,6 +962,8 @@ bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
Res = ScalarizeVecOp_VECREDUCE(N);
break;
case ISD::VECREDUCE_SEQ_FADD:
@@ -3942,6 +3944,8 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
Res = SplitVecOp_VECREDUCE(N, OpNo);
break;
case ISD::VECREDUCE_SEQ_FADD:
@@ -7716,6 +7720,8 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VECREDUCE_FMIN:
case ISD::VECREDUCE_FMAXIMUM:
case ISD::VECREDUCE_FMINIMUM:
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ case ISD::VECREDUCE_FMINIMUMNUM:
Res = WidenVecOp_VECREDUCE(N);
break;
case ISD::VECREDUCE_SEQ_FADD:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c542f8e7cc20b..34fa9ce904d55 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -502,6 +502,10 @@ ISD::NodeType ISD::getVecReduceBaseOpcode(unsigned VecReduceOpcode) {
case ISD::VECREDUCE_FMINIMUM:
case ISD::VP_REDUCE_FMINIMUM:
return ISD::FMINIMUM;
+ case ISD::VECREDUCE_FMAXIMUMNUM:
+ return ISD::FMAXIMUMNUM;
+ case ISD::VECREDUCE_FMINIMUMNUM:
+ return ISD::FMINIMUMNUM;
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f5a4e891ce133..453084143d203 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8159,6 +8159,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::vector_reduce_fmin:
case Intrinsic::vector_reduce_fmaximum:
case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fmaximumnum:
+ case Intrinsic::vector_reduce_fminimumnum:
visitVectorReduce(I, Intrinsic);
return;
@@ -11364,6 +11366,12 @@ void SelectionDAGBuilder::visitVectorReduce(const CallInst &I,
case Intrinsic::vector_reduce_fminimum:
Res = DAG.getNode(ISD::VECREDUCE_FMINIMUM, dl, VT, Op1, SDFlags);
break;
+ case Intrinsic::vector_reduce_fmaximumnum:
+ Res = DAG.getNode(ISD::VECREDUCE_FMAXIMUMNUM, dl, VT, Op1, SDFlags);
+ break;
+ case Intrinsic::vector_reduce_fminimumnum:
+ Res = DAG.getNode(ISD::VECREDUCE_FMINIMUMNUM, dl, VT, Op1, SDFlags);
+ break;
default:
llvm_unreachable("Unhandled vector reduce intrinsic");
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index a00d7555f15f6..ce3cee52c9588 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -585,6 +585,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::VECREDUCE_FMIN: return "vecreduce_fmin";
case ISD::VECREDUCE_FMAXIMUM: return "vecreduce_fmaximum";
case ISD::VECREDUCE_FMINIMUM: return "vecreduce_fminimum";
+ case ISD::VECREDUCE_FMAXIMUMNUM: return "vecreduce_fmaximumnum";
+ case ISD::VECREDUCE_FMINIMUMNUM: return "vecreduce_fminimumnum";
case ISD::STACKMAP:
return "stackmap";
case ISD::PATCHPOINT:
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 3330f43c38178..26a8ea8e8f1b6 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1238,6 +1238,7 @@ void TargetLoweringBase::initActions() {
ISD::VECREDUCE_XOR, ISD::VECREDUCE_SMAX, ISD::VECREDUCE_SMIN,
ISD::VECREDUCE_UMAX, ISD::VECREDUCE_UMIN, ISD::VECREDUCE_FMAX,
ISD::VECREDUCE_FMIN, ISD::VECREDUCE_FMAXIMUM, ISD::VECREDUCE_FMINIMUM,
+ ISD::VECREDUCE_FMAXIMUMNUM, ISD::VECREDUCE_FMINIMUMNUM,
ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_SEQ_FMUL},
VT, Expand);
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 39032f710eadb..8ede48e39e1a8 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -1135,9 +1135,9 @@ constexpr Intrinsic::ID llvm::getReductionIntrinsicID(RecurKind RK) {
case RecurKind::FMinimum:
return Intrinsic::vector_reduce_fminimum;
case RecurKind::FMaximumNum:
- return Intrinsic::vector_reduce_fmax;
+ return Intrinsic::vector_reduce_fmaximumnum;
case RecurKind::FMinimumNum:
- return Intrinsic::vector_reduce_fmin;
+ return Intrinsic::vector_reduce_fminimumnum;
}
}
@@ -1229,6 +1229,10 @@ Intrinsic::ID llvm::getMinMaxReductionIntrinsicOp(Intrinsic::ID RdxID) {
return Intrinsic::minimum;
case Intrinsic::vector_reduce_fmaximum:
return Intrinsic::maximum;
+ case Intrinsic::vector_reduce_fminimumnum:
+ return Intrinsic::minimumnum;
+ case Intrinsic::vector_reduce_fmaximumnum:
+ return Intrinsic::maximumnum;
}
}
@@ -1524,10 +1528,12 @@ Value *llvm::getReductionIdentity(Intrinsic::ID RdxID, Type *Ty,
}
case Intrinsic::vector_reduce_fmax:
case Intrinsic::vector_reduce_fmaximum:
+ case Intrinsic::vector_reduce_fmaximumnum:
Negative = true;
[[fallthrough]];
case Intrinsic::vector_reduce_fmin:
- case Intrinsic::vector_reduce_fminimum: {
+ case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fminimumnum: {
bool PropagatesNaN = RdxID == Intrinsic::vector_reduce_fminimum ||
RdxID == Intrinsic::vector_reduce_fmaximum;
const fltSemantics &Semantics = Ty->getFltSemantics();
diff --git a/llvm/test/Transforms/LoopVectorize/minimumnum-maximumnum-reductions.ll b/llvm/test/Transforms/LoopVectorize/minimumnum-maximumnum-reductions.ll
index 0d4a8a9991912..2757dbb0d2219 100644
--- a/llvm/test/Transforms/LoopVectorize/minimumnum-maximumnum-reductions.ll
+++ b/llvm/test/Transforms/LoopVectorize/minimumnum-maximumnum-reductions.ll
@@ -24,7 +24,7 @@ define float @maximumnum_intrinsic(ptr readonly %x) {
; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[RDX_MINMAX:%.*]] = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> [[TMP3]], <2 x float> [[TMP4]])
-; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.vector.reduce.fmax.v2f32(<2 x float> [[RDX_MINMAX]])
+; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.vector.reduce.fmaximumnum.v2f32(<2 x float> [[RDX_MINMAX]])
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret float [[TMP6]]
@@ -68,7 +68,7 @@ define float @maximumnum_intrinsic_fast(ptr readonly %x) {
; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[RDX_MINMAX:%.*]] = call fast <2 x float> @llvm.maximumnum.v2f32(<2 x float> [[TMP3]], <2 x float> [[TMP4]])
-; CHECK-NEXT: [[TMP6:%.*]] = call fast float @llvm.vector.reduce.fmax.v2f32(<2 x float> [[RDX_MINMAX]])
+; CHECK-NEXT: [[TMP6:%.*]] = call fast float @llvm.vector.reduce.fmaximumnum.v2f32(<2 x float> [[RDX_MINMAX]])
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret float [[TMP6]]
@@ -112,7 +112,7 @@ define float @minimumnum_intrinsic(ptr readonly %x) {
; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[RDX_MINMAX:%.*]] = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> [[TMP3]], <2 x float> [[TMP4]])
-; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.vector.reduce.fmin.v2f32(<2 x float> [[RDX_MINMAX]])
+; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.vector.reduce.fminimumnum.v2f32(<2 x float> [[RDX_MINMAX]])
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret float [[TMP6]]
@@ -156,7 +156,7 @@ define float @minimumnum_intrinsic_fast(ptr readonly %x) {
; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
; CHECK: [[MIDDLE_BLOCK]]:
; CHECK-NEXT: [[RDX_MINMAX:%.*]] = call fast <2 x float> @llvm.minimumnum.v2f32(<2 x float> [[TMP3]], <2 x float> [[TMP4]])
-; CHECK-NEXT: [[TMP6:%.*]] = call fast float @llvm.vector.reduce.fmin.v2f32(<2 x float> [[RDX_MINMAX]])
+; CHECK-NEXT: [[TMP6:%.*]] = call fast float @llvm.vector.reduce.fminimumnum.v2f32(<2 x float> [[RDX_MINMAX]])
; CHECK-NEXT: br label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret float [[TMP6]]
More information about the llvm-commits
mailing list