Author: Koakuma Date: 2025-11-29T21:30:39+07:00 New Revision: 3e16aef2a650a8c2da4ebd5c58c6a9e261361828
URL: https://github.com/llvm/llvm-project/commit/3e16aef2a650a8c2da4ebd5c58c6a9e261361828 DIFF: https://github.com/llvm/llvm-project/commit/3e16aef2a650a8c2da4ebd5c58c6a9e261361828.diff LOG: [SPARC] Properly handle CC for long double on sparc32 (#162226) 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. Added: llvm/test/CodeGen/SPARC/fp128-abi.ll Modified: clang/lib/Basic/Targets/Sparc.cpp clang/lib/Basic/Targets/Sparc.h clang/lib/CodeGen/Targets/Sparc.cpp clang/test/CodeGen/Sparc/sparcv8-abi.c clang/test/Preprocessor/init.c clang/test/Preprocessor/predefined-arch-macros.c compiler-rt/lib/builtins/CMakeLists.txt compiler-rt/test/builtins/CMakeLists.txt compiler-rt/test/sanitizer_common/TestCases/printf-ldbl.c compiler-rt/test/sanitizer_common/TestCases/scanf-ldbl.c compiler-rt/test/ubsan/TestCases/Float/cast-overflow.cpp compiler-rt/test/ubsan/TestCases/Misc/log-path_test.cpp llvm/lib/Target/Sparc/SparcCallingConv.td llvm/lib/Target/Sparc/SparcISelLowering.cpp llvm/test/CodeGen/SPARC/fp16-promote.ll llvm/test/CodeGen/SPARC/llvm.sincos.ll Removed: ################################################################################ diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp index d47eecb3cf058..fe1aad6804aa6 100644 --- a/clang/lib/Basic/Targets/Sparc.cpp +++ b/clang/lib/Basic/Targets/Sparc.cpp @@ -165,6 +165,7 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } + Builder.defineMacro("__LONG_DOUBLE_128__"); } void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts, 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..3fa4e84823d51 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -26,23 +26,39 @@ class SparcV8ABIInfo : public DefaultABIInfo { private: ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType Ty) const; void computeInfo(CGFunctionInfo &FI) const override; }; } // end anonymous namespace +ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { + 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; -ABIArgInfo -SparcV8ABIInfo::classifyReturnType(QualType Ty) const { - if (Ty->isAnyComplexType()) { - return ABIArgInfo::getDirect(); - } - else { - return DefaultABIInfo::classifyReturnType(Ty); - } + // 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(), + /*ByVal=*/false); + + return DefaultABIInfo::classifyReturnType(Ty); } -void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const { +ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const { + if (const auto *BT = Ty->getAs<BuiltinType>(); + BT && BT->getKind() == BuiltinType::LongDouble) + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); + return DefaultABIInfo::classifyArgumentType(Ty); +} + +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 c5faf130890f8..7beddd20e5e4d 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c @@ -1,22 +1,52 @@ +// 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; } + +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; +} + +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; +} 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 diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 27feeb57b5de2..1e38b4d3ba350 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -4210,6 +4210,11 @@ // CHECK_SPARC-NOT: #define __sparcv9 1 // CHECK_SPARC-NOT: #define __sparcv9__ 1 +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target sparc-unknown-linux \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL +// CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1 + // RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \ // RUN: -target sparc-unknown-linux \ // RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9 diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index aa2a2519afc02..7e8621855eb84 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -1011,9 +1011,10 @@ 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..36135c7905900 100644 --- a/compiler-rt/test/builtins/CMakeLists.txt +++ b/compiler-rt/test/builtins/CMakeLists.txt @@ -48,7 +48,8 @@ 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/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[]) { diff --git a/llvm/lib/Target/Sparc/SparcCallingConv.td b/llvm/lib/Target/Sparc/SparcCallingConv.td index 8afd0a7fc09ad..d9c50483a029c 100644 --- a/llvm/lib/Target/Sparc/SparcCallingConv.td +++ b/llvm/lib/Target/Sparc/SparcCallingConv.td @@ -17,6 +17,9 @@ 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]>>, // f64 arguments are split and passed through registers or through stack. @@ -24,20 +27,20 @@ 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">>, - - // 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]>>, 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 a4a9eafd52ffe..de8768a7cdbca 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; @@ -453,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) @@ -466,6 +468,7 @@ SDValue SparcTargetLowering::LowerFormalArguments_32( continue; } + SDValue Arg; if (VA.isRegLoc()) { if (VA.needsCustom()) { assert(VA.getLocVT() == MVT::f64 || VA.getLocVT() == MVT::v2i32); @@ -500,76 +503,85 @@ 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 = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8, + Offset, true); + SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); + SDValue Load = DAG.getLoad(LocVT, dl, Chain, FIPtr, + MachinePointerInfo::getFixedStack(MF, FI)); + if (VA.getLocInfo() != CCValAssign::Indirect) { + InVals.push_back(Load); + continue; + } + Arg = Load; } - int FI = MF.getFrameInfo().CreateFixedObject(4, - Offset, - true); - SDValue FIPtr = DAG.getFrameIndex(FI, PtrVT); - SDValue Load ; - if (VA.getValVT() == MVT::i32 || VA.getValVT() == MVT::f32) { - Load = DAG.getLoad(VA.getValVT(), dl, Chain, FIPtr, MachinePointerInfo()); - } else if (VA.getValVT() == MVT::f128) { - report_fatal_error("SPARCv8 does not handle f128 in calls; " - "pass indirectly"); - } 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; + assert(Ins[InIdx].PartOffset == 0); + while (i + 1 != e && Ins[InIdx + 1].OrigArgIndex == ArgIndex) { + CCValAssign &PartVA = ArgLocs[i + 1]; + unsigned PartOffset = Ins[InIdx + 1].PartOffset; + SDValue Address = DAG.getMemBasePlusOffset( + ArgValue, TypeSize::getFixed(PartOffset), dl); + InVals.push_back(DAG.getLoad(PartVA.getValVT(), dl, Chain, Address, + MachinePointerInfo())); + ++i; + ++InIdx; } - InVals.push_back(Load); } if (MF.getFunction().hasStructRetAttr()) { @@ -836,6 +848,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; @@ -914,7 +928,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; @@ -1013,6 +1029,49 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, continue; } + if (VA.getLocInfo() == CCValAssign::Indirect) { + // Store the argument in a stack slot and pass its address. + unsigned ArgIndex = Outs[realArgIdx].OrigArgIndex; + assert(Outs[realArgIdx].PartOffset == 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. 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]; + unsigned PartOffset = Outs[realArgIdx + 1].PartOffset; + SDValue Address = DAG.getMemBasePlusOffset( + DAG.getFrameIndex(FI, PtrVT), TypeSize::getFixed(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; + } + // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { diff --git a/llvm/test/CodeGen/SPARC/fp128-abi.ll b/llvm/test/CodeGen/SPARC/fp128-abi.ll new file mode 100644 index 0000000000000..341e05d80e71e --- /dev/null +++ b/llvm/test/CodeGen/SPARC/fp128-abi.ll @@ -0,0 +1,89 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -mtriple=sparc | FileCheck %s --check-prefix=SPARC32 +; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s --check-prefix=SPARC64 + +define fp128 @f128_direct(fp128 %num) nounwind { +; SPARC32-LABEL: f128_direct: +; SPARC32: ! %bb.0: +; SPARC32-NEXT: save %sp, -144, %sp +; SPARC32-NEXT: ldd [%i0], %f0 +; SPARC32-NEXT: ldd [%i0+8], %f4 +; SPARC32-NEXT: ld [%fp+64], %i0 +; SPARC32-NEXT: add %fp, -16, %i1 +; SPARC32-NEXT: st %i1, [%sp+64] +; SPARC32-NEXT: std %f4, [%fp+-40] +; SPARC32-NEXT: std %f0, [%fp+-48] +; SPARC32-NEXT: std %f4, [%fp+-24] +; SPARC32-NEXT: add %fp, -32, %o0 +; SPARC32-NEXT: add %fp, -48, %o1 +; SPARC32-NEXT: call f128_callee +; SPARC32-NEXT: std %f0, [%fp+-32] +; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: ldd [%fp+-8], %f0 +; SPARC32-NEXT: ldd [%fp+-16], %f4 +; SPARC32-NEXT: std %f0, [%i0+8] +; SPARC32-NEXT: std %f4, [%i0] +; SPARC32-NEXT: ret +; SPARC32-NEXT: restore +; +; SPARC64-LABEL: f128_direct: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -176, %sp +; SPARC64-NEXT: fmovd %f0, %f4 +; SPARC64-NEXT: fmovd %f2, %f6 +; SPARC64-NEXT: call f128_callee +; SPARC64-NEXT: nop +; SPARC64-NEXT: ret +; SPARC64-NEXT: restore + %ret = call fp128 @f128_callee(fp128 %num, fp128 %num) + 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 { +; SPARC32-LABEL: f128_direct_spill: +; SPARC32: ! %bb.0: +; SPARC32-NEXT: save %sp, -136, %sp +; SPARC32-NEXT: ld [%fp+96], %g2 +; SPARC32-NEXT: ldd [%g2], %f0 +; SPARC32-NEXT: ldd [%g2+8], %f4 +; SPARC32-NEXT: ld [%fp+64], %l0 +; SPARC32-NEXT: mov %i5, %o5 +; SPARC32-NEXT: mov %i4, %o4 +; SPARC32-NEXT: mov %i3, %o3 +; SPARC32-NEXT: mov %i2, %o2 +; SPARC32-NEXT: mov %i1, %o1 +; SPARC32-NEXT: mov %i0, %o0 +; 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: std %f4, [%fp+-24] +; SPARC32-NEXT: call f128_callee_spill +; SPARC32-NEXT: std %f0, [%fp+-32] +; SPARC32-NEXT: unimp 16 +; SPARC32-NEXT: ldd [%fp+-8], %f0 +; SPARC32-NEXT: ldd [%fp+-16], %f4 +; SPARC32-NEXT: std %f0, [%l0+8] +; SPARC32-NEXT: std %f4, [%l0] +; SPARC32-NEXT: ret +; SPARC32-NEXT: restore +; +; SPARC64-LABEL: f128_direct_spill: +; SPARC64: ! %bb.0: +; SPARC64-NEXT: save %sp, -192, %sp +; SPARC64-NEXT: fmovd %f16, %f12 +; SPARC64-NEXT: fmovd %f18, %f14 +; SPARC64-NEXT: mov %i5, %o5 +; SPARC64-NEXT: mov %i4, %o4 +; SPARC64-NEXT: mov %i3, %o3 +; SPARC64-NEXT: mov %i2, %o2 +; SPARC64-NEXT: mov %i1, %o1 +; SPARC64-NEXT: call f128_callee_spill +; SPARC64-NEXT: mov %i0, %o0 +; SPARC64-NEXT: ret +; SPARC64-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) diff --git a/llvm/test/CodeGen/SPARC/fp16-promote.ll b/llvm/test/CodeGen/SPARC/fp16-promote.ll index 64873b744de50..4e46fd073923e 100644 --- a/llvm/test/CodeGen/SPARC/fp16-promote.ll +++ b/llvm/test/CodeGen/SPARC/fp16-promote.ll @@ -268,19 +268,20 @@ 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, -112, %sp ; V8-OPT-NEXT: ldd [%i0], %f0 ; V8-OPT-NEXT: ldd [%i0+8], %f4 -; V8-OPT-NEXT: std %f4, [%sp+100] +; V8-OPT-NEXT: std %f4, [%fp+-8] +; V8-OPT-NEXT: add %fp, -16, %o0 ; 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, -112, %sp ; V8-UNOPT-NEXT: ldd [%i0], %f4 ; V8-UNOPT-NEXT: ! implicit-def: $q0 ; V8-UNOPT-NEXT: fmovs %f4, %f0 @@ -290,22 +291,24 @@ define void @test_fptrunc_fp128(ptr %dp, ptr %p) nounwind { ; V8-UNOPT-NEXT: fmovs %f5, %f3 ; 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: std %f0, [%fp+-16] ; V8-UNOPT-NEXT: call __trunctfhf2 -; V8-UNOPT-NEXT: std %f0, [%sp+92] +; 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, -104, %sp +; V9-NEXT: save %sp, -112, %sp ; V9-NEXT: ldd [%i0], %f0 ; V9-NEXT: ldd [%i0+8], %f4 -; V9-NEXT: std %f4, [%sp+100] +; V9-NEXT: std %f4, [%fp+-8] +; V9-NEXT: add %fp, -16, %o0 ; 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..ea5de64607042 100644 --- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll +++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll @@ -943,42 +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, -168, %sp +; SPARC32-NEXT: save %sp, -184, %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+-88] +; SPARC32-NEXT: std %f2, [%fp+-80] ! 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+-72] ! 8-byte Folded Spill +; 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: add %fp, -64, %o0 ; SPARC32-NEXT: call sinl -; SPARC32-NEXT: std %f0, [%sp+92] +; SPARC32-NEXT: std %f0, [%fp+-64] ; SPARC32-NEXT: unimp 16 ; 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+-72], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-24] +; 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+-64] +; 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+-64], %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: 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 ; @@ -1006,15 +1002,16 @@ 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, -144, %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, -16, %o0 -; GNU32-NEXT: add %fp, -32, %o1 +; GNU32-NEXT: std %f4, [%fp+-40] +; 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, [%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 +1054,71 @@ 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, -272, %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+-176] +; SPARC32-NEXT: std %f2, [%fp+-168] ! 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+-160] ! 8-byte Folded Spill +; 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: add %fp, -128, %o0 ; SPARC32-NEXT: call sinl -; SPARC32-NEXT: std %f0, [%sp+92] +; SPARC32-NEXT: std %f0, [%fp+-128] ; SPARC32-NEXT: unimp 16 ; 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: 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, [%sp+92] +; SPARC32-NEXT: std %f0, [%fp+-32] ; SPARC32-NEXT: unimp 16 -; SPARC32-NEXT: add %fp, -32, %i1 +; 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: 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, [%sp+92] +; SPARC32-NEXT: std %f0, [%fp+-64] ; SPARC32-NEXT: unimp 16 -; SPARC32-NEXT: add %fp, -48, %i1 +; 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+-16], %f0 -; SPARC32-NEXT: std %f0, [%fp+-136] -; SPARC32-NEXT: std %f2, [%fp+-128] ! 16-byte Folded Spill -; SPARC32-NEXT: ldd [%fp+-8], %f0 +; SPARC32-NEXT: ldd [%fp+-160], %f0 ! 8-byte Folded Reload +; SPARC32-NEXT: std %f0, [%fp+-88] +; 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+-144] +; SPARC32-NEXT: std %f0, [%fp+-96] ; SPARC32-NEXT: unimp 16 -; SPARC32-NEXT: ldd [%fp+-40], %f0 -; SPARC32-NEXT: ldd [%fp+-48], %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: std %f0, [%i0+40] -; SPARC32-NEXT: ldd [%fp+-136], %f0 -; SPARC32-NEXT: ldd [%fp+-128], %f2 ! 16-byte Folded Reload -; SPARC32-NEXT: std %f0, [%i0+32] -; SPARC32-NEXT: ldd [%fp+-120], %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: std %f0, [%i0+16] -; SPARC32-NEXT: ldd [%fp+-88], %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+-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 @@ -1186,37 +1169,39 @@ 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, -216, %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: std %f4, [%fp+-88] +; 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, [%sp+92] -; GNU32-NEXT: ldd [%fp+-88], %f0 ! 8-byte Folded Reload -; GNU32-NEXT: std %f0, [%sp+100] -; 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: std %f0, [%fp+-96] +; GNU32-NEXT: ldd [%fp+-120], %f0 ! 8-byte Folded Reload +; GNU32-NEXT: std %f0, [%fp+-40] +; 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 -; 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] _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
