https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/162226
>From ff3ad98dfe826048a60b035269e85e9b196085d4 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 7 Oct 2025 12:55:39 +0700 Subject: [PATCH 01/15] [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 e781c2460e488..01f9c38766be5 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -1009,9 +1009,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 8e3cb35183ba7..cef23ba557b9e 100644 --- a/compiler-rt/test/builtins/CMakeLists.txt +++ b/compiler-rt/test/builtins/CMakeLists.txt @@ -48,7 +48,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 dc1196127e3d4..001e4a39b20fd 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 84b1b6dfcdc093b082e7e2ababe5ffffd54afb43 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 13 Oct 2025 22:30:53 +0700 Subject: [PATCH 02/15] Implement indirect argument handling in LowerCall/FormalArguments --- clang/lib/CodeGen/Targets/Sparc.cpp | 10 + clang/test/CodeGen/Sparc/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/Sparc/sparcv8-abi.c b/clang/test/CodeGen/Sparc/sparcv8-abi.c index c5faf130890f8..07a90cd8087df 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/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 001e4a39b20fd..beaf63afb1e98 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 0c673aea9fe784b5fedc4a4c6cfec1daa8a456a9 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 14 Oct 2025 08:46:19 +0700 Subject: [PATCH 03/15] 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 aee28958addc855b75011f8817afe9a5da410256 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Wed, 15 Oct 2025 13:05:14 +0700 Subject: [PATCH 04/15] 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 f62d4df9d6141e92530ce6bb08bb69a074aeef35 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 20 Oct 2025 14:37:12 +0700 Subject: [PATCH 05/15] 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 b283fee20a8d96084fdecb88efa2483876ae52ed Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Wed, 29 Oct 2025 19:07:34 +0700 Subject: [PATCH 06/15] 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 8724a592352026ace068a2c9c74f92e864038b5a Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 10 Nov 2025 10:34:57 +0700 Subject: [PATCH 07/15] Apply suggestions --- clang/lib/CodeGen/Targets/Sparc.cpp | 5 +---- clang/test/CodeGen/Sparc/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/Sparc/sparcv8-abi.c b/clang/test/CodeGen/Sparc/sparcv8-abi.c index 07a90cd8087df..4e53e50cd2c0d 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/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 01f9c38766be5..93d9e4b9242c5 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -1011,7 +1011,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 } >From 5e8aa4a1871d12ef53f3be1eebbd44b597317c15 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 18 Nov 2025 22:45:05 +0700 Subject: [PATCH 08/15] Try to make complex f128 work --- clang/test/CodeGen/Sparc/sparcv8-abi.c | 2 +- llvm/lib/Target/Sparc/SparcCallingConv.td | 2 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 20 ++- llvm/test/CodeGen/SPARC/fp128.ll | 24 ++- llvm/test/CodeGen/SPARC/llvm.sincos.ll | 170 ++++++++++++-------- 5 files changed, 140 insertions(+), 78 deletions(-) diff --git a/clang/test/CodeGen/Sparc/sparcv8-abi.c b/clang/test/CodeGen/Sparc/sparcv8-abi.c index 4e53e50cd2c0d..67f0dea611aef 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c @@ -28,7 +28,7 @@ s(long double a) return 0; } -// CHECK-LABEL: define{{.*}} { fp128, fp128 } @t(ptr noundef byval({ fp128, fp128 }) align 8 %a) #0 +// CHECK-LABEL: define{{.*}}inreg{{.*}} { fp128, fp128 } @t(ptr noundef byval({ fp128, fp128 }) align 8 %a) #0 long double _Complex t(long double _Complex a) { diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index 1cc73688185c1..d50aa2cf449b6 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -34,7 +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<[f128], CCCustom<"CC_Sparc_Assign_Ret_F128">>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index beaf63afb1e98..1a315a190a3bf 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -106,6 +106,23 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, return true; } +static bool CC_Sparc_Assign_Ret_F128(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const MCPhysReg RegList[] = {SP::Q0, SP::Q1}; + + if (!ArgFlags.isInReg()) + return false; + + if (Register Reg = State.AllocateReg(RegList)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else + return false; + + return true; +} + // Allocate a full-sized argument for the 64-bit ABI. static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, @@ -289,8 +306,7 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, SDValue Arg = OutVals[realRVLocIdx]; - if (VA.needsCustom()) { - assert(VA.getLocVT() == MVT::v2i32); + if (VA.needsCustom() && VA.getLocVT() == MVT::v2i32) { // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would // happen by default if this wasn't a legal type) diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index 5a0c7031b7a15..3529d091145a6 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -245,18 +245,26 @@ entry: define fp128 @f128_direct(fp128 %num) nounwind { ; CHECK-LABEL: f128_direct: ; CHECK: ! %bb.0: -; CHECK-NEXT: save %sp, -136, %sp +; CHECK-NEXT: save %sp, -152, %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: ld [%fp+64], %i0 +; CHECK-NEXT: add %fp, -48, %i1 +; CHECK-NEXT: st %i1, [%sp+96] +; CHECK-NEXT: add %fp, -32, %i1 +; CHECK-NEXT: st %i1, [%sp+92] +; CHECK-NEXT: add %fp, -16, %i1 +; CHECK-NEXT: st %i1, [%sp+64] +; CHECK-NEXT: std %f4, [%fp+-40] +; CHECK-NEXT: std %f0, [%fp+-48] ; 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: std %f0, [%fp+-32] +; CHECK-NEXT: unimp 16 +; CHECK-NEXT: ldd [%fp+-8], %f0 +; CHECK-NEXT: ldd [%fp+-16], %f4 +; CHECK-NEXT: std %f0, [%i0+8] +; CHECK-NEXT: std %f4, [%i0] ; CHECK-NEXT: ret ; CHECK-NEXT: restore %ret = call fp128 @f128_callee(fp128 %num, fp128 %num) diff --git a/llvm/test/CodeGen/SPARC/llvm.sincos.ll b/llvm/test/CodeGen/SPARC/llvm.sincos.ll index bbb8906974fb5..cc4ceb20a4651 100644 --- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll +++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll @@ -943,33 +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, -176, %sp +; SPARC32-NEXT: save %sp, -200, %sp ; SPARC32-NEXT: ld [%fp+64], %i1 ; SPARC32-NEXT: ldd [%i0], %f0 -; SPARC32-NEXT: std %f0, [%fp+-72] -; SPARC32-NEXT: std %f2, [%fp+-64] ! 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+-56] ! 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: std %f4, [%fp+-24] +; 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+-32] -; SPARC32-NEXT: std %f0, [%fp+-48] -; SPARC32-NEXT: std %f2, [%fp+-40] ! 16-byte Folded Spill -; SPARC32-NEXT: add %fp, -16, %i0 +; SPARC32-NEXT: std %f0, [%fp+-64] +; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: add %fp, -32, %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+-16] -; SPARC32-NEXT: std %f2, [%i1+24] -; SPARC32-NEXT: std %f0, [%i1+16] +; 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 %f0, [%fp+-32] ; 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, [%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+-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, [%i1] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore %g0, %i1, %o0 @@ -1051,67 +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, -256, %sp +; SPARC32-NEXT: save %sp, -312, %sp ; SPARC32-NEXT: mov %i0, %i1 ; SPARC32-NEXT: ld [%fp+64], %i0 -; SPARC32-NEXT: ldd [%i1+16], %f0 -; 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: 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: std %f4, [%fp+-24] +; 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: 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 %f0, [%fp+-32] -; SPARC32-NEXT: std %f0, [%fp+-104] -; SPARC32-NEXT: std %f2, [%fp+-96] ! 16-byte Folded Spill +; SPARC32-NEXT: unimp 16 ; SPARC32-NEXT: add %fp, -64, %i1 ; SPARC32-NEXT: st %i1, [%sp+92] -; SPARC32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: add %fp, -48, %i1 +; SPARC32-NEXT: st %i1, [%sp+64] +; SPARC32-NEXT: ldd [%fp+-152], %f0 ! 8-byte Folded Reload ; SPARC32-NEXT: std %f0, [%fp+-56] -; 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: call sinl ; SPARC32-NEXT: std %f0, [%fp+-64] -; 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: 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+-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: unimp 16 +; SPARC32-NEXT: add %fp, -96, %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: 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: 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, [%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, [%i0+32] -; SPARC32-NEXT: ldd [%fp+-120], %f0 -; SPARC32-NEXT: ldd [%fp+-112], %f2 ! 16-byte Folded Reload -; SPARC32-NEXT: std %f2, [%i0+24] +; 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: std %f0, [%i0+16] -; SPARC32-NEXT: ldd [%fp+-104], %f0 -; SPARC32-NEXT: ldd [%fp+-96], %f2 ! 16-byte Folded Reload -; SPARC32-NEXT: std %f2, [%i0+8] +; 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: std %f0, [%i0] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore >From f9ed024a6e9a53d2cd5622a98fe334979a532ce6 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Tue, 18 Nov 2025 23:02:52 +0700 Subject: [PATCH 09/15] Apply suggestions --- clang/lib/CodeGen/Targets/Sparc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 7f7eb959d8809..df497d2b47b6c 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -32,7 +32,8 @@ class SparcV8ABIInfo : public DefaultABIInfo { } // end anonymous namespace ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { - if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128) + if (const auto *BT = Ty->getAs<BuiltinType>(); + BT && BT->getKind() == BuiltinType::LongDouble) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); if (Ty->isAnyComplexType()) { @@ -43,7 +44,8 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { } ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const { - if (Ty->isRealFloatingType() && getContext().getTypeSize(Ty) == 128) + if (const auto *BT = Ty->getAs<BuiltinType>(); + BT && BT->getKind() == BuiltinType::LongDouble) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); return DefaultABIInfo::classifyArgumentType(Ty); >From ff6e10e262158f53518fc7317f757e22c00c2ab7 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Sun, 23 Nov 2025 10:21:16 +0700 Subject: [PATCH 10/15] Apply suggestions --- clang/lib/CodeGen/Targets/Sparc.cpp | 3 +-- llvm/lib/Target/Sparc/SparcCallingConv.td | 2 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 20 ++------------------ 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index df497d2b47b6c..1aa370cead357 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -36,9 +36,8 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { BT && BT->getKind() == BuiltinType::LongDouble) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); - if (Ty->isAnyComplexType()) { + if (Ty->isAnyComplexType()) return ABIArgInfo::getDirectInReg(); - } return DefaultABIInfo::classifyReturnType(Ty); } diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index d50aa2cf449b6..2782aecdc1101 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -34,7 +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], CCCustom<"CC_Sparc_Assign_Ret_F128">>, + CCIfType<[f128], CCIfInReg<CCAssignToReg<[Q0, Q1]>>>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 1a315a190a3bf..beaf63afb1e98 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -106,23 +106,6 @@ static bool CC_Sparc_Assign_Ret_Split_64(unsigned &ValNo, MVT &ValVT, return true; } -static bool CC_Sparc_Assign_Ret_F128(unsigned &ValNo, MVT &ValVT, MVT &LocVT, - CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, - CCState &State) { - static const MCPhysReg RegList[] = {SP::Q0, SP::Q1}; - - if (!ArgFlags.isInReg()) - return false; - - if (Register Reg = State.AllocateReg(RegList)) - State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - else - return false; - - return true; -} - // Allocate a full-sized argument for the 64-bit ABI. static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, @@ -306,7 +289,8 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv, SDValue Arg = OutVals[realRVLocIdx]; - if (VA.needsCustom() && VA.getLocVT() == MVT::v2i32) { + if (VA.needsCustom()) { + assert(VA.getLocVT() == MVT::v2i32); // Legalize ret v2i32 -> ret 2 x i32 (Basically: do what would // happen by default if this wasn't a legal type) >From e38af2a622ac5387804d9ce33f9181f127b98f9c Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 24 Nov 2025 09:03:02 +0700 Subject: [PATCH 11/15] Use CCIfConsecutiveRegs --- llvm/lib/Target/Sparc/SparcCallingConv.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index 2782aecdc1101..a87680ab36c48 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -34,7 +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], CCIfInReg<CCAssignToReg<[Q0, Q1]>>>, + CCIfType<[f128], CCIfInReg<CCIfConsecutiveRegs<CCAssignToReg<[Q0, Q1]>>>>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; >From cb69bc66f8a9c649e348747573ee060d02a61e47 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 24 Nov 2025 09:47:26 +0700 Subject: [PATCH 12/15] inreg should only apply to long double _Complex --- clang/lib/CodeGen/Targets/Sparc.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 1aa370cead357..17fe26222c29d 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -32,13 +32,20 @@ class SparcV8ABIInfo : public DefaultABIInfo { } // end anonymous namespace ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { - if (const auto *BT = Ty->getAs<BuiltinType>(); - BT && BT->getKind() == BuiltinType::LongDouble) + const auto *CT = Ty->getAs<ComplexType>(); + const auto *BT = Ty->getAs<BuiltinType>(); + if (CT) + BT = CT->getElementType()->getAs<BuiltinType>(); + bool IsLongDouble = BT && BT->getKind() == BuiltinType::LongDouble; + + // long double _Complex is special in that it should be marked as inreg. + if (CT) + return IsLongDouble ? ABIArgInfo::getDirectInReg() + : ABIArgInfo::getDirect(); + + if (IsLongDouble) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); - if (Ty->isAnyComplexType()) - return ABIArgInfo::getDirectInReg(); - return DefaultABIInfo::classifyReturnType(Ty); } >From 34bfc88ff4b9d284d97f6c4bd5405d0696b5b17d Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 24 Nov 2025 13:18:57 +0700 Subject: [PATCH 13/15] Use autogenerated tests --- clang/test/CodeGen/Sparc/sparcv8-abi.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/clang/test/CodeGen/Sparc/sparcv8-abi.c b/clang/test/CodeGen/Sparc/sparcv8-abi.c index 67f0dea611aef..7beddd20e5e4d 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c @@ -1,35 +1,51 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 6 // RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s -// CHECK-LABEL: define{{.*}} { float, float } @p(ptr noundef byval({ float, float }) align 4 %a, ptr noundef byval({ float, float }) align 4 %b) #0 { float __complex__ +// CHECK-LABEL: define dso_local { float, float } @p( +// CHECK-SAME: ptr noundef byval({ float, float }) align 4 [[A:%.*]], ptr noundef byval({ float, float }) align 4 [[B:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK: [[ENTRY:.*:]] +// p (float __complex__ a, float __complex__ b) { return 0; } -// CHECK-LABEL: define{{.*}} { double, double } @q(ptr noundef byval({ double, double }) align 8 %a, ptr noundef byval({ double, double }) align 8 %b) #0 { double __complex__ +// CHECK-LABEL: define dso_local { double, double } @q( +// CHECK-SAME: ptr noundef byval({ double, double }) align 8 [[A:%.*]], ptr noundef byval({ double, double }) align 8 [[B:%.*]]) #[[ATTR0]] { +// CHECK: [[ENTRY:.*:]] +// q (double __complex__ a, double __complex__ b) { return 0; } -// CHECK-LABEL: define{{.*}} { i64, i64 } @r(ptr noundef byval({ i64, i64 }) align 8 %a, ptr noundef byval({ i64, i64 }) align 8 %b) #0 { long long __complex__ +// CHECK-LABEL: define dso_local { i64, i64 } @r( +// CHECK-SAME: ptr noundef byval({ i64, i64 }) align 8 [[A:%.*]], ptr noundef byval({ i64, i64 }) align 8 [[B:%.*]]) #[[ATTR0]] { +// CHECK: [[ENTRY:.*:]] +// 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 +// CHECK-LABEL: define dso_local void @s( +// CHECK-SAME: ptr dead_on_unwind noalias writable sret(fp128) align 8 [[AGG_RESULT:%.*]], ptr noundef byval(fp128) align 8 [[TMP0:%.*]]) #[[ATTR0]] { +// CHECK: [[ENTRY:.*:]] +// s(long double a) { return 0; } -// CHECK-LABEL: define{{.*}}inreg{{.*}} { fp128, fp128 } @t(ptr noundef byval({ fp128, fp128 }) align 8 %a) #0 long double _Complex +// CHECK-LABEL: define dso_local inreg { fp128, fp128 } @t( +// CHECK-SAME: ptr noundef byval({ fp128, fp128 }) align 8 [[A:%.*]]) #[[ATTR0]] { +// CHECK: [[ENTRY:.*:]] +// t(long double _Complex a) { return 0; >From 69e93a865e33f74648715d3403fa0f4d62a03976 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 24 Nov 2025 15:32:22 +0700 Subject: [PATCH 14/15] Fix direct fp128 arg passing --- llvm/lib/Target/Sparc/SparcCallingConv.td | 5 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 180 ++++++++++---------- llvm/test/CodeGen/SPARC/fp128.ll | 43 +++-- llvm/test/CodeGen/SPARC/fp16-promote.ll | 17 +- llvm/test/CodeGen/SPARC/llvm.sincos.ll | 137 ++++++--------- 5 files changed, 171 insertions(+), 211 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index a87680ab36c48..e829935a3dfb3 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -17,6 +17,8 @@ def CC_Sparc32 : CallingConv<[ // Custom assign SRet to [sp+64]. CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>, + // f128 arguments are passed indirectly, using i32 pointers. + CCIfType<[f128], CCPassIndirect<i32>>, // i32 f32 arguments get passed in integer registers if there is space. CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, // f64 arguments are split and passed through registers or through stack. @@ -24,12 +26,11 @@ 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> ]>; + def RetCC_Sparc32 : CallingConv<[ CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>, diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index beaf63afb1e98..a4a498cc81776 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -440,6 +440,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>(); + EVT PtrVT = getPointerTy(DAG.getDataLayout()); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; @@ -466,6 +467,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( continue; } + SDValue Arg; if (VA.isRegLoc()) { if (VA.needsCustom()) { assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); @@ -500,98 +502,92 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( } Register VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); MF.getRegInfo().addLiveIn(VA.getLocReg(), VReg); - SDValue Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); - if (VA.getLocVT() == MVT::f32) - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); - else if (VA.getLocVT() != MVT::i32) { - Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, - DAG.getValueType(VA.getLocVT())); - Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); + Arg = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + if (VA.getLocInfo() != CCValAssign::Indirect) { + if (VA.getLocVT() == MVT::f32) + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Arg); + else if (VA.getLocVT() != MVT::i32) { + Arg = DAG.getNode(ISD::AssertSext, dl, MVT::i32, Arg, + DAG.getValueType(VA.getLocVT())); + Arg = DAG.getNode(ISD::TRUNCATE, dl, VA.getLocVT(), Arg); + } + InVals.push_back(Arg); + continue; } - InVals.push_back(Arg); - continue; - } + } else { + assert(VA.isMemLoc()); - assert(VA.isMemLoc()); + unsigned Offset = VA.getLocMemOffset() + StackOffset; - unsigned Offset = VA.getLocMemOffset()+StackOffset; - auto PtrVT = getPointerTy(DAG.getDataLayout()); + if (VA.needsCustom()) { + assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); + // If it is double-word aligned, just load. + if (Offset % 8 == 0) { + int FI = MF.getFrameInfo().CreateFixedObject(8, Offset, true); + SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); + SDValue Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, + MachinePointerInfo()); + InVals.push_back(Load); + continue; + } - if (VA.needsCustom()) { - assert(VA.getValVT() == MVT::f64 || VA.getValVT() == MVT::v2i32); - // If it is double-word aligned, just load. - if (Offset % 8 == 0) { - int FI = MF.getFrameInfo().CreateFixedObject(8, - Offset, - true); + int FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true); SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load = - DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - InVals.push_back(Load); - continue; - } + SDValue HiVal = + DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); + int FI2 = MF.getFrameInfo().CreateFixedObject(4, Offset + 4, true); + SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT); - int FI = MF.getFrameInfo().CreateFixedObject(4, - Offset, - true); - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue HiVal = - DAG.getLoad(MVT::i32, dl, Chain, FIPtr, MachinePointerInfo()); - int FI2 = MF.getFrameInfo().CreateFixedObject(4, - Offset+4, - true); - SDValue FIPtr2 = DAG.getFrameIndex(FI2, PtrVT); + SDValue LoVal = + DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo()); - SDValue LoVal = - DAG.getLoad(MVT::i32, dl, Chain, FIPtr2, MachinePointerInfo()); + if (IsLittleEndian) + std::swap(LoVal, HiVal); - if (IsLittleEndian) - std::swap(LoVal, HiVal); + SDValue WholeValue = + DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); + WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue); + InVals.push_back(WholeValue); + continue; + } - SDValue WholeValue = - DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal); - WholeValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), WholeValue); - InVals.push_back(WholeValue); - continue; - } + int FI; + if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { + FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true); + } else { + // We shouldn't see any other value types here. + llvm_unreachable("Unexpected ValVT encountered in frame lowering."); + } - 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; + SDValue Load = + DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); + if (VA.getLocInfo() != CCValAssign::Indirect) { + InVals.push_back(Load); + continue; } - continue; + Arg = Load; } - int FI; - if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { - FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true); - } else { - // We shouldn't see any other value types here. - llvm_unreachable("Unexpected ValVT encountered in frame lowering."); + assert(VA.getLocInfo() == CCValAssign::Indirect); + + SDValue ArgValue = + DAG.getLoad(VA.getValVT(), dl, Chain, Arg, MachinePointerInfo()); + 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; } - - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load = - DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - InVals.push_back(Load); } if (MF.getFunction().hasStructRetAttr()) { @@ -1039,20 +1035,6 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, continue; } - // Arguments that can be passed on register must be kept at - // RegsToPass vector - if (VA.isRegLoc()) { - if (VA.getLocVT() != MVT::f32) { - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); - continue; - } - Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); - continue; - } - - assert(VA.isMemLoc()); - if (VA.getLocInfo() == CCValAssign::Indirect) { // Store the argument in a stack slot and pass its address. unsigned ArgIndex = Outs[realArgIdx].OrigArgIndex; @@ -1077,7 +1059,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, MemOpChains.push_back( DAG.getStore(Chain, dl, Arg, SpillSlot, MachinePointerInfo::getFixedStack(MF, FI))); - // If the original argument was split (e.g. i128), we need + // If the original argument was split (e.g. f128), 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]; @@ -1097,6 +1079,20 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, Arg = SpillSlot; } + // Arguments that can be passed on register must be kept at + // RegsToPass vector + if (VA.isRegLoc()) { + if (VA.getLocVT() != MVT::f32) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + continue; + } + Arg = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Arg); + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + continue; + } + + assert(VA.isMemLoc()); + // 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 3529d091145a6..0ff84bdc0067e 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -245,28 +245,27 @@ entry: define fp128 @f128_direct(fp128 %num) nounwind { ; CHECK-LABEL: f128_direct: ; CHECK: ! %bb.0: -; CHECK-NEXT: save %sp, -152, %sp -; CHECK-NEXT: ldd [%fp+92], %f0 -; CHECK-NEXT: ldd [%fp+100], %f4 -; CHECK-NEXT: ld [%fp+64], %i0 -; CHECK-NEXT: add %fp, -48, %i1 -; CHECK-NEXT: st %i1, [%sp+96] -; CHECK-NEXT: add %fp, -32, %i1 -; CHECK-NEXT: st %i1, [%sp+92] -; CHECK-NEXT: add %fp, -16, %i1 -; CHECK-NEXT: st %i1, [%sp+64] -; CHECK-NEXT: std %f4, [%fp+-40] -; CHECK-NEXT: std %f0, [%fp+-48] -; CHECK-NEXT: std %f4, [%fp+-24] -; CHECK-NEXT: call f128_callee -; CHECK-NEXT: std %f0, [%fp+-32] -; CHECK-NEXT: unimp 16 -; CHECK-NEXT: ldd [%fp+-8], %f0 -; CHECK-NEXT: ldd [%fp+-16], %f4 -; CHECK-NEXT: std %f0, [%i0+8] -; CHECK-NEXT: std %f4, [%i0] -; CHECK-NEXT: ret -; CHECK-NEXT: restore +; CHECK-NEXT: save %sp, -144, %sp +; CHECK-NEXT: ldd [%i0], %f0 +; CHECK-NEXT: ldd [%i0+8], %f4 +; CHECK-NEXT: ld [%fp+64], %i0 +; CHECK-NEXT: add %fp, -16, %i1 +; CHECK-NEXT: st %i1, [%sp+64] +; CHECK-NEXT: std %f4, [%fp+-40] +; CHECK-NEXT: std %f0, [%fp+-48] +; CHECK-NEXT: std %f4, [%fp+-24] +; CHECK-NEXT: add %fp, -32, %o0 +; CHECK-NEXT: add %fp, -48, %o1 +; CHECK-NEXT: call f128_callee +; CHECK-NEXT: std %f0, [%fp+-32] +; CHECK-NEXT: unimp 16 +; CHECK-NEXT: ldd [%fp+-8], %f0 +; CHECK-NEXT: ldd [%fp+-16], %f4 +; CHECK-NEXT: std %f0, [%i0+8] +; CHECK-NEXT: std %f4, [%i0] +; CHECK-NEXT: ret +; CHECK-NEXT: restore + %ret = call fp128 @f128_callee(fp128 %num, fp128 %num) ret fp128 %ret } diff --git a/llvm/test/CodeGen/SPARC/fp16-promote.ll b/llvm/test/CodeGen/SPARC/fp16-promote.ll index ed956eb807be7..4e46fd073923e 100644 --- a/llvm/test/CodeGen/SPARC/fp16-promote.ll +++ b/llvm/test/CodeGen/SPARC/fp16-promote.ll @@ -268,12 +268,11 @@ 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, -120, %sp +; V8-OPT-NEXT: save %sp, -112, %sp ; V8-OPT-NEXT: ldd [%i0], %f0 ; V8-OPT-NEXT: ldd [%i0+8], %f4 -; V8-OPT-NEXT: add %fp, -16, %i0 -; V8-OPT-NEXT: st %i0, [%sp+92] ; V8-OPT-NEXT: std %f4, [%fp+-8] +; V8-OPT-NEXT: add %fp, -16, %o0 ; V8-OPT-NEXT: call __trunctfhf2 ; V8-OPT-NEXT: std %f0, [%fp+-16] ; V8-OPT-NEXT: sth %o0, [%i1] @@ -282,7 +281,7 @@ define void @test_fptrunc_fp128(ptr %dp, ptr %p) nounwind { ; ; V8-UNOPT-LABEL: test_fptrunc_fp128: ; V8-UNOPT: ! %bb.0: -; V8-UNOPT-NEXT: save %sp, -120, %sp +; V8-UNOPT-NEXT: save %sp, -112, %sp ; V8-UNOPT-NEXT: ldd [%i0], %f4 ; V8-UNOPT-NEXT: ! implicit-def: $q0 ; V8-UNOPT-NEXT: fmovs %f4, %f0 @@ -290,26 +289,24 @@ 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, [%fp+-8] ; V8-UNOPT-NEXT: ! kill: def $d0 killed $d0 killed $q0 -; V8-UNOPT-NEXT: call __trunctfhf2 ; V8-UNOPT-NEXT: std %f0, [%fp+-16] +; V8-UNOPT-NEXT: call __trunctfhf2 +; V8-UNOPT-NEXT: add %fp, -16, %o0 ; 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, -120, %sp +; V9-NEXT: save %sp, -112, %sp ; V9-NEXT: ldd [%i0], %f0 ; V9-NEXT: ldd [%i0+8], %f4 -; V9-NEXT: add %fp, -16, %i0 -; V9-NEXT: st %i0, [%sp+92] ; V9-NEXT: std %f4, [%fp+-8] +; V9-NEXT: add %fp, -16, %o0 ; V9-NEXT: call __trunctfhf2 ; V9-NEXT: std %f0, [%fp+-16] ; V9-NEXT: sth %o0, [%i1] diff --git a/llvm/test/CodeGen/SPARC/llvm.sincos.ll b/llvm/test/CodeGen/SPARC/llvm.sincos.ll index cc4ceb20a4651..ea5de64607042 100644 --- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll +++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll @@ -943,46 +943,38 @@ 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, -184, %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+-88] +; SPARC32-NEXT: std %f2, [%fp+-80] ! 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: std %f4, [%fp+-72] ! 8-byte Folded Spill ; SPARC32-NEXT: add %fp, -48, %i0 ; SPARC32-NEXT: st %i0, [%sp+64] ; SPARC32-NEXT: std %f4, [%fp+-56] +; SPARC32-NEXT: add %fp, -64, %o0 ; SPARC32-NEXT: call sinl ; 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+-80], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: ldd [%fp+-72], %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: add %fp, -32, %o0 +; SPARC32-NEXT: ldd [%fp+-88], %f0 +; SPARC32-NEXT: ldd [%fp+-80], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call cosl -; SPARC32-NEXT: std %f0, [%fp+-96] +; SPARC32-NEXT: std %f0, [%fp+-32] ; SPARC32-NEXT: unimp 16 ; SPARC32-NEXT: ldd [%fp+-8], %f0 ; SPARC32-NEXT: ldd [%fp+-16], %f4 +; SPARC32-NEXT: ldd [%fp+-40], %f2 +; SPARC32-NEXT: ldd [%fp+-48], %f8 ; 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, [%i1] +; SPARC32-NEXT: std %f2, [%i1+8] +; SPARC32-NEXT: std %f8, [%i1] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore %g0, %i1, %o0 ; @@ -1010,15 +1002,14 @@ 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, -152, %sp +; GNU32-NEXT: save %sp, -144, %sp ; GNU32-NEXT: ld [%fp+64], %i1 ; GNU32-NEXT: ldd [%i0], %f0 ; GNU32-NEXT: ldd [%i0+8], %f4 -; 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: add %fp, -48, %o0 +; GNU32-NEXT: add %fp, -16, %o1 +; GNU32-NEXT: add %fp, -32, %o2 ; GNU32-NEXT: call sincosl ; GNU32-NEXT: std %f0, [%fp+-48] ; GNU32-NEXT: ldd [%fp+-24], %f0 @@ -1063,7 +1054,7 @@ 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, -272, %sp ; SPARC32-NEXT: mov %i0, %i1 ; SPARC32-NEXT: ld [%fp+64], %i0 ; SPARC32-NEXT: ldd [%i1], %f0 @@ -1072,84 +1063,62 @@ define void @test_sincos_v2f128(ptr sret({ <2 x fp128>, <2 x fp128> }) %ret, ptr ; 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: std %f0, [%fp+-176] +; SPARC32-NEXT: std %f2, [%fp+-168] ! 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: std %f4, [%fp+-160] ! 8-byte Folded Spill ; SPARC32-NEXT: add %fp, -112, %i1 ; SPARC32-NEXT: st %i1, [%sp+64] ; SPARC32-NEXT: std %f4, [%fp+-120] +; SPARC32-NEXT: add %fp, -128, %o0 ; SPARC32-NEXT: call sinl ; 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+-152], %f0 ! 8-byte Folded Reload ; SPARC32-NEXT: std %f0, [%fp+-24] +; SPARC32-NEXT: add %fp, -32, %o0 ; SPARC32-NEXT: ldd [%fp+-144], %f0 ; SPARC32-NEXT: ldd [%fp+-136], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call cosl ; SPARC32-NEXT: std %f0, [%fp+-32] ; SPARC32-NEXT: unimp 16 -; 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: std %f0, [%fp+-56] +; SPARC32-NEXT: add %fp, -64, %o0 ; SPARC32-NEXT: ldd [%fp+-144], %f0 ; SPARC32-NEXT: ldd [%fp+-136], %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: 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: ldd [%fp+-160], %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: add %fp, -96, %o0 +; SPARC32-NEXT: ldd [%fp+-176], %f0 +; SPARC32-NEXT: ldd [%fp+-168], %f2 ! 16-byte Folded Reload ; SPARC32-NEXT: call cosl -; SPARC32-NEXT: std %f0, [%fp+-208] +; SPARC32-NEXT: std %f0, [%fp+-96] ; 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, [%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: 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+-48], %f0 +; SPARC32-NEXT: ldd [%fp+-40], %f8 +; SPARC32-NEXT: ldd [%fp+-112], %f4 +; SPARC32-NEXT: ldd [%fp+-104], %f10 +; SPARC32-NEXT: ldd [%fp+-72], %f12 +; SPARC32-NEXT: ldd [%fp+-80], %f16 +; SPARC32-NEXT: ldd [%fp+-8], %f14 +; SPARC32-NEXT: ldd [%fp+-16], %f20 +; SPARC32-NEXT: std %f12, [%i0+56] +; SPARC32-NEXT: std %f16, [%i0+48] +; SPARC32-NEXT: std %f14, [%i0+40] +; SPARC32-NEXT: std %f20, [%i0+32] +; SPARC32-NEXT: std %f10, [%i0+24] +; SPARC32-NEXT: std %f4, [%i0+16] +; SPARC32-NEXT: std %f8, [%i0+8] ; SPARC32-NEXT: std %f0, [%i0] ; SPARC32-NEXT: jmp %i7+12 ; SPARC32-NEXT: restore @@ -1200,7 +1169,7 @@ 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, -224, %sp +; GNU32-NEXT: save %sp, -216, %sp ; GNU32-NEXT: mov %i0, %i1 ; GNU32-NEXT: ld [%fp+64], %i0 ; GNU32-NEXT: ldd [%i1+16], %f0 @@ -1210,19 +1179,17 @@ define void @test_sincos_v2f128(ptr sret({ <2 x fp128>, <2 x fp128> }) %ret, ptr ; GNU32-NEXT: std %f0, [%fp+-120] ! 8-byte Folded Spill ; GNU32-NEXT: ldd [%i1], %f0 ; GNU32-NEXT: ldd [%i1+8], %f4 -; 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: add %fp, -96, %o0 +; GNU32-NEXT: add %fp, -64, %o1 +; GNU32-NEXT: add %fp, -80, %o2 ; GNU32-NEXT: call sincosl ; 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: add %fp, -48, %o0 +; GNU32-NEXT: add %fp, -16, %o1 +; GNU32-NEXT: add %fp, -32, %o2 ; GNU32-NEXT: ldd [%fp+-112], %f0 ; GNU32-NEXT: ldd [%fp+-104], %f2 ! 16-byte Folded Reload ; GNU32-NEXT: call sincosl >From 16391d0e7e5fd8f6b16c304f75281aef3f802830 Mon Sep 17 00:00:00 2001 From: Koakuma <[email protected]> Date: Mon, 24 Nov 2025 20:43:45 +0700 Subject: [PATCH 15/15] Add FIXME note and stack argument test --- llvm/lib/Target/Sparc/SparcCallingConv.td | 3 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 17 ++++------- llvm/test/CodeGen/SPARC/fp128.ll | 34 +++++++++++++++++++++ 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index e829935a3dfb3..d9c50483a029c 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -18,6 +18,7 @@ def CC_Sparc32 : CallingConv<[ // Custom assign SRet to [sp+64]. CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>, // f128 arguments are passed indirectly, using i32 pointers. + // FIXME GCC in soft-float mode passes f128 as if 2xi64 values. CCIfType<[f128], CCPassIndirect<i32>>, // i32 f32 arguments get passed in integer registers if there is space. CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>, @@ -35,11 +36,11 @@ 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]>>, + // FIXME GCC in soft-float mode passes f128 as if 2xi64 values. CCIfType<[f128], CCIfInReg<CCIfConsecutiveRegs<CCAssignToReg<[Q0, Q1]>>>>, CCIfType<[v2i32], CCCustom<"CC_Sparc_Assign_Ret_Split_64">> ]>; - //===----------------------------------------------------------------------===// // SPARC v9 64-bit. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index a4a498cc81776..d995eaab47ef8 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -454,6 +454,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( unsigned InIdx = 0; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i, ++InIdx) { CCValAssign &VA = ArgLocs[i]; + EVT LocVT = VA.getLocVT(); if (Ins[InIdx].Flags.isSRet()) { if (InIdx != 0) @@ -551,17 +552,11 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( continue; } - int FI; - if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { - FI = MF.getFrameInfo().CreateFixedObject(4, Offset, true); - } else { - // We shouldn't see any other value types here. - llvm_unreachable("Unexpected ValVT encountered in frame lowering."); - } - + int FI = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8, + Offset, true); SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load = - DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); + SDValue Load = DAG.getLoad(LocVT, dl, Chain, FIPtr, + MachinePointerInfo::getFixedStack(MF, FI)); if (VA.getLocInfo() != CCValAssign::Indirect) { InVals.push_back(Load); continue; @@ -580,7 +575,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( assert(ArgPartOffset == 0); while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) { CCValAssign &PartVA = ArgLocs[i + 1]; - unsigned PartOffset = Ins[InIdx + 1].PartOffset - ArgPartOffset; + unsigned PartOffset = Ins[InIdx + 1].PartOffset; 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, diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index 0ff84bdc0067e..ca99f12468910 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -270,3 +270,37 @@ define fp128 @f128_direct(fp128 %num) nounwind { ret fp128 %ret } declare fp128 @f128_callee(fp128 %a, fp128 %b) + +define fp128 @f128_direct_spill(i32 %o0, i32 %o1, i32 %o2, i32 %o3, i32 %o4, i32 %o5, i32 %ss0, fp128 %num) nounwind { +; CHECK-LABEL: f128_direct_spill: +; CHECK: ! %bb.0: +; CHECK-NEXT: save %sp, -136, %sp +; CHECK-NEXT: ld [%fp+96], %g2 +; CHECK-NEXT: ldd [%g2], %f0 +; CHECK-NEXT: ldd [%g2+8], %f4 +; CHECK-NEXT: ld [%fp+64], %l0 +; CHECK-NEXT: mov %i5, %o5 +; CHECK-NEXT: mov %i4, %o4 +; CHECK-NEXT: mov %i3, %o3 +; CHECK-NEXT: mov %i2, %o2 +; CHECK-NEXT: mov %i1, %o1 +; CHECK-NEXT: mov %i0, %o0 +; CHECK-NEXT: add %fp, -32, %i0 +; CHECK-NEXT: st %i0, [%sp+92] +; CHECK-NEXT: add %fp, -16, %i0 +; CHECK-NEXT: st %i0, [%sp+64] +; CHECK-NEXT: std %f4, [%fp+-24] +; CHECK-NEXT: call f128_callee_spill +; CHECK-NEXT: std %f0, [%fp+-32] +; CHECK-NEXT: unimp 16 +; CHECK-NEXT: ldd [%fp+-8], %f0 +; CHECK-NEXT: ldd [%fp+-16], %f4 +; CHECK-NEXT: std %f0, [%l0+8] +; CHECK-NEXT: std %f4, [%l0] +; CHECK-NEXT: ret +; CHECK-NEXT: restore + + %ret = call fp128 @f128_callee_spill(i32 %o0, i32 %o1, i32 %o2, i32 %o3, i32 %o4, i32 %o5, fp128 %num) + ret fp128 %ret +} +declare fp128 @f128_callee_spill(i32 %o0, i32 %o1, i32 %o2, i32 %o3, i32 %o4, i32 %o5, fp128 %a) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
