[llvm] [SPARC] Don't combine misaligned memory ops with BSWAP (PR #206345)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 5 03:53:58 PDT 2026


https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/206345

>From 5461d123107b0193a591af1a8987b70ff32a292f Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sun, 28 Jun 2026 15:28:58 +0700
Subject: [PATCH 1/4] [SPARC] Don't combine misaligned memory ops with BSWAP

Doing it will result in a misaligned LD*A/ST*A instruction, which will raise a
bus error.

This should fix the failure in `clamscan` test.
---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp |  19 +-
 llvm/test/CodeGen/SPARC/bswap.ll            | 405 ++++++++++++++++++++
 2 files changed, 420 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index bd1ca913a258e..0d201ec97e676 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3266,9 +3266,14 @@ SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
   EVT VT = N->getValueType(0);
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
 
-  // Turn BSWAP (LOAD) -> ld*a #ASI_P(_L) on V9.
-  if (Subtarget->isV9() && ISD::isNormalLoad(Op.getNode()) &&
-      Op.getNode()->hasOneUse() &&
+  LoadSDNode *LN = dyn_cast<LoadSDNode>(Op.getNode());
+  bool IsAlignedLoad =
+      LN && ISD::isNormalLoad(Op.getNode()) &&
+      allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(), VT,
+                                     *LN->getMemOperand());
+
+  // Turn BSWAP (aligned-LOAD) -> ld*a #ASI_P(_L) on V9.
+  if (Subtarget->isV9() && IsAlignedLoad && Op.getNode()->hasOneUse() &&
       (VT == MVT::i16 || VT == MVT::i32 ||
        (Subtarget->is64Bit() && VT == MVT::i64))) {
     SDValue Load = Op;
@@ -3302,8 +3307,14 @@ SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
   unsigned Opcode = Op.getOpcode();
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
 
-  // Turn STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
+  StoreSDNode *SN = dyn_cast<StoreSDNode>(N);
+  bool IsAlignedStore = SN && allowsMemoryAccessForAlignment(
+                                  *DAG.getContext(), DAG.getDataLayout(), VT,
+                                  *SN->getMemOperand());
+
+  // Turn aligned-STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && Opcode == ISD::BSWAP && Op.getNode()->hasOneUse() &&
+      IsAlignedStore &&
       (VT == MVT::i16 || VT == MVT::i32 ||
        (Subtarget->is64Bit() && VT == MVT::i64))) {
 
diff --git a/llvm/test/CodeGen/SPARC/bswap.ll b/llvm/test/CodeGen/SPARC/bswap.ll
index b182862561752..e63efcec77101 100644
--- a/llvm/test/CodeGen/SPARC/bswap.ll
+++ b/llvm/test/CodeGen/SPARC/bswap.ll
@@ -186,6 +186,223 @@ define i64 @u64_bswapload(ptr %0) #0 {
   ret i64 %3
 }
 
