Skip to content

Commit 213cae7

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 faeead5 commit 213cae7

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
@@ -2468,167 +2468,6 @@ SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) {
24682468
return getZExtOrTrunc(Op, SDLoc(Op), ShTy);
24692469
}
24702470

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

0 commit comments

Comments
 (0)