https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/162226
>From 0c5c263bf23f0b102b829a9d95cf4adfdc49630f Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 7 Oct 2025 12:55:39 +0700 Subject: [PATCH 1/7] [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 cbb7db68f7e7c..a73cf69df1ca4 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -555,20 +555,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); } @@ -914,7 +913,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 20f96a7d569ca6b4e1165687fed37401a3f150da Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 13 Oct 2025 22:30:53 +0700 Subject: [PATCH 2/7] 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 a73cf69df1ca4..4abc74012fb38 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -555,11 +555,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."); @@ -835,6 +858,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; @@ -1028,6 +1053,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 2836fb70caa56853414d01cbb4d345ae4f7703c9 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 14 Oct 2025 08:46:19 +0700 Subject: [PATCH 3/7] 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 4dea1b583a089..32c758699120e 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 77a33f868918320fa3daace0c52efe67cf53ef53 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Wed, 15 Oct 2025 13:05:14 +0700 Subject: [PATCH 4/7] 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); >From 65c0156304f2d721e419f9bd4181e946f0fd6abc Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 20 Oct 2025 14:37:12 +0700 Subject: [PATCH 5/7] Un-xfail tests that are now passing --- compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c | 3 --- compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c | 3 --- compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp | 3 --- compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp | 3 --- 4 files changed, 12 deletions(-) diff --git a/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c index cfe8d800d3834..f6629ab81c3b3 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c +++ b/compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c @@ -1,8 +1,5 @@ // RUN: %clang %s -o %t && %run %t 2>&1 -// Issue #41838 -// XFAIL: sparc-target-arch && target={{.*solaris.*}} - #include <assert.h> #include <stdio.h> #include <string.h> diff --git a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c index a38f34a245fae..9ca30f4a65688 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c +++ b/compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c @@ -1,8 +1,5 @@ // RUN: %clang %s -o %t && %run %t 2>&1 -// Issue #41838 -// XFAIL: sparc-target-arch && target={{.*solaris.*}} - #include <assert.h> #include <stdio.h> #include <string.h> diff --git a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp index 8638bf69f749e..80063b7a0f9f9 100644 --- a/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp +++ b/compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp @@ -9,9 +9,6 @@ // RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6 // RUN: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7 -// Issue #41838 -// XFAIL: sparc-target-arch && target={{.*solaris.*}} - // This test assumes float and double are IEEE-754 single- and double-precision. #if defined(__APPLE__) diff --git a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp index 4773884cb4cc0..3fd02957a6903 100644 --- a/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp +++ b/compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp @@ -24,9 +24,6 @@ // FIXME: log_path is not supported on Windows yet. // XFAIL: target={{.*windows-msvc.*}} -// Issue #41838 -// XFAIL: sparc-target-arch && target={{.*solaris.*}} - #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { >From b3a57f3d1788ec4a7b711bf2d623d06c0e4385b7 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Wed, 29 Oct 2025 19:07:34 +0700 Subject: [PATCH 6/7] Fix long double __Complex returns --- llvm/lib/Target/Sparc/SparcCallingConv.td | 1 + llvm/test/CodeGen/SPARC/llvm.sincos.ll | 170 +++++++++------------- 2 files changed, 67 insertions(+), 104 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index 55be696c14a78..1cc73688185c1 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -34,6 +34,7 @@ def RetCC_Sparc32 : CallingConv<[ CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>, CCIfType<[f64], CCAssignToReg<[D0, D1]>>, + CCIfType<[f128], CCAssignToReg<[Q0, Q1]>>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; diff --git a/llvm/test/CodeGen/SPARC/llvm.sincos.ll b/llvm/test/CodeGen/SPARC/llvm.sincos.ll index cc4ceb20a4651..bbb8906974fb5 100644 --- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll +++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll @@ -943,45 +943,33 @@ 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, -200, %sp +; SPARC32-NEXT: save %sp, -176, %sp ; SPARC32-NEXT: ld [%fp+64], %i1 ; SPARC32-NEXT: ldd [%i0], %f0 -; SPARC32-NEXT: std %f0, [%fp+-96] -; SPARC32-NEXT: std %f2, [%fp+-88] ! 16-byte Folded Spill +; SPARC32-NEXT: std %f0, [%fp+-72] +; SPARC32-NEXT: std %f2, [%fp+-64] ! 16-byte Folded Spill ; SPARC32-NEXT: ldd [%i0+8], %f4 -; 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, [%fp+-56] -; SPARC32-NEXT: call sinl -; SPARC32-NEXT: std %f0, [%fp+-64] -; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: std %f4, [%fp+-56] ! 8-byte Folded Spill ; 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+-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 %f4, [%fp+-24] +; SPARC32-NEXT: call sinl ; 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: std %f0, [%fp+-48] +; SPARC32-NEXT: std %f2, [%fp+-40] ! 16-byte Folded Spill +; SPARC32-NEXT: add %fp, -16, %i0 +; SPARC32-NEXT: st %i0, [%sp+92] +; SPARC32-NEXT: ldd [%fp+-56], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-8] +; SPARC32-NEXT: ldd [%fp+-72], %f0 +; SPARC32-NEXT: ldd [%fp+-64], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call cosl -; 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+-96], %f0 ! 8-byte Folded Reload -; SPARC32-NEXT: std %f0, [%i1+8] -; SPARC32-NEXT: ldd [%fp+-80], %f0 -; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-16] +; SPARC32-NEXT: std %f2, [%i1+24] +; SPARC32-NEXT: std %f0, [%i1+16] +; SPARC32-NEXT: ldd [%fp+-48], %f0 +; SPARC32-NEXT: ldd [%fp+-40], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f2, [%i1+8] ; SPARC32-NEXT: std %f0, [%i1] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore %g0, %i1, %o0 @@ -1063,93 +1051,67 @@ 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, -312, %sp +; SPARC32-NEXT: save %sp, -256, %sp ; SPARC32-NEXT: mov %i0, %i1 ; SPARC32-NEXT: ld [%fp+64], %i0 -; SPARC32-NEXT: ldd [%i1], %f0 -; 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+-152] ! 8-byte Folded Spill ; SPARC32-NEXT: ldd [%i1+16], %f0 -; 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+-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, [%fp+-120] -; SPARC32-NEXT: call sinl -; SPARC32-NEXT: std %f0, [%fp+-128] -; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: std %f0, [%fp+-80] +; SPARC32-NEXT: std %f2, [%fp+-72] ! 16-byte Folded Spill +; SPARC32-NEXT: ldd [%i1+24], %f0 +; SPARC32-NEXT: std %f0, [%fp+-88] ! 8-byte Folded Spill +; SPARC32-NEXT: ldd [%i1], %f0 +; SPARC32-NEXT: std %f0, [%fp+-152] +; SPARC32-NEXT: std %f2, [%fp+-144] ! 16-byte Folded Spill +; SPARC32-NEXT: ldd [%i1+8], %f4 +; SPARC32-NEXT: std %f4, [%fp+-136] ! 8-byte Folded Spill ; 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+-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 %f4, [%fp+-24] +; SPARC32-NEXT: call sinl ; SPARC32-NEXT: std %f0, [%fp+-32] -; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: std %f0, [%fp+-104] +; SPARC32-NEXT: std %f2, [%fp+-96] ! 16-byte Folded Spill ; 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+-152], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: ldd [%fp+-88], %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: ldd [%fp+-80], %f0 +; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call sinl ; SPARC32-NEXT: std %f0, [%fp+-64] -; SPARC32-NEXT: unimp 16 -; SPARC32-NEXT: add %fp, -96, %i1 +; SPARC32-NEXT: std %f0, [%fp+-120] +; SPARC32-NEXT: std %f2, [%fp+-112] ! 16-byte Folded Spill +; SPARC32-NEXT: add %fp, -16, %i1 ; SPARC32-NEXT: st %i1, [%sp+92] -; SPARC32-NEXT: add %fp, -80, %i1 -; SPARC32-NEXT: st %i1, [%sp+64] -; 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+-200] -; SPARC32-NEXT: std %f2, [%fp+-192] ! 16-byte Folded Spill -; SPARC32-NEXT: ldd [%fp+-8], %f0 +; SPARC32-NEXT: ldd [%fp+-136], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-8] +; SPARC32-NEXT: ldd [%fp+-152], %f0 +; SPARC32-NEXT: ldd [%fp+-144], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call cosl -; SPARC32-NEXT: std %f0, [%fp+-208] -; SPARC32-NEXT: unimp 16 -; 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+-208], %f0 ! 8-byte Folded Reload -; SPARC32-NEXT: std %f0, [%i0+40] -; SPARC32-NEXT: ldd [%fp+-200], %f0 -; SPARC32-NEXT: ldd [%fp+-192], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-16] +; SPARC32-NEXT: std %f0, [%fp+-136] +; SPARC32-NEXT: std %f2, [%fp+-128] ! 16-byte Folded Spill +; SPARC32-NEXT: add %fp, -48, %i1 +; SPARC32-NEXT: st %i1, [%sp+92] +; SPARC32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-40] +; SPARC32-NEXT: ldd [%fp+-80], %f0 +; SPARC32-NEXT: ldd [%fp+-72], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: call cosl +; SPARC32-NEXT: std %f0, [%fp+-48] +; SPARC32-NEXT: std %f2, [%i0+56] +; SPARC32-NEXT: std %f0, [%i0+48] +; SPARC32-NEXT: ldd [%fp+-136], %f0 +; SPARC32-NEXT: ldd [%fp+-128], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f2, [%i0+40] ; SPARC32-NEXT: std %f0, [%i0+32] -; SPARC32-NEXT: ldd [%fp+-184], %f0 ! 8-byte Folded Reload -; SPARC32-NEXT: std %f0, [%i0+24] -; SPARC32-NEXT: ldd [%fp+-168], %f0 -; SPARC32-NEXT: ldd [%fp+-160], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: ldd [%fp+-120], %f0 +; SPARC32-NEXT: ldd [%fp+-112], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f2, [%i0+24] ; SPARC32-NEXT: std %f0, [%i0+16] -; SPARC32-NEXT: ldd [%fp+-152], %f0 ! 8-byte Folded Reload -; SPARC32-NEXT: std %f0, [%i0+8] -; SPARC32-NEXT: ldd [%fp+-144], %f0 -; SPARC32-NEXT: ldd [%fp+-136], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: ldd [%fp+-104], %f0 +; SPARC32-NEXT: ldd [%fp+-96], %f2 ! 16-byte Folded Reload +; SPARC32-NEXT: std %f2, [%i0+8] ; SPARC32-NEXT: std %f0, [%i0] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore >From cf4e5281d103dd0e07fe73058632baf774c1f424 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 10 Nov 2025 10:34:57 +0700 Subject: [PATCH 7/7] Apply suggestions --- clang/lib/CodeGen/Targets/Sparc.cpp | 5 +---- clang/test/CodeGen/sparcv8-abi.c | 7 +++++++ compiler-rt/lib/builtins/CMakeLists.txt | 2 +- llvm/test/CodeGen/SPARC/fp128.ll | 18 +++++++++++++++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index f67b794f80491..7f7eb959d8809 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -36,9 +36,7 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); if (Ty->isAnyComplexType()) { - auto AI = ABIArgInfo::getDirect(); - AI.setInReg(true); - return AI; + return ABIArgInfo::getDirectInReg(); } return DefaultABIInfo::classifyReturnType(Ty); @@ -52,7 +50,6 @@ ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const { } void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { - FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); for (auto &Arg : FI.arguments()) Arg.info = classifyArgumentType(Arg.type); diff --git a/clang/test/CodeGen/sparcv8-abi.c b/clang/test/CodeGen/sparcv8-abi.c index 07a90cd8087df..4e53e50cd2c0d 100644 --- a/clang/test/CodeGen/sparcv8-abi.c +++ b/clang/test/CodeGen/sparcv8-abi.c @@ -27,3 +27,10 @@ s(long double a) { return 0; } + +// CHECK-LABEL: define{{.*}} { fp128, fp128 } @t(ptr noundef byval({ fp128, fp128 }) align 8 %a) #0 +long double _Complex +t(long double _Complex a) +{ + return 0; +} diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 790bf5758f4a2..0e74d39368f6c 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -962,7 +962,7 @@ else () # For RISCV32 and 32-bit SPARC, we must force enable int128 for compiling long # double routines. - if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" MATCHES "riscv32|sparc$" AND NOT CMAKE_COMPILER_IS_GNUCC) + if(COMPILER_RT_ENABLE_SOFTWARE_INT128 OR "${arch}" STREQUAL "riscv32" OR ("${arch}" STREQUAL "sparc" AND NOT CMAKE_COMPILER_IS_GNUCC)) list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128) endif() diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index fbdc99394eb9e..5a0c7031b7a15 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -242,7 +242,23 @@ entry: ret void } -define fp128 @f128_direct(fp128 %num) { +define fp128 @f128_direct(fp128 %num) nounwind { +; CHECK-LABEL: f128_direct: +; CHECK: ! %bb.0: +; CHECK-NEXT: save %sp, -136, %sp +; CHECK-NEXT: ldd [%fp+92], %f0 +; CHECK-NEXT: ldd [%fp+100], %f4 +; CHECK-NEXT: add %fp, -32, %i0 +; CHECK-NEXT: st %i0, [%sp+96] +; CHECK-NEXT: add %fp, -16, %i0 +; CHECK-NEXT: st %i0, [%sp+92] +; CHECK-NEXT: std %f4, [%fp+-24] +; CHECK-NEXT: std %f0, [%fp+-32] +; CHECK-NEXT: std %f4, [%fp+-8] +; CHECK-NEXT: call f128_callee +; CHECK-NEXT: std %f0, [%fp+-16] +; CHECK-NEXT: ret +; CHECK-NEXT: restore %ret = call fp128 @f128_callee(fp128 %num, fp128 %num) ret fp128 %ret } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
