[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