[llvm] 6117bdd - [DAGCombiner] Fix subvector extraction index for big-endian STLF (#180795)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 12 01:42:18 PST 2026


Author: 陈子昂
Date: 2026-02-12T17:42:13+08:00
New Revision: 6117bdd90324af22a920d56d673acff21342a1cb

URL: https://github.com/llvm/llvm-project/commit/6117bdd90324af22a920d56d673acff21342a1cb
DIFF: https://github.com/llvm/llvm-project/commit/6117bdd90324af22a920d56d673acff21342a1cb.diff

LOG: [DAGCombiner] Fix subvector extraction index for big-endian STLF (#180795)

This PR fixes a big-endian regression in `ForwardStoreValueToDirectLoad`
where the wrong subvector was being extracted. In big-endian, memory
offset 0 corresponds to the high bits, so the extraction index needs to
be adjusted.

As suggested by @KennethHilmersson, calculate the extraction index as
the difference between the number of elements in the intermediate vector
and the load vector when in big-endian mode.

Special thanks to Kenneth Hilmersson for providing the fix logic and the
ARM regression test.
https://github.com/llvm/llvm-project/pull/172523#issuecomment-3878065191
https://github.com/llvm/llvm-project/pull/172523#issuecomment-3879575092

Added: 
    llvm/test/CodeGen/ARM/stlf-vector-extract.ll

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index d61999f2ee0a2..65675036d1305 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -20831,11 +20831,22 @@ 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;
 
+        // 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();
+        }
+
+        if (!TLI.isExtractSubvectorCheap(LDMemType, InterVT, ExtIdx))
+          break;
         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.ll b/llvm/test/CodeGen/ARM/stlf-vector-extract.ll
new file mode 100644
index 0000000000000..8734d6f432e90
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/stlf-vector-extract.ll
@@ -0,0 +1,28 @@
+; 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) {
+; 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..f646f609d7e70 100644
--- a/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll
+++ b/llvm/test/CodeGen/X86/avx512-shuffles/shuffle-chained-bf16.ll
@@ -15,8 +15,7 @@ define <2 x bfloat> @shuffle_chained_v32bf16_v2bf16(<32 x bfloat> %a) {
 ; CHECK-NEXT:    subq $128, %rsp
 ; CHECK-NEXT:    vmovd {{.*#+}} xmm1 = [0,16,0,0,0,0,0,0]
 ; CHECK-NEXT:    vpermw %zmm0, %zmm1, %zmm0
-; CHECK-NEXT:    vmovdqa64 %zmm0, (%rsp)
-; CHECK-NEXT:    vmovaps (%rsp), %xmm0
+; CHECK-NEXT:    # kill: def $xmm0 killed $xmm0 killed $zmm0
 ; CHECK-NEXT:    movq %rbp, %rsp
 ; CHECK-NEXT:    popq %rbp
 ; CHECK-NEXT:    .cfi_def_cfa %rsp, 8


        


More information about the llvm-commits mailing list