[clang] [compiler-rt] [llvm] [WIP][SPARC] Properly handle CC for long double on sparc32 (PR #162226)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 14 23:06:38 PDT 2025
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/162226
>From 99cd21841c3b325d3335af5b4110414a49ad9bb3 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 7 Oct 2025 12:55:39 +0700
Subject: [PATCH 1/4] [WIP][SPARC] Properly handle CC for long double on
sparc32
Pass and return `long double`s indirectly, as specified in the psABI.
This continues the patch at https://reviews.llvm.org/D89130.
This should fix the issue at https://github.com/llvm/llvm-project/issues/41838.
---
clang/lib/Basic/Targets/Sparc.h | 7 +++++
clang/lib/CodeGen/Targets/Sparc.cpp | 30 ++++++++++++++++++---
compiler-rt/lib/builtins/CMakeLists.txt | 4 +--
compiler-rt/test/builtins/CMakeLists.txt | 2 +-
llvm/lib/Target/Sparc/SparcCallingConv.td | 4 +--
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 19 ++++++-------
6 files changed, 48 insertions(+), 18 deletions(-)
diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h
index 3215e648ba6c3..acc27194c38ea 100644
--- a/clang/lib/Basic/Targets/Sparc.h
+++ b/clang/lib/Basic/Targets/Sparc.h
@@ -166,6 +166,13 @@ class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
PtrDiffType = SignedLong;
break;
}
+
+ // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
+ // aligned.
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+
// Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're
// willing to do atomic ops on up to 64 bits.
MaxAtomicPromoteWidth = 64;
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index 38dbebdec2429..4259c8bbfdcae 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -26,6 +26,7 @@ class SparcV8ABIInfo : public DefaultABIInfo {
private:
ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
void computeInfo(CGFunctionInfo &FI) const override;
};
} // end anonymous namespace
@@ -33,12 +34,33 @@ class SparcV8ABIInfo : public DefaultABIInfo {
ABIArgInfo
SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+
if (Ty->isAnyComplexType()) {
- return ABIArgInfo::getDirect();
- }
- else {
- return DefaultABIInfo::classifyReturnType(Ty);
+ auto AI = ABIArgInfo::getDirect();
+ AI.setInReg(true);
+ return AI;
}
+
+ return DefaultABIInfo::classifyReturnType(Ty);
+}
+
+ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {
+ const BuiltinType *BT = Ty->getAs<BuiltinType>();
+ bool IsF128 = false;
+
+ if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
+ IsF128 = true;
+
+ // FIXME not sure if redundant
+ if (BT && BT->getKind() == BuiltinType::LongDouble)
+ IsF128 = true;
+
+ if (IsF128)
+ return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
+
+ return DefaultABIInfo::classifyArgumentType(Ty);
}
void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 6c226aa7d2d48..790bf5758f4a2 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -960,9 +960,9 @@ else ()
list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET)
endif()
- # For RISCV32, we must force enable int128 for compiling long
+ # For RISCV32 and 32-bit SPARC, we must force enable int128 for compiling long
# double routines.
- if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" STREQUAL "riscv32")
+ if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC)
list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128)
endif()
diff --git a/compiler-rt/test/builtins/CMakeLists.txt b/compiler-rt/test/builtins/CMakeLists.txt
index 63f4c94605c90..5643bfc51ea81 100644
--- a/compiler-rt/test/builtins/CMakeLists.txt
+++ b/compiler-rt/test/builtins/CMakeLists.txt
@@ -44,7 +44,7 @@ foreach(arch ${BUILTIN_TEST_ARCH})
string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
endif()
- if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR ${arch} STREQUAL "riscv32")
+ if (COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC)
list(APPEND BUILTINS_TEST_TARGET_CFLAGS -fforce-enable-int128)
string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}")
endif()
diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td
index 8afd0a7fc09ad..55be696c14a78 100644
--- a/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/llvm/lib/Target/Sparc/SparcCallingConv.td
@@ -24,8 +24,8 @@ def CC_Sparc32 : CallingConv<[
// As are v2i32 arguments (this would be the default behavior for
// v2i32 if it wasn't allocated to the IntPair register-class)
CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Split_64">>,
-
-
+ // f128 arguments are passed indirectly.
+ CCIfType<[f128], CCPassIndirect<i32>>,
// Alternatively, they are assigned to the stack in 4-byte aligned units.
CCAssignToStack<4, 4>
]>;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index a1607097af1ef..6ce636f470896 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -554,20 +554,19 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
- int FI = MF.getFrameInfo().CreateFixedObject(4,
- Offset,
- true);
- SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
- SDValue Load ;
+ int FI;
if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
- Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
+ FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
} else if (VA.getValVT() == MVT::f128) {
- report_fatal_error("SPARCv8 does not handle f128 in calls; "
- "pass indirectly");
+ FI = MF.getFrameInfo().CreateFixedObject(16, Offset, false);
} else {
// We shouldn't see any other value types here.
llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
}
+
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue Load =
+ DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo());
InVals.push_back(Load);
}
@@ -913,7 +912,9 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
// Promote the value if needed.
switch (VA.getLocInfo()) {
default: llvm_unreachable("Unknown loc info!");
- case CCValAssign::Full: break;
+ case CCValAssign::Full:
+ case CCValAssign::Indirect:
+ break;
case CCValAssign::SExt:
Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
break;
>From 4b6d5942f0058a6b10496964109b50a5c1463718 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Mon, 13 Oct 2025 22:30:53 +0700
Subject: [PATCH 2/4] Implement indirect argument handling in
LowerCall/FormalArguments
---
clang/lib/CodeGen/Targets/Sparc.cpp | 10 +
clang/test/CodeGen/sparcv8-abi.c | 7 +
llvm/lib/Target/Sparc/SparcISelLowering.cpp | 73 ++++++-
llvm/test/CodeGen/SPARC/fp128.ll | 6 +
llvm/test/CodeGen/SPARC/fp16-promote.ll | 24 ++-
llvm/test/CodeGen/SPARC/llvm.sincos.ll | 200 +++++++++++---------
6 files changed, 218 insertions(+), 102 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index 4259c8bbfdcae..80a2b3d6c0085 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -34,7 +34,17 @@ class SparcV8ABIInfo : public DefaultABIInfo {
ABIArgInfo
SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
+ const BuiltinType *BT = Ty->getAs<BuiltinType>();
+ bool IsF128 = false;
+
if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
+ IsF128 = true;
+
+ // FIXME not sure if redundant
+ if (BT && BT->getKind() == BuiltinType::LongDouble)
+ IsF128 = true;
+
+ if (IsF128)
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
if (Ty->isAnyComplexType()) {
diff --git a/clang/test/CodeGen/sparcv8-abi.c b/clang/test/CodeGen/sparcv8-abi.c
index c5faf130890f8..07a90cd8087df 100644
--- a/clang/test/CodeGen/sparcv8-abi.c
+++ b/clang/test/CodeGen/sparcv8-abi.c
@@ -20,3 +20,10 @@ r (long long __complex__ a, long long __complex__ b)
{
return 0;
}
+
+// CHECK-LABEL: define{{.*}} void @s(ptr dead_on_unwind noalias writable sret(fp128) align 8 %agg.result, ptr noundef byval(fp128) align 8 %0) #0
+long double
+s(long double a)
+{
+ return 0;
+}
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 6ce636f470896..87faee5ef3567 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -554,11 +554,34 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
continue;
}
+ if (VA.getLocInfo() == CCValAssign::Indirect) {
+ EVT LocVT = VA.getLocVT();
+ int FI = MF.getFrameInfo().CreateFixedObject(
+ LocVT.getFixedSizeInBits() / 8, Offset, true);
+ SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT);
+ SDValue ArgValue = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr,
+ MachinePointerInfo::getFixedStack(MF, FI));
+ InVals.push_back(ArgValue);
+
+ unsigned ArgIndex = Ins[InIdx].OrigArgIndex;
+ unsigned ArgPartOffset = Ins[InIdx].PartOffset;
+ assert(ArgPartOffset == 0);
+ while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) {
+ CCValAssign &PartVA = ArgLocs[i + 1];
+ unsigned PartOffset = Ins[InIdx + 1].PartOffset - ArgPartOffset;
+ SDValue Offset = DAG.getIntPtrConstant(PartOffset, dl);
+ SDValue Address = DAG.getNode(ISD::ADD, dl, PtrVT, ArgValue, Offset);
+ InVals.push_back(DAG.getLoad(PartVA.getValVT(), dl, Chain, Address,
+ MachinePointerInfo()));
+ ++i;
+ ++InIdx;
+ }
+ continue;
+ }
+
int FI;
if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) {
FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true);
- } else if (VA.getValVT() == MVT::f128) {
- FI = MF.getFrameInfo().CreateFixedObject(16, Offset, false);
} else {
// We shouldn't see any other value types here.
llvm_unreachable("Unexpected ValVT encountered in frame lowering.");
@@ -834,6 +857,8 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
CallingConv::ID CallConv = CLI.CallConv;
bool isVarArg = CLI.IsVarArg;
MachineFunction &MF = DAG.getMachineFunction();
+ LLVMContext &Ctx = *DAG.getContext();
+ EVT PtrVT = getPointerTy(MF.getDataLayout());
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -1027,6 +1052,50 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
assert(VA.isMemLoc());
+ if (VA.getLocInfo() == CCValAssign::Indirect) {
+ // Store the argument in a stack slot and pass its address.
+ unsigned ArgIndex = Outs[realArgIdx].OrigArgIndex;
+ unsigned ArgPartOffset = Outs[realArgIdx].PartOffset;
+ assert(ArgPartOffset == 0);
+
+ EVT SlotVT;
+ if (i + 1 != e && Outs[realArgIdx + 1].OrigArgIndex == ArgIndex) {
+ Type *OrigArgType = CLI.Args[ArgIndex].Ty;
+ EVT OrigArgVT = getValueType(MF.getDataLayout(), OrigArgType);
+ MVT PartVT =
+ getRegisterTypeForCallingConv(Ctx, CLI.CallConv, OrigArgVT);
+ unsigned N =
+ getNumRegistersForCallingConv(Ctx, CLI.CallConv, OrigArgVT);
+ SlotVT = EVT::getIntegerVT(Ctx, PartVT.getSizeInBits() * N);
+ } else {
+ SlotVT = Outs[realArgIdx].VT;
+ }
+
+ SDValue SpillSlot = DAG.CreateStackTemporary(SlotVT);
+ int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
+ MemOpChains.push_back(
+ DAG.getStore(Chain, dl, Arg, SpillSlot,
+ MachinePointerInfo::getFixedStack(MF, FI)));
+ // If the original argument was split (e.g. i128), we need
+ // to store all parts of it here (and pass just one address).
+ while (i + 1 != e && Outs[realArgIdx + 1].OrigArgIndex == ArgIndex) {
+ SDValue PartValue = OutVals[realArgIdx + 1];
+ unsigned PartOffset = Outs[realArgIdx + 1].PartOffset;
+ SDValue Address = DAG.getNode(ISD::ADD, dl, PtrVT, SpillSlot,
+ DAG.getIntPtrConstant(PartOffset, dl));
+ MemOpChains.push_back(
+ DAG.getStore(Chain, dl, PartValue, Address,
+ MachinePointerInfo::getFixedStack(MF, FI)));
+ assert((PartOffset + PartValue.getValueType().getStoreSize() <=
+ SlotVT.getStoreSize()) &&
+ "Not enough space for argument part!");
+ ++i;
+ ++realArgIdx;
+ }
+
+ Arg = SpillSlot;
+ }
+
// Create a store off the stack pointer for this argument.
SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset() + StackOffset,
diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll
index 99bfb8d742711..fbdc99394eb9e 100644
--- a/llvm/test/CodeGen/SPARC/fp128.ll
+++ b/llvm/test/CodeGen/SPARC/fp128.ll
@@ -241,3 +241,9 @@ entry:
store fp128 %1, ptr %scalar.result, align 8
ret void
}
+
+define fp128 @f128_direct(fp128 %num) {
+ %ret = call fp128 @f128_callee(fp128 %num, fp128 %num)
+ ret fp128 %ret
+}
+declare fp128 @f128_callee(fp128 %a, fp128 %b)
diff --git a/llvm/test/CodeGen/SPARC/fp16-promote.ll b/llvm/test/CodeGen/SPARC/fp16-promote.ll
index 64873b744de50..ed956eb807be7 100644
--- a/llvm/test/CodeGen/SPARC/fp16-promote.ll
+++ b/llvm/test/CodeGen/SPARC/fp16-promote.ll
@@ -268,19 +268,21 @@ define void @test_fptrunc_double(double %d, ptr %p) nounwind {
define void @test_fptrunc_fp128(ptr %dp, ptr %p) nounwind {
; V8-OPT-LABEL: test_fptrunc_fp128:
; V8-OPT: ! %bb.0:
-; V8-OPT-NEXT: save %sp, -104, %sp
+; V8-OPT-NEXT: save %sp, -120, %sp
; V8-OPT-NEXT: ldd [%i0], %f0
; V8-OPT-NEXT: ldd [%i0+8], %f4
-; V8-OPT-NEXT: std %f4, [%sp+100]
+; V8-OPT-NEXT: add %fp, -16, %i0
+; V8-OPT-NEXT: st %i0, [%sp+92]
+; V8-OPT-NEXT: std %f4, [%fp+-8]
; V8-OPT-NEXT: call __trunctfhf2
-; V8-OPT-NEXT: std %f0, [%sp+92]
+; V8-OPT-NEXT: std %f0, [%fp+-16]
; V8-OPT-NEXT: sth %o0, [%i1]
; V8-OPT-NEXT: ret
; V8-OPT-NEXT: restore
;
; V8-UNOPT-LABEL: test_fptrunc_fp128:
; V8-UNOPT: ! %bb.0:
-; V8-UNOPT-NEXT: save %sp, -104, %sp
+; V8-UNOPT-NEXT: save %sp, -120, %sp
; V8-UNOPT-NEXT: ldd [%i0], %f4
; V8-UNOPT-NEXT: ! implicit-def: $q0
; V8-UNOPT-NEXT: fmovs %f4, %f0
@@ -288,24 +290,28 @@ define void @test_fptrunc_fp128(ptr %dp, ptr %p) nounwind {
; V8-UNOPT-NEXT: ldd [%i0+8], %f4
; V8-UNOPT-NEXT: fmovs %f4, %f2
; V8-UNOPT-NEXT: fmovs %f5, %f3
+; V8-UNOPT-NEXT: add %fp, -16, %i0
+; V8-UNOPT-NEXT: st %i0, [%sp+92]
; V8-UNOPT-NEXT: fmovs %f2, %f4
; V8-UNOPT-NEXT: fmovs %f3, %f5
-; V8-UNOPT-NEXT: std %f4, [%sp+100]
+; V8-UNOPT-NEXT: std %f4, [%fp+-8]
; V8-UNOPT-NEXT: ! kill: def $d0 killed $d0 killed $q0
; V8-UNOPT-NEXT: call __trunctfhf2
-; V8-UNOPT-NEXT: std %f0, [%sp+92]
+; V8-UNOPT-NEXT: std %f0, [%fp+-16]
; V8-UNOPT-NEXT: sth %o0, [%i1]
; V8-UNOPT-NEXT: ret
; V8-UNOPT-NEXT: restore
;
; V9-LABEL: test_fptrunc_fp128:
; V9: ! %bb.0:
-; V9-NEXT: save %sp, -104, %sp
+; V9-NEXT: save %sp, -120, %sp
; V9-NEXT: ldd [%i0], %f0
; V9-NEXT: ldd [%i0+8], %f4
-; V9-NEXT: std %f4, [%sp+100]
+; V9-NEXT: add %fp, -16, %i0
+; V9-NEXT: st %i0, [%sp+92]
+; V9-NEXT: std %f4, [%fp+-8]
; V9-NEXT: call __trunctfhf2
-; V9-NEXT: std %f0, [%sp+92]
+; V9-NEXT: std %f0, [%fp+-16]
; V9-NEXT: sth %o0, [%i1]
; V9-NEXT: ret
; V9-NEXT: restore
diff --git a/llvm/test/CodeGen/SPARC/llvm.sincos.ll b/llvm/test/CodeGen/SPARC/llvm.sincos.ll
index 8d0d50f67e3f5..cc4ceb20a4651 100644
--- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll
+++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll
@@ -943,41 +943,45 @@ define { <2 x double>, <2 x double> } @test_sincos_v2f64(<2 x double> %a) #0 {
define void @test_sincos_f128(ptr sret({ fp128, fp128 }) %ret, ptr %in) #0 {
; SPARC32-LABEL: test_sincos_f128:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: save %sp, -168, %sp
+; SPARC32-NEXT: save %sp, -200, %sp
; SPARC32-NEXT: ld [%fp+64], %i1
; SPARC32-NEXT: ldd [%i0], %f0
-; SPARC32-NEXT: std %f0, [%fp+-64]
-; SPARC32-NEXT: std %f2, [%fp+-56] ! 16-byte Folded Spill
+; SPARC32-NEXT: std %f0, [%fp+-96]
+; SPARC32-NEXT: std %f2, [%fp+-88] ! 16-byte Folded Spill
; SPARC32-NEXT: ldd [%i0+8], %f4
-; SPARC32-NEXT: std %f4, [%fp+-48] ! 8-byte Folded Spill
-; SPARC32-NEXT: add %fp, -32, %i0
+; SPARC32-NEXT: std %f4, [%fp+-80] ! 8-byte Folded Spill
+; SPARC32-NEXT: add %fp, -64, %i0
+; SPARC32-NEXT: st %i0, [%sp+92]
+; SPARC32-NEXT: add %fp, -48, %i0
; SPARC32-NEXT: st %i0, [%sp+64]
-; SPARC32-NEXT: std %f4, [%sp+100]
+; SPARC32-NEXT: std %f4, [%fp+-56]
; SPARC32-NEXT: call sinl
-; SPARC32-NEXT: std %f0, [%sp+92]
+; SPARC32-NEXT: std %f0, [%fp+-64]
; SPARC32-NEXT: unimp 16
+; SPARC32-NEXT: add %fp, -32, %i0
+; SPARC32-NEXT: st %i0, [%sp+92]
; SPARC32-NEXT: add %fp, -16, %i0
; SPARC32-NEXT: st %i0, [%sp+64]
-; SPARC32-NEXT: ldd [%fp+-48], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+100]
-; SPARC32-NEXT: ldd [%fp+-64], %f0
-; SPARC32-NEXT: ldd [%fp+-56], %f2 ! 16-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+92]
-; SPARC32-NEXT: ldd [%fp+-32], %f0
-; SPARC32-NEXT: std %f0, [%fp+-48]
-; SPARC32-NEXT: std %f2, [%fp+-40] ! 16-byte Folded Spill
-; SPARC32-NEXT: ldd [%fp+-24], %f0
+; SPARC32-NEXT: ldd [%fp+-80], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-24]
+; SPARC32-NEXT: ldd [%fp+-96], %f0
+; SPARC32-NEXT: ldd [%fp+-88], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-32]
+; SPARC32-NEXT: ldd [%fp+-48], %f0
+; SPARC32-NEXT: std %f0, [%fp+-80]
+; SPARC32-NEXT: std %f2, [%fp+-72] ! 16-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-40], %f0
; SPARC32-NEXT: call cosl
-; SPARC32-NEXT: std %f0, [%fp+-64]
+; SPARC32-NEXT: std %f0, [%fp+-96]
; SPARC32-NEXT: unimp 16
; SPARC32-NEXT: ldd [%fp+-8], %f0
; SPARC32-NEXT: ldd [%fp+-16], %f4
; SPARC32-NEXT: std %f0, [%i1+24]
; SPARC32-NEXT: std %f4, [%i1+16]
-; SPARC32-NEXT: ldd [%fp+-64], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-96], %f0 ! 8-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i1+8]
-; SPARC32-NEXT: ldd [%fp+-48], %f0
-; SPARC32-NEXT: ldd [%fp+-40], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-80], %f0
+; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i1]
; SPARC32-NEXT: jmp %i7+12
; SPARC32-NEXT: restore %g0, %i1, %o0
@@ -1006,15 +1010,17 @@ define void @test_sincos_f128(ptr sret({ fp128, fp128 }) %ret, ptr %in) #0 {
;
; GNU32-LABEL: test_sincos_f128:
; GNU32: ! %bb.0:
-; GNU32-NEXT: save %sp, -136, %sp
+; GNU32-NEXT: save %sp, -152, %sp
; GNU32-NEXT: ld [%fp+64], %i1
; GNU32-NEXT: ldd [%i0], %f0
; GNU32-NEXT: ldd [%i0+8], %f4
-; GNU32-NEXT: std %f4, [%sp+100]
+; GNU32-NEXT: add %fp, -48, %i0
+; GNU32-NEXT: st %i0, [%sp+92]
+; GNU32-NEXT: std %f4, [%fp+-40]
; GNU32-NEXT: add %fp, -16, %o0
; GNU32-NEXT: add %fp, -32, %o1
; GNU32-NEXT: call sincosl
-; GNU32-NEXT: std %f0, [%sp+92]
+; GNU32-NEXT: std %f0, [%fp+-48]
; GNU32-NEXT: ldd [%fp+-24], %f0
; GNU32-NEXT: ldd [%fp+-32], %f4
; GNU32-NEXT: ldd [%fp+-8], %f2
@@ -1057,85 +1063,93 @@ define void @test_sincos_f128(ptr sret({ fp128, fp128 }) %ret, ptr %in) #0 {
define void @test_sincos_v2f128(ptr sret({ <2 x fp128>, <2 x fp128> }) %ret, ptr %in) #0 {
; SPARC32-LABEL: test_sincos_v2f128:
; SPARC32: ! %bb.0:
-; SPARC32-NEXT: save %sp, -248, %sp
+; SPARC32-NEXT: save %sp, -312, %sp
; SPARC32-NEXT: mov %i0, %i1
; SPARC32-NEXT: ld [%fp+64], %i0
; SPARC32-NEXT: ldd [%i1], %f0
-; SPARC32-NEXT: std %f0, [%fp+-80]
-; SPARC32-NEXT: std %f2, [%fp+-72] ! 16-byte Folded Spill
+; SPARC32-NEXT: std %f0, [%fp+-144]
+; SPARC32-NEXT: std %f2, [%fp+-136] ! 16-byte Folded Spill
; SPARC32-NEXT: ldd [%i1+8], %f0
-; SPARC32-NEXT: std %f0, [%fp+-88] ! 8-byte Folded Spill
+; SPARC32-NEXT: std %f0, [%fp+-152] ! 8-byte Folded Spill
; SPARC32-NEXT: ldd [%i1+16], %f0
-; SPARC32-NEXT: std %f0, [%fp+-120]
-; SPARC32-NEXT: std %f2, [%fp+-112] ! 16-byte Folded Spill
+; SPARC32-NEXT: std %f0, [%fp+-184]
+; SPARC32-NEXT: std %f2, [%fp+-176] ! 16-byte Folded Spill
; SPARC32-NEXT: ldd [%i1+24], %f4
-; SPARC32-NEXT: std %f4, [%fp+-104] ! 8-byte Folded Spill
-; SPARC32-NEXT: add %fp, -64, %i1
+; SPARC32-NEXT: std %f4, [%fp+-168] ! 8-byte Folded Spill
+; SPARC32-NEXT: add %fp, -128, %i1
+; SPARC32-NEXT: st %i1, [%sp+92]
+; SPARC32-NEXT: add %fp, -112, %i1
; SPARC32-NEXT: st %i1, [%sp+64]
-; SPARC32-NEXT: std %f4, [%sp+100]
+; SPARC32-NEXT: std %f4, [%fp+-120]
; SPARC32-NEXT: call sinl
-; SPARC32-NEXT: std %f0, [%sp+92]
+; SPARC32-NEXT: std %f0, [%fp+-128]
; SPARC32-NEXT: unimp 16
+; SPARC32-NEXT: add %fp, -32, %i1
+; SPARC32-NEXT: st %i1, [%sp+92]
; SPARC32-NEXT: add %fp, -16, %i1
; SPARC32-NEXT: st %i1, [%sp+64]
-; SPARC32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+100]
-; SPARC32-NEXT: ldd [%fp+-80], %f0
-; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-152], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-24]
+; SPARC32-NEXT: ldd [%fp+-144], %f0
+; SPARC32-NEXT: ldd [%fp+-136], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: call cosl
-; SPARC32-NEXT: std %f0, [%sp+92]
+; SPARC32-NEXT: std %f0, [%fp+-32]
; SPARC32-NEXT: unimp 16
-; SPARC32-NEXT: add %fp, -32, %i1
+; SPARC32-NEXT: add %fp, -64, %i1
+; SPARC32-NEXT: st %i1, [%sp+92]
+; SPARC32-NEXT: add %fp, -48, %i1
; SPARC32-NEXT: st %i1, [%sp+64]
-; SPARC32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+100]
-; SPARC32-NEXT: ldd [%fp+-80], %f0
-; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-152], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-56]
+; SPARC32-NEXT: ldd [%fp+-144], %f0
+; SPARC32-NEXT: ldd [%fp+-136], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: call sinl
-; SPARC32-NEXT: std %f0, [%sp+92]
+; SPARC32-NEXT: std %f0, [%fp+-64]
; SPARC32-NEXT: unimp 16
-; SPARC32-NEXT: add %fp, -48, %i1
+; SPARC32-NEXT: add %fp, -96, %i1
+; SPARC32-NEXT: st %i1, [%sp+92]
+; SPARC32-NEXT: add %fp, -80, %i1
; SPARC32-NEXT: st %i1, [%sp+64]
-; SPARC32-NEXT: ldd [%fp+-104], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+100]
-; SPARC32-NEXT: ldd [%fp+-120], %f0
-; SPARC32-NEXT: ldd [%fp+-112], %f2 ! 16-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%sp+92]
-; SPARC32-NEXT: ldd [%fp+-32], %f0
-; SPARC32-NEXT: std %f0, [%fp+-80]
-; SPARC32-NEXT: std %f2, [%fp+-72] ! 16-byte Folded Spill
-; SPARC32-NEXT: ldd [%fp+-24], %f0
-; SPARC32-NEXT: std %f0, [%fp+-88] ! 8-byte Folded Spill
-; SPARC32-NEXT: ldd [%fp+-64], %f0
-; SPARC32-NEXT: std %f0, [%fp+-104]
-; SPARC32-NEXT: std %f2, [%fp+-96] ! 16-byte Folded Spill
-; SPARC32-NEXT: ldd [%fp+-56], %f0
-; SPARC32-NEXT: std %f0, [%fp+-120] ! 8-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-168], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-88]
+; SPARC32-NEXT: ldd [%fp+-184], %f0
+; SPARC32-NEXT: ldd [%fp+-176], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: std %f0, [%fp+-96]
+; SPARC32-NEXT: ldd [%fp+-48], %f0
+; SPARC32-NEXT: std %f0, [%fp+-144]
+; SPARC32-NEXT: std %f2, [%fp+-136] ! 16-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-40], %f0
+; SPARC32-NEXT: std %f0, [%fp+-152] ! 8-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-112], %f0
+; SPARC32-NEXT: std %f0, [%fp+-168]
+; SPARC32-NEXT: std %f2, [%fp+-160] ! 16-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-104], %f0
+; SPARC32-NEXT: std %f0, [%fp+-184] ! 8-byte Folded Spill
; SPARC32-NEXT: ldd [%fp+-16], %f0
-; SPARC32-NEXT: std %f0, [%fp+-136]
-; SPARC32-NEXT: std %f2, [%fp+-128] ! 16-byte Folded Spill
+; SPARC32-NEXT: std %f0, [%fp+-200]
+; SPARC32-NEXT: std %f2, [%fp+-192] ! 16-byte Folded Spill
; SPARC32-NEXT: ldd [%fp+-8], %f0
; SPARC32-NEXT: call cosl
-; SPARC32-NEXT: std %f0, [%fp+-144]
+; SPARC32-NEXT: std %f0, [%fp+-208]
; SPARC32-NEXT: unimp 16
-; SPARC32-NEXT: ldd [%fp+-40], %f0
-; SPARC32-NEXT: ldd [%fp+-48], %f4
+; SPARC32-NEXT: ldd [%fp+-72], %f0
+; SPARC32-NEXT: ldd [%fp+-80], %f4
; SPARC32-NEXT: std %f0, [%i0+56]
; SPARC32-NEXT: std %f4, [%i0+48]
-; SPARC32-NEXT: ldd [%fp+-144], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-208], %f0 ! 8-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0+40]
-; SPARC32-NEXT: ldd [%fp+-136], %f0
-; SPARC32-NEXT: ldd [%fp+-128], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-200], %f0
+; SPARC32-NEXT: ldd [%fp+-192], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0+32]
-; SPARC32-NEXT: ldd [%fp+-120], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-184], %f0 ! 8-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0+24]
-; SPARC32-NEXT: ldd [%fp+-104], %f0
-; SPARC32-NEXT: ldd [%fp+-96], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-168], %f0
+; SPARC32-NEXT: ldd [%fp+-160], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0+16]
-; SPARC32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-152], %f0 ! 8-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0+8]
-; SPARC32-NEXT: ldd [%fp+-80], %f0
-; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload
+; SPARC32-NEXT: ldd [%fp+-144], %f0
+; SPARC32-NEXT: ldd [%fp+-136], %f2 ! 16-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i0]
; SPARC32-NEXT: jmp %i7+12
; SPARC32-NEXT: restore
@@ -1186,37 +1200,41 @@ define void @test_sincos_v2f128(ptr sret({ <2 x fp128>, <2 x fp128> }) %ret, ptr
;
; GNU32-LABEL: test_sincos_v2f128:
; GNU32: ! %bb.0:
-; GNU32-NEXT: save %sp, -192, %sp
+; GNU32-NEXT: save %sp, -224, %sp
; GNU32-NEXT: mov %i0, %i1
; GNU32-NEXT: ld [%fp+64], %i0
; GNU32-NEXT: ldd [%i1+16], %f0
-; GNU32-NEXT: std %f0, [%fp+-80]
-; GNU32-NEXT: std %f2, [%fp+-72] ! 16-byte Folded Spill
+; GNU32-NEXT: std %f0, [%fp+-112]
+; GNU32-NEXT: std %f2, [%fp+-104] ! 16-byte Folded Spill
; GNU32-NEXT: ldd [%i1+24], %f0
-; GNU32-NEXT: std %f0, [%fp+-88] ! 8-byte Folded Spill
+; GNU32-NEXT: std %f0, [%fp+-120] ! 8-byte Folded Spill
; GNU32-NEXT: ldd [%i1], %f0
; GNU32-NEXT: ldd [%i1+8], %f4
-; GNU32-NEXT: std %f4, [%sp+100]
-; GNU32-NEXT: add %fp, -48, %o0
-; GNU32-NEXT: add %fp, -64, %o1
+; GNU32-NEXT: add %fp, -96, %i1
+; GNU32-NEXT: st %i1, [%sp+92]
+; GNU32-NEXT: std %f4, [%fp+-88]
+; GNU32-NEXT: add %fp, -64, %o0
+; GNU32-NEXT: add %fp, -80, %o1
; GNU32-NEXT: call sincosl
-; GNU32-NEXT: std %f0, [%sp+92]
-; GNU32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload
-; GNU32-NEXT: std %f0, [%sp+100]
+; GNU32-NEXT: std %f0, [%fp+-96]
+; GNU32-NEXT: add %fp, -48, %i1
+; GNU32-NEXT: st %i1, [%sp+92]
+; GNU32-NEXT: ldd [%fp+-120], %f0 ! 8-byte Folded Reload
+; GNU32-NEXT: std %f0, [%fp+-40]
; GNU32-NEXT: add %fp, -16, %o0
; GNU32-NEXT: add %fp, -32, %o1
-; GNU32-NEXT: ldd [%fp+-80], %f0
-; GNU32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload
+; GNU32-NEXT: ldd [%fp+-112], %f0
+; GNU32-NEXT: ldd [%fp+-104], %f2 ! 16-byte Folded Reload
; GNU32-NEXT: call sincosl
-; GNU32-NEXT: std %f0, [%sp+92]
-; GNU32-NEXT: ldd [%fp+-48], %f0
-; GNU32-NEXT: ldd [%fp+-40], %f8
+; GNU32-NEXT: std %f0, [%fp+-48]
+; GNU32-NEXT: ldd [%fp+-64], %f0
+; GNU32-NEXT: ldd [%fp+-56], %f8
; GNU32-NEXT: ldd [%fp+-16], %f4
; GNU32-NEXT: ldd [%fp+-8], %f10
; GNU32-NEXT: ldd [%fp+-24], %f12
; GNU32-NEXT: ldd [%fp+-32], %f16
-; GNU32-NEXT: ldd [%fp+-56], %f14
-; GNU32-NEXT: ldd [%fp+-64], %f20
+; GNU32-NEXT: ldd [%fp+-72], %f14
+; GNU32-NEXT: ldd [%fp+-80], %f20
; GNU32-NEXT: std %f12, [%i0+56]
; GNU32-NEXT: std %f16, [%i0+48]
; GNU32-NEXT: std %f14, [%i0+40]
>From 4f6405dac384ea6c2d41c3470d090883284bb189 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Tue, 14 Oct 2025 08:46:19 +0700
Subject: [PATCH 3/4] Update tests
---
clang/test/Preprocessor/init.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c
index 7e0df96141364..3ef33de35f9ec 100644
--- a/clang/test/Preprocessor/init.c
+++ b/clang/test/Preprocessor/init.c
@@ -1106,19 +1106,19 @@
// SPARC:#define __INT_LEAST8_MAX__ 127
// SPARC:#define __INT_LEAST8_TYPE__ signed char
// SPARC:#define __INT_MAX__ 2147483647
-// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
-// SPARC:#define __LDBL_DIG__ 15
-// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
+// SPARC:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// SPARC:#define __LDBL_DIG__ 33
+// SPARC:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// SPARC:#define __LDBL_HAS_DENORM__ 1
// SPARC:#define __LDBL_HAS_INFINITY__ 1
// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
-// SPARC:#define __LDBL_MANT_DIG__ 53
-// SPARC:#define __LDBL_MAX_10_EXP__ 308
-// SPARC:#define __LDBL_MAX_EXP__ 1024
-// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308L
-// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
-// SPARC:#define __LDBL_MIN_EXP__ (-1021)
-// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308L
+// SPARC:#define __LDBL_MANT_DIG__ 113
+// SPARC:#define __LDBL_MAX_10_EXP__ 4932
+// SPARC:#define __LDBL_MAX_EXP__ 16384
+// SPARC:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// SPARC:#define __LDBL_MIN_10_EXP__ (-4931)
+// SPARC:#define __LDBL_MIN_EXP__ (-16381)
+// SPARC:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// SPARC:#define __LONG_MAX__ 2147483647L
// SPARC-NOT:#define __LP64__
@@ -1134,7 +1134,7 @@
// SPARC:#define __SIZEOF_DOUBLE__ 8
// SPARC:#define __SIZEOF_FLOAT__ 4
// SPARC:#define __SIZEOF_INT__ 4
-// SPARC:#define __SIZEOF_LONG_DOUBLE__ 8
+// SPARC:#define __SIZEOF_LONG_DOUBLE__ 16
// SPARC:#define __SIZEOF_LONG_LONG__ 8
// SPARC:#define __SIZEOF_LONG__ 4
// SPARC:#define __SIZEOF_POINTER__ 4
>From c86a0485e250acf8aba040916b039406ab47fdc7 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Wed, 15 Oct 2025 13:05:14 +0700
Subject: [PATCH 4/4] Remove redundant checks
---
clang/lib/CodeGen/Targets/Sparc.cpp | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp
index 80a2b3d6c0085..f67b794f80491 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -31,20 +31,8 @@ class SparcV8ABIInfo : public DefaultABIInfo {
};
} // end anonymous namespace
-
-ABIArgInfo
-SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
- const BuiltinType *BT = Ty->getAs<BuiltinType>();
- bool IsF128 = false;
-
+ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
- IsF128 = true;
-
- // FIXME not sure if redundant
- if (BT && BT->getKind() == BuiltinType::LongDouble)
- IsF128 = true;
-
- if (IsF128)
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
if (Ty->isAnyComplexType()) {
@@ -57,17 +45,7 @@ SparcV8ABIInfo::classifyReturnType(QualType Ty) const {
}
ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {
- const BuiltinType *BT = Ty->getAs<BuiltinType>();
- bool IsF128 = false;
-
if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128)
- IsF128 = true;
-
- // FIXME not sure if redundant
- if (BT && BT->getKind() == BuiltinType::LongDouble)
- IsF128 = true;
-
- if (IsF128)
return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
return DefaultABIInfo::classifyArgumentType(Ty);
More information about the cfe-commits
mailing list