Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions llvm/include/llvm/CodeGen/SelectionDAG.h
Original file line number Diff line number Diff line change
Expand Up @@ -1718,16 +1718,6 @@ class SelectionDAG {
/// the target's desired shift amount type.
LLVM_ABI SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op);

/// Expands a node with multiple results to an FP or vector libcall. The
/// libcall is expected to take all the operands of the \p Node followed by
/// output pointers for each of the results. \p CallRetResNo can be optionally
/// set to indicate that one of the results comes from the libcall's return
/// value.
LLVM_ABI bool
expandMultipleResultFPLibCall(RTLIB::Libcall LC, SDNode *Node,
SmallVectorImpl<SDValue> &Results,
std::optional<unsigned> CallRetResNo = {});

/// Expand the specified \c ISD::VAARG node as the Legalize pass would.
LLVM_ABI SDValue expandVAArg(SDNode *Node);

Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm/CodeGen/TargetLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -5757,6 +5757,16 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
/// consisting of zext/sext, extract_subvector, mul and add operations.
SDValue expandPartialReduceMLA(SDNode *Node, SelectionDAG &DAG) const;

/// Expands a node with multiple results to an FP or vector libcall. The
/// libcall is expected to take all the operands of the \p Node followed by
/// output pointers for each of the results. \p CallRetResNo can be optionally
/// set to indicate that one of the results comes from the libcall's return
/// value.
bool expandMultipleResultFPLibCall(
SelectionDAG &DAG, RTLIB::Libcall LC, SDNode *Node,
SmallVectorImpl<SDValue> &Results,
std::optional<unsigned> CallRetResNo = {}) const;

