Skip to content

[SelectionDAG] Add SDNode::user_begin() and use it in some places #120509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 19, 2024
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
5 changes: 5 additions & 0 deletions llvm/include/llvm/CodeGen/SelectionDAGNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,11 @@ END_TWO_BYTE_PACK()

static use_iterator use_end() { return use_iterator(nullptr); }

/// Provide iteration support to walk over all users of an SDNode.
/// For now, this should only be used to get a pointer to the first user.
/// FIXME: Rename use_iterator to user_iterator. Add user_end().
use_iterator user_begin() const { return use_iterator(UseList); }

// Dereferencing use_iterator returns the user SDNode* making it closer to a
// user_iterator thus this function is called users() to reflect that.
// FIXME: Rename to user_iterator and introduce a use_iterator that returns
Expand Down
38 changes: 19 additions & 19 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2136,8 +2136,8 @@ SDValue DAGCombiner::visitTokenFactor(SDNode *N) {
// If the sole user is a token factor, we should make sure we have a
// chance to merge them together. This prevents TF chains from inhibiting
// optimizations.
if (N->hasOneUse() && N->use_begin()->getOpcode() == ISD::TokenFactor)
AddToWorklist(*(N->use_begin()));
if (N->hasOneUse() && N->user_begin()->getOpcode() == ISD::TokenFactor)
AddToWorklist(*(N->user_begin()));

SmallVector<SDNode *, 8> TFs; // List of token factors to visit.
SmallVector<SDValue, 8> Ops; // Ops for replacing token factor.
Expand Down Expand Up @@ -10906,15 +10906,15 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
// which we plan to do. This workaround can be removed once the DAG is
// processed in topological order.
if (N->hasOneUse()) {
SDNode *Use = *N->use_begin();
SDNode *User = *N->user_begin();

// Look pass the truncate.
if (Use->getOpcode() == ISD::TRUNCATE && Use->hasOneUse())
Use = *Use->use_begin();
if (User->getOpcode() == ISD::TRUNCATE && User->hasOneUse())
User = *User->user_begin();
Comment on lines +10912 to +10913
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have a getOneUser helper

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an equivalent in IR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IR has hasOneUser, which is strictly less useful than returning the user.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasOneUser in IR returns whether or not the User of all Uses is unique. Should your proposed getOneUser() return the unique User or all Uses? Or should it only return the User if there is exactly one Use? Most of these places probably expect the latter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, the point is to handle instructions where the same value is used multiple times. It's a single user, which is usually what you want. It returns the single unique instruction which may use the value multiple times as an operand


if (Use->getOpcode() == ISD::BRCOND || Use->getOpcode() == ISD::AND ||
Use->getOpcode() == ISD::OR || Use->getOpcode() == ISD::XOR)
AddToWorklist(Use);
if (User->getOpcode() == ISD::BRCOND || User->getOpcode() == ISD::AND ||
User->getOpcode() == ISD::OR || User->getOpcode() == ISD::XOR)
AddToWorklist(User);
}

// Try to transform this shift into a multiply-high if
Expand Down Expand Up @@ -12917,7 +12917,7 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
// also lend itself to numerous combines and, as a result, it is desired
// we keep the argument to a brcond as a setcc as much as possible.
bool PreferSetCC =
N->hasOneUse() && N->use_begin()->getOpcode() == ISD::BRCOND;
N->hasOneUse() && N->user_begin()->getOpcode() == ISD::BRCOND;

ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(2))->get();
EVT VT = N->getValueType(0);
Expand Down Expand Up @@ -14825,7 +14825,7 @@ SDValue DAGCombiner::reduceLoadWidth(SDNode *N) {

// If the SRL is only used by a masking AND, we may be able to adjust
// the ExtVT to make the AND redundant.
SDNode *Mask = *(SRL->use_begin());
SDNode *Mask = *(SRL->user_begin());
if (SRL.hasOneUse() && Mask->getOpcode() == ISD::AND &&
isa<ConstantSDNode>(Mask->getOperand(1))) {
unsigned Offset, ActiveBits;
Expand Down Expand Up @@ -15364,7 +15364,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) {
}

// If this is anyext(trunc), don't fold it, allow ourselves to be folded.
if (N->hasOneUse() && (N->use_begin()->getOpcode() == ISD::ANY_EXTEND))
if (N->hasOneUse() && (N->user_begin()->getOpcode() == ISD::ANY_EXTEND))
return SDValue();

// Fold extract-and-trunc into a narrow extract. For example:
Expand Down Expand Up @@ -18370,7 +18370,7 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) {
return FoldedVOp;

// If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
if (N->hasOneUse() && N->use_begin()->getOpcode() == ISD::FP_ROUND)
if (N->hasOneUse() && N->user_begin()->getOpcode() == ISD::FP_ROUND)
return SDValue();

// fold (fp_extend c1fp) -> c1fp
Expand Down Expand Up @@ -19847,17 +19847,17 @@ struct LoadedSlice {
bool canMergeExpensiveCrossRegisterBankCopy() const {
if (!Inst || !Inst->hasOneUse())
return false;
SDNode *Use = *Inst->use_begin();
if (Use->getOpcode() != ISD::BITCAST)
SDNode *User = *Inst->user_begin();
if (User->getOpcode() != ISD::BITCAST)
return false;
assert(DAG && "Missing context");
const TargetLowering &TLI = DAG->getTargetLoweringInfo();
EVT ResVT = Use->getValueType(0);
EVT ResVT = User->getValueType(0);
const TargetRegisterClass *ResRC =
TLI.getRegClassFor(ResVT.getSimpleVT(), Use->isDivergent());
TLI.getRegClassFor(ResVT.getSimpleVT(), User->isDivergent());
const TargetRegisterClass *ArgRC =
TLI.getRegClassFor(Use->getOperand(0).getValueType().getSimpleVT(),
Use->getOperand(0)->isDivergent());
TLI.getRegClassFor(User->getOperand(0).getValueType().getSimpleVT(),
User->getOperand(0)->isDivergent());
if (ArgRC == ResRC || !TLI.isOperationLegal(ISD::LOAD, ResVT))
return false;

Expand Down Expand Up @@ -20069,7 +20069,7 @@ bool DAGCombiner::SliceUpLoad(SDNode *N) {
if (User->getOpcode() == ISD::SRL && User->hasOneUse() &&
isa<ConstantSDNode>(User->getOperand(1))) {
Shift = User->getConstantOperandVal(1);
User = *User->use_begin();
User = *User->user_begin();
}

// At this point, User is a Truncate, iff we encountered, trunc or
Expand Down
20 changes: 10 additions & 10 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18109,9 +18109,9 @@ bool AArch64TargetLowering::shouldFoldConstantShiftPairToMask(
if (N->getOpcode() == ISD::SHL && N->hasOneUse()) {
if (auto C2 = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
unsigned ShlAmt = C2->getZExtValue();
if (auto ShouldADD = *N->use_begin();
if (auto ShouldADD = *N->user_begin();
ShouldADD->getOpcode() == ISD::ADD && ShouldADD->hasOneUse()) {
if (auto ShouldLOAD = dyn_cast<LoadSDNode>(*ShouldADD->use_begin())) {
if (auto ShouldLOAD = dyn_cast<LoadSDNode>(*ShouldADD->user_begin())) {
unsigned ByteVT = ShouldLOAD->getMemoryVT().getSizeInBits() / 8;
if ((1ULL << ShlAmt) == ByteVT &&
isIndexedLoadLegal(ISD::PRE_INC, ShouldLOAD->getMemoryVT()))
Expand Down Expand Up @@ -18902,8 +18902,8 @@ static SDValue performMulCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
// Conservatively do not lower to shift+add+shift if the mul might be
// folded into madd or msub.
if (N->hasOneUse() && (N->use_begin()->getOpcode() == ISD::ADD ||
N->use_begin()->getOpcode() == ISD::SUB))
if (N->hasOneUse() && (N->user_begin()->getOpcode() == ISD::ADD ||
N->user_begin()->getOpcode() == ISD::SUB))
return SDValue();
}
// Use ShiftedConstValue instead of ConstValue to support both shift+add/sub
Expand Down Expand Up @@ -21803,7 +21803,7 @@ static SDValue tryCombineWhileLo(SDNode *N,
if (HalfSize < 2)
return SDValue();

auto It = N->use_begin();
auto It = N->user_begin();
SDNode *Lo = *It++;
SDNode *Hi = *It;

Expand Down Expand Up @@ -23402,7 +23402,7 @@ static SDValue performPostLD1Combine(SDNode *N,
// TODO: This could be expanded to more operations if they reliably use the
// index variants.
if (N->hasOneUse()) {
unsigned UseOpc = N->use_begin()->getOpcode();
unsigned UseOpc = N->user_begin()->getOpcode();
if (UseOpc == ISD::FMUL || UseOpc == ISD::FMA)
return SDValue();
}
Expand Down Expand Up @@ -24755,7 +24755,7 @@ static SDValue tryToWidenSetCCOperands(SDNode *Op, SelectionDAG &DAG) {

// Make sure that all uses of Op are VSELECTs with result matching types where
// the result type has a larger element type than the SetCC operand.
SDNode *FirstUse = *Op->use_begin();
SDNode *FirstUse = *Op->user_begin();
if (FirstUse->getOpcode() != ISD::VSELECT)
return SDValue();
EVT UseMVT = FirstUse->getValueType(0);
Expand Down Expand Up @@ -25905,7 +25905,7 @@ static SDValue performFPExtendCombine(SDNode *N, SelectionDAG &DAG,
EVT VT = N->getValueType(0);

// If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
if (N->hasOneUse() && N->use_begin()->getOpcode() == ISD::FP_ROUND)
if (N->hasOneUse() && N->user_begin()->getOpcode() == ISD::FP_ROUND)
return SDValue();

auto hasValidElementTypeForFPExtLoad = [](EVT VT) {
Expand Down Expand Up @@ -26072,7 +26072,7 @@ static SDValue tryCombineMULLWithUZP1(SDNode *N,

// Check ExtractLow's user.
if (HasFoundMULLow) {
SDNode *ExtractLowUser = *ExtractLow.getNode()->use_begin();
SDNode *ExtractLowUser = *ExtractLow.getNode()->user_begin();
if (ExtractLowUser->getOpcode() != N->getOpcode()) {
HasFoundMULLow = false;
} else {
Expand Down Expand Up @@ -26549,7 +26549,7 @@ bool AArch64TargetLowering::isUsedByReturnOnly(SDNode *N,
return false;

SDValue TCChain = Chain;
SDNode *Copy = *N->use_begin();
SDNode *Copy = *N->user_begin();
if (Copy->getOpcode() == ISD::CopyToReg) {
// If the copy has a glue operand, we conservatively assume it isn't safe to
// perform a tail call.
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,9 @@ bool AMDGPUTargetLowering::isDesirableToCommuteWithShift(
return true;

// If only user is a i32 right-shift, then don't destroy a BFE pattern.
if (N->getValueType(0) == MVT::i32 && N->use_size() == 1 &&
(N->use_begin()->getOpcode() == ISD::SRA ||
N->use_begin()->getOpcode() == ISD::SRL))
if (N->getValueType(0) == MVT::i32 && N->hasOneUse() &&
(N->user_begin()->getOpcode() == ISD::SRA ||
N->user_begin()->getOpcode() == ISD::SRL))
return false;

// Don't destroy or(shl(load_zext(),c), load_zext()) patterns.
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/SIISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16896,7 +16896,7 @@ bool SITargetLowering::isReassocProfitable(SelectionDAG &DAG, SDValue N0,
// Check if we have a good chance to form the memory access pattern with the
// base and offset
return (DAG.isBaseWithConstantOffset(N0) &&
hasMemSDNodeUser(*N0->use_begin()));
hasMemSDNodeUser(*N0->user_begin()));
}

bool SITargetLowering::isReassocProfitable(MachineRegisterInfo &MRI,
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,14 +505,14 @@ bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const {
if (!N->hasOneUse())
return false;

SDNode *Use = *N->use_begin();
if (Use->getOpcode() == ISD::CopyToReg)
SDNode *User = *N->user_begin();
if (User->getOpcode() == ISD::CopyToReg)
return true;
if (Use->isMachineOpcode()) {
if (User->isMachineOpcode()) {
const ARMBaseInstrInfo *TII = static_cast<const ARMBaseInstrInfo *>(
CurDAG->getSubtarget().getInstrInfo());

const MCInstrDesc &MCID = TII->get(Use->getMachineOpcode());
const MCInstrDesc &MCID = TII->get(User->getMachineOpcode());
if (MCID.mayStore())
return true;
unsigned Opcode = MCID.getOpcode();
Expand Down
29 changes: 14 additions & 15 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3456,7 +3456,7 @@ bool ARMTargetLowering::isUsedByReturnOnly(SDNode *N, SDValue &Chain) const {
return false;

SDValue TCChain = Chain;
SDNode *Copy = *N->use_begin();
SDNode *Copy = *N->user_begin();
if (Copy->getOpcode() == ISD::CopyToReg) {
// If the copy has a glue operand, we conservatively assume it isn't safe to
// perform a tail call.
Expand Down Expand Up @@ -3494,7 +3494,7 @@ bool ARMTargetLowering::isUsedByReturnOnly(SDNode *N, SDValue &Chain) const {
// f32 returned in a single GPR.
if (!Copy->hasOneUse())
return false;
Copy = *Copy->use_begin();
Copy = *Copy->user_begin();
if (Copy->getOpcode() != ISD::CopyToReg || !Copy->hasNUsesOfValue(1, 0))
return false;
// If the copy has a glue operand, we conservatively assume it isn't safe to
Expand Down Expand Up @@ -15356,7 +15356,7 @@ PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
assert(EltVT == MVT::f32 && "Unexpected type!");

// Check 1.2.
SDNode *Use = *N->use_begin();
SDNode *Use = *N->user_begin();
if (Use->getOpcode() != ISD::BITCAST ||
Use->getValueType(0).isFloatingPoint())
return SDValue();
Expand Down Expand Up @@ -15561,9 +15561,8 @@ PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
!isa<ConstantSDNode>(Ext.getOperand(1)) ||
Ext.getConstantOperandVal(1) % 2 != 0)
return SDValue();
if (Ext->use_size() == 1 &&
(Ext->use_begin()->getOpcode() == ISD::SINT_TO_FP ||
Ext->use_begin()->getOpcode() == ISD::UINT_TO_FP))
if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() == ISD::SINT_TO_FP ||
Ext->user_begin()->getOpcode() == ISD::UINT_TO_FP))
return SDValue();

SDValue Op0 = Ext.getOperand(0);
Expand All @@ -15587,11 +15586,11 @@ PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
// lanes.
SDValue OtherExt(*OtherIt, 0);
if (OtherExt.getValueType() != MVT::i32) {
if (OtherExt->use_size() != 1 ||
OtherExt->use_begin()->getOpcode() != ISD::BITCAST ||
OtherExt->use_begin()->getValueType(0) != MVT::i32)
if (!OtherExt->hasOneUse() ||
OtherExt->user_begin()->getOpcode() != ISD::BITCAST ||
OtherExt->user_begin()->getValueType(0) != MVT::i32)
return SDValue();
OtherExt = SDValue(*OtherExt->use_begin(), 0);
OtherExt = SDValue(*OtherExt->user_begin(), 0);
}

// Convert the type to a f64 and extract with a VMOVRRD.
Expand Down Expand Up @@ -18326,9 +18325,9 @@ static SDValue PerformHWLoopCombine(SDNode *N,
SelectionDAG &DAG = DCI.DAG;
SDValue Elements = Int.getOperand(2);
unsigned IntOp = Int->getConstantOperandVal(1);
assert((N->hasOneUse() && N->use_begin()->getOpcode() == ISD::BR)
&& "expected single br user");
SDNode *Br = *N->use_begin();
assert((N->hasOneUse() && N->user_begin()->getOpcode() == ISD::BR) &&
"expected single br user");
SDNode *Br = *N->user_begin();
SDValue OtherTarget = Br->getOperand(1);

// Update the unconditional branch to branch to the given Dest.
Expand Down Expand Up @@ -19330,10 +19329,10 @@ bool ARMTargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
// If there's more than one user instruction, the loadext is desirable no
// matter what. There can be two uses by the same instruction.
if (ExtVal->use_empty() ||
!ExtVal->use_begin()->isOnlyUserOf(ExtVal.getNode()))
!ExtVal->user_begin()->isOnlyUserOf(ExtVal.getNode()))
return true;

SDNode *U = *ExtVal->use_begin();
SDNode *U = *ExtVal->user_begin();
if ((U->getOpcode() == ISD::ADD || U->getOpcode() == ISD::SUB ||
U->getOpcode() == ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
return false;
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ static bool isMemOPCandidate(SDNode *I, SDNode *U) {
SDValue S1 = U->getOperand(1);
SDValue SY = (S0.getNode() == I) ? S1 : S0;

SDNode *UUse = *U->use_begin();
SDNode *UUse = *U->user_begin();
if (UUse->getNumValues() != 1)
return false;

Expand Down Expand Up @@ -2431,7 +2431,7 @@ void HexagonDAGToDAGISel::rebalanceAddressTrees() {
Worklist.push_back(N->getOperand(1).getNode());

// Not a root if it has only one use and same opcode as its parent
if (N->hasOneUse() && Opcode == N->use_begin()->getOpcode())
if (N->hasOneUse() && Opcode == N->user_begin()->getOpcode())
continue;

// This root node has already been processed
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5340,7 +5340,7 @@ bool LoongArchTargetLowering::isUsedByReturnOnly(SDNode *N,
if (!N->hasNUsesOfValue(1, 0))
return false;

SDNode *Copy = *N->use_begin();
SDNode *Copy = *N->user_begin();
if (Copy->getOpcode() != ISD::CopyToReg)
return false;

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6610,7 +6610,7 @@ void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) {
SDValue ConstFalse = CurDAG->getConstant(0, dl, VT);

do {
SDNode *User = *N->use_begin();
SDNode *User = *N->user_begin();
if (User->getNumOperands() != 2)
break;

Expand Down Expand Up @@ -7564,7 +7564,7 @@ static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) {
while (V->isMachineOpcode() &&
V->getMachineOpcode() == TargetOpcode::COPY_TO_REGCLASS) {
// All values in the chain should have single use.
if (V->use_empty() || !V->use_begin()->isOnlyUserOf(V.getNode()))
if (V->use_empty() || !V->user_begin()->isOnlyUserOf(V.getNode()))
return SDValue();
V = V->getOperand(0);
}
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16331,7 +16331,7 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
if (!LD->hasNUsesOfValue(2, 0))
return false;

auto UI = LD->use_begin();
auto UI = LD->user_begin();
while (UI.getUse().getResNo() != 0) ++UI;
SDNode *Trunc = *UI++;
while (UI.getUse().getResNo() != 0) ++UI;
Expand All @@ -16349,14 +16349,14 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
!RightShift->hasOneUse())
return false;

SDNode *Trunc2 = *RightShift->use_begin();
SDNode *Trunc2 = *RightShift->user_begin();
if (Trunc2->getOpcode() != ISD::TRUNCATE ||
Trunc2->getValueType(0) != MVT::i32 ||
!Trunc2->hasOneUse())
return false;

SDNode *Bitcast = *Trunc->use_begin();
SDNode *Bitcast2 = *Trunc2->use_begin();
SDNode *Bitcast = *Trunc->user_begin();
SDNode *Bitcast2 = *Trunc2->user_begin();

if (Bitcast->getOpcode() != ISD::BITCAST ||
Bitcast->getValueType(0) != MVT::f32)
Expand Down
Loading
Loading