+define i16 @u16_bswapload_misaligned(ptr %0) #0 {
+; SPARC32-LABEL: u16_bswapload_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -96, %sp
+; SPARC32-NEXT:    ldub [%o0], %o1
+; SPARC32-NEXT:    ldub [%o0+1], %o0
+; SPARC32-NEXT:    sll %o1, 8, %o1
+; SPARC32-NEXT:    or %o1, %o0, %o0
+; SPARC32-NEXT:    add %sp, 92, %o1
+; SPARC32-NEXT:    sta %o0, [%o1] #ASI_P_L
+; SPARC32-NEXT:    lduh [%sp+92], %o0
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 96, %sp
+;
+; SPARCEL-LABEL: u16_bswapload_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -96, %sp
+; SPARCEL-NEXT:    ldub [%o0+1], %o1
+; SPARCEL-NEXT:    ldub [%o0], %o0
+; SPARCEL-NEXT:    sll %o1, 8, %o1
+; SPARCEL-NEXT:    or %o1, %o0, %o0
+; SPARCEL-NEXT:    add %sp, 92, %o1
+; SPARCEL-NEXT:    sta %o0, [%o1] #ASI_P
+; SPARCEL-NEXT:    or %o1, 2, %o0
+; SPARCEL-NEXT:    lduh [%o0], %o0
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 96, %sp
+;
+; SPARC64-LABEL: u16_bswapload_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    ldub [%o0], %o1
+; SPARC64-NEXT:    ldub [%o0+1], %o0
+; SPARC64-NEXT:    sll %o1, 8, %o1
+; SPARC64-NEXT:    or %o1, %o0, %o0
+; SPARC64-NEXT:    add %sp, 2187, %o1
+; SPARC64-NEXT:    sta %o0, [%o1] #ASI_P_L
+; SPARC64-NEXT:    lduh [%sp+2187], %o0
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %2 = load i16, ptr %0, align 1
+  %3 = tail call i16 @llvm.bswap.i16(i16 %2)
+  ret i16 %3
+}
+
+define i32 @u32_bswapload_misaligned(ptr %0) #0 {
+; SPARC32-LABEL: u32_bswapload_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -96, %sp
+; SPARC32-NEXT:    ldub [%o0+2], %o1
+; SPARC32-NEXT:    ldub [%o0+3], %o2
+; SPARC32-NEXT:    ldub [%o0+1], %o3
+; SPARC32-NEXT:    ldub [%o0], %o0
+; SPARC32-NEXT:    sll %o1, 8, %o1
+; SPARC32-NEXT:    or %o1, %o2, %o1
+; SPARC32-NEXT:    sll %o3, 16, %o2
+; SPARC32-NEXT:    sll %o0, 24, %o0
+; SPARC32-NEXT:    or %o0, %o2, %o0
+; SPARC32-NEXT:    or %o0, %o1, %o0
+; SPARC32-NEXT:    add %sp, 92, %o1
+; SPARC32-NEXT:    sta %o0, [%o1] #ASI_P_L
+; SPARC32-NEXT:    ld [%sp+92], %o0
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 96, %sp
+;
+; SPARCEL-LABEL: u32_bswapload_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -96, %sp
+; SPARCEL-NEXT:    ldub [%o0+1], %o1
+; SPARCEL-NEXT:    ldub [%o0], %o2
+; SPARCEL-NEXT:    ldub [%o0+2], %o3
+; SPARCEL-NEXT:    ldub [%o0+3], %o0
+; SPARCEL-NEXT:    sll %o1, 8, %o1
+; SPARCEL-NEXT:    or %o1, %o2, %o1
+; SPARCEL-NEXT:    sll %o3, 16, %o2
+; SPARCEL-NEXT:    sll %o0, 24, %o0
+; SPARCEL-NEXT:    or %o0, %o2, %o0
+; SPARCEL-NEXT:    or %o0, %o1, %o0
+; SPARCEL-NEXT:    add %sp, 92, %o1
+; SPARCEL-NEXT:    sta %o0, [%o1] #ASI_P
+; SPARCEL-NEXT:    ld [%sp+92], %o0
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 96, %sp
+;
+; SPARC64-LABEL: u32_bswapload_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    ldub [%o0+2], %o1
+; SPARC64-NEXT:    ldub [%o0+3], %o2
+; SPARC64-NEXT:    ldub [%o0+1], %o3
+; SPARC64-NEXT:    ldub [%o0], %o0
+; SPARC64-NEXT:    sll %o1, 8, %o1
+; SPARC64-NEXT:    or %o1, %o2, %o1
+; SPARC64-NEXT:    sll %o3, 16, %o2
+; SPARC64-NEXT:    sll %o0, 24, %o0
+; SPARC64-NEXT:    or %o0, %o2, %o0
+; SPARC64-NEXT:    or %o0, %o1, %o0
+; SPARC64-NEXT:    add %sp, 2187, %o1
+; SPARC64-NEXT:    sta %o0, [%o1] #ASI_P_L
+; SPARC64-NEXT:    ld [%sp+2187], %o0
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %2 = load i32, ptr %0, align 1
+  %3 = tail call i32 @llvm.bswap.i32(i32 %2)
+  ret i32 %3
+}
+
+define i64 @u64_bswapload_misaligned(ptr %0) #0 {
+; SPARC32-LABEL: u64_bswapload_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -112, %sp
+; SPARC32-NEXT:    ldub [%o0+6], %o1
+; SPARC32-NEXT:    ldub [%o0+7], %o2
+; SPARC32-NEXT:    ldub [%o0+5], %o3
+; SPARC32-NEXT:    ldub [%o0+4], %o4
+; SPARC32-NEXT:    sll %o1, 8, %o1
+; SPARC32-NEXT:    or %o1, %o2, %o1
+; SPARC32-NEXT:    sll %o3, 16, %o2
+; SPARC32-NEXT:    sll %o4, 24, %o3
+; SPARC32-NEXT:    or %o3, %o2, %o2
+; SPARC32-NEXT:    or %o2, %o1, %o1
+; SPARC32-NEXT:    add %sp, 96, %o2
+; SPARC32-NEXT:    or %o2, 4, %o2
+; SPARC32-NEXT:    st %o1, [%o2]
+; SPARC32-NEXT:    ldub [%o0+2], %o1
+; SPARC32-NEXT:    ldub [%o0+3], %o2
+; SPARC32-NEXT:    ldub [%o0+1], %o3
+; SPARC32-NEXT:    ldub [%o0], %o0
+; SPARC32-NEXT:    sll %o1, 8, %o1
+; SPARC32-NEXT:    or %o1, %o2, %o1
+; SPARC32-NEXT:    sll %o3, 16, %o2
+; SPARC32-NEXT:    sll %o0, 24, %o0
+; SPARC32-NEXT:    or %o0, %o2, %o0
+; SPARC32-NEXT:    or %o0, %o1, %o0
+; SPARC32-NEXT:    st %o0, [%sp+96]
+; SPARC32-NEXT:    ldd [%sp+96], %o0
+; SPARC32-NEXT:    add %sp, 104, %o2
+; SPARC32-NEXT:    sta %o1, [%o2] #ASI_P_L
+; SPARC32-NEXT:    add %sp, 108, %o2
+; SPARC32-NEXT:    sta %o0, [%o2] #ASI_P_L
+; SPARC32-NEXT:    ld [%sp+104], %o0
+; SPARC32-NEXT:    ld [%sp+108], %o1
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 112, %sp
+;
+; SPARCEL-LABEL: u64_bswapload_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -112, %sp
+; SPARCEL-NEXT:    ldub [%o0+5], %o1
+; SPARCEL-NEXT:    ldub [%o0+4], %o2
+; SPARCEL-NEXT:    ldub [%o0+6], %o3
+; SPARCEL-NEXT:    ldub [%o0+7], %o4
+; SPARCEL-NEXT:    sll %o1, 8, %o1
+; SPARCEL-NEXT:    or %o1, %o2, %o1
+; SPARCEL-NEXT:    sll %o3, 16, %o2
+; SPARCEL-NEXT:    sll %o4, 24, %o3
+; SPARCEL-NEXT:    or %o3, %o2, %o2
+; SPARCEL-NEXT:    or %o2, %o1, %o1
+; SPARCEL-NEXT:    add %sp, 96, %o2
+; SPARCEL-NEXT:    or %o2, 4, %o2
+; SPARCEL-NEXT:    st %o1, [%o2]
+; SPARCEL-NEXT:    ldub [%o0+1], %o1
+; SPARCEL-NEXT:    ldub [%o0], %o2
+; SPARCEL-NEXT:    ldub [%o0+2], %o3
+; SPARCEL-NEXT:    ldub [%o0+3], %o0
+; SPARCEL-NEXT:    sll %o1, 8, %o1
+; SPARCEL-NEXT:    or %o1, %o2, %o1
+; SPARCEL-NEXT:    sll %o3, 16, %o2
+; SPARCEL-NEXT:    sll %o0, 24, %o0
+; SPARCEL-NEXT:    or %o0, %o2, %o0
+; SPARCEL-NEXT:    or %o0, %o1, %o0
+; SPARCEL-NEXT:    st %o0, [%sp+96]
+; SPARCEL-NEXT:    ldd [%sp+96], %o0
+; SPARCEL-NEXT:    add %sp, 104, %o2
+; SPARCEL-NEXT:    sta %o1, [%o2] #ASI_P
+; SPARCEL-NEXT:    add %sp, 108, %o2
+; SPARCEL-NEXT:    sta %o0, [%o2] #ASI_P
+; SPARCEL-NEXT:    ld [%sp+104], %o0
+; SPARCEL-NEXT:    ld [%sp+108], %o1
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 112, %sp
+;
+; SPARC64-LABEL: u64_bswapload_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    ldub [%o0+6], %o1
+; SPARC64-NEXT:    ldub [%o0+7], %o2
+; SPARC64-NEXT:    ldub [%o0+5], %o3
+; SPARC64-NEXT:    ldub [%o0+4], %o4
+; SPARC64-NEXT:    sllx %o1, 8, %o1
+; SPARC64-NEXT:    or %o1, %o2, %o1
+; SPARC64-NEXT:    sllx %o3, 16, %o2
+; SPARC64-NEXT:    sllx %o4, 24, %o3
+; SPARC64-NEXT:    or %o3, %o2, %o2
+; SPARC64-NEXT:    or %o2, %o1, %o1
+; SPARC64-NEXT:    ldub [%o0+2], %o2
+; SPARC64-NEXT:    ldub [%o0+3], %o3
+; SPARC64-NEXT:    ldub [%o0+1], %o4
+; SPARC64-NEXT:    ldub [%o0], %o0
+; SPARC64-NEXT:    sllx %o2, 8, %o2
+; SPARC64-NEXT:    or %o2, %o3, %o2
+; SPARC64-NEXT:    sllx %o4, 16, %o3
+; SPARC64-NEXT:    sllx %o0, 24, %o0
+; SPARC64-NEXT:    or %o0, %o3, %o0
+; SPARC64-NEXT:    or %o0, %o2, %o0
+; SPARC64-NEXT:    sllx %o0, 32, %o0
+; SPARC64-NEXT:    or %o0, %o1, %o0
+; SPARC64-NEXT:    add %sp, 2183, %o1
+; SPARC64-NEXT:    stxa %o0, [%o1] #ASI_P_L
+; SPARC64-NEXT:    ldx [%sp+2183], %o0
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %2 = load i64, ptr %0, align 1
+  %3 = tail call i64 @llvm.bswap.i64(i64 %2)
+  ret i64 %3
+}
+
 define void @u16_bswapstore(ptr %0, i16 %1) #0 {
 ; SPARC32-LABEL: u16_bswapstore:
 ; SPARC32:       ! %bb.0:
