[llvm] [SPARC] Use hardware byteswapper when we have V9 (PR #191720)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 19 00:59:11 PDT 2026
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/191720
>From 76d56e710d19bc8fa23a8b6df6790b303b0e24e4 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sat, 11 Apr 2026 22:54:59 +0700
Subject: [PATCH 1/3] [SPARC] Use hardware byteswapper when we have V9
On V9 processors we have endianness-adjusted memory operations, that can be
used to implement BSWAPs. Use those instructions whenever possible to reduce
code size.
---
llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 15 ++
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 137 +++++++++-
llvm/lib/Target/Sparc/SparcISelLowering.h | 4 +
llvm/lib/Target/Sparc/SparcInstr64Bit.td | 12 +
llvm/lib/Target/Sparc/SparcInstrInfo.td | 46 +++-
llvm/test/CodeGen/SPARC/bswap.ll | 265 ++++++++++++++++++++
6 files changed, 475 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/SPARC/bswap.ll
diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index 55bf40e185ff4..db45fa0c509bb 100644
--- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -49,6 +49,7 @@ class SparcDAGToDAGISel : public SelectionDAGISel {
// Complex Pattern Selectors.
bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
+ bool SelectForceADDRrr(SDValue N, SDValue &R1, SDValue &R2);
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
@@ -152,6 +153,20 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
return true;
}
+bool SparcDAGToDAGISel::SelectForceADDRrr(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
+ // If it's already in R+R form then hand it over to regular ADDRrr handling.
+ if (Addr.getNumOperands() == 2 &&
+ !isa<ConstantSDNode>(Addr.getOperand(0).getNode()) &&
+ !isa<ConstantSDNode>(Addr.getOperand(1).getNode()))
+ return SelectADDRrr(Addr, Base, Offset);
+
+ // Otherwise we'll use the full address in base and set the offset part to
+ // zero.
+ Base = Addr;
+ Offset = CurDAG->getRegister(SP::G0, Addr.getValueType());
+ return true;
+}
// Re-assemble i64 arguments split up in SelectionDAGBuilder's
// visitInlineAsm / GetRegistersForValue functions.
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index bfca95c9b1a38..2af28dae44268 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1807,7 +1807,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTPOP, MVT::i64,
Subtarget->usePopc() ? Legal : Expand);
- setOperationAction(ISD::BSWAP, MVT::i64, Expand);
+ setOperationAction(ISD::BSWAP, MVT::i64, Custom);
setOperationAction(ISD::ROTL , MVT::i64, Expand);
setOperationAction(ISD::ROTR , MVT::i64, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
@@ -1871,7 +1871,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
Subtarget->isUA2007() ? Legal : Expand);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
- setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+ setOperationAction(ISD::BSWAP, MVT::i32, Subtarget->isV9() ? Custom : Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f128, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
@@ -1984,6 +1984,9 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (!Subtarget->is64Bit())
setTargetDAGCombine(ISD::BITCAST);
+ if (Subtarget->isV9())
+ setTargetDAGCombine({ISD::BSWAP, ISD::STORE});
+
if (Subtarget->hasLeonCycleCounter())
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);
@@ -3001,6 +3004,37 @@ static SDValue LowerF128Load(SDValue Op, SelectionDAG &DAG)
return DAG.getMergeValues(Ops, dl);
}
+SDValue SparcTargetLowering::LowerBSWAP(SDValue Op, SelectionDAG &DAG) const {
+ // We don't have an in-register bswap, so expand bswap(x) into
+ // load(store-swapped(x)). The reason the swap is done during the store is
+ // that on some implementations (mainly older ones) ASI-tagged memory
+ // operations are not pipelined, and generally stores finish faster than
+ // loads.
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+ SDValue Chain = DAG.getEntryNode();
+ bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
+ SDLoc DL(Op);
+
+ SDValue BSwapOp = Op.getOperand(0);
+ EVT BSwapVT = BSwapOp.getValueType();
+
+ // Create a stack object to serve as temporary storage.
+ int BSwapFI = MFI.CreateStackObject(BSwapVT.getStoreSize(), Align(8), false);
+ SDValue BSwapPtr = DAG.getFrameIndex(BSwapFI, PtrVT);
+
+ // Store-swap the value, then load it back.
+ SDValue Ops[] = {Chain, BSwapOp, BSwapPtr, DAG.getValueType(BSwapVT)};
+ SDValue SwappedMem = DAG.getMemIntrinsicNode(
+ IsLittleEndian ? SPISD::STORE_BIG : SPISD::STORE_LITTLE, DL,
+ DAG.getVTList(MVT::Other), Ops, BSwapVT, MachinePointerInfo(), Align(8),
+ MachineMemOperand::MOStore);
+ return DAG.getLoad(BSwapVT, DL, SwappedMem, BSwapPtr, MachinePointerInfo(),
+ Align(8));
+}
+
static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG)
{
LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
@@ -3173,6 +3207,9 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::STACKADDRESS:
return LowerSTACKADDRESS(Op, DAG, *Subtarget);
+ case ISD::BSWAP:
+ return LowerBSWAP(Op, DAG);
+
case ISD::LOAD: return LowerLOAD(Op, DAG);
case ISD::STORE: return LowerSTORE(Op, DAG);
case ISD::FADD:
@@ -3218,6 +3255,98 @@ SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
return SDValue();
}
+SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ SDLoc DL(N);
+ SelectionDAG &DAG = DCI.DAG;
+ SDValue Op0 = N->getOperand(0);
+ EVT Op0VT = N->getValueType(0);
+ bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
+
+ // Turn BSWAP (LOAD) -> ld*a #ASI_P(_L) on V9.
+ if (Subtarget->isV9() && ISD::isNormalLoad(Op0.getNode()) &&
+ Op0.getNode()->hasOneUse() &&
+ (Op0VT == MVT::i16 || Op0VT == MVT::i32 ||
+ (Subtarget->is64Bit() && Op0VT == MVT::i64))) {
+ SDValue Load = Op0;
+ LoadSDNode *LD = cast<LoadSDNode>(Load);
+
+ // Create the byte-swapping load.
+ SDValue Ops[] = {
+ LD->getChain(), // Chain
+ LD->getBasePtr(), // Ptr
+ DAG.getValueType(Op0VT) // VT
+ };
+
+ SDValue BSLoad = DAG.getMemIntrinsicNode(
+ IsLittleEndian ? SPISD::LOAD_BIG : SPISD::LOAD_LITTLE, DL,
+ DAG.getVTList(Op0VT == MVT::i64 ? MVT::i64 : MVT::i32, MVT::Other), Ops,
+ LD->getMemoryVT(), LD->getMemOperand());
+
+ // If this is an i16 load, insert the truncate.
+ SDValue ResVal = BSLoad;
+ if (Op0VT == MVT::i16)
+ ResVal = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, BSLoad);
+
+ // First, combine the bswap away. This makes the value produced by the
+ // load dead.
+ DCI.CombineTo(N, ResVal);
+
+ // Next, combine the load away, we give it a bogus result value but a real
+ // chain result. The result value is dead because the bswap is dead.
+ DCI.CombineTo(Load.getNode(), ResVal, BSLoad.getValue(1));
+
+ // Return N so it doesn't get rechecked!
+ return SDValue(N, 0);
+ }
+
+ return SDValue();
+}
+
+SDValue SparcTargetLowering::PerformSTORECombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ SDLoc DL(N);
+ SelectionDAG &DAG = DCI.DAG;
+ EVT Op1VT = N->getOperand(1).getValueType();
+ unsigned Opcode = N->getOperand(1).getOpcode();
+ bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
+
+ // Turn STORE (BSWAP) -> st*a #ASI_P(_L) on V9.
+ if (Subtarget->isV9() && Opcode == ISD::BSWAP &&
+ N->getOperand(1).getNode()->hasOneUse() &&
+ (Op1VT == MVT::i16 || Op1VT == MVT::i32 ||
+ (Subtarget->is64Bit() && Op1VT == MVT::i64))) {
+
+ // 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.isExtended() || MemVT.getSizeInBits() < 16)
+ return SDValue();
+
+ SDValue BSwapOp = N->getOperand(1).getOperand(0);
+ // Do an any-extend to 32-bits if this is a half-word input.
+ if (BSwapOp.getValueType() == MVT::i16)
+ BSwapOp = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, BSwapOp);
+
+ // If the type of BSWAP operand is wider than stored memory width
+ // it needs to be shifted to the right side before st*a.
+ if (Op1VT.bitsGT(MemVT)) {
+ int Shift = Op1VT.getSizeInBits() - MemVT.getSizeInBits();
+ BSwapOp = DAG.getNode(ISD::SRL, DL, Op1VT, BSwapOp,
+ DAG.getConstant(Shift, DL, MVT::i32));
+ }
+
+ SDValue Ops[] = {N->getOperand(0), BSwapOp, N->getOperand(2),
+ DAG.getValueType(MemVT)};
+ return DAG.getMemIntrinsicNode(
+ IsLittleEndian ? SPISD::STORE_BIG : SPISD::STORE_LITTLE, DL,
+ DAG.getVTList(MVT::Other), Ops, cast<StoreSDNode>(N)->getMemoryVT(),
+ cast<StoreSDNode>(N)->getMemOperand());
+ }
+
+ return SDValue();
+}
+
SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
switch (N->getOpcode()) {
@@ -3225,6 +3354,10 @@ SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
break;
case ISD::BITCAST:
return PerformBITCASTCombine(N, DCI);
+ case ISD::BSWAP:
+ return PerformBSWAPCombine(N, DCI);
+ case ISD::STORE:
+ return PerformSTORECombine(N, DCI);
}
return SDValue();
}
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h
index f97b0ab9edd93..5098480e192a6 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.h
@@ -143,9 +143,13 @@ namespace llvm {
SDValue LowerF128Compare(SDValue LHS, SDValue RHS, unsigned &SPCC,
const SDLoc &DL, SelectionDAG &DAG) const;
+ SDValue LowerBSWAP(SDValue Op, SelectionDAG &DAG) const;
+
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue PerformBITCASTCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformBSWAPCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformSTORECombine(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue bitcastConstantFPToInt(ConstantFPSDNode *C, const SDLoc &DL,
SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index d6d081d51e4bc..5680dcd81ce86 100644
--- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -500,3 +500,15 @@ def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDri $r, tconstpool:$in)>;
def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)),
(ADDri $r, tblockaddress:$in)>;
}
+
+// Endian adjusted memory operations.
+let Predicates = [HasV9, Is64Bit] in {
+ // LDSWA is only usable on 64-bit environment.
+ def : Pat<(sext (i32 (SPloadbig ForceADDRrr:$src, i32))), (LDSWArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(sext (i32 (SPloadlittle ForceADDRrr:$src, i32))), (LDSWArr ForceADDRrr:$src, 0x88)>;
+
+ def : Pat<(SPloadbig ForceADDRrr:$src, i64), (LDXArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(SPloadlittle ForceADDRrr:$src, i64), (LDXArr ForceADDRrr:$src, 0x88)>;
+ def : Pat<(SPstorebig i64:$val, ForceADDRrr:$dst, i64), (STXArr ForceADDRrr:$dst, $val, 0x80)>;
+ def : Pat<(SPstorelittle i64:$val, ForceADDRrr:$dst, i64), (STXArr ForceADDRrr:$dst, $val, 0x88)>;
+}
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index 8717b9347210c..4686cd9f278ce 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -158,6 +158,7 @@ def SETHIimm_not : PatLeaf<(i32 imm), [{
// Addressing modes.
def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr", [], []>;
def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [], []>;
+def ForceADDRrr : ComplexPattern<iPTR, 2, "SelectForceADDRrr", [], []>;
// Constrained operands for the shift operations.
class ShiftAmtImmAsmOperand<int Bits> : AsmOperandClass {
@@ -336,6 +337,11 @@ SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
def SDTSPloadgdop :
SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;
+def SDTSPloadbig : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
+def SDTSPloadlittle : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
+def SDTSPstorebig : SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
+def SDTSPstorelittle : SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
+
def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;
def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;
def SPcmpfccv9 : SDNode<"SPISD::CMPFCC_V9", SDTSPcmpfcc, [SDNPOutGlue]>;
@@ -359,6 +365,24 @@ def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>;
def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>;
def SPselectreg : SDNode<"SPISD::SELECT_REG", SDTSPselectreg>;
+// GPRC, CHAIN = LOAD_BIG/LITTLE CHAIN, Ptr, Type
+// These are endianness-adjusted load instructions. They load the low "Type"
+// bits of the memory pointed by Ptr, possibly byte swapping it as necessary
+// to account for its in-memory endianness. Type can be i16, i32, or i64.
+def SPloadbig : SDNode<"SPISD::LOAD_BIG", SDTSPloadbig,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def SPloadlittle : SDNode<"SPISD::LOAD_LITTLE", SDTSPloadlittle,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+
+// CHAIN = STORE_BIG/LITTLE CHAIN, GPRC, Ptr, Type
+// These are endianness-adjusted store instructions. They store the low "Type"
+// bits of the GPR input out through Ptr, possibly byte swapping it as necessary
+// to adjust its in-memory endianness. Type can be i16, i32, or i64.
+def SPstorebig : SDNode<"SPISD::STORE_BIG", SDTSPstorebig,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+def SPstorelittle : SDNode<"SPISD::STORE_LITTLE", SDTSPstorelittle,
+ [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+
// These are target-independent nodes, but have target-specific formats.
def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,
SDTCisVT<1, i32> ]>;
@@ -546,8 +570,6 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
itin>;
}
-// TODO: Instructions of the StoreASI class are currently asm only; hooking up
-// CodeGen's address spaces to use these is a future task.
multiclass StoreASI<string OpcStr, bits<6> Op3Val, RegisterClass RC,
InstrItinClass itin = IIC_st> {
def rr : F3_1_asi<3, Op3Val, (outs), (ins (MEMrr $rs1, $rs2):$addr, RC:$rd, ASITag:$asi),
@@ -2050,6 +2072,26 @@ def : Pat<(build_vector (i32 IntRegs:$a1), (i32 IntRegs:$a2)),
(INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), (i32 IntRegs:$a1), sub_even),
(i32 IntRegs:$a2), sub_odd)>;
+// Endian adjusted memory operations.
+let Predicates = [HasV9] in {
+ def : Pat<(i32 (SPloadbig ForceADDRrr:$src, i16)), (LDUHArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(i32 (SPloadbig ForceADDRrr:$src, i32)), (LDArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(i32 (SPloadlittle ForceADDRrr:$src, i16)), (LDUHArr ForceADDRrr:$src, 0x88)>;
+ def : Pat<(i32 (SPloadlittle ForceADDRrr:$src, i32)), (LDArr ForceADDRrr:$src, 0x88)>;
+
+ def : Pat<(zanyext (i32 (SPloadbig ForceADDRrr:$src, i16))), (LDUHArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(zanyext (i32 (SPloadbig ForceADDRrr:$src, i32))), (LDArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(zanyext (i32 (SPloadlittle ForceADDRrr:$src, i16))), (LDUHArr ForceADDRrr:$src, 0x88)>;
+ def : Pat<(zanyext (i32 (SPloadlittle ForceADDRrr:$src, i32))), (LDArr ForceADDRrr:$src, 0x88)>;
+
+ def : Pat<(sext (i32 (SPloadbig ForceADDRrr:$src, i16))), (LDSHArr ForceADDRrr:$src, 0x80)>;
+ def : Pat<(sext (i32 (SPloadlittle ForceADDRrr:$src, i16))), (LDSHArr ForceADDRrr:$src, 0x88)>;
+
+ def : Pat<(SPstorebig i32:$val, ForceADDRrr:$dst, i16), (STHArr ForceADDRrr:$dst, $val, 0x80)>;
+ def : Pat<(SPstorebig i32:$val, ForceADDRrr:$dst, i32), (STArr ForceADDRrr:$dst, $val, 0x80)>;
+ def : Pat<(SPstorelittle i32:$val, ForceADDRrr:$dst, i16), (STHArr ForceADDRrr:$dst, $val, 0x88)>;
+ def : Pat<(SPstorelittle i32:$val, ForceADDRrr:$dst, i32), (STArr ForceADDRrr:$dst, $val, 0x88)>;
+}
include "SparcInstr64Bit.td"
include "SparcInstrVIS.td"
diff --git a/llvm/test/CodeGen/SPARC/bswap.ll b/llvm/test/CodeGen/SPARC/bswap.ll
new file mode 100644
index 0000000000000..b007d588f02c6
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/bswap.ll
@@ -0,0 +1,265 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=sparc -mcpu=v9 | FileCheck %s --check-prefix=SPARC32
+; RUN: llc < %s -mtriple=sparcel -mcpu=v9 | FileCheck %s --check-prefix=SPARCEL
+; RUN: llc < %s -mtriple=sparc64 -mcpu=v9 | FileCheck %s --check-prefix=SPARC64
+
+;; On V9 processors we can use endian-adjusted memory accessess to implement
+;; byte swapping for more compact code.
+
+declare i16 @llvm.bswap.i16(i16)
+declare i32 @llvm.bswap.i32(i32)
+declare i64 @llvm.bswap.i64(i64)
+
+define i16 @u16_bswap(i16 %0) #0 {
+; SPARC32-LABEL: u16_bswap:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: add %sp, -104, %sp
+; SPARC32-NEXT: add %sp, 96, %o1
+; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
+; SPARC32-NEXT: lduh [%sp+96], %o0
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: add %sp, 104, %sp
+;
+; SPARCEL-LABEL: u16_bswap:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: add %sp, -104, %sp
+; SPARCEL-NEXT: add %sp, 96, %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, 104, %sp
+;
+; SPARC64-LABEL: u16_bswap:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: add %sp, 2183, %o1
+; SPARC64-NEXT: sta %o0, [%o1] #ASI_P_L
+; SPARC64-NEXT: lduh [%sp+2183], %o0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+ %2 = tail call i16 @llvm.bswap.i16(i16 %0)
+ ret i16 %2
+}
+
+define i32 @u32_bswap(i32 %0) #0 {
+; SPARC32-LABEL: u32_bswap:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: add %sp, -104, %sp
+; SPARC32-NEXT: add %sp, 96, %o1
+; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
+; SPARC32-NEXT: ld [%sp+96], %o0
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: add %sp, 104, %sp
+;
+; SPARCEL-LABEL: u32_bswap:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: add %sp, -104, %sp
+; SPARCEL-NEXT: add %sp, 96, %o1
+; SPARCEL-NEXT: sta %o0, [%o1] #ASI_P
+; SPARCEL-NEXT: ld [%sp+96], %o0
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: add %sp, 104, %sp
+;
+; SPARC64-LABEL: u32_bswap:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: add %sp, 2183, %o1
+; SPARC64-NEXT: sta %o0, [%o1] #ASI_P_L
+; SPARC64-NEXT: ld [%sp+2183], %o0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+ %2 = tail call i32 @llvm.bswap.i32(i32 %0)
+ ret i32 %2
+}
+
+define i64 @u64_bswap(i64 %0) #0 {
+; SPARC32-LABEL: u64_bswap:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: add %sp, -112, %sp
+; SPARC32-NEXT: add %sp, 104, %o2
+; SPARC32-NEXT: sta %o1, [%o2] #ASI_P_L
+; SPARC32-NEXT: add %sp, 96, %o1
+; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
+; SPARC32-NEXT: ld [%sp+104], %o0
+; SPARC32-NEXT: ld [%sp+96], %o1
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: add %sp, 112, %sp
+;
+; SPARCEL-LABEL: u64_bswap:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: add %sp, -112, %sp
+; SPARCEL-NEXT: add %sp, 104, %o2
+; SPARCEL-NEXT: sta %o1, [%o2] #ASI_P
+; SPARCEL-NEXT: add %sp, 96, %o1
+; SPARCEL-NEXT: sta %o0, [%o1] #ASI_P
+; SPARCEL-NEXT: ld [%sp+104], %o0
+; SPARCEL-NEXT: ld [%sp+96], %o1
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: add %sp, 112, %sp
+;
+; SPARC64-LABEL: u64_bswap:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; 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 = tail call i64 @llvm.bswap.i64(i64 %0)
+ ret i64 %2
+}
+
+define i16 @u16_bswapload(ptr %0) #0 {
+; SPARC32-LABEL: u16_bswapload:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: lduha [%o0] #ASI_P_L, %o0
+;
+; SPARCEL-LABEL: u16_bswapload:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: lduha [%o0] #ASI_P, %o0
+;
+; SPARC64-LABEL: u16_bswapload:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: lduha [%o0] #ASI_P_L, %o0
+ %2 = load i16, ptr %0, align 2
+ %3 = tail call i16 @llvm.bswap.i16(i16 %2)
+ ret i16 %3
+}
+
+define i32 @u32_bswapload(ptr %0) #0 {
+; SPARC32-LABEL: u32_bswapload:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: lda [%o0] #ASI_P_L, %o0
+;
+; SPARCEL-LABEL: u32_bswapload:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: lda [%o0] #ASI_P, %o0
+;
+; SPARC64-LABEL: u32_bswapload:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: lda [%o0] #ASI_P_L, %o0
+ %2 = load i32, ptr %0, align 4
+ %3 = tail call i32 @llvm.bswap.i32(i32 %2)
+ ret i32 %3
+}
+
+define i64 @u64_bswapload(ptr %0) #0 {
+; SPARC32-LABEL: u64_bswapload:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: add %sp, -112, %sp
+; SPARC32-NEXT: ldd [%o0], %o0
+; SPARC32-NEXT: add %sp, 96, %o2
+; SPARC32-NEXT: sta %o1, [%o2] #ASI_P_L
+; SPARC32-NEXT: add %sp, 104, %o2
+; SPARC32-NEXT: sta %o0, [%o2] #ASI_P_L
+; SPARC32-NEXT: ld [%sp+96], %o0
+; SPARC32-NEXT: ld [%sp+104], %o1
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: add %sp, 112, %sp
+;
+; SPARCEL-LABEL: u64_bswapload:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: add %sp, -112, %sp
+; SPARCEL-NEXT: ldd [%o0], %o0
+; SPARCEL-NEXT: add %sp, 96, %o2
+; SPARCEL-NEXT: sta %o1, [%o2] #ASI_P
+; SPARCEL-NEXT: add %sp, 104, %o2
+; SPARCEL-NEXT: sta %o0, [%o2] #ASI_P
+; SPARCEL-NEXT: ld [%sp+96], %o0
+; SPARCEL-NEXT: ld [%sp+104], %o1
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: add %sp, 112, %sp
+;
+; SPARC64-LABEL: u64_bswapload:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: ldxa [%o0] #ASI_P_L, %o0
+ %2 = load i64, ptr %0, align 8
+ %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:
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: stha %o1, [%o0] #ASI_P_L
+;
+; SPARCEL-LABEL: u16_bswapstore:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: stha %o1, [%o0] #ASI_P
+;
+; SPARC64-LABEL: u16_bswapstore:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: stha %o1, [%o0] #ASI_P_L
+ %3 = tail call i16 @llvm.bswap.i16(i16 %1)
+ store i16 %3, ptr %0, align 2
+ ret void
+}
+
+define void @u32_bswapstore(ptr %0, i32 %1) #0 {
+; SPARC32-LABEL: u32_bswapstore:
+; SPARC32: ! %bb.0:
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: sta %o1, [%o0] #ASI_P_L
+;
+; SPARCEL-LABEL: u32_bswapstore:
+; SPARCEL: ! %bb.0:
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: sta %o1, [%o0] #ASI_P
+;
+; SPARC64-LABEL: u32_bswapstore:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: sta %o1, [%o0] #ASI_P_L
+ %3 = tail call i32 @llvm.bswap.i32(i32 %1)
+ store i32 %3, ptr %0, align 4
+ ret void
+}
+
+define void @u64_bswapstore(ptr %0, i64 %1) #0 {
+; SPARC32-LABEL: u64_bswapstore:
+; 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, 104, %o1
+; SPARC32-NEXT: sta %o2, [%o1] #ASI_P_L
+; SPARC32-NEXT: ld [%sp+96], %o3
+; SPARC32-NEXT: ld [%sp+104], %o2
+; SPARC32-NEXT: std %o2, [%o0]
+; SPARC32-NEXT: retl
+; SPARC32-NEXT: add %sp, 112, %sp
+;
+; SPARCEL-LABEL: u64_bswapstore:
+; 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, 104, %o1
+; SPARCEL-NEXT: sta %o2, [%o1] #ASI_P
+; SPARCEL-NEXT: ld [%sp+96], %o3
+; SPARCEL-NEXT: ld [%sp+104], %o2
+; SPARCEL-NEXT: std %o2, [%o0]
+; SPARCEL-NEXT: retl
+; SPARCEL-NEXT: add %sp, 112, %sp
+;
+; SPARC64-LABEL: u64_bswapstore:
+; SPARC64: ! %bb.0:
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: stxa %o1, [%o0] #ASI_P_L
+ %3 = tail call i64 @llvm.bswap.i64(i64 %1)
+ store i64 %3, ptr %0, align 8
+ ret void
+}
+
+attributes #0 = { nounwind }
>From 2fb812e990853591c761ec810c0d0523f4969690 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 14 Apr 2026 06:11:36 +0700
Subject: [PATCH 2/3] Use getPointerTy for SelectForceADDRrr
---
llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index db45fa0c509bb..8ed9c5222a3a1 100644
--- a/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -49,7 +49,7 @@ class SparcDAGToDAGISel : public SelectionDAGISel {
// Complex Pattern Selectors.
bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
- bool SelectForceADDRrr(SDValue N, SDValue &R1, SDValue &R2);
+ bool SelectForceADDRrr(SDValue N, SDValue &Base, SDValue &Disp);
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
@@ -154,17 +154,18 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
}
bool SparcDAGToDAGISel::SelectForceADDRrr(SDValue Addr, SDValue &Base,
- SDValue &Offset) {
+ SDValue &Disp) {
// If it's already in R+R form then hand it over to regular ADDRrr handling.
if (Addr.getNumOperands() == 2 &&
!isa<ConstantSDNode>(Addr.getOperand(0).getNode()) &&
!isa<ConstantSDNode>(Addr.getOperand(1).getNode()))
- return SelectADDRrr(Addr, Base, Offset);
+ return SelectADDRrr(Addr, Base, Disp);
// Otherwise we'll use the full address in base and set the offset part to
// zero.
Base = Addr;
- Offset = CurDAG->getRegister(SP::G0, Addr.getValueType());
+ Disp =
+ CurDAG->getRegister(SP::G0, TLI->getPointerTy(CurDAG->getDataLayout()));
return true;
}
>From 7fe968551b9fa65e032ea485adb742d17086757e Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Sun, 19 Apr 2026 14:48:27 +0700
Subject: [PATCH 3/3] Apply feedback
---
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 33 ++++----
llvm/test/CodeGen/SPARC/bswap.ll | 86 ++++++++++-----------
2 files changed, 56 insertions(+), 63 deletions(-)
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 2af28dae44268..4bacca06a9eb0 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3013,26 +3013,28 @@ SDValue SparcTargetLowering::LowerBSWAP(SDValue Op, SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo &MFI = MF.getFrameInfo();
- auto PtrVT = getPointerTy(DAG.getDataLayout());
+ MVT PtrVT = getPointerTy(DAG.getDataLayout());
SDValue Chain = DAG.getEntryNode();
bool IsLittleEndian = DAG.getDataLayout().isLittleEndian();
SDLoc DL(Op);
SDValue BSwapOp = Op.getOperand(0);
- EVT BSwapVT = BSwapOp.getValueType();
+ EVT VT = BSwapOp.getValueType();
+ Type *Ty = VT.getTypeForEVT(*DAG.getContext());
+ Align Al = DAG.getDataLayout().getABITypeAlign(Ty);
// Create a stack object to serve as temporary storage.
- int BSwapFI = MFI.CreateStackObject(BSwapVT.getStoreSize(), Align(8), false);
- SDValue BSwapPtr = DAG.getFrameIndex(BSwapFI, PtrVT);
+ int TmpFI = MFI.CreateStackObject(VT.getStoreSize(), Al, false);
+ SDValue TmpPtr = DAG.getFrameIndex(TmpFI, PtrVT);
// Store-swap the value, then load it back.
- SDValue Ops[] = {Chain, BSwapOp, BSwapPtr, DAG.getValueType(BSwapVT)};
- SDValue SwappedMem = DAG.getMemIntrinsicNode(
+ SDValue Ops[] = {Chain, BSwapOp, TmpPtr, DAG.getValueType(VT)};
+ SDValue ST = DAG.getMemIntrinsicNode(
IsLittleEndian ? SPISD::STORE_BIG : SPISD::STORE_LITTLE, DL,
- DAG.getVTList(MVT::Other), Ops, BSwapVT, MachinePointerInfo(), Align(8),
- MachineMemOperand::MOStore);
- return DAG.getLoad(BSwapVT, DL, SwappedMem, BSwapPtr, MachinePointerInfo(),
- Align(8));
+ DAG.getVTList(MVT::Other), Ops, VT,
+ MachinePointerInfo::getFixedStack(MF, TmpFI));
+ return DAG.getLoad(VT, DL, ST, TmpPtr,
+ MachinePointerInfo::getFixedStack(MF, TmpFI));
}
static SDValue LowerLOAD(SDValue Op, SelectionDAG &DAG)
@@ -3288,16 +3290,7 @@ SDValue SparcTargetLowering::PerformBSWAPCombine(SDNode *N,
if (Op0VT == MVT::i16)
ResVal = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, BSLoad);
- // First, combine the bswap away. This makes the value produced by the
- // load dead.
- DCI.CombineTo(N, ResVal);
-
- // Next, combine the load away, we give it a bogus result value but a real
- // chain result. The result value is dead because the bswap is dead.
- DCI.CombineTo(Load.getNode(), ResVal, BSLoad.getValue(1));
-
- // Return N so it doesn't get rechecked!
- return SDValue(N, 0);
+ return DCI.CombineTo(N, ResVal);
}
return SDValue();
diff --git a/llvm/test/CodeGen/SPARC/bswap.ll b/llvm/test/CodeGen/SPARC/bswap.ll
index b007d588f02c6..b182862561752 100644
--- a/llvm/test/CodeGen/SPARC/bswap.ll
+++ b/llvm/test/CodeGen/SPARC/bswap.ll
@@ -13,29 +13,29 @@ declare i64 @llvm.bswap.i64(i64)
define i16 @u16_bswap(i16 %0) #0 {
; SPARC32-LABEL: u16_bswap:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: add %sp, -104, %sp
-; SPARC32-NEXT: add %sp, 96, %o1
+; SPARC32-NEXT: add %sp, -96, %sp
+; SPARC32-NEXT: add %sp, 92, %o1
; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
-; SPARC32-NEXT: lduh [%sp+96], %o0
+; SPARC32-NEXT: lduh [%sp+92], %o0
; SPARC32-NEXT: retl
-; SPARC32-NEXT: add %sp, 104, %sp
+; SPARC32-NEXT: add %sp, 96, %sp
;
; SPARCEL-LABEL: u16_bswap:
; SPARCEL: ! %bb.0:
-; SPARCEL-NEXT: add %sp, -104, %sp
-; SPARCEL-NEXT: add %sp, 96, %o1
+; SPARCEL-NEXT: add %sp, -96, %sp
+; 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, 104, %sp
+; SPARCEL-NEXT: add %sp, 96, %sp
;
; SPARC64-LABEL: u16_bswap:
; SPARC64: ! %bb.0:
; SPARC64-NEXT: add %sp, -144, %sp
-; SPARC64-NEXT: add %sp, 2183, %o1
+; SPARC64-NEXT: add %sp, 2187, %o1
; SPARC64-NEXT: sta %o0, [%o1] #ASI_P_L
-; SPARC64-NEXT: lduh [%sp+2183], %o0
+; SPARC64-NEXT: lduh [%sp+2187], %o0
; SPARC64-NEXT: retl
; SPARC64-NEXT: add %sp, 144, %sp
%2 = tail call i16 @llvm.bswap.i16(i16 %0)
@@ -45,28 +45,28 @@ define i16 @u16_bswap(i16 %0) #0 {
define i32 @u32_bswap(i32 %0) #0 {
; SPARC32-LABEL: u32_bswap:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: add %sp, -104, %sp
-; SPARC32-NEXT: add %sp, 96, %o1
+; SPARC32-NEXT: add %sp, -96, %sp
+; SPARC32-NEXT: add %sp, 92, %o1
; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
-; SPARC32-NEXT: ld [%sp+96], %o0
+; SPARC32-NEXT: ld [%sp+92], %o0
; SPARC32-NEXT: retl
-; SPARC32-NEXT: add %sp, 104, %sp
+; SPARC32-NEXT: add %sp, 96, %sp
;
; SPARCEL-LABEL: u32_bswap:
; SPARCEL: ! %bb.0:
-; SPARCEL-NEXT: add %sp, -104, %sp
-; SPARCEL-NEXT: add %sp, 96, %o1
+; SPARCEL-NEXT: add %sp, -96, %sp
+; SPARCEL-NEXT: add %sp, 92, %o1
; SPARCEL-NEXT: sta %o0, [%o1] #ASI_P
-; SPARCEL-NEXT: ld [%sp+96], %o0
+; SPARCEL-NEXT: ld [%sp+92], %o0
; SPARCEL-NEXT: retl
-; SPARCEL-NEXT: add %sp, 104, %sp
+; SPARCEL-NEXT: add %sp, 96, %sp
;
; SPARC64-LABEL: u32_bswap:
; SPARC64: ! %bb.0:
; SPARC64-NEXT: add %sp, -144, %sp
-; SPARC64-NEXT: add %sp, 2183, %o1
+; SPARC64-NEXT: add %sp, 2187, %o1
; SPARC64-NEXT: sta %o0, [%o1] #ASI_P_L
-; SPARC64-NEXT: ld [%sp+2183], %o0
+; SPARC64-NEXT: ld [%sp+2187], %o0
; SPARC64-NEXT: retl
; SPARC64-NEXT: add %sp, 144, %sp
%2 = tail call i32 @llvm.bswap.i32(i32 %0)
@@ -76,27 +76,27 @@ define i32 @u32_bswap(i32 %0) #0 {
define i64 @u64_bswap(i64 %0) #0 {
; SPARC32-LABEL: u64_bswap:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: add %sp, -112, %sp
-; SPARC32-NEXT: add %sp, 104, %o2
+; SPARC32-NEXT: add %sp, -104, %sp
+; SPARC32-NEXT: add %sp, 100, %o2
; SPARC32-NEXT: sta %o1, [%o2] #ASI_P_L
; SPARC32-NEXT: add %sp, 96, %o1
; SPARC32-NEXT: sta %o0, [%o1] #ASI_P_L
-; SPARC32-NEXT: ld [%sp+104], %o0
+; SPARC32-NEXT: ld [%sp+100], %o0
; SPARC32-NEXT: ld [%sp+96], %o1
; SPARC32-NEXT: retl
-; SPARC32-NEXT: add %sp, 112, %sp
+; SPARC32-NEXT: add %sp, 104, %sp
;
; SPARCEL-LABEL: u64_bswap:
; SPARCEL: ! %bb.0:
-; SPARCEL-NEXT: add %sp, -112, %sp
-; SPARCEL-NEXT: add %sp, 104, %o2
+; SPARCEL-NEXT: add %sp, -104, %sp
+; SPARCEL-NEXT: add %sp, 100, %o2
; SPARCEL-NEXT: sta %o1, [%o2] #ASI_P
; SPARCEL-NEXT: add %sp, 96, %o1
; SPARCEL-NEXT: sta %o0, [%o1] #ASI_P
-; SPARCEL-NEXT: ld [%sp+104], %o0
+; SPARCEL-NEXT: ld [%sp+100], %o0
; SPARCEL-NEXT: ld [%sp+96], %o1
; SPARCEL-NEXT: retl
-; SPARCEL-NEXT: add %sp, 112, %sp
+; SPARCEL-NEXT: add %sp, 104, %sp
;
; SPARC64-LABEL: u64_bswap:
; SPARC64: ! %bb.0:
@@ -153,29 +153,29 @@ define i32 @u32_bswapload(ptr %0) #0 {
define i64 @u64_bswapload(ptr %0) #0 {
; SPARC32-LABEL: u64_bswapload:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: add %sp, -112, %sp
+; SPARC32-NEXT: add %sp, -104, %sp
; SPARC32-NEXT: ldd [%o0], %o0
; SPARC32-NEXT: add %sp, 96, %o2
; SPARC32-NEXT: sta %o1, [%o2] #ASI_P_L
-; SPARC32-NEXT: add %sp, 104, %o2
+; SPARC32-NEXT: add %sp, 100, %o2
; SPARC32-NEXT: sta %o0, [%o2] #ASI_P_L
; SPARC32-NEXT: ld [%sp+96], %o0
-; SPARC32-NEXT: ld [%sp+104], %o1
+; SPARC32-NEXT: ld [%sp+100], %o1
; SPARC32-NEXT: retl
-; SPARC32-NEXT: add %sp, 112, %sp
+; SPARC32-NEXT: add %sp, 104, %sp
;
; SPARCEL-LABEL: u64_bswapload:
; SPARCEL: ! %bb.0:
-; SPARCEL-NEXT: add %sp, -112, %sp
+; SPARCEL-NEXT: add %sp, -104, %sp
; SPARCEL-NEXT: ldd [%o0], %o0
; SPARCEL-NEXT: add %sp, 96, %o2
; SPARCEL-NEXT: sta %o1, [%o2] #ASI_P
-; SPARCEL-NEXT: add %sp, 104, %o2
+; SPARCEL-NEXT: add %sp, 100, %o2
; SPARCEL-NEXT: sta %o0, [%o2] #ASI_P
; SPARCEL-NEXT: ld [%sp+96], %o0
-; SPARCEL-NEXT: ld [%sp+104], %o1
+; SPARCEL-NEXT: ld [%sp+100], %o1
; SPARCEL-NEXT: retl
-; SPARCEL-NEXT: add %sp, 112, %sp
+; SPARCEL-NEXT: add %sp, 104, %sp
;
; SPARC64-LABEL: u64_bswapload:
; SPARC64: ! %bb.0:
@@ -229,29 +229,29 @@ define void @u32_bswapstore(ptr %0, i32 %1) #0 {
define void @u64_bswapstore(ptr %0, i64 %1) #0 {
; SPARC32-LABEL: u64_bswapstore:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: add %sp, -112, %sp
+; SPARC32-NEXT: add %sp, -104, %sp
; SPARC32-NEXT: add %sp, 96, %o3
; SPARC32-NEXT: sta %o1, [%o3] #ASI_P_L
-; SPARC32-NEXT: add %sp, 104, %o1
+; SPARC32-NEXT: add %sp, 100, %o1
; SPARC32-NEXT: sta %o2, [%o1] #ASI_P_L
; SPARC32-NEXT: ld [%sp+96], %o3
-; SPARC32-NEXT: ld [%sp+104], %o2
+; SPARC32-NEXT: ld [%sp+100], %o2
; SPARC32-NEXT: std %o2, [%o0]
; SPARC32-NEXT: retl
-; SPARC32-NEXT: add %sp, 112, %sp
+; SPARC32-NEXT: add %sp, 104, %sp
;
; SPARCEL-LABEL: u64_bswapstore:
; SPARCEL: ! %bb.0:
-; SPARCEL-NEXT: add %sp, -112, %sp
+; SPARCEL-NEXT: add %sp, -104, %sp
; SPARCEL-NEXT: add %sp, 96, %o3
; SPARCEL-NEXT: sta %o1, [%o3] #ASI_P
-; SPARCEL-NEXT: add %sp, 104, %o1
+; SPARCEL-NEXT: add %sp, 100, %o1
; SPARCEL-NEXT: sta %o2, [%o1] #ASI_P
; SPARCEL-NEXT: ld [%sp+96], %o3
-; SPARCEL-NEXT: ld [%sp+104], %o2
+; SPARCEL-NEXT: ld [%sp+100], %o2
; SPARCEL-NEXT: std %o2, [%o0]
; SPARCEL-NEXT: retl
-; SPARCEL-NEXT: add %sp, 112, %sp
+; SPARCEL-NEXT: add %sp, 104, %sp
;
; SPARC64-LABEL: u64_bswapstore:
; SPARC64: ! %bb.0:
More information about the llvm-commits
mailing list