[llvm] [DAGCombiner] Fix subvector extraction index for big-endian STLF (PR #180795)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 09:31:30 PST 2026
https://github.com/Michael-Chen-NJU updated https://github.com/llvm/llvm-project/pull/180795
>From 089f4d0016da5ced2d395aa562dad067fb6aa03a Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Wed, 11 Feb 2026 01:37:11 +0800
Subject: [PATCH 1/2] [DAGCombiner] Fix subvector extraction index for
big-endian STLF
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 10 +++++++++-
llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll | 17 +++++++++++++++++
2 files changed, 26 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index b05157289892b..0f5147ccd92af 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -20831,8 +20831,16 @@ SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
if (!TLI.isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, InterVT))
break;
+ // In case of big-endian the offset is normalized to zero, denoting
+ // the last bit. For big-endian we need to transform the extraction
+ // to the last sub-vector.
+ unsigned ExtIdx = 0;
+ if (DAG.getDataLayout().isBigEndian()) {
+ ExtIdx =
+ InterVT.getVectorNumElements() - LDMemType.getVectorNumElements();
+ }
Val = DAG.getExtractSubvector(SDLoc(LD), LDMemType,
- DAG.getBitcast(InterVT, Val), 0);
+ DAG.getBitcast(InterVT, Val), ExtIdx);
} else if (!STMemType.isVector() && !LDMemType.isVector() &&
STMemType.isInteger() && LDMemType.isInteger())
Val = DAG.getNode(ISD::TRUNCATE, SDLoc(LD), LDMemType, Val);
diff --git a/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll b/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
new file mode 100644
index 0000000000000..75de1ae3ac6d4
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=armeb-eabi -mattr=+v7,+neon | FileCheck %s
+
+define <2 x i32> @test_offset_load(ptr %p, <4 x i32> %v) {
+; CHECK-LABEL: test_offset_load:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: vldr d17, [sp]
+; CHECK-NEXT: vmov r1, r12, d17
+; CHECK-NEXT: vmov d16, r3, r2
+; CHECK-NEXT: vst1.64 {d16, d17}, [r0:128]
+; CHECK-NEXT: mov r0, r12
+; CHECK-NEXT: bx lr
+ store <4 x i32> %v, ptr %p, align 16
+ %p2 = getelementptr i8, ptr %p, i64 8
+ %res = load <2 x i32>, ptr %p2, align 8
+ ret <2 x i32> %res
+}
>From 7cd5df83d43617f3aa0c4c3c2f91601f9d82357f Mon Sep 17 00:00:00 2001
From: Michael-Chen-NJU <2802328816 at qq.com>
Date: Thu, 12 Feb 2026 01:24:05 +0800
Subject: [PATCH 2/2] [DAGCombiner] Improve subvector extraction handling for
big-endian STLF
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 13 ++++++-
.../CodeGen/ARM/stlf-vector-extract-be.ll | 17 ---------
llvm/test/CodeGen/ARM/stlf-vector-extract.ll | 36 +++++++++++++++++++
.../avx512-shuffles/shuffle-chained-bf16.ll | 5 ++-
4 files changed, 52 insertions(+), 19 deletions(-)
delete mode 100644 llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
create mode 100644 llvm/test/CodeGen/ARM/stlf-vector-extract.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 0f5147ccd92af..2698d3e7c126b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -20828,7 +20828,15 @@ SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
EVT InterVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
StMemSize.divideCoefficientBy(EltSize));
- if (!TLI.isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, InterVT))
+ if (!TLI.isOperationLegalOrCustom(ISD::EXTRACT_SUBVECTOR, LDMemType))
+ break;
+
+ // Avoid infinite loop: Don't transform loads from fixed stack objects,
+ // as legalization expands extract_subvector to such loads.
+ SDValue LDBase = LD->getBasePtr();
+ if (LDBase.getOpcode() == ISD::ADD)
+ LDBase = LDBase.getOperand(0);
+ if (LDBase.getOpcode() == ISD::FrameIndex)
break;
// In case of big-endian the offset is normalized to zero, denoting
@@ -20839,6 +20847,9 @@ SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
ExtIdx =
InterVT.getVectorNumElements() - LDMemType.getVectorNumElements();
}
+
+ if (!TLI.isExtractSubvectorCheap(LDMemType, InterVT, ExtIdx))
+ break;
Val = DAG.getExtractSubvector(SDLoc(LD), LDMemType,
DAG.getBitcast(InterVT, Val), ExtIdx);
} else if (!STMemType.isVector() && !LDMemType.isVector() &&
diff --git a/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll b/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
deleted file mode 100644
index 75de1ae3ac6d4..0000000000000
--- a/llvm/test/CodeGen/ARM/stlf-vector-extract-be.ll
+++ /dev/null
@@ -1,17 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=armeb-eabi -mattr=+v7,+neon | FileCheck %s
-
-define <2 x i32> @test_offset_load(ptr %p, <4 x i32> %v) {
-; CHECK-LABEL: test_offset_load:
-; CHECK: @ %bb.0:
-; CHECK-NEXT: vldr d17, [sp]
-; CHECK-NEXT: vmov r1, r12, d17
-; CHECK-NEXT: vmov d16, r3, r2
-; CHECK-NEXT: vst1.64 {d16, d17}, [r0:128]
-; CHECK-NEXT: mov r0, r12
-; CHECK-NEXT: bx lr
- store <4 x i32> %v, ptr %p, align 16
- %p2 = getelementptr i8, ptr %p, i64 8
- %res = load <2 x i32>, ptr %p2, align 8
- ret <2 x i32> %res
-}
diff --git a/llvm/test/CodeGen/ARM/stlf-vector-extract.ll b/llvm/test/CodeGen/ARM/stlf-vector-extract.ll
new file mode 100644
index 0000000000000..b0bc99009d83d
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/stlf-vector-extract.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=armeb-eabi -mattr=+v7,+neon | FileCheck %s --check-prefix=BE
+; RUN: llc < %s -mtriple=arm-eabi -mattr=+v7,+neon | FileCheck %s --check-prefix=LE
+
+define <2 x i32> @test_offset_load(ptr %p, <4 x i32> %v) {
+; CHECK-LABEL: test_offset_load:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: vldr d17, [sp]
+; CHECK-NEXT: vmov r1, r12, d17
+; CHECK-NEXT: vmov d16, r3, r2
+; CHECK-NEXT: vst1.64 {d16, d17}, [r0:128]
+; CHECK-NEXT: mov r0, r12
+; CHECK-NEXT: bx lr
+; BE-LABEL: test_offset_load:
+; BE: @ %bb.0:
+; BE-NEXT: vldr d17, [sp]
+; BE-NEXT: vmov r1, r12, d17
+; BE-NEXT: vmov d16, r3, r2
+; BE-NEXT: vst1.64 {d16, d17}, [r0:128]
+; BE-NEXT: mov r0, r12
+; BE-NEXT: bx lr
+;
+; LE-LABEL: test_offset_load:
+; LE: @ %bb.0:
+; LE-NEXT: vldr d17, [sp]
+; LE-NEXT: mov r1, #8
+; LE-NEXT: vmov d16, r2, r3
+; LE-NEXT: vst1.32 {d16, d17}, [r0:128], r1
+; LE-NEXT: vldr d16, [r0]
+; LE-NEXT: vmov r0, r1, d16
+; LE-NEXT: bx lr
+ store <4 x i32> %v, ptr %p, align 16
+ %p2 = getelementptr i8, ptr %p, i64 8
+ %res = load <2 x i32>, ptr %p2, align 8
+ ret <2 x i32> %res
+}
diff --git a/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll b/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll
index c7200850af699..12ce721b8c5d5 100644
--- a/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll
+++ b/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll
@@ -37,8 +37,11 @@ define <2 x bfloat> @shuffle_chained_v16bf16(<16 x bfloat> %a) {
; CHECK-NEXT: .cfi_def_cfa_register %rbp
; CHECK-NEXT: andq $-32, %rsp
; CHECK-NEXT: subq $96, %rsp
-; CHECK-NEXT: vmovdqa %ymm0, (%rsp)
+; CHECK-NEXT: vmovaps %ymm0, (%rsp)
+; CHECK-NEXT: vmovdqa (%rsp), %xmm0
; CHECK-NEXT: vpunpcklwd {{.*#+}} xmm0 = xmm0[0],mem[0],xmm0[1],mem[1],xmm0[2],mem[2],xmm0[3],mem[3]
+; CHECK-NEXT: vmovdqa %ymm0, {{[0-9]+}}(%rsp)
+; CHECK-NEXT: vmovaps {{[0-9]+}}(%rsp), %xmm0
; CHECK-NEXT: movq %rbp, %rsp
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: .cfi_def_cfa %rsp, 8
More information about the llvm-commits
mailing list