llvm.org GIT mirror llvm / cb01efb
Enable optimization of sin / cos pair into call to __sincos_stret for iOS7+. rdar://12856873 Patch by Evan Cheng, with a fix for rdar://13209539 by Tilmann Scheller git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193942 91177308-0d34-0410-b5e6-96231b3b80d8 Bob Wilson 6 years ago
5 changed file(s) with 125 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
866866 if (!Subtarget->hasFP16()) {
867867 setOperationAction(ISD::FP16_TO_FP32, MVT::f32, Expand);
868868 setOperationAction(ISD::FP32_TO_FP16, MVT::i32, Expand);
869 }
870 }
871
872 // Combine sin / cos into one node or libcall if possible.
873 if (Subtarget->hasSinCos()) {
874 setLibcallName(RTLIB::SINCOS_F32, "sincosf");
875 setLibcallName(RTLIB::SINCOS_F64, "sincos");
876 if (Subtarget->getTargetTriple().getOS() == Triple::IOS) {
877 // For iOS, we don't want to the normal expansion of a libcall to
878 // sincos. We want to issue a libcall to __sincos_stret.
879 setOperationAction(ISD::FSINCOS, MVT::f64, Custom);
880 setOperationAction(ISD::FSINCOS, MVT::f32, Custom);
869881 }
870882 }
871883
59495961 Op.getOperand(1), Op.getOperand(2));
59505962 }
59515963
5964 SDValue ARMTargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const {
5965 assert(Subtarget->isTargetDarwin());
5966
5967 // For iOS, we want to call an alternative entry point: __sincos_stret,
5968 // return values are passed via sret.
5969 SDLoc dl(Op);
5970 SDValue Arg = Op.getOperand(0);
5971 EVT ArgVT = Arg.getValueType();
5972 Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
5973
5974 MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
5975 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
5976
5977 // Pair of floats / doubles used to pass the result.
5978 StructType *RetTy = StructType::get(ArgTy, ArgTy, NULL);
5979
5980 // Create stack object for sret.
5981 const uint64_t ByteSize = TLI.getDataLayout()->getTypeAllocSize(RetTy);
5982 const unsigned StackAlign = TLI.getDataLayout()->getPrefTypeAlignment(RetTy);
5983 int FrameIdx = FrameInfo->CreateStackObject(ByteSize, StackAlign, false);
5984 SDValue SRet = DAG.getFrameIndex(FrameIdx, TLI.getPointerTy());
5985
5986 ArgListTy Args;
5987 ArgListEntry Entry;
5988
5989 Entry.Node = SRet;
5990 Entry.Ty = RetTy->getPointerTo();
5991 Entry.isSExt = false;
5992 Entry.isZExt = false;
5993 Entry.isSRet = true;
5994 Args.push_back(Entry);
5995
5996 Entry.Node = Arg;
5997 Entry.Ty = ArgTy;
5998 Entry.isSExt = false;
5999 Entry.isZExt = false;
6000 Args.push_back(Entry);
6001
6002 const char *LibcallName = (ArgVT == MVT::f64)
6003 ? "__sincos_stret" : "__sincosf_stret";
6004 SDValue Callee = DAG.getExternalSymbol(LibcallName, getPointerTy());
6005
6006 TargetLowering::
6007 CallLoweringInfo CLI(DAG.getEntryNode(), Type::getVoidTy(*DAG.getContext()),
6008 false, false, false, false, 0,
6009 CallingConv::C, /*isTaillCall=*/false,
6010 /*doesNotRet=*/false, /*isReturnValueUsed*/false,
6011 Callee, Args, DAG, dl);
6012 std::pair CallResult = LowerCallTo(CLI);
6013
6014 SDValue LoadSin = DAG.getLoad(ArgVT, dl, CallResult.second, SRet,
6015 MachinePointerInfo(), false, false, false, 0);
6016
6017 // Address of cos field.
6018 SDValue Add = DAG.getNode(ISD::ADD, dl, getPointerTy(), SRet,
6019 DAG.getIntPtrConstant(ArgVT.getStoreSize()));
6020 SDValue LoadCos = DAG.getLoad(ArgVT, dl, LoadSin.getValue(1), Add,
6021 MachinePointerInfo(), false, false, false, 0);
6022
6023 SDVTList Tys = DAG.getVTList(ArgVT, ArgVT);
6024 return DAG.getNode(ISD::MERGE_VALUES, dl, Tys,
6025 LoadSin.getValue(0), LoadCos.getValue(0));
6026 }
6027
59526028 static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG) {
59536029 // Monotonic load/store is legal for all targets
59546030 if (cast(Op)->getOrdering() <= Monotonic)
60806156 case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
60816157 case ISD::ATOMIC_LOAD:
60826158 case ISD::ATOMIC_STORE: return LowerAtomicLoadStore(Op, DAG);
6159 case ISD::FSINCOS: return LowerFSINCOS(Op, DAG);
60836160 case ISD::SDIVREM:
60846161 case ISD::UDIVREM: return LowerDivRem(Op, DAG);
60856162 }
447447 const ARMSubtarget *ST) const;
448448 SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
449449 const ARMSubtarget *ST) const;
450 SDValue LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const;
450451 SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
451452
452453 /// isFMAFasterThanFMulAndFAdd - Return true if an FMA operation is faster
280280 return SchedModel->MispredictPenalty;
281281 }
282282
283 bool ARMSubtarget::hasSinCos() const {
284 return getTargetTriple().getOS() == Triple::IOS &&
285 !getTargetTriple().isOSVersionLT(7, 0);
286 }
287
283288 bool ARMSubtarget::enablePostRAScheduler(
284289 CodeGenOpt::Level OptLevel,
285290 TargetSubtargetInfo::AntiDepBreakMode& Mode,
329329 const std::string & getCPUString() const { return CPUString; }
330330
331331 unsigned getMispredictionPenalty() const;
332
333 /// This function returns true if the target has sincos() routine in its
334 /// compiler runtime or math libraries.
335 bool hasSinCos() const;
332336
333337 /// enablePostRAScheduler - True at 'More' optimization.
334338 bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
0 ; RUN: llc < %s -mtriple=armv7-apple-ios6 -mcpu=cortex-a8 | FileCheck %s --check-prefix=NOOPT
1 ; RUN: llc < %s -mtriple=armv7-apple-ios7 -mcpu=cortex-a8 | FileCheck %s --check-prefix=SINCOS
2
3 ; Combine sin / cos into a single call.
4 ; rdar://12856873
5
6 define float @test1(float %x) nounwind {
7 entry:
8 ; SINCOS-LABEL: test1:
9 ; SINCOS: bl ___sincosf_stret
10
11 ; NOOPT-LABEL: test1:
12 ; NOOPT: bl _sinf
13 ; NOOPT: bl _cosf
14 %call = tail call float @sinf(float %x) nounwind readnone
15 %call1 = tail call float @cosf(float %x) nounwind readnone
16 %add = fadd float %call, %call1
17 ret float %add
18 }
19
20 define double @test2(double %x) nounwind {
21 entry:
22 ; SINCOS-LABEL: test2:
23 ; SINCOS: bl ___sincos_stret
24
25 ; NOOPT-LABEL: test2:
26 ; NOOPT: bl _sin
27 ; NOOPT: bl _cos
28 %call = tail call double @sin(double %x) nounwind readnone
29 %call1 = tail call double @cos(double %x) nounwind readnone
30 %add = fadd double %call, %call1
31 ret double %add
32 }
33
34 declare float @sinf(float) readonly
35 declare double @sin(double) readonly
36 declare float @cosf(float) readonly
37 declare double @cos(double) readonly