[llvm] [VectorCombine] Preserve FMF when scalarizing FP intrinsics (PR #228211)
Jinsong Ji via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 2 07:50:28 PDT 2026
https://github.com/jsji updated https://github.com/llvm/llvm-project/pull/228211
>From 9a49923e95028ee517def99d3260520bce4eecd9 Mon Sep 17 00:00:00 2001
From: Jinsong Ji <jinsong.ji at intel.com>
Date: Thu, 1 Oct 2026 19:34:56 +0200
Subject: [PATCH 1/3] [VectorCombine] Preserve FMF when scalarizing FP
intrinsics
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
992ca79c83b0 refactored scalarizeOpOrCmp to pass IR flags during
instruction creation instead of copying them afterward. All branches
(compare, unary op, binary op) were updated to pass flags, but the
intrinsic branch was missed — CreateIntrinsic was called without an
FMFSource, silently dropping fast-math flags such as afn, arcp, and
contract.
This caused downstream crashes on targets where
the legalizer for G_FPOW requires the afn flag: VectorCombine
scalarized a vector llvm.pow(afn) into scalar llvm.pow calls without
afn.
Pass the original instruction's FMF to CreateIntrinsic via FMFSource,
guarded by isa<FPMathOperator> for non-FP intrinsic safety.
Fixes #192607 (partially — the original fix missed this case).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply at anthropic.com>
---
llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 6 +++++-
.../Transforms/VectorCombine/intrinsic-scalarize.ll | 13 +++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 7a08eff6cc64d57..103b80be002fa9d 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1375,7 +1375,11 @@ bool VectorCombine::scalarizeOpOrCmp(Instruction &I) {
BO->getName() + ".scalar");
}
} else {
- Scalar = Builder.CreateIntrinsic(ScalarTy, II->getIntrinsicID(), ScalarOps);
+ FMFSource FMFS;
+ if (isa<FPMathOperator>(I))
+ FMFS = &I;
+ Scalar = Builder.CreateIntrinsic(ScalarTy, II->getIntrinsicID(), ScalarOps,
+ FMFS, II->getName() + ".scalar");
}
Value *Insert = Builder.CreateInsertElement(NewVecC, Scalar, *Index);
diff --git a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
index ec3711eabb7e14c..559f928df3bbd80 100644
--- a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
+++ b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
@@ -154,6 +154,19 @@ define <4 x float> @scalar_argument(float %x) {
ret <4 x float> %v
}
+; Verify that fast-math flags on FP intrinsics survive scalarization.
+define <4 x float> @pow_fmf_preserved(float %x) {
+; CHECK-LABEL: define <4 x float> @pow_fmf_preserved(
+; CHECK-SAME: float [[X:%.*]]) {
+; CHECK-NEXT: [[V_SCALAR:%.*]] = call arcp contract afn float @llvm.pow.f32(float [[X]], float 2.000000e+00)
+; CHECK-NEXT: [[V:%.*]] = insertelement <4 x float> splat (float 1.000000e+00), float [[V_SCALAR]], i64 0
+; CHECK-NEXT: ret <4 x float> [[V]]
+;
+ %x.insert = insertelement <4 x float> splat (float 1.0), float %x, i64 0
+ %v = call arcp contract afn <4 x float> @llvm.pow(<4 x float> %x.insert, <4 x float> splat (float 2.0))
+ ret <4 x float> %v
+}
+
define <4 x i2> @scmp(i32 %x) {
; CHECK-LABEL: define <4 x i2> @scmp(
; CHECK-SAME: i32 [[X:%.*]]) {
>From f3869f7e76da76bc70d4441f053587b7014b7f2b Mon Sep 17 00:00:00 2001
From: Jinsong Ji <jinsong.ji at intel.com>
Date: Thu, 1 Oct 2026 15:42:21 -0400
Subject: [PATCH 2/3] Apply suggestion from @arsenm
Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
index 559f928df3bbd80..59eb930acb3256a 100644
--- a/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
+++ b/llvm/test/Transforms/VectorCombine/intrinsic-scalarize.ll
@@ -163,7 +163,7 @@ define <4 x float> @pow_fmf_preserved(float %x) {
; CHECK-NEXT: ret <4 x float> [[V]]
;
%x.insert = insertelement <4 x float> splat (float 1.0), float %x, i64 0
- %v = call arcp contract afn <4 x float> @llvm.pow(<4 x float> %x.insert, <4 x float> splat (float 2.0))
+ %v = call arcp contract afn <4 x float> @llvm.pow.v4f32(<4 x float> %x.insert, <4 x float> splat (float 2.0))
ret <4 x float> %v
}
>From b5cdd971d714c52bec361d26b9750f0ba3b2e3db Mon Sep 17 00:00:00 2001
From: Jinsong Ji <jinsong.ji at intel.com>
Date: Thu, 1 Oct 2026 21:43:03 +0200
Subject: [PATCH 3/3] address comments
---
llvm/lib/Transforms/Vectorize/VectorCombine.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 103b80be002fa9d..65522c616fbe056 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1375,11 +1375,11 @@ bool VectorCombine::scalarizeOpOrCmp(Instruction &I) {
BO->getName() + ".scalar");
}
} else {
- FMFSource FMFS;
- if (isa<FPMathOperator>(I))
- FMFS = &I;
+ FastMathFlags FMF;
+ if (auto *FPMO = dyn_cast<FPMathOperator>(&I))
+ FMF = FPMO->getFastMathFlags();
Scalar = Builder.CreateIntrinsic(ScalarTy, II->getIntrinsicID(), ScalarOps,
- FMFS, II->getName() + ".scalar");
+ FMF, II->getName() + ".scalar");
}
Value *Insert = Builder.CreateInsertElement(NewVecC, Scalar, *Index);
More information about the llvm-commits
mailing list