@@ -262,4 +479,192 @@ define void @u64_bswapstore(ptr %0, i64 %1) #0 {
   ret void
 }
 
+define void @u16_bswapstore_misaligned(ptr %0, i16 %1) #0 {
+; SPARC32-LABEL: u16_bswapstore_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -96, %sp
+; SPARC32-NEXT:    add %sp, 92, %o2
+; SPARC32-NEXT:    sta %o1, [%o2] #ASI_P_L
+; SPARC32-NEXT:    ld [%sp+92], %o1
+; SPARC32-NEXT:    srl %o1, 16, %o2
+; SPARC32-NEXT:    stb %o2, [%o0+1]
+; SPARC32-NEXT:    srl %o1, 24, %o1
+; SPARC32-NEXT:    stb %o1, [%o0]
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 96, %sp
+;
+; SPARCEL-LABEL: u16_bswapstore_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -96, %sp
+; SPARCEL-NEXT:    add %sp, 92, %o2
+; SPARCEL-NEXT:    sta %o1, [%o2] #ASI_P
+; SPARCEL-NEXT:    ld [%sp+92], %o1
+; SPARCEL-NEXT:    srl %o1, 16, %o2
+; SPARCEL-NEXT:    srl %o1, 24, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+1]
+; SPARCEL-NEXT:    stb %o2, [%o0]
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 96, %sp
+;
+; SPARC64-LABEL: u16_bswapstore_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    add %sp, 2187, %o2
+; SPARC64-NEXT:    sta %o1, [%o2] #ASI_P_L
+; SPARC64-NEXT:    ld [%sp+2187], %o1
+; SPARC64-NEXT:    srl %o1, 16, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+1]
+; SPARC64-NEXT:    srl %o1, 24, %o1
+; SPARC64-NEXT:    stb %o1, [%o0]
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %3 = tail call i16 @llvm.bswap.i16(i16 %1)
+  store i16 %3, ptr %0, align 1
+  ret void
+}
+
+define void @u32_bswapstore_misaligned(ptr %0, i32 %1) #0 {
+; SPARC32-LABEL: u32_bswapstore_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -96, %sp
+; SPARC32-NEXT:    add %sp, 92, %o2
+; SPARC32-NEXT:    sta %o1, [%o2] #ASI_P_L
+; SPARC32-NEXT:    ld [%sp+92], %o1
+; SPARC32-NEXT:    stb %o1, [%o0+3]
+; SPARC32-NEXT:    srl %o1, 8, %o2
+; SPARC32-NEXT:    stb %o2, [%o0+2]
+; SPARC32-NEXT:    srl %o1, 16, %o2
+; SPARC32-NEXT:    stb %o2, [%o0+1]
+; SPARC32-NEXT:    srl %o1, 24, %o1
+; SPARC32-NEXT:    stb %o1, [%o0]
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 96, %sp
+;
+; SPARCEL-LABEL: u32_bswapstore_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -96, %sp
+; SPARCEL-NEXT:    add %sp, 92, %o2
+; SPARCEL-NEXT:    sta %o1, [%o2] #ASI_P
+; SPARCEL-NEXT:    ld [%sp+92], %o1
+; SPARCEL-NEXT:    stb %o1, [%o0]
+; SPARCEL-NEXT:    srl %o1, 24, %o2
+; SPARCEL-NEXT:    stb %o2, [%o0+3]
+; SPARCEL-NEXT:    srl %o1, 16, %o2
+; SPARCEL-NEXT:    stb %o2, [%o0+2]
+; SPARCEL-NEXT:    srl %o1, 8, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+1]
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 96, %sp
+;
+; SPARC64-LABEL: u32_bswapstore_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    add %sp, 2187, %o2
+; SPARC64-NEXT:    sta %o1, [%o2] #ASI_P_L
+; SPARC64-NEXT:    ld [%sp+2187], %o1
+; SPARC64-NEXT:    stb %o1, [%o0+3]
+; SPARC64-NEXT:    srl %o1, 8, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+2]
+; SPARC64-NEXT:    srl %o1, 16, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+1]
+; SPARC64-NEXT:    srl %o1, 24, %o1
+; SPARC64-NEXT:    stb %o1, [%o0]
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %3 = tail call i32 @llvm.bswap.i32(i32 %1)
+  store i32 %3, ptr %0, align 1
+  ret void
+}
+
+define void @u64_bswapstore_misaligned(ptr %0, i64 %1) #0 {
+; SPARC32-LABEL: u64_bswapstore_misaligned:
+; SPARC32:       ! %bb.0:
+; SPARC32-NEXT:    add %sp, -112, %sp
+; SPARC32-NEXT:    add %sp, 96, %o3
+; SPARC32-NEXT:    sta %o1, [%o3] #ASI_P_L
+; SPARC32-NEXT:    add %sp, 100, %o1
+; SPARC32-NEXT:    sta %o2, [%o1] #ASI_P_L
+; SPARC32-NEXT:    ld [%sp+96], %o3
+; SPARC32-NEXT:    ld [%sp+100], %o2
+; SPARC32-NEXT:    std %o2, [%sp+104]
+; SPARC32-NEXT:    add %sp, 104, %o1
+; SPARC32-NEXT:    or %o1, 4, %o1
+; SPARC32-NEXT:    ld [%o1], %o1
+; SPARC32-NEXT:    stb %o1, [%o0+7]
+; SPARC32-NEXT:    ld [%sp+104], %o2
+; SPARC32-NEXT:    stb %o2, [%o0+3]
+; SPARC32-NEXT:    srl %o1, 8, %o3
+; SPARC32-NEXT:    stb %o3, [%o0+6]
+; SPARC32-NEXT:    srl %o1, 16, %o3
+; SPARC32-NEXT:    stb %o3, [%o0+5]
+; SPARC32-NEXT:    srl %o1, 24, %o1
+; SPARC32-NEXT:    stb %o1, [%o0+4]
+; SPARC32-NEXT:    srl %o2, 8, %o1
+; SPARC32-NEXT:    stb %o1, [%o0+2]
+; SPARC32-NEXT:    srl %o2, 16, %o1
+; SPARC32-NEXT:    stb %o1, [%o0+1]
+; SPARC32-NEXT:    srl %o2, 24, %o1
+; SPARC32-NEXT:    stb %o1, [%o0]
+; SPARC32-NEXT:    retl
+; SPARC32-NEXT:    add %sp, 112, %sp
+;
+; SPARCEL-LABEL: u64_bswapstore_misaligned:
+; SPARCEL:       ! %bb.0:
+; SPARCEL-NEXT:    add %sp, -112, %sp
+; SPARCEL-NEXT:    add %sp, 96, %o3
+; SPARCEL-NEXT:    sta %o1, [%o3] #ASI_P
+; SPARCEL-NEXT:    add %sp, 100, %o1
+; SPARCEL-NEXT:    sta %o2, [%o1] #ASI_P
+; SPARCEL-NEXT:    ld [%sp+96], %o3
+; SPARCEL-NEXT:    ld [%sp+100], %o2
+; SPARCEL-NEXT:    std %o2, [%sp+104]
+; SPARCEL-NEXT:    add %sp, 104, %o1
+; SPARCEL-NEXT:    or %o1, 4, %o1
+; SPARCEL-NEXT:    ld [%o1], %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+4]
+; SPARCEL-NEXT:    ld [%sp+104], %o2
+; SPARCEL-NEXT:    stb %o2, [%o0]
+; SPARCEL-NEXT:    srl %o1, 24, %o3
+; SPARCEL-NEXT:    stb %o3, [%o0+7]
+; SPARCEL-NEXT:    srl %o1, 16, %o3
+; SPARCEL-NEXT:    stb %o3, [%o0+6]
+; SPARCEL-NEXT:    srl %o1, 8, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+5]
+; SPARCEL-NEXT:    srl %o2, 24, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+3]
+; SPARCEL-NEXT:    srl %o2, 16, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+2]
+; SPARCEL-NEXT:    srl %o2, 8, %o1
+; SPARCEL-NEXT:    stb %o1, [%o0+1]
+; SPARCEL-NEXT:    retl
+; SPARCEL-NEXT:    add %sp, 112, %sp
+;
+; SPARC64-LABEL: u64_bswapstore_misaligned:
+; SPARC64:       ! %bb.0:
+; SPARC64-NEXT:    add %sp, -144, %sp
+; SPARC64-NEXT:    add %sp, 2183, %o2
+; SPARC64-NEXT:    stxa %o1, [%o2] #ASI_P_L
+; SPARC64-NEXT:    ldx [%sp+2183], %o1
+; SPARC64-NEXT:    stb %o1, [%o0+7]
+; SPARC64-NEXT:    srlx %o1, 8, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+6]
+; SPARC64-NEXT:    srlx %o1, 16, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+5]
+; SPARC64-NEXT:    srlx %o1, 24, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+4]
+; SPARC64-NEXT:    srlx %o1, 32, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+3]
+; SPARC64-NEXT:    srlx %o1, 40, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+2]
+; SPARC64-NEXT:    srlx %o1, 48, %o2
+; SPARC64-NEXT:    stb %o2, [%o0+1]
+; SPARC64-NEXT:    srlx %o1, 56, %o1
+; SPARC64-NEXT:    stb %o1, [%o0]
+; SPARC64-NEXT:    retl
+; SPARC64-NEXT:    add %sp, 144, %sp
+  %3 = tail call i64 @llvm.bswap.i64(i64 %1)
+  store i64 %3, ptr %0, align 1
+  ret void
+}
+
 attributes #0 = { nounwind }