/// Legalize a SETCC or VP_SETCC with given LHS and RHS and condition code CC
/// on the current target. A VP_SETCC will additionally be given a Mask
/// and/or EVL not equal to SDValue().
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4842,7 +4842,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::Libcall LC = Node->getOpcode() == ISD::FSINCOS
? RTLIB::getSINCOS(VT)
: RTLIB::getSINCOSPI(VT);
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results);
bool Expanded = TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results);
if (!Expanded) {
DAG.getContext()->emitError(Twine("no libcall available for ") +
Node->getOperationName(&DAG));
Expand Down Expand Up @@ -4940,7 +4940,7 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = Node->getOpcode() == ISD::FMODF ? RTLIB::getMODF(VT)
: RTLIB::getFREXP(VT);
bool Expanded = DAG.expandMultipleResultFPLibCall(LC, Node, Results,
bool Expanded = TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
/*CallRetResNo=*/0);
if (!Expanded)
llvm_unreachable("Expected scalar FFREXP/FMODF to expand to libcall!");
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1726,7 +1726,7 @@ void DAGTypeLegalizer::ExpandFloatRes_UnaryWithTwoFPResults(
SDNode *N, RTLIB::Libcall LC, std::optional<unsigned> CallRetResNo) {
assert(!N->isStrictFPOpcode() && "strictfp not implemented");
SmallVector<SDValue> Results;
DAG.expandMultipleResultFPLibCall(LC, N, Results, CallRetResNo);
TLI.expandMultipleResultFPLibCall(DAG, LC, N, Results, CallRetResNo);
for (auto [ResNo, Res] : enumerate(Results)) {
SDValue Lo, Hi;
GetPairElements(Res, Lo, Hi);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
? RTLIB::getSINCOS(VT)
: RTLIB::getSINCOSPI(VT);
if (LC != RTLIB::UNKNOWN_LIBCALL &&
DAG.expandMultipleResultFPLibCall(LC, Node, Results))
TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results))
return;

// TODO: Try to see if there's a narrower call available to use before
Expand All @@ -1286,7 +1286,7 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
EVT VT = Node->getValueType(0);
RTLIB::Libcall LC = RTLIB::getMODF(VT);
if (LC != RTLIB::UNKNOWN_LIBCALL &&
DAG.expandMultipleResultFPLibCall(LC, Node, Results,
TLI.expandMultipleResultFPLibCall(DAG, LC, Node, Results,
/*CallRetResNo=*/0))
return;
break;
Expand Down
161 changes: 0 additions & 161 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2467,167 +2467,6 @@ SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) {
return getZExtOrTrunc(Op, SDLoc(Op), ShTy);
}

/// Given a store node \p StoreNode, return true if it is safe to fold that node
/// into \p FPNode, which expands to a library call with output pointers.
static bool canFoldStoreIntoLibCallOutputPointers(StoreSDNode *StoreNode,
SDNode *FPNode) {
SmallVector<const SDNode *, 8> Worklist;
SmallVector<const SDNode *, 8> DeferredNodes;
SmallPtrSet<const SDNode *, 16> Visited;

// Skip FPNode use by StoreNode (that's the use we want to fold into FPNode).
for (SDValue Op : StoreNode->ops())
if (Op.getNode() != FPNode)
Worklist.push_back(Op.getNode());

unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
while (!Worklist.empty()) {
const SDNode *Node = Worklist.pop_back_val();
auto [_, Inserted] = Visited.insert(Node);
if (!Inserted)
continue;

if (MaxSteps > 0 && Visited.size() >= MaxSteps)
return false;

// Reached the FPNode (would result in a cycle).
// OR Reached CALLSEQ_START (would result in nested call sequences).
if (Node == FPNode || Node->getOpcode() == ISD::CALLSEQ_START)
return false;

if (Node->getOpcode() == ISD::CALLSEQ_END) {
// Defer looking into call sequences (so we can check we're outside one).
// We still need to look through these for the predecessor check.
DeferredNodes.push_back(Node);
continue;
}

for (SDValue Op : Node->ops())
Worklist.push_back(Op.getNode());
}

// True if we're outside a call sequence and don't have the FPNode as a
// predecessor. No cycles or nested call sequences possible.
return !SDNode::hasPredecessorHelper(FPNode, Visited, DeferredNodes,
MaxSteps);
}

bool SelectionDAG::expandMultipleResultFPLibCall(
RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl<SDValue> &Results,
std::optional<unsigned> CallRetResNo) {
if (LC == RTLIB::UNKNOWN_LIBCALL)
return false;

RTLIB::LibcallImpl LibcallImpl = TLI->getLibcallImpl(LC);
if (LibcallImpl == RTLIB::Unsupported)
return false;

LLVMContext &Ctx = *getContext();
EVT VT = Node->getValueType(0);
unsigned NumResults = Node->getNumValues();

// Find users of the node that store the results (and share input chains). The
// destination pointers can be used instead of creating stack allocations.
SDValue StoresInChain;
SmallVector<StoreSDNode *, 2> ResultStores(NumResults);
for (SDNode *User : Node->users()) {
if (!ISD::isNormalStore(User))
continue;
auto *ST = cast<StoreSDNode>(User);
SDValue StoreValue = ST->getValue();
unsigned ResNo = StoreValue.getResNo();
// Ensure the store corresponds to an output pointer.
if (CallRetResNo == ResNo)
continue;
// Ensure the store to the default address space and not atomic or volatile.
if (!ST->isSimple() || ST->getAddressSpace() != 0)
continue;
// Ensure all store chains are the same (so they don't alias).
if (StoresInChain && ST->getChain() != StoresInChain)
continue;
// Ensure the store is properly aligned.
Type *StoreType = StoreValue.getValueType().getTypeForEVT(Ctx);
if (ST->getAlign() <
getDataLayout().getABITypeAlign(StoreType->getScalarType()))
continue;
// Avoid:
// 1. Creating cyclic dependencies.
// 2. Expanding the node to a call within a call sequence.
if (!canFoldStoreIntoLibCallOutputPointers(ST, Node))
continue;
ResultStores[ResNo] = ST;
StoresInChain = ST->getChain();
}

TargetLowering::ArgListTy Args;

// Pass the arguments.
for (const SDValue &Op : Node->op_values()) {
EVT ArgVT = Op.getValueType();
Type *ArgTy = ArgVT.getTypeForEVT(Ctx);
Args.emplace_back(Op, ArgTy);
}

// Pass the output pointers.
SmallVector<SDValue, 2> ResultPtrs(NumResults);
Type *PointerTy = PointerType::getUnqual(Ctx);
for (auto [ResNo, ST] : llvm::enumerate(ResultStores)) {
if (ResNo == CallRetResNo)
continue;
EVT ResVT = Node->getValueType(ResNo);
SDValue ResultPtr = ST ? ST->getBasePtr() : CreateStackTemporary(ResVT);
ResultPtrs[ResNo] = ResultPtr;
Args.emplace_back(ResultPtr, PointerTy);
}

SDLoc DL(Node);

if (RTLIB::RuntimeLibcallsInfo::hasVectorMaskArgument(LibcallImpl)) {
// Pass the vector mask (if required).
EVT MaskVT = TLI->getSetCCResultType(getDataLayout(), Ctx, VT);
SDValue Mask = getBoolConstant(true, DL, MaskVT, VT);
Args.emplace_back(Mask, MaskVT.getTypeForEVT(Ctx));
}

Type *RetType = CallRetResNo.has_value()
? Node->getValueType(*CallRetResNo).getTypeForEVT(Ctx)
: Type::getVoidTy(Ctx);
SDValue InChain = StoresInChain ? StoresInChain : getEntryNode();
SDValue Callee =
getExternalSymbol(TLI->getLibcallImplName(LibcallImpl).data(),
TLI->getPointerTy(getDataLayout()));
TargetLowering::CallLoweringInfo CLI(*this);
CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
TLI->getLibcallImplCallingConv(LibcallImpl), RetType, Callee,
std::move(Args));

auto [Call, CallChain] = TLI->LowerCallTo(CLI);

for (auto [ResNo, ResultPtr] : llvm::enumerate(ResultPtrs)) {
if (ResNo == CallRetResNo) {
Results.push_back(Call);
continue;
}
MachinePointerInfo PtrInfo;
SDValue LoadResult =
getLoad(Node->getValueType(ResNo), DL, CallChain, ResultPtr, PtrInfo);
SDValue OutChain = LoadResult.getValue(1);

if (StoreSDNode *ST = ResultStores[ResNo]) {
// Replace store with the library call.
ReplaceAllUsesOfValueWith(SDValue(ST, 0), OutChain);
PtrInfo = ST->getPointerInfo();
} else {
PtrInfo = MachinePointerInfo::getFixedStack(
getMachineFunction(), cast<FrameIndexSDNode>(ResultPtr)->getIndex());
}

Results.push_back(LoadResult);
}

return true;
}

SDValue SelectionDAG::expandVAArg(SDNode *Node) {
SDLoc dl(Node);
const TargetLowering &TLI = getTargetLoweringInfo();
Expand Down
Loading
Loading