Skip to content

Commit 9853e99

Browse files
committed
DAG: Move expandMultipleResultFPLibCall to TargetLowering (NFC)
This kind of helper is higher level and not general enough to go directly in SelectionDAG. Most similar utilities are in TargetLowering.
1 parent dc62ebd commit 9853e99

File tree

7 files changed

+176
-176
lines changed

7 files changed

+176
-176
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,16 +1718,6 @@ class SelectionDAG {
17181718
/// the target's desired shift amount type.
17191719
LLVM_ABI SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op);
17201720

1721-
/// Expands a node with multiple results to an FP or vector libcall. The
1722-
/// libcall is expected to take all the operands of the \p Node followed by
1723-
/// output pointers for each of the results. \p CallRetResNo can be optionally
1724-
/// set to indicate that one of the results comes from the libcall's return
1725-
/// value.
1726-
LLVM_ABI bool
1727-
expandMultipleResultFPLibCall(RTLIB::Libcall LC, SDNode *Node,
1728-
SmallVectorImpl<SDValue> &Results,
1729-
std::optional<unsigned> CallRetResNo = {});
1730-
17311721
/// Expand the specified \c ISD::VAARG node as the Legalize pass would.
17321722
LLVM_ABI SDValue expandVAArg(SDNode *Node);
17331723

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5758,6 +5758,16 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
57585758
/// consisting of zext/sext, extract_subvector, mul and add operations.
57595759
SDValue expandPartialReduceMLA(SDNode *Node, SelectionDAG &DAG) const;
57605760

5761+
/// Expands a node with multiple results to an FP or vector libcall. The
5762+
/// libcall is expected to take all the operands of the \p Node followed by
5763+
/// output pointers for each of the results. \p CallRetResNo can be optionally
5764+
/// set to indicate that one of the results comes from the libcall's return
5765+
/// value.
5766+
bool expandMultipleResultFPLibCall(
5767+
SelectionDAG &DAG, RTLIB::Libcall LC, SDNode *Node,
5768+
SmallVectorImpl<SDValue> &Results,
5769+
std::optional<unsigned> CallRetResNo = {}) const;
5770+
57615771
/// Legalize a SETCC or VP_SETCC with given LHS and RHS and condition code CC
57625772
/// on the current target. A VP_SETCC will additionally be given a Mask
57635773
/// and/or EVL not equal to SDValue().

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4842,7 +4842,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
48424842
RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
48434843
? RTLIB::getSINCOS(VT)
48444844
: RTLIB::getSINCOSPI(VT);
4845-
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results);
4845+
bool Expanded = TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results);
48464846
if (!Expanded) {
48474847
DAG.getContext()->emitError(Twine("no libcall available for ") +
48484848
Node->getOperationName(&DAG));
@@ -4940,7 +4940,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
49404940
EVT VT = Node->getValueType(0);
49414941
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
49424942
: RTLIB::getFREXP(VT);
4943-
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
4943+
bool Expanded = TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
49444944
/*CallRetResNo=*/0);
49454945
if (!Expanded)
49464946
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1726,7 +1726,7 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
17261726
SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
17271727
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
17281728
SmallVector<SDValue> Results;
1729-
DAG.expandMultipleResultFPLibCall(LC, N, Results, CallRetResNo);
1729+
TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
17301730
for (auto [ResNo, Res] : enumerate(Results)) {
17311731
SDValue Lo, Hi;
17321732
GetPairElements(Res, Lo, Hi);

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
12751275
? RTLIB::getSINCOS(VT)
12761276
: RTLIB::getSINCOSPI(VT);
12771277
if (LC != RTLIB::UNKNOWN_LIBCALL &&
1278-
DAG.expandMultipleResultFPLibCall(LC, Node, Results))
1278+
TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results))
12791279
return;
12801280

12811281
// TODO: Try to see if there's a narrower call available to use before
@@ -1286,7 +1286,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
12861286
EVT VT = Node->getValueType(0);
12871287
RTLIB::Libcall LC = RTLIB::getMODF(VT);
12881288
if (LC != RTLIB::UNKNOWN_LIBCALL &&
1289-
DAG.expandMultipleResultFPLibCall(LC, Node, Results,
1289+
TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
12901290
/*CallRetResNo=*/0))
12911291
return;
12921292
break;

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 0 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,167 +2467,6 @@ SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) {
24672467
return getZExtOrTrunc(Op, SDLoc(Op), ShTy);
24682468
}
24692469