>From 257c9075975dd63b2e5dcfc0ff1db60d3b2a8aaf Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sun, 5 Jul 2026 10:00:59 +0700
Subject: [PATCH 2/4] Apply feedback

---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp | 23 +++++++++++++--------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 0d201ec97e676..1e97e7374ad35 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3264,13 +3264,15 @@ SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
   SelectionDAG &DAG = DCI.DAG;
   SDValue Op = N->getOperand(0);
   EVT VT = N->getValueType(0);
-  bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
-
+  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
   LoadSDNode *LN = dyn_cast<LoadSDNode>(Op.getNode());
+
+  bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
   bool IsAlignedLoad =
       LN && ISD::isNormalLoad(Op.getNode()) &&
-      allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(), VT,
-                                     *LN->getMemOperand());
+      (VT.isZeroSized() ||
+       LN->getAlign() >= DAG.getDataLayout().getABITypeAlign(Ty)) &&
+      (LN->getAlign() >= VT.getScalarStoreSize());
 
   // Turn BSWAP (aligned-LOAD) -> ld*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && IsAlignedLoad && Op.getNode()->hasOneUse() &&
@@ -3305,12 +3307,15 @@ SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
   SDValue Op = N->getOperand(1);
   EVT VT = Op.getValueType();
   unsigned Opcode = Op.getOpcode();
