[llvm] [ConstantFolding] Fold `vector.fmax` and `vector.fmin` (PR #143904)
Nikolay Panchenko via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 12 07:13:49 PDT 2025
https://github.com/npanchen created https://github.com/llvm/llvm-project/pull/143904
The changeset adds folding of `vector.fmax` and `vector.fmin` intrinsics
by invoking `maxnum` and `minnum` respectively.
>From 14d58c2f2b5a44901b3994ba5660d1167aee7d56 Mon Sep 17 00:00:00 2001
From: Kolya Panchenko <npanchen at modular.com>
Date: Tue, 27 May 2025 15:33:30 -0400
Subject: [PATCH] [ConstantFolding] Fold `vector.fmax` and `vector.fmin`
The changeset adds folding of `vector.fmax` and `vector.fmin` intrinsics
by invoking `maxnum` and `minnum` respectively.
---
llvm/lib/Analysis/ConstantFolding.cpp | 25 +++++++++++++++++++
.../InstSimplify/ConstProp/vector-calls.ll | 16 ++++++++++++
2 files changed, 41 insertions(+)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 139a0b81e299b..788ad93627cf3 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1635,6 +1635,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::vector_reduce_smax:
case Intrinsic::vector_reduce_umin:
case Intrinsic::vector_reduce_umax:
+ case Intrinsic::vector_reduce_fmin:
+ case Intrinsic::vector_reduce_fmax:
case Intrinsic::vector_extract:
case Intrinsic::vector_insert:
case Intrinsic::vector_interleave2:
@@ -2021,6 +2023,27 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) {
if (!isa<ConstantVector>(Op) && !isa<ConstantDataVector>(Op))
return nullptr;
+ // Try to fold floating point reductions
+ if (auto *EltC = dyn_cast<ConstantFP>(Op->getAggregateElement(0U))) {
+ APFloat Res(EltC->getValueAPF());
+ for (unsigned I = 1, E = VT->getNumElements(); I != E; ++I) {
+ if (!(EltC = dyn_cast<ConstantFP>(Op->getAggregateElement(I))))
+ return nullptr;
+
+ switch (IID) {
+ case Intrinsic::vector_reduce_fmin:
+ Res = minnum(Res, EltC->getValueAPF());
+ break;
+ case Intrinsic::vector_reduce_fmax:
+ Res = maxnum(Res, EltC->getValueAPF());
+ break;
+ default:
+ return nullptr;
+ }
+ }
+ return ConstantFP::get(VT->getElementType(), Res);
+ }
+
auto *EltC = dyn_cast<ConstantInt>(Op->getAggregateElement(0U));
if (!EltC)
return nullptr;
@@ -2826,6 +2849,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
case Intrinsic::vector_reduce_smax:
case Intrinsic::vector_reduce_umin:
case Intrinsic::vector_reduce_umax:
+ case Intrinsic::vector_reduce_fmin:
+ case Intrinsic::vector_reduce_fmax:
if (Constant *C = constantFoldVectorReduce(IntrinsicID, Operands[0]))
return C;
break;
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/vector-calls.ll b/llvm/test/Transforms/InstSimplify/ConstProp/vector-calls.ll
index 9dbe3d4e50ee1..641cb77f30b82 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/vector-calls.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/vector-calls.ll
@@ -66,3 +66,19 @@ define {<vscale x 4 x i32>, <vscale x 4 x i32>} @fold_scalable_vector_deinterlea
%1 = call {<vscale x 4 x i32>, <vscale x 4 x i32>} @llvm.vector.deinterleave2.v4i32.v8i32(<vscale x 8 x i32> zeroinitializer)
ret {<vscale x 4 x i32>, <vscale x 4 x i32>} %1
}
+
+define float @fold_vector_fmin() {
+; CHECK-LABEL: define float @fold_vector_fmin() {
+; CHECK-NEXT: ret float 1.000000e+00
+;
+ %1 = call float @llvm.vector.reduce.fmin.v4f32(<4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>)
+ ret float %1
+}
+
+define float @fold_vector_fmax() {
+; CHECK-LABEL: define float @fold_vector_fmax() {
+; CHECK-NEXT: ret float 4.000000e+00
+;
+ %1 = call float @llvm.vector.reduce.fmax.v4f32(<4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>)
+ ret float %1
+}
More information about the llvm-commits
mailing list