mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
[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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -166,6 +166,13 @@ public:
|
||||
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;
|
||||
|
||||
@@ -26,23 +26,39 @@ public:
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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[]) {
|
||||
|
||||
@@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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);
|
||||
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());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int FI = MF.getFrameInfo().CreateFixedObject(4,
|
||||
Offset,
|
||||
true);
|
||||
int FI = MF.getFrameInfo().CreateFixedObject(LocVT.getSizeInBits() / 8,
|
||||
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());
|
||||
|
||||
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 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()) {
|
||||
|
||||
89
llvm/test/CodeGen/SPARC/fp128-abi.ll
Normal file
89
llvm/test/CodeGen/SPARC/fp128-abi.ll
Normal file
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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: unimp 16
|
||||
; SPARC32-NEXT: add %fp, -32, %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: call sinl
|
||||
; SPARC32-NEXT: std %f0, [%sp+92]
|
||||
; SPARC32-NEXT: std %f0, [%fp+-32]
|
||||
; SPARC32-NEXT: unimp 16
|
||||
; SPARC32-NEXT: add %fp, -48, %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: call cosl
|
||||
; SPARC32-NEXT: std %f0, [%fp+-144]
|
||||
; 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: 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: add %fp, -80, %i1
|
||||
; SPARC32-NEXT: st %i1, [%sp+64]
|
||||
; 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+-96]
|
||||
; SPARC32-NEXT: unimp 16
|
||||
; 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]
|
||||
|
||||
Reference in New Issue
Block a user