2470-
/// Given a store node \p StoreNode, return true if it is safe to fold that node
2471-
/// into \p FPNode, which expands to a library call with output pointers.
2472-
static bool canFoldStoreIntoLibCallOutputPointers(StoreSDNode *StoreNode,
2473-
SDNode *FPNode) {
2474-
SmallVector<const SDNode *, 8> Worklist;
2475-
SmallVector<const SDNode *, 8> DeferredNodes;
2476-
SmallPtrSet<const SDNode *, 16> Visited;
2477-
2478-
// Skip FPNode use by StoreNode (that's the use we want to fold into FPNode).
2479-
for (SDValue Op : StoreNode->ops())
2480-
if (Op.getNode() != FPNode)
2481-
Worklist.push_back(Op.getNode());
2482-
2483-
unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
2484-
while (!Worklist.empty()) {
2485-
const SDNode *Node = Worklist.pop_back_val();
2486-
auto [_, Inserted] = Visited.insert(Node);
2487-
if (!Inserted)
2488-
continue;
2489-
2490-
if (MaxSteps > 0 && Visited.size() >= MaxSteps)
2491-
return false;
2492-
2493-
// Reached the FPNode (would result in a cycle).
2494-
// OR Reached CALLSEQ_START (would result in nested call sequences).
2495-
if (Node == FPNode || Node->getOpcode() == ISD::CALLSEQ_START)
2496-
return false;
2497-
2498-
if (Node->getOpcode() == ISD::CALLSEQ_END) {
2499-
// Defer looking into call sequences (so we can check we're outside one).
2500-
// We still need to look through these for the predecessor check.
2501-
DeferredNodes.push_back(Node);
2502-
continue;
2503-
}
2504-
2505-
for (SDValue Op : Node->ops())
2506-
Worklist.push_back(Op.getNode());
2507-
}
2508-
2509-
// True if we're outside a call sequence and don't have the FPNode as a
2510-
// predecessor. No cycles or nested call sequences possible.
2511-
return !SDNode::hasPredecessorHelper(FPNode, Visited, DeferredNodes,
2512-
MaxSteps);
2513-
}
2514-
2515-
bool SelectionDAG::expandMultipleResultFPLibCall(
2516-
RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl<SDValue> &Results,
2517-
std::optional<unsigned> CallRetResNo) {
2518-
if (LC == RTLIB::UNKNOWN_LIBCALL)
2519-
return false;
2520-
2521-
RTLIB::LibcallImpl LibcallImpl = TLI->getLibcallImpl(LC);
2522-
if (LibcallImpl == RTLIB::Unsupported)
2523-
return false;
2524-
2525-
LLVMContext &Ctx = *getContext();
2526-
EVT VT = Node->getValueType(0);
2527-
unsigned NumResults = Node->getNumValues();
2528-
2529-
// Find users of the node that store the results (and share input chains). The
2530-
// destination pointers can be used instead of creating stack allocations.
2531-
SDValue StoresInChain;
2532-
SmallVector<StoreSDNode *, 2> ResultStores(NumResults);
2533-
for (SDNode *User : Node->users()) {
2534-
if (!ISD::isNormalStore(User))
2535-
continue;
2536-
auto *ST = cast<StoreSDNode>(User);
2537-
SDValue StoreValue = ST->getValue();
2538-
unsigned ResNo = StoreValue.getResNo();
2539-
// Ensure the store corresponds to an output pointer.
2540-
if (CallRetResNo == ResNo)
2541-
continue;
2542-
// Ensure the store to the default address space and not atomic or volatile.
2543-
if (!ST->isSimple() || ST->getAddressSpace() != 0)
2544-
continue;
2545-
// Ensure all store chains are the same (so they don't alias).
2546-
if (StoresInChain && ST->getChain() != StoresInChain)
2547-
continue;
2548-
// Ensure the store is properly aligned.
2549-
Type *StoreType = StoreValue.getValueType().getTypeForEVT(Ctx);
2550-
if (ST->getAlign() <
2551-
getDataLayout().getABITypeAlign(StoreType->getScalarType()))
2552-
continue;
2553-
// Avoid:
2554-
// 1. Creating cyclic dependencies.
2555-
// 2. Expanding the node to a call within a call sequence.
2556-
if (!canFoldStoreIntoLibCallOutputPointers(ST, Node))
2557-
continue;
2558-
ResultStores[ResNo] = ST;
2559-
StoresInChain = ST->getChain();
2560-
}
2561-
2562-
TargetLowering::ArgListTy Args;
2563-
2564-
// Pass the arguments.
2565-
for (const SDValue &Op : Node->op_values()) {
2566-
EVT ArgVT = Op.getValueType();
2567-
Type *ArgTy = ArgVT.getTypeForEVT(Ctx);
2568-
Args.emplace_back(Op, ArgTy);
2569-
}
2570-
2571-
// Pass the output pointers.
2572-
SmallVector<SDValue, 2> ResultPtrs(NumResults);
2573-
Type *PointerTy = PointerType::getUnqual(Ctx);
2574-
for (auto [ResNo, ST] : llvm::enumerate(ResultStores)) {
2575-
if (ResNo == CallRetResNo)
2576-
continue;
2577-
EVT ResVT = Node->getValueType(ResNo);
2578-
SDValue ResultPtr = ST ? ST->getBasePtr() : CreateStackTemporary(ResVT);
2579-
ResultPtrs[ResNo] = ResultPtr;
2580-
Args.emplace_back(ResultPtr, PointerTy);
2581-
}
2582-
2583-
SDLoc DL(Node);
2584-
2585-
if (RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(LibcallImpl)) {
2586-
// Pass the vector mask (if required).
2587-
EVT MaskVT = TLI->getSetCCResultType(getDataLayout(), Ctx, VT);
2588-
SDValue Mask = getBoolConstant(true, DL, MaskVT, VT);
2589-
Args.emplace_back(Mask, MaskVT.getTypeForEVT(Ctx));
2590-
}
2591-
2592-
Type *RetType = CallRetResNo.has_value()
2593-
? Node->getValueType(*CallRetResNo).getTypeForEVT(Ctx)
2594-
: Type::getVoidTy(Ctx);
2595-
SDValue InChain = StoresInChain ? StoresInChain : getEntryNode();
2596-
SDValue Callee =
2597-
getExternalSymbol(TLI->getLibcallImplName(LibcallImpl).data(),
2598-
TLI->getPointerTy(getDataLayout()));
2599-
TargetLowering::CallLoweringInfo CLI(*this);
2600-
CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
2601-
TLI->getLibcallImplCallingConv(LibcallImpl), RetType, Callee,
2602-
std::move(Args));
2603-
2604-
auto [Call, CallChain] = TLI->LowerCallTo(CLI);
2605-
2606-
for (auto [ResNo, ResultPtr] : llvm::enumerate(ResultPtrs)) {
2607-
if (ResNo == CallRetResNo) {
2608-
Results.push_back(Call);
2609-
continue;
2610-
}
2611-
MachinePointerInfo PtrInfo;
2612-
SDValue LoadResult =
2613-
getLoad(Node->getValueType(ResNo), DL, CallChain, ResultPtr, PtrInfo);
2614-
SDValue OutChain = LoadResult.getValue(1);
2615-
2616-
if (StoreSDNode *ST = ResultStores[ResNo]) {
2617-
// Replace store with the library call.
2618-
ReplaceAllUsesOfValueWith(SDValue(ST, 0), OutChain);
2619-
PtrInfo = ST->getPointerInfo();
2620-
} else {
2621-
PtrInfo = MachinePointerInfo::getFixedStack(
2622-
getMachineFunction(), cast<FrameIndexSDNode>(ResultPtr)->getIndex());
2623-
}
2624-
2625-
Results.push_back(LoadResult);
2626-
}
2627-
2628-
return true;
2629-
}
2630-
26312470
SDValue SelectionDAG::expandVAArg(SDNode *Node) {
26322471
SDLoc dl(Node);
26332472
const TargetLowering &TLI = getTargetLoweringInfo();

0 commit comments

Comments
 (0)