diff options
author | Evan Cheng <evan.cheng@apple.com> | 2013-04-10 01:26:07 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2013-04-10 01:26:07 +0000 |
commit | 3a6b7d38a7c41189b75f0d40a92700aa42cc6a91 (patch) | |
tree | 69a0b432d3637847473039b87aba76d7b5a923c7 | |
parent | 5ed028385c39f3de4570fa6f77c734d968d26902 (diff) | |
download | external_llvm-3a6b7d38a7c41189b75f0d40a92700aa42cc6a91.zip external_llvm-3a6b7d38a7c41189b75f0d40a92700aa42cc6a91.tar.gz external_llvm-3a6b7d38a7c41189b75f0d40a92700aa42cc6a91.tar.bz2 |
__sincosf_stret returns sinf / cosf in bits 0:31 and 32:63 of xmm0, not in
xmm0 / xmm1.
rdar://13599493
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179141 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 24 | ||||
-rw-r--r-- | test/CodeGen/X86/sincos-opt.ll | 4 |
2 files changed, 22 insertions, 6 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index c4f1176..95e7f85 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -12319,7 +12319,8 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const { assert(Subtarget->isTargetDarwin() && Subtarget->is64Bit()); // 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(); SDValue Arg = Op.getOperand(0); EVT ArgVT = Arg.getValueType(); @@ -12334,14 +12335,16 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const { Entry.isZExt = false; Args.push_back(Entry); + bool isF64 = ArgVT == MVT::f64; // 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 results are returned via SRet in memory. - const char *LibcallName = (ArgVT == MVT::f64) - ? "__sincos_stret" : "__sincosf_stret"; + const char *LibcallName = isF64 ? "__sincos_stret" : "__sincosf_stret"; 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:: CallLoweringInfo CLI(DAG.getEntryNode(), RetTy, false, false, false, false, 0, @@ -12349,7 +12352,18 @@ SDValue X86TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const { /*doesNotRet=*/false, /*isReturnValueUsed*/true, Callee, Args, DAG, dl); std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); - return CallResult.first; + + if (isF64) + // Returned in xmm0 and xmm1. + 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. diff --git a/test/CodeGen/X86/sincos-opt.ll b/test/CodeGen/X86/sincos-opt.ll index f364d1f..333c466 100644 --- a/test/CodeGen/X86/sincos-opt.ll +++ b/test/CodeGen/X86/sincos-opt.ll @@ -4,6 +4,7 @@ ; Combine sin / cos into a single call. ; rdar://13087969 +; rdar://13599493 define float @test1(float %x) nounwind { entry: @@ -14,7 +15,8 @@ entry: ; OSX_SINCOS: test1: ; 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: callq _cosf |