[llvm] [DAG] Scalarise trivial splat operations (PR #226257)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 25 02:49:38 PDT 2026
https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/226257
>From fde678a56af434457f6d22bec1cf4329a362a946 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Thu, 24 Sep 2026 19:06:47 +0100
Subject: [PATCH 1/2] [DAG] Scalarise trivial splat operations
This fixes an issue reported on #224255, where a single active lane masked
store is converted to a v1f16 extract_subvector, which becomes a v1f16 splat,
which fails to scalarize. Add the necessary trivial scalarisation of the splat
by using the f16 input operand.
(I was originally going to fix this by generating a scalar f16 extract directly
(which would have the benefit of treating f16 as legal), but that seems to
cause a regression in 2 x86 tests).
---
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 3 +++
llvm/test/CodeGen/AArch64/lowmaskedlanes.ll | 11 +++++++++++
2 files changed, 14 insertions(+)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 56ad7c65b48d1..33446913ffc9b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -57,6 +57,9 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
report_fatal_error("Do not know how to scalarize the result of this "
"operator!\n");
+ case ISD::SPLAT_VECTOR:
+ R = N->getOperand(0);
+ break;
case ISD::LOOP_DEPENDENCE_WAR_MASK:
case ISD::LOOP_DEPENDENCE_RAW_MASK:
R = ScalarizeVecRes_LOOP_DEPENDENCE_MASK(N);
diff --git a/llvm/test/CodeGen/AArch64/lowmaskedlanes.ll b/llvm/test/CodeGen/AArch64/lowmaskedlanes.ll
index 1a3f88ef11b33..e8de2bdcfb98d 100644
--- a/llvm/test/CodeGen/AArch64/lowmaskedlanes.ll
+++ b/llvm/test/CodeGen/AArch64/lowmaskedlanes.ll
@@ -245,3 +245,14 @@ define void @store_low4_nxv8i16(ptr %p, <vscale x 8 x i16> %a) {
tail call void @llvm.masked.store(<vscale x 8 x i16> %a, ptr align 1 %p, <vscale x 8 x i1> %m)
ret void
}
+
+define void @store_low1_nxv8f16_splat(ptr %0) {
+; CHECK-LABEL: store_low1_nxv8f16_splat:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov h0, #1.00000000
+; CHECK-NEXT: str h0, [x0]
+; CHECK-NEXT: ret
+ %2 = tail call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i32(i32 0, i32 1)
+ tail call void @llvm.masked.store.nxv8f16.p0(<vscale x 8 x half> splat (half 0xH3C00), ptr align 2 %0, <vscale x 8 x i1> %2)
+ ret void
+}
>From 99618a5130eb879977a42e46ed0a9a9b1dac2bfe Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Fri, 25 Sep 2026 10:47:05 +0100
Subject: [PATCH 2/2] Move into ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT
---
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 2 +-
.../lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index c9583d99ddbf4..f53862738e16b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -835,7 +835,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue ScalarizeVecRes_ADDRSPACECAST(SDNode *N);
SDValue ScalarizeVecRes_BITCAST(SDNode *N);
- SDValue ScalarizeVecRes_BUILD_VECTOR(SDNode *N);
+ SDValue ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(SDNode *N);
SDValue ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N);
SDValue ScalarizeVecRes_FP_ROUND(SDNode *N);
SDValue ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 33446913ffc9b..2e6190b307013 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -57,16 +57,16 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
report_fatal_error("Do not know how to scalarize the result of this "
"operator!\n");
- case ISD::SPLAT_VECTOR:
- R = N->getOperand(0);
- break;
case ISD::LOOP_DEPENDENCE_WAR_MASK:
case ISD::LOOP_DEPENDENCE_RAW_MASK:
R = ScalarizeVecRes_LOOP_DEPENDENCE_MASK(N);
break;
case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
- case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
+ case ISD::SPLAT_VECTOR:
+ case ISD::BUILD_VECTOR:
+ R = ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(N);
+ break;
case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
case ISD::CONVERT_FROM_ARBITRARY_FP:
@@ -478,10 +478,10 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
NewVT, Op);
}
-SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
+SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR_OR_SPLAT(SDNode *N) {
EVT EltVT = N->getValueType(0).getVectorElementType();
SDValue InOp = N->getOperand(0);
- // The BUILD_VECTOR operands may be of wider element types and
+ // The BUILD_VECTOR / SPLAT operands may be of wider element types and
// we may need to truncate them back to the requested return type.
if (EltVT.isInteger())
return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
More information about the llvm-commits
mailing list