@@ -163,6 +163,8 @@ class SelectionDAGLegalize {
163163 RTLIB::Libcall CallI128);
164164 void ExpandDivRemLibCall (SDNode *Node, SmallVectorImpl<SDValue> &Results);
165165
166+ SDValue ExpandSincosStretLibCall (SDNode *Node) const ;
167+
166168 SDValue EmitStackConvert (SDValue SrcOp, EVT SlotVT, EVT DestVT,
167169 const SDLoc &dl);
168170 SDValue EmitStackConvert (SDValue SrcOp, EVT SlotVT, EVT DestVT,
@@ -2423,6 +2425,101 @@ static bool useSinCos(SDNode *Node) {
24232425 return false ;
24242426}
24252427
2428+ SDValue SelectionDAGLegalize::ExpandSincosStretLibCall (SDNode *Node) const {
2429+ // For iOS, we want to call an alternative entry point: __sincos_stret,
2430+ // which returns the values in two S / D registers.
2431+ SDLoc dl (Node);
2432+ SDValue Arg = Node->getOperand (0 );
2433+ EVT ArgVT = Arg.getValueType ();
2434+ RTLIB::Libcall LC = RTLIB::getSINCOS_STRET (ArgVT);
2435+ RTLIB::LibcallImpl SincosStret = TLI.getLibcallImpl (LC);
2436+ if (SincosStret == RTLIB::Unsupported)
2437+ return SDValue ();
2438+
2439+ // / There are 3 different ABI cases to handle:
2440+ // / - Direct return of separate fields in registers
2441+ // / - Single return as vector elements
2442+ // / - sret struct
2443+
2444+ const RTLIB::RuntimeLibcallsInfo &CallsInfo = TLI.getRuntimeLibcallsInfo ();
2445+
2446+ const DataLayout &DL = DAG.getDataLayout ();
2447+
2448+ auto [FuncTy, FuncAttrs] = CallsInfo.getFunctionTy (
2449+ *DAG.getContext (), TM.getTargetTriple (), DL, SincosStret);
2450+
2451+ Type *SincosStretRetTy = FuncTy->getReturnType ();
2452+ CallingConv::ID CallConv = CallsInfo.getLibcallImplCallingConv (SincosStret);
2453+ StringRef LibcallImplName = CallsInfo.getLibcallImplName (SincosStret);
2454+
2455+ SDValue Callee = DAG.getExternalSymbol (LibcallImplName.data (),
2456+ TLI.getProgramPointerTy (DL));
2457+
2458+ TargetLowering::ArgListTy Args;
2459+ SDValue SRet;
2460+
2461+ int FrameIdx;
2462+ if (FuncTy->getParamType (0 )->isPointerTy ()) {
2463+ // Uses sret
2464+ MachineFrameInfo &MFI = DAG.getMachineFunction ().getFrameInfo ();
2465+
2466+ AttributeSet PtrAttrs = FuncAttrs.getParamAttrs (0 );
2467+ Type *StructTy = PtrAttrs.getStructRetType ();
2468+ const uint64_t ByteSize = DL.getTypeAllocSize (StructTy);
2469+ const Align StackAlign = DL.getPrefTypeAlign (StructTy);
2470+
2471+ FrameIdx = MFI.CreateStackObject (ByteSize, StackAlign, false );
2472+ SRet = DAG.getFrameIndex (FrameIdx, TLI.getFrameIndexTy (DL));
2473+
2474+ TargetLowering::ArgListEntry Entry (SRet, FuncTy->getParamType (0 ));
2475+ Entry.IsSRet = true ;
2476+ Entry.IndirectType = StructTy;
2477+ Entry.Alignment = StackAlign;
2478+
2479+ Args.push_back (Entry);
2480+ Args.emplace_back (Arg, FuncTy->getParamType (1 ));
2481+ } else {
2482+ Args.emplace_back (Arg, FuncTy->getParamType (0 ));
2483+ }
2484+
2485+ TargetLowering::CallLoweringInfo CLI (DAG);
2486+ CLI.setDebugLoc (dl)
2487+ .setChain (DAG.getEntryNode ())
2488+ .setLibCallee (CallConv, SincosStretRetTy, Callee, std::move (Args))
2489+ .setIsPostTypeLegalization ();
2490+
2491+ std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo (CLI);
2492+
2493+ if (SRet) {
2494+ MachinePointerInfo PtrInfo =
2495+ MachinePointerInfo::getFixedStack (DAG.getMachineFunction (), FrameIdx);
2496+ SDValue LoadSin = DAG.getLoad (ArgVT, dl, CallResult.second , SRet, PtrInfo);
2497+
2498+ TypeSize StoreSize = ArgVT.getStoreSize ();
2499+
2500+ // Address of cos field.
2501+ SDValue Add = DAG.getObjectPtrOffset (dl, SRet, StoreSize);
2502+ SDValue LoadCos = DAG.getLoad (ArgVT, dl, LoadSin.getValue (1 ), Add,
2503+ PtrInfo.getWithOffset (StoreSize));
2504+
2505+ SDVTList Tys = DAG.getVTList (ArgVT, ArgVT);
2506+ return DAG.getNode (ISD::MERGE_VALUES, dl, Tys, LoadSin.getValue (0 ),
2507+ LoadCos.getValue (0 ));
2508+ }
2509+
2510+ if (!CallResult.first .getValueType ().isVector ())
2511+ return CallResult.first ;
2512+
2513+ SDValue SinVal =
2514+ DAG.getNode (ISD::EXTRACT_VECTOR_ELT, dl, ArgVT, CallResult.first ,
2515+ DAG.getVectorIdxConstant (0 , dl));
2516+ SDValue CosVal =
2517+ DAG.getNode (ISD::EXTRACT_VECTOR_ELT, dl, ArgVT, CallResult.first ,
2518+ DAG.getVectorIdxConstant (1 , dl));
2519+ SDVTList Tys = DAG.getVTList (ArgVT, ArgVT);
2520+ return DAG.getNode (ISD::MERGE_VALUES, dl, Tys, SinVal, CosVal);
2521+ }
2522+
24262523SDValue SelectionDAGLegalize::expandLdexp (SDNode *Node) const {
24272524 SDLoc dl (Node);
24282525 EVT VT = Node->getValueType (0 );
@@ -4730,6 +4827,18 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
47304827 case ISD::FSINCOS:
47314828 case ISD::FSINCOSPI: {
47324829 EVT VT = Node->getValueType (0 );
4830+
4831+ if (Node->getOpcode () == ISD::FSINCOS) {
4832+ RTLIB::Libcall SincosStret = RTLIB::getSINCOS_STRET (VT);
4833+ if (SincosStret != RTLIB::UNKNOWN_LIBCALL) {
4834+ if (SDValue Expanded = ExpandSincosStretLibCall (Node)) {
4835+ Results.push_back (Expanded);
4836+ Results.push_back (Expanded.getValue (1 ));
4837+ break ;
4838+ }
4839+ }
4840+ }
4841+
47334842 RTLIB::Libcall LC = Node->getOpcode () == ISD::FSINCOS
47344843 ? RTLIB::getSINCOS (VT)
47354844 : RTLIB::getSINCOSPI (VT);
0 commit comments