forked from OSchip/llvm-project
__sincosf_stret returns sinf / cosf in bits 0:31 and 32:63 of xmm0, not in
xmm0 / xmm1. rdar://13599493 llvm-svn: 179141
This commit is contained in:
parent
e220323c7f
commit
ac0469c5d0
|
@ -12319,7 +12319,8 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const {
|
||||||
assert(Subtarget->isTargetDarwin() && Subtarget->is64Bit());
|
assert(Subtarget->isTargetDarwin() && Subtarget->is64Bit());
|
||||||
|
|
||||||
// For MacOSX, we want to call an alternative entry point: __sincos_stret,
|
// For MacOSX, we want to call an alternative entry point: __sincos_stret,
|
||||||
// which returns the values in two XMM registers.
|
// which returns the values as { float, float } (in XMM0) or
|
||||||
|
// { double, double } (which is returned in XMM0, XMM1).
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
SDValue Arg = Op.getOperand(0);
|
SDValue Arg = Op.getOperand(0);
|
||||||
EVT ArgVT = Arg.getValueType();
|
EVT ArgVT = Arg.getValueType();
|
||||||
|
@ -12334,14 +12335,16 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const {
|
||||||
Entry.isZExt = false;
|
Entry.isZExt = false;
|
||||||
Args.push_back(Entry);
|
Args.push_back(Entry);
|
||||||
|
|
||||||
|
bool isF64 = ArgVT == MVT::f64;
|
||||||
// Only optimize x86_64 for now. i386 is a bit messy. For f32,
|
// Only optimize x86_64 for now. i386 is a bit messy. For f32,
|
||||||
// the small struct {f32, f32} is returned in (eax, edx). For f64,
|
// the small struct {f32, f32} is returned in (eax, edx). For f64,
|
||||||
// the results are returned via SRet in memory.
|
// the results are returned via SRet in memory.
|
||||||
const char *LibcallName = (ArgVT == MVT::f64)
|
const char *LibcallName = isF64 ? "__sincos_stret" : "__sincosf_stret";
|
||||||
? "__sincos_stret" : "__sincosf_stret";
|
|
||||||
SDValue Callee = DAG.getExternalSymbol(LibcallName, getPointerTy());
|
SDValue Callee = DAG.getExternalSymbol(LibcallName, getPointerTy());
|
||||||
|
|
||||||
StructType *RetTy = StructType::get(ArgTy, ArgTy, NULL);
|
Type *RetTy = isF64
|
||||||
|
? (Type*)StructType::get(ArgTy, ArgTy, NULL)
|
||||||
|
: (Type*)VectorType::get(ArgTy, 4);
|
||||||
TargetLowering::
|
TargetLowering::
|
||||||
CallLoweringInfo CLI(DAG.getEntryNode(), RetTy,
|
CallLoweringInfo CLI(DAG.getEntryNode(), RetTy,
|
||||||
false, false, false, false, 0,
|
false, false, false, false, 0,
|
||||||
|
@ -12349,7 +12352,18 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const {
|
||||||
/*doesNotRet=*/false, /*isReturnValueUsed*/true,
|
/*doesNotRet=*/false, /*isReturnValueUsed*/true,
|
||||||
Callee, Args, DAG, dl);
|
Callee, Args, DAG, dl);
|
||||||
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
|
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
|
||||||
|
|
||||||
|
if (isF64)
|
||||||
|
// Returned in xmm0 and xmm1.
|
||||||
return CallResult.first;
|
return CallResult.first;
|
||||||
|
|
||||||
|
// Returned in bits 0:31 and 32:64 xmm0.
|
||||||
|
SDValue SinVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ArgVT,
|
||||||
|
CallResult.first, DAG.getIntPtrConstant(0));
|
||||||
|
SDValue CosVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ArgVT,
|
||||||
|
CallResult.first, DAG.getIntPtrConstant(1));
|
||||||
|
SDVTList Tys = DAG.getVTList(ArgVT, ArgVT);
|
||||||
|
return DAG.getNode(ISD::MERGE_VALUES, dl, Tys, SinVal, CosVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
; Combine sin / cos into a single call.
|
; Combine sin / cos into a single call.
|
||||||
; rdar://13087969
|
; rdar://13087969
|
||||||
|
; rdar://13599493
|
||||||
|
|
||||||
define float @test1(float %x) nounwind {
|
define float @test1(float %x) nounwind {
|
||||||
entry:
|
entry:
|
||||||
|
@ -14,7 +15,8 @@ entry:
|
||||||
|
|
||||||
; OSX_SINCOS: test1:
|
; OSX_SINCOS: test1:
|
||||||
; OSX_SINCOS: callq ___sincosf_stret
|
; OSX_SINCOS: callq ___sincosf_stret
|
||||||
; OSX_SINCOS: addss %xmm1, %xmm0
|
; OSX_SINCOS: pshufd $1, %xmm0, %xmm1
|
||||||
|
; OSX_SINCOS: addss %xmm0, %xmm1
|
||||||
|
|
||||||
; OSX_NOOPT: test1
|
; OSX_NOOPT: test1
|
||||||
; OSX_NOOPT: callq _cosf
|
; OSX_NOOPT: callq _cosf
|
||||||
|
|
Loading…
Reference in New Issue