-  bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
-
+  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
   StoreSDNode *SN = dyn_cast<StoreSDNode>(N);
-  bool IsAlignedStore = SN && allowsMemoryAccessForAlignment(
-                                  *DAG.getContext(), DAG.getDataLayout(), VT,
-                                  *SN->getMemOperand());
+
+  bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
+  bool IsAlignedStore =
+      SN &&
+      (VT.isZeroSized() ||
+       SN->getAlign() >= DAG.getDataLayout().getABITypeAlign(Ty)) &&
+      (SN->getAlign() >= VT.getScalarStoreSize());
 
   // Turn aligned-STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && Opcode == ISD::BSWAP && Op.getNode()->hasOneUse() &&

>From c92dd8017ec9196de5b42fe13ace456353fa8ad4 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sun, 5 Jul 2026 13:20:29 +0700
Subject: [PATCH 3/4] Apply feedback

---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 1e97e7374ad35..35688ee64dfb8 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3268,11 +3268,8 @@ SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
   LoadSDNode *LN = dyn_cast<LoadSDNode>(Op.getNode());
 
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
-  bool IsAlignedLoad =
-      LN && ISD::isNormalLoad(Op.getNode()) &&
-      (VT.isZeroSized() ||
-       LN->getAlign() >= DAG.getDataLayout().getABITypeAlign(Ty)) &&
-      (LN->getAlign() >= VT.getScalarStoreSize());
+  bool IsAlignedLoad = LN && ISD::isNormalLoad(Op.getNode()) &&
+                       LN->getAlign() >= VT.getScalarStoreSize();
 
   // Turn BSWAP (aligned-LOAD) -> ld*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && IsAlignedLoad && Op.getNode()->hasOneUse() &&
@@ -3311,11 +3308,7 @@ SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
   StoreSDNode *SN = dyn_cast<StoreSDNode>(N);
 
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
-  bool IsAlignedStore =
-      SN &&
-      (VT.isZeroSized() ||
-       SN->getAlign() >= DAG.getDataLayout().getABITypeAlign(Ty)) &&
-      (SN->getAlign() >= VT.getScalarStoreSize());
+  bool IsAlignedStore = SN && SN->getAlign() >= VT.getScalarStoreSize();
 
   // Turn aligned-STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && Opcode == ISD::BSWAP && Op.getNode()->hasOneUse() &&

>From 0be2f9d0affc9ca87c18d09fa691f682a7715a10 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sun, 5 Jul 2026 17:53:36 +0700
Subject: [PATCH 4/4] Apply feedback

---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 35688ee64dfb8..72894dc2aca4e 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3264,7 +3264,6 @@ SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
   SelectionDAG &DAG = DCI.DAG;
   SDValue Op = N->getOperand(0);
   EVT VT = N->getValueType(0);
-  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
   LoadSDNode *LN = dyn_cast<LoadSDNode>(Op.getNode());
 
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
@@ -3303,12 +3302,12 @@ SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
   SelectionDAG &DAG = DCI.DAG;
   SDValue Op = N->getOperand(1);
   EVT VT = Op.getValueType();
+  EVT MemVT = cast<StoreSDNode>(N)->getMemoryVT();
   unsigned Opcode = Op.getOpcode();
-  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
   StoreSDNode *SN = dyn_cast<StoreSDNode>(N);
 
   bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
-  bool IsAlignedStore = SN && SN->getAlign() >= VT.getScalarStoreSize();
+  bool IsAlignedStore = SN && SN->getAlign() >= MemVT.getScalarStoreSize();
 
   // Turn aligned-STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
   if (Subtarget->isV9() && Opcode == ISD::BSWAP && Op.getNode()->hasOneUse() &&
@@ -3318,7 +3317,6 @@ SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
 
     // st*a can only handle simple types and it makes no sense to store less
     // than two bytes in byte-reversed order.
-    EVT MemVT = cast<StoreSDNode>(N)->getMemoryVT();
     if (MemVT.getSizeInBits() < 16)
       return SDValue();
 



More information about the llvm-commits mailing list