88#define DEBUG_TYPE "dagcombine"
90STATISTIC(NodesCombined ,
"Number of dag nodes combined");
91STATISTIC(PreIndexedNodes ,
"Number of pre-indexed nodes created");
92STATISTIC(PostIndexedNodes,
"Number of post-indexed nodes created");
93STATISTIC(OpsNarrowed ,
"Number of load/op/store narrowed");
94STATISTIC(LdStFP2Int ,
"Number of fp load/store pairs transformed to int");
96STATISTIC(NumFPLogicOpsConv,
"Number of logic ops converted to fp ops");
99 "Controls whether a DAG combine is performed for a node");
103 cl::desc(
"Enable DAG combiner's use of IR alias analysis"));
107 cl::desc(
"Enable DAG combiner's use of TBAA"));
112 cl::desc(
"Only use DAG-combiner alias analysis in this"
120 cl::desc(
"Bypass the profitability model of load slicing"),
125 cl::desc(
"DAG combiner may split indexing from loads"));
129 cl::desc(
"DAG combiner enable merging multiple stores "
130 "into a wider store"));
134 cl::desc(
"Limit the number of operands to inline for Token Factors"));
138 cl::desc(
"Limit the number of times for the same StoreNode and RootNode "
139 "to bail out in store merging dependence check"));
143 cl::desc(
"DAG combiner enable reducing the width of load/op/store "
146 "combiner-reduce-load-op-store-width-force-narrowing-profitable",
148 cl::desc(
"DAG combiner force override the narrowing profitable check when "
149 "reducing the width of load/op/store sequences"));
153 cl::desc(
"DAG combiner enable load/<replace bytes>/store with "
154 "a narrower store"));
158 cl::desc(
"DAG combiner nodes consistently processed in topological order"));
162 cl::desc(
"Disable the DAG combiner"));
172 bool LegalDAG =
false;
173 bool LegalOperations =
false;
174 bool LegalTypes =
false;
176 bool DisableGenericCombines;
212 void AddUsersToWorklist(
SDNode *
N) {
218 void AddToWorklistWithUsers(SDNode *
N) {
219 AddUsersToWorklist(
N);
226 void clearAddedDanglingWorklistEntries() {
228 while (!PruningList.empty()) {
229 auto *
N = PruningList.pop_back_val();
231 recursivelyDeleteUnusedNodes(
N);
235 SDNode *getNextWorklistEntry() {
237 clearAddedDanglingWorklistEntries();
241 while (!
N && !Worklist.empty()) {
242 N = Worklist.pop_back_val();
246 assert(
N->getCombinerWorklistIndex() >= 0 &&
247 "Found a worklist entry without a corresponding map entry!");
249 N->setCombinerWorklistIndex(-2);
259 : DAG(
D), TLI(
D.getTargetLoweringInfo()),
260 STI(
D.getSubtarget().getSelectionDAGInfo()), OptLevel(OL),
262 ForCodeSize = DAG.shouldOptForSize();
263 DisableGenericCombines =
267 void ConsiderForPruning(SDNode *
N) {
269 PruningList.insert(
N);
274 void AddToWorklist(SDNode *
N,
bool IsCandidateForPruning =
true,
275 bool SkipIfCombinedBefore =
false) {
277 "Deleted Node added to Worklist");
284 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
287 if (IsCandidateForPruning)
288 ConsiderForPruning(
N);
290 if (
N->getCombinerWorklistIndex() < 0) {
291 N->setCombinerWorklistIndex(Worklist.size());
292 Worklist.push_back(
N);
297 void removeFromWorklist(SDNode *
N) {
298 PruningList.remove(
N);
299 StoreRootCountMap.erase(
N);
301 int WorklistIndex =
N->getCombinerWorklistIndex();
305 if (WorklistIndex < 0)
309 Worklist[WorklistIndex] =
nullptr;
310 N->setCombinerWorklistIndex(-1);
313 void deleteAndRecombine(SDNode *
N);
314 bool recursivelyDeleteUnusedNodes(SDNode *
N);
322 return CombineTo(
N, &Res, 1, AddTo);
329 return CombineTo(
N, To, 2, AddTo);
332 SDValue CombineTo(SDNode *
N, SmallVectorImpl<SDValue> *To,
334 return CombineTo(
N, To->
data(), To->
size(), AddTo);
337 void CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO);
344 unsigned BitWidth =
Op.getScalarValueSizeInBits();
346 return SimplifyDemandedBits(
Op, DemandedBits);
349 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits) {
350 EVT VT =
Op.getValueType();
354 return SimplifyDemandedBits(
Op, DemandedBits, DemandedElts,
false);
360 bool SimplifyDemandedVectorElts(
SDValue Op) {
362 if (
Op.getValueType().isScalableVector())
365 unsigned NumElts =
Op.getValueType().getVectorNumElements();
367 return SimplifyDemandedVectorElts(
Op, DemandedElts);
370 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
371 const APInt &DemandedElts,
372 bool AssumeSingleUse =
false);
373 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
374 bool AssumeSingleUse =
false);
376 bool CombineToPreIndexedLoadStore(SDNode *
N);
377 bool CombineToPostIndexedLoadStore(SDNode *
N);
378 SDValue SplitIndexingFromLoad(LoadSDNode *LD);
379 bool SliceUpLoad(SDNode *
N);
385 StoreSDNode *getUniqueStoreFeeding(LoadSDNode *LD, int64_t &
Offset);
387 SDValue ForwardStoreValueToDirectLoad(LoadSDNode *LD);
388 bool getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val);
389 bool extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val);
391 void ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad);
400 SDValue foldShiftToAvg(SDNode *
N,
const SDLoc &
DL);
402 SDValue foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT);
420 SDValue visitTokenFactor(SDNode *
N);
421 SDValue visitMERGE_VALUES(SDNode *
N);
425 SDNode *LocReference);
436 SDValue visitUADDO_CARRY(SDNode *
N);
437 SDValue visitSADDO_CARRY(SDNode *
N);
443 SDValue visitUSUBO_CARRY(SDNode *
N);
444 SDValue visitSSUBO_CARRY(SDNode *
N);
445 template <
class MatchContextClass>
SDValue visitMUL(SDNode *
N);
466 SDValue SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL);
467 SDValue SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL);
471 SDValue visitFunnelShift(SDNode *
N);
479 SDValue visitCTLZ_ZERO_POISON(SDNode *
N);
481 SDValue visitCTTZ_ZERO_POISON(SDNode *
N);
489 SDValue visitSIGN_EXTEND(SDNode *
N);
490 SDValue visitZERO_EXTEND(SDNode *
N);
493 SDValue visitAssertAlign(SDNode *
N);
495 SDValue visitSIGN_EXTEND_INREG(SDNode *
N);
496 SDValue visitEXTEND_VECTOR_INREG(SDNode *
N);
498 SDValue visitTRUNCATE_USAT_U(SDNode *
N);
505 SDValue visitSTRICT_FADD(SDNode *
N);
508 template <
class MatchContextClass>
SDValue visitFMA(SDNode *
N);
516 SDValue visitFCANONICALIZE(SDNode *
N);
536 SDValue replaceStoreOfFPConstant(StoreSDNode *ST);
537 SDValue replaceStoreOfInsertLoad(StoreSDNode *ST);
539 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(SDNode *
N);
542 SDValue visitATOMIC_STORE(SDNode *
N);
543 SDValue visitLIFETIME_END(SDNode *
N);
544 SDValue visitINSERT_VECTOR_ELT(SDNode *
N);
545 SDValue visitEXTRACT_VECTOR_ELT(SDNode *
N);
546 SDValue visitBUILD_VECTOR(SDNode *
N);
547 SDValue visitCONCAT_VECTORS(SDNode *
N);
548 SDValue visitVECTOR_INTERLEAVE(SDNode *
N);
549 SDValue visitEXTRACT_SUBVECTOR(SDNode *
N);
550 SDValue visitVECTOR_SHUFFLE(SDNode *
N);
551 SDValue visitSCALAR_TO_VECTOR(SDNode *
N);
552 SDValue visitINSERT_SUBVECTOR(SDNode *
N);
553 SDValue visitVECTOR_COMPRESS(SDNode *
N);
559 SDValue visitPARTIAL_REDUCE_MLA(SDNode *
N);
562 SDValue visitVP_STRIDED_LOAD(SDNode *
N);
563 SDValue visitVP_STRIDED_STORE(SDNode *
N);
570 SDValue visitGET_FPENV_MEM(SDNode *
N);
571 SDValue visitSET_FPENV_MEM(SDNode *
N);
573 template <
class MatchContextClass>
574 SDValue visitFADDForFMACombine(SDNode *
N);
575 template <
class MatchContextClass>
576 SDValue visitFSUBForFMACombine(SDNode *
N);
577 SDValue visitFMULForFMADistributiveCombine(SDNode *
N);
579 SDValue XformToShuffleWithZero(SDNode *
N);
580 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
586 SDValue N1, SDNodeFlags Flags);
588 SDValue N1, SDNodeFlags Flags);
589 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
591 SDNodeFlags Flags = SDNodeFlags());
593 SDValue visitShiftByConstant(SDNode *
N);
595 SDValue foldSelectOfConstants(SDNode *
N);
596 SDValue foldVSelectOfConstants(SDNode *
N);
597 SDValue foldBinOpIntoSelect(SDNode *BO);
599 SDValue hoistLogicOpWithSameOpcodeHands(SDNode *
N);
603 bool NotExtCompare =
false);
604 SDValue convertSelectOfFPConstantsToLoadOffset(
607 SDValue foldSignChangeInBitcast(SDNode *
N);
610 SDValue foldSelectOfBinops(SDNode *
N);
614 SDValue foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL);
615 SDValue foldABSToABD(SDNode *
N,
const SDLoc &
DL);
620 SDValue unfoldMaskedMerge(SDNode *
N);
621 SDValue unfoldExtremeBitClearingToShifts(SDNode *
N);
623 const SDLoc &
DL,
bool foldBooleans);
627 SDValue &CC,
bool MatchStrict =
false)
const;
628 bool isOneUseSetCC(
SDValue N)
const;
630 SDValue foldAddToAvg(SDNode *
N,
const SDLoc &
DL);
631 SDValue foldSubToAvg(SDNode *
N,
const SDLoc &
DL);
635 SDValue SimplifyNodeWithTwoResults(SDNode *
N,
unsigned LoOp,
637 SDValue CombineConsecutiveLoads(SDNode *
N, EVT VT);
638 SDValue foldBitcastedFPLogic(SDNode *
N, SelectionDAG &DAG,
639 const TargetLowering &TLI);
640 SDValue foldPartialReduceMLAMulOp(SDNode *
N);
641 SDValue foldPartialReduceAdd(SDNode *
N);
644 SDValue CombineZExtLogicopShiftLoad(SDNode *
N);
645 SDValue combineRepeatedFPDivisors(SDNode *
N);
646 SDValue combineFMulOrFDivWithIntPow2(SDNode *
N);
647 SDValue replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf);
648 SDValue mergeInsertEltWithShuffle(SDNode *
N,
unsigned InsIndex);
649 SDValue combineInsertEltToShuffle(SDNode *
N,
unsigned InsIndex);
650 SDValue combineInsertEltToLoad(SDNode *
N,
unsigned InsIndex);
657 bool KnownNeverZero =
false,
658 bool InexpensiveOnly =
false,
659 std::optional<EVT> OutVT = std::nullopt);
669 bool DemandHighBits =
true);
673 bool HasPos,
unsigned PosOpcode,
674 unsigned NegOpcode,
const SDLoc &
DL);
677 bool HasPos,
unsigned PosOpcode,
678 unsigned NegOpcode,
const SDLoc &
DL);
681 SDValue MatchLoadCombine(SDNode *
N);
682 SDValue mergeTruncStores(StoreSDNode *
N);
684 SDValue ReduceLoadOpStoreWidth(SDNode *
N);
686 SDValue TransformFPLoadStorePair(SDNode *
N);
687 SDValue convertBuildVecExtToExt(SDNode *
N);
688 SDValue convertBuildVecZextToBuildVecWithZeros(SDNode *
N);
689 SDValue reduceBuildVecExtToExtBuildVec(SDNode *
N);
690 SDValue reduceBuildVecTruncToBitCast(SDNode *
N);
691 SDValue reduceBuildVecToShuffle(SDNode *
N);
692 SDValue createBuildVecShuffle(
const SDLoc &
DL, SDNode *
N,
693 ArrayRef<int> VectorMask,
SDValue VecIn1,
694 SDValue VecIn2,
unsigned LeftIdx,
696 SDValue matchVSelectOpSizesWithSetCC(SDNode *Cast);
700 void GatherAllAliases(SDNode *
N,
SDValue OriginalChain,
701 SmallVectorImpl<SDValue> &Aliases);
704 bool mayAlias(SDNode *Op0, SDNode *Op1)
const;
716 bool findBetterNeighborChains(StoreSDNode *St);
720 bool parallelizeChainedStores(StoreSDNode *St);
726 LSBaseSDNode *MemNode;
729 int64_t OffsetFromBase;
731 MemOpLink(LSBaseSDNode *
N, int64_t
Offset)
732 : MemNode(
N), OffsetFromBase(
Offset) {}
737 StoreSource getStoreSource(
SDValue StoreVal) {
741 return StoreSource::Constant;
745 return StoreSource::Constant;
746 return StoreSource::Unknown;
749 return StoreSource::Extract;
751 return StoreSource::Load;
753 return StoreSource::Unknown;
761 bool isMulAddWithConstProfitable(SDNode *MulNode,
SDValue AddNode,
767 bool isAndLoadExtLoad(ConstantSDNode *AndC, LoadSDNode *LoadN,
768 EVT LoadResultTy, EVT &ExtVT);
773 EVT &MemVT,
unsigned ShAmt = 0);
776 bool SearchForAndLoads(SDNode *
N, SmallVectorImpl<LoadSDNode*> &Loads,
777 SmallPtrSetImpl<SDNode*> &NodesWithConsts,
778 ConstantSDNode *Mask, SDNode *&NodeToMask);
781 bool BackwardsPropagateMask(SDNode *
N);
785 SDValue getMergeStoreChains(SmallVectorImpl<MemOpLink> &StoreNodes,
797 bool mergeStoresOfConstantsOrVecElts(SmallVectorImpl<MemOpLink> &StoreNodes,
798 EVT MemVT,
unsigned NumStores,
799 bool IsConstantSrc,
bool UseVector,
805 SDNode *getStoreMergeCandidates(StoreSDNode *St,
806 SmallVectorImpl<MemOpLink> &StoreNodes);
812 bool checkMergeStoreCandidatesForDependencies(
813 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumStores,
818 bool hasCallInLdStChain(StoreSDNode *St, LoadSDNode *Ld);
823 unsigned getConsecutiveStores(SmallVectorImpl<MemOpLink> &StoreNodes,
824 int64_t ElementSizeBytes)
const;
828 bool tryStoreMergeOfConstants(SmallVectorImpl<MemOpLink> &StoreNodes,
829 unsigned NumConsecutiveStores,
830 EVT MemVT, SDNode *Root,
bool AllowVectors);
836 bool tryStoreMergeOfExtracts(SmallVectorImpl<MemOpLink> &StoreNodes,
837 unsigned NumConsecutiveStores, EVT MemVT,
842 bool tryStoreMergeOfLoads(SmallVectorImpl<MemOpLink> &StoreNodes,
843 unsigned NumConsecutiveStores, EVT MemVT,
844 SDNode *Root,
bool AllowVectors,
845 bool IsNonTemporalStore,
bool IsNonTemporalLoad);
850 bool mergeConsecutiveStores(StoreSDNode *St);
858 SDValue distributeTruncateThroughAnd(SDNode *
N);
864 bool hasOperation(
unsigned Opcode, EVT VT) {
865 return TLI.isOperationLegalOrCustom(Opcode, VT, LegalOperations);
868 bool hasUMin(EVT VT)
const {
869 auto LK = TLI.getTypeConversion(*DAG.getContext(), VT);
872 TLI.isOperationLegalOrCustom(
ISD::UMIN, LK.second);
879 SelectionDAG &getDAG()
const {
return DAG; }
882 EVT getShiftAmountTy(EVT LHSTy) {
883 return TLI.getShiftAmountTy(LHSTy, DAG.getDataLayout());
888 bool isTypeLegal(
const EVT &VT) {
889 if (!LegalTypes)
return true;
890 return TLI.isTypeLegal(VT);
894 EVT getSetCCResultType(EVT VT)
const {
895 return TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
898 void ExtendSetCCUses(
const SmallVectorImpl<SDNode *> &SetCCs,
909 explicit WorklistRemover(DAGCombiner &dc)
910 : SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
912 void NodeDeleted(SDNode *
N, SDNode *
E)
override {
913 DC.removeFromWorklist(
N);
921 explicit WorklistInserter(DAGCombiner &dc)
922 : SelectionDAG::DAGUpdateListener(dc.getDAG()), DC(dc) {}
926 void NodeInserted(SDNode *
N)
override { DC.ConsiderForPruning(
N); }
936 ((DAGCombiner*)
DC)->AddToWorklist(
N);
941 return ((DAGCombiner*)
DC)->CombineTo(
N, &To[0], To.
size(), AddTo);
946 return ((DAGCombiner*)
DC)->CombineTo(
N, Res, AddTo);
951 return ((DAGCombiner*)
DC)->CombineTo(
N, Res0, Res1, AddTo);
956 return ((DAGCombiner*)
DC)->recursivelyDeleteUnusedNodes(
N);
961 return ((DAGCombiner*)
DC)->CommitTargetLoweringOpt(TLO);
968void DAGCombiner::deleteAndRecombine(
SDNode *
N) {
969 removeFromWorklist(
N);
977 if (
Op->hasOneUse() ||
Op->getNumValues() > 1)
978 AddToWorklist(
Op.getNode());
987 unsigned Bits =
Offset + std::max(
LHS.getBitWidth(),
RHS.getBitWidth());
998 SDValue &CC,
bool MatchStrict)
const {
1000 LHS =
N.getOperand(0);
1001 RHS =
N.getOperand(1);
1009 LHS =
N.getOperand(1);
1010 RHS =
N.getOperand(2);
1023 LHS =
N.getOperand(0);
1024 RHS =
N.getOperand(1);
1032bool DAGCombiner::isOneUseSetCC(
SDValue N)
const {
1034 if (isSetCCEquivalent(
N, N0, N1, N2) &&
N->hasOneUse())
1046 MaskForTy = 0xFFULL;
1049 MaskForTy = 0xFFFFULL;
1052 MaskForTy = 0xFFFFFFFFULL;
1070 bool AllowTruncation =
false) {
1072 return !(Const->isOpaque() && NoOpaques);
1075 unsigned BitWidth =
N.getScalarValueSizeInBits();
1080 if (!Const || (Const->isOpaque() && NoOpaques))
1084 if ((AllowTruncation &&
1085 Const->getAPIntValue().getActiveBits() >
BitWidth) ||
1086 (!AllowTruncation && Const->getAPIntValue().getBitWidth() !=
BitWidth))
1108bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1136 : (N1.
getOperand(0).getConstantOperandVal(0) *
1141 ScalableOffset = -ScalableOffset;
1142 if (
all_of(
N->users(), [&](SDNode *Node) {
1143 if (auto *LoadStore = dyn_cast<MemSDNode>(Node);
1144 LoadStore && LoadStore->hasUniqueMemOperand() &&
1145 LoadStore->getBasePtr().getNode() == N) {
1146 TargetLoweringBase::AddrMode AM;
1147 AM.HasBaseReg = true;
1148 AM.ScalableOffset = ScalableOffset;
1149 EVT VT = LoadStore->getMemoryVT();
1150 unsigned AS = LoadStore->getAddressSpace();
1151 Type *AccessTy = VT.getTypeForEVT(*DAG.getContext());
1152 return TLI.isLegalAddressingMode(DAG.getDataLayout(), AM, AccessTy,
1167 const APInt &C2APIntVal = C2->getAPIntValue();
1175 const APInt &C1APIntVal = C1->getAPIntValue();
1176 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1179 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1181 for (SDNode *Node :
N->users()) {
1188 TargetLoweringBase::AddrMode AM;
1190 AM.
BaseOffs = C2APIntVal.getSExtValue();
1192 unsigned AS =
LoadStore->getAddressSpace();
1208 for (SDNode *Node :
N->users()) {
1210 if (!LoadStore || !
LoadStore->hasUniqueMemOperand())
1215 TargetLoweringBase::AddrMode AM;
1217 AM.
BaseOffs = C2APIntVal.getSExtValue();
1219 unsigned AS =
LoadStore->getAddressSpace();
1232SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1234 SDNodeFlags Flags) {
1244 SDNodeFlags NewFlags;
1246 Flags.hasNoUnsignedWrap())
1254 return DAG.
getNode(
Opc,
DL, VT, N00, OpNode, NewFlags);
1262 return DAG.
getNode(
Opc,
DL, VT, OpNode, N01, NewFlags);
1272 if (N1 == N00 || N1 == N01)
1318 if (CC1 == CC00 && CC1 != CC01) {
1322 if (CC1 == CC01 && CC1 != CC00) {
1336 SDValue N1, SDNodeFlags Flags) {
1342 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1345 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N0, N1, Flags))
1347 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N1, N0, Flags))
1355SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1357 SDValue N1, SDNodeFlags Flags) {
1363 SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
1385 A.getValueType() ==
C.getValueType() &&
1386 hasOperation(
Opc,
A.getValueType()) &&
1394 SelectionDAG::FlagInserter FlagsInserter(
1405SDValue DAGCombiner::CombineTo(SDNode *
N,
const SDValue *To,
unsigned NumTo,
1407 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1411 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1412 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1414 N->getValueType(i) == To[i].getValueType()) &&
1415 "Cannot combine value to value of different type!");
1417 WorklistRemover DeadNodes(*
this);
1421 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1423 AddToWorklistWithUsers(To[i].
getNode());
1431 deleteAndRecombine(
N);
1436CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO) {
1449 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1454bool DAGCombiner::SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
1455 const APInt &DemandedElts,
1456 bool AssumeSingleUse) {
1457 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1464 AddToWorklist(
Op.getNode());
1466 CommitTargetLoweringOpt(TLO);
1473bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1474 const APInt &DemandedElts,
1475 bool AssumeSingleUse) {
1476 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1477 APInt KnownUndef, KnownZero;
1479 TLO, 0, AssumeSingleUse))
1483 AddToWorklist(
Op.getNode());
1485 CommitTargetLoweringOpt(TLO);
1489void DAGCombiner::ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad) {
1491 EVT VT =
Load->getValueType(0);
1500 AddToWorklist(Trunc.
getNode());
1501 recursivelyDeleteUnusedNodes(Load);
1509 EVT MemVT =
LD->getMemoryVT();
1511 :
LD->getExtensionType();
1514 LD->getChain(),
LD->getBasePtr(),
1515 MemVT,
LD->getMemOperand());
1518 unsigned Opc =
Op.getOpcode();
1522 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1526 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1544 EVT OldVT =
Op.getValueType();
1550 AddToWorklist(NewOp.
getNode());
1553 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1559 EVT OldVT =
Op.getValueType();
1565 AddToWorklist(NewOp.
getNode());
1568 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1576 if (!LegalOperations)
1579 EVT VT =
Op.getValueType();
1585 unsigned Opc =
Op.getOpcode();
1593 assert(PVT != VT &&
"Don't know what type to promote to!");
1597 bool Replace0 =
false;
1599 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1601 bool Replace1 =
false;
1603 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1615 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1618 CombineTo(
Op.getNode(), RV);
1644 if (!LegalOperations)
1647 EVT VT =
Op.getValueType();
1653 unsigned Opc =
Op.getOpcode();
1661 assert(PVT != VT &&
"Don't know what type to promote to!");
1665 SDNodeFlags TruncFlags;
1669 N0 = SExtPromoteOperand(N0, PVT);
1671 N0 = ZExtPromoteOperand(N0, PVT);
1673 if (
Op->getFlags().hasNoUnsignedWrap()) {
1674 N0 = ZExtPromoteOperand(N0, PVT);
1676 }
else if (
Op->getFlags().hasNoSignedWrap()) {
1677 N0 = SExtPromoteOperand(N0, PVT);
1680 N0 = PromoteOperand(N0, PVT,
Replace);
1693 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1703 if (!LegalOperations)
1706 EVT VT =
Op.getValueType();
1712 unsigned Opc =
Op.getOpcode();
1720 assert(PVT != VT &&
"Don't know what type to promote to!");
1725 return DAG.
getNode(
Op.getOpcode(), SDLoc(
Op), VT,
Op.getOperand(0));
1730bool DAGCombiner::PromoteLoad(
SDValue Op) {
1731 if (!LegalOperations)
1737 EVT VT =
Op.getValueType();
1743 unsigned Opc =
Op.getOpcode();
1751 assert(PVT != VT &&
"Don't know what type to promote to!");
1754 SDNode *
N =
Op.getNode();
1756 EVT MemVT =
LD->getMemoryVT();
1758 :
LD->getExtensionType();
1760 LD->getChain(),
LD->getBasePtr(),
1761 MemVT,
LD->getMemOperand());
1770 AddToWorklist(
Result.getNode());
1771 recursivelyDeleteUnusedNodes(
N);
1784bool DAGCombiner::recursivelyDeleteUnusedNodes(SDNode *
N) {
1785 if (!
N->use_empty())
1788 SmallSetVector<SDNode *, 16> Nodes;
1795 if (
N->use_empty()) {
1796 for (
const SDValue &ChildN :
N->op_values())
1797 Nodes.
insert(ChildN.getNode());
1799 removeFromWorklist(
N);
1804 }
while (!Nodes.
empty());
1823 WorklistInserter AddNodes(*
this);
1825 if (UseTopologicalSorting)
1834 if (UseTopologicalSorting) {
1836 AddToWorklist(&Node,
Node.use_empty());
1838 for (SDNode &Node : DAG.
allnodes())
1839 AddToWorklist(&Node,
Node.use_empty());
1845 HandleSDNode Dummy(DAG.
getRoot());
1848 while (SDNode *
N = getNextWorklistEntry()) {
1852 if (recursivelyDeleteUnusedNodes(
N))
1855 WorklistRemover DeadNodes(*
this);
1860 SmallSetVector<SDNode *, 16> UpdatedNodes;
1863 for (SDNode *LN : UpdatedNodes)
1864 AddToWorklistWithUsers(LN);
1876 for (
const SDValue &ChildN :
N->op_values())
1877 AddToWorklist(ChildN.getNode(),
true,
1888 ChainsWithoutMergeableStores.
clear();
1899 "Node was deleted but visit returned new node!");
1907 N->getNumValues() == 1 &&
"Type mismatch");
1917 AddToWorklistWithUsers(RV.
getNode());
1923 recursivelyDeleteUnusedNodes(
N);
1927 DAG.
setRoot(Dummy.getValue());
1931SDValue DAGCombiner::visit(SDNode *
N) {
1933 switch (
N->getOpcode()) {
1960 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
2028 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
2081 return visitPARTIAL_REDUCE_MLA(
N);
2107#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2108#include "llvm/IR/VPIntrinsics.def"
2109 return visitVPOp(
N);
2115SDValue DAGCombiner::combine(SDNode *
N) {
2120 if (!DisableGenericCombines)
2126 "Node was deleted but visit returned NULL!");
2132 TargetLowering::DAGCombinerInfo
2133 DagCombineInfo(DAG, Level,
false,
this);
2141 switch (
N->getOpcode()) {
2149 RV = PromoteIntBinOp(
SDValue(
N, 0));
2154 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2190 if (
unsigned NumOps =
N->getNumOperands()) {
2191 if (
N->getOperand(0).getValueType() == MVT::Other)
2192 return N->getOperand(0);
2193 if (
N->getOperand(
NumOps-1).getValueType() == MVT::Other)
2194 return N->getOperand(
NumOps-1);
2195 for (
unsigned i = 1; i <
NumOps-1; ++i)
2196 if (
N->getOperand(i).getValueType() == MVT::Other)
2197 return N->getOperand(i);
2202SDValue DAGCombiner::visitFCANONICALIZE(SDNode *
N) {
2203 SDValue Operand =
N->getOperand(0);
2215SDValue DAGCombiner::visitTokenFactor(SDNode *
N) {
2218 if (
N->getNumOperands() == 2) {
2220 return N->getOperand(0);
2222 return N->getOperand(1);
2237 AddToWorklist(*(
N->user_begin()));
2241 SmallPtrSet<SDNode*, 16> SeenOps;
2249 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2254 for (
unsigned j = i;
j < TFs.
size();
j++)
2255 Ops.emplace_back(TFs[j], 0);
2262 SDNode *TF = TFs[i];
2265 switch (
Op.getOpcode()) {
2283 if (SeenOps.
insert(
Op.getNode()).second)
2294 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2295 AddToWorklist(TFs[i]);
2305 SmallVector<unsigned, 8> OpWorkCount;
2306 SmallPtrSet<SDNode *, 16> SeenChains;
2307 bool DidPruneOps =
false;
2309 unsigned NumLeftToConsider = 0;
2311 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2315 auto AddToWorklist = [&](
unsigned CurIdx, SDNode *
Op,
unsigned OpNumber) {
2321 unsigned OrigOpNumber = 0;
2322 while (OrigOpNumber <
Ops.size() &&
Ops[OrigOpNumber].getNode() !=
Op)
2325 "expected to find TokenFactor Operand");
2327 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2328 if (Worklist[i].second == OrigOpNumber) {
2329 Worklist[i].second = OpNumber;
2332 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2333 OpWorkCount[OrigOpNumber] = 0;
2334 NumLeftToConsider--;
2337 if (SeenChains.
insert(
Op).second) {
2338 OpWorkCount[OpNumber]++;
2343 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2345 if (NumLeftToConsider <= 1)
2347 auto CurNode = Worklist[i].first;
2348 auto CurOpNumber = Worklist[i].second;
2349 assert((OpWorkCount[CurOpNumber] > 0) &&
2350 "Node should not appear in worklist");
2351 switch (CurNode->getOpcode()) {
2357 NumLeftToConsider++;
2360 for (
const SDValue &
Op : CurNode->op_values())
2361 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2367 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2371 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2374 OpWorkCount[CurOpNumber]--;
2375 if (OpWorkCount[CurOpNumber] == 0)
2376 NumLeftToConsider--;
2390 if (SeenChains.
count(
Op.getNode()) == 0)
2404SDValue DAGCombiner::visitMERGE_VALUES(SDNode *
N) {
2405 WorklistRemover DeadNodes(*
this);
2411 AddUsersToWorklist(
N);
2416 }
while (!
N->use_empty());
2417 deleteAndRecombine(
N);
2425 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2435 Op =
N->getOperand(0);
2437 if (
N->getFlags().hasNoUnsignedWrap())
2442 if (
N.getValueType().getScalarType() != MVT::i1 ||
2459 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2461 VT = LD->getMemoryVT();
2462 AS = LD->getAddressSpace();
2464 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2466 VT = ST->getMemoryVT();
2467 AS = ST->getAddressSpace();
2469 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2471 VT = LD->getMemoryVT();
2472 AS = LD->getAddressSpace();
2474 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2476 VT = ST->getMemoryVT();
2477 AS = ST->getAddressSpace();
2483 if (
N->isAnyAdd()) {
2492 }
else if (
N->getOpcode() ==
ISD::SUB) {
2514 bool ShouldCommuteOperands) {
2520 if (ShouldCommuteOperands)
2534 unsigned Opcode =
N->getOpcode();
2535 EVT VT =
N->getValueType(0);
2540 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2560SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
2563 "Unexpected binary operator");
2575 unsigned SelOpNo = 0;
2612 bool CanFoldNonConst =
2618 if (!CanFoldNonConst &&
2627 if (CanFoldNonConst) {
2646 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CT, CBO});
2651 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CF, CBO});
2662 "Expecting add or sub");
2667 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2668 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2669 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2675 if (Z.getOperand(0).getValueType() != MVT::i1)
2687 EVT VT =
C.getValueType();
2695SDValue DAGCombiner::foldSubToAvg(SDNode *
N,
const SDLoc &
DL) {
2700 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2705 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2716SDValue DAGCombiner::visitPTRADD(SDNode *
N) {
2726 "PTRADD with different operand types is not supported");
2737 !reassociationCanBreakAddressingModePattern(
ISD::PTRADD,
DL,
N, N0, N1)) {
2748 if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) {
2753 AddToWorklist(
Add.getNode());
2777 if (
const GlobalAddressSDNode *GA =
2792 AddToWorklist(Inner.
getNode());
2814 SDNodeFlags CommonFlags =
N->getFlags() & N1->
getFlags();
2822 if (ZIsConstant != YIsConstant) {
2826 AddToWorklist(Inner.
getNode());
2836 bool TransformCannotBreakAddrMode =
none_of(
N->users(), [&](SDNode *User) {
2837 return canFoldInAddressingMode(N, User, DAG, TLI);
2840 if (TransformCannotBreakAddrMode)
2852 "Expecting add or sub");
2856 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2857 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2858 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2880 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2882 Not.getOperand(0), ShAmt);
2898SDValue DAGCombiner::visitADDLike(SDNode *
N) {
2924 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2956 if ((!LegalOperations ||
2959 X.getScalarValueSizeInBits() == 1) {
2975 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2979 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
2991 SDNodeFlags NewFlags =
3081 auto MatchUSUBSAT = [](ConstantSDNode *
Max, ConstantSDNode *
Op) {
3082 return (!Max && !
Op) ||
3083 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
3124 !
N->getFlags().hasNoSignedWrap()))) {
3145 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3149 if (
N->getFlags().hasNoUnsignedWrap() &&
3153 if (
N->getFlags().hasNoSignedWrap() &&
3162 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3170 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3176 if (
N->getFlags().hasNoUnsignedWrap() &&
3181 if (
N->getFlags().hasNoSignedWrap() &&
3192 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3197 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
3200 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
3209SDValue DAGCombiner::foldAddToAvg(SDNode *
N,
const SDLoc &
DL) {
3235 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
3242 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
3253SDValue DAGCombiner::visitADD(SDNode *
N) {
3259 if (
SDValue Combined = visitADDLike(
N))
3268 if (
SDValue V = MatchRotate(N0, N1, SDLoc(
N),
true))
3302 APInt NewStep = C0 + C1;
3312 APInt NewStep = SV0 + SV1;
3320SDValue DAGCombiner::visitADDSAT(SDNode *
N) {
3321 unsigned Opcode =
N->getOpcode();
3339 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3343 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3363 bool ForceCarryReconstruction =
false) {
3368 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3372 V = V.getOperand(0);
3377 if (ForceCarryReconstruction)
3381 V = V.getOperand(0);
3389 if (V.getResNo() != 1)
3396 EVT VT = V->getValueType(0);
3440 SDNode *LocReference) {
3442 SDLoc
DL(LocReference);
3504 if (TN->
getVT() == MVT::i1) {
3521 DAG.
getVTList(VT, Carry.getValueType()), N0,
3527SDValue DAGCombiner::visitADDC(SDNode *
N) {
3534 if (!
N->hasAnyUseOfValue(1))
3574 return V.getOperand(0);
3580SDValue DAGCombiner::visitADDO(SDNode *
N) {
3586 EVT CarryVT =
N->getValueType(1);
3590 if (!
N->hasAnyUseOfValue(1))
3597 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3622 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3625 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3656SDValue DAGCombiner::visitADDE(SDNode *
N) {
3675SDValue DAGCombiner::visitUADDO_CARRY(SDNode *
N) {
3689 if (!LegalOperations ||
3699 AddToWorklist(CarryExt.
getNode());
3705 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3708 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3855 EVT CarryOutType =
N->getValueType(0);
3871 unsigned CarryInOperandNum =
3873 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3926 EVT IntVT =
A.getValueType();
3991SDValue DAGCombiner::visitSADDO_CARRY(SDNode *
N) {
4005 if (!LegalOperations ||
4010 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
4013 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
4025 "Illegal truncation");
4049SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL) {
4051 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
4054 EVT SubVT =
N->getValueType(0);
4122template <
class MatchContextClass>
4145 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
4156 unsigned AndMaskWidth =
BitWidth - BitWidthDiff;
4157 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
4192 if (
SDValue Res = CheckAndFoldMulCase(Mul0, Mul1))
4195 if (
SDValue Res = CheckAndFoldMulCase(Mul1, Mul0))
4233SDValue DAGCombiner::visitSUB(SDNode *
N) {
4253 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4280 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4303 if (
N->getFlags().hasNoUnsignedWrap())
4309 if (
N->getFlags().hasNoSignedWrap())
4335 if (hasOperation(NewOpc, VT))
4477 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4515 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4525 if (GA->getGlobal() == GB->getGlobal())
4526 return DAG.
getConstant((uint64_t)GA->getOffset() - GB->getOffset(),
4533 if (TN->
getVT() == MVT::i1) {
4544 if (!
IntVal.isPowerOf2() ||
4589 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4595 const APInt &C0Val = C0->getAPIntValue();
4598 if (
N->getFlags().hasNoUnsignedWrap() && C0Val.
isMask())
4603 if (!C0->isOpaque()) {
4604 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4605 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4611 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4623 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4637SDValue DAGCombiner::visitSUBSAT(SDNode *
N) {
4638 unsigned Opcode =
N->getOpcode();
4659 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4678SDValue DAGCombiner::visitSUBC(SDNode *
N) {
4685 if (!
N->hasAnyUseOfValue(1))
4706SDValue DAGCombiner::visitSUBO(SDNode *
N) {
4712 EVT CarryVT =
N->getValueType(1);
4716 if (!
N->hasAnyUseOfValue(1))
4748SDValue DAGCombiner::visitSUBE(SDNode *
N) {
4760SDValue DAGCombiner::visitUSUBO_CARRY(SDNode *
N) {
4767 if (!LegalOperations ||
4775SDValue DAGCombiner::visitSSUBO_CARRY(SDNode *
N) {
4782 if (!LegalOperations ||
4792SDValue DAGCombiner::visitMULFIX(SDNode *
N) {
4805 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0, Scale);
4814template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(SDNode *
N) {
4820 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4821 MatchContextClass Matcher(DAG, TLI,
N);
4836 bool N1IsConst =
false;
4837 bool N1IsOpaqueConst =
false;
4844 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4849 "Splat APInt should be element width");
4859 if (N1IsConst && ConstValue1.
isZero())
4863 if (N1IsConst && ConstValue1.
isOne())
4867 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4871 if (N1IsConst && ConstValue1.
isAllOnes())
4877 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4881 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap());
4884 if (
N->getFlags().hasNoSignedWrap() && N1IsConst &&
4886 Flags.setNoSignedWrap(
true);
4887 return Matcher.getNode(
ISD::SHL,
DL, VT, N0, Trunc, Flags);
4893 unsigned Log2Val = (-ConstValue1).logBase2();
4897 return Matcher.getNode(
4908 SDVTList LoHiVT = DAG.
getVTList(VT, VT);
4911 if (LoHi->hasAnyUseOfValue(1))
4914 if (LoHi->hasAnyUseOfValue(1))
4935 if (!UseVP && N1IsConst &&
4941 APInt MulC = ConstValue1.
abs();
4943 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4945 if ((MulC - 1).isPowerOf2())
4947 else if ((MulC + 1).isPowerOf2())
4952 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4955 "multiply-by-constant generated out of bounds shift");
4959 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4995 return Matcher.getNode(
5016 APInt NewStep = C0 * MulVal;
5022 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
5036 SmallBitVector ClearMask;
5038 auto IsClearMask = [&ClearMask](ConstantSDNode *
V) {
5039 if (!V ||
V->isZero()) {
5053 for (
unsigned I = 0;
I != NumElts; ++
I)
5084 EVT NodeType =
Node->getValueType(0);
5085 if (!NodeType.isSimple())
5087 switch (NodeType.getSimpleVT().SimpleTy) {
5088 default:
return false;
5089 case MVT::i8: LC=
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
5090 case MVT::i16: LC=
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
5091 case MVT::i32: LC=
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
5092 case MVT::i64: LC=
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
5093 case MVT::i128: LC=
isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
5100SDValue DAGCombiner::useDivRem(SDNode *Node) {
5101 if (
Node->use_empty())
5104 unsigned Opcode =
Node->getOpcode();
5109 EVT VT =
Node->getValueType(0);
5123 unsigned OtherOpcode = 0;
5137 for (SDNode *User : Op0->
users()) {
5144 unsigned UserOpc =
User->getOpcode();
5145 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
5146 User->getOperand(0) == Op0 &&
5147 User->getOperand(1) == Op1) {
5149 if (UserOpc == OtherOpcode) {
5151 combined = DAG.
getNode(DivRemOpc, SDLoc(Node), VTs, Op0, Op1);
5152 }
else if (UserOpc == DivRemOpc) {
5155 assert(UserOpc == Opcode);
5160 CombineTo(User, combined);
5162 CombineTo(User, combined.
getValue(1));
5171 EVT VT =
N->getValueType(0);
5174 unsigned Opc =
N->getOpcode();
5193 if (N0C && N0C->
isZero())
5213SDValue DAGCombiner::visitSDIV(SDNode *
N) {
5216 EVT VT =
N->getValueType(0);
5226 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5243 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5251 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
5258 if (!
N->getFlags().hasExact()) {
5261 AddToWorklist(
Mul.getNode());
5262 AddToWorklist(
Sub.getNode());
5263 CombineTo(RemNode,
Sub);
5284 if (
C->isZero() ||
C->isOpaque())
5286 if (
C->getAPIntValue().isPowerOf2())
5288 if (
C->getAPIntValue().isNegatedPowerOf2())
5299 EVT VT =
N->getValueType(0);
5310 if ((!
N->getFlags().hasExact() ||
BitWidth > MaxLegalDivRemBitWidth) &&
5328 AddToWorklist(Sign.
getNode());
5334 AddToWorklist(
Add.getNode());
5345 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
5371SDValue DAGCombiner::visitUDIV(SDNode *
N) {
5374 EVT VT =
N->getValueType(0);
5384 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5398 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5401 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5408 if (!
N->getFlags().hasExact()) {
5411 AddToWorklist(
Mul.getNode());
5412 AddToWorklist(
Sub.getNode());
5413 CombineTo(RemNode,
Sub);
5438 EVT VT =
N->getValueType(0);
5443 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5444 AddToWorklist(LogBase2.getNode());
5448 AddToWorklist(Trunc.
getNode());
5458 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5459 AddToWorklist(LogBase2.getNode());
5463 AddToWorklist(Trunc.
getNode());
5465 AddToWorklist(
Add.getNode());
5493SDValue DAGCombiner::visitREM(SDNode *
N) {
5494 unsigned Opcode =
N->getOpcode();
5497 EVT VT =
N->getValueType(0);
5519 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5532 AddToWorklist(
Add.getNode());
5549 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5550 return OptimizedRem;
5554 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5557 unsigned DivOpcode = isSigned ? ISD::SDIV : ISD::UDIV;
5558 if (SDNode *DivNode = DAG.getNodeIfExists(DivOpcode, N->getVTList(),
5560 CombineTo(DivNode, OptimizedDiv);
5563 AddToWorklist(OptimizedDiv.
getNode());
5564 AddToWorklist(
Mul.getNode());
5571 return DivRem.getValue(1);
5594SDValue DAGCombiner::visitMULHS(SDNode *
N) {
5597 EVT VT =
N->getValueType(0);
5610 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5653SDValue DAGCombiner::visitMULHU(SDNode *
N) {
5656 EVT VT =
N->getValueType(0);
5669 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5693 (!LegalOperations || hasOperation(
ISD::SRL, VT))) {
5694 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5709 unsigned SimpleSize =
Simple.getSizeInBits();
5730SDValue DAGCombiner::visitAVG(SDNode *
N) {
5731 unsigned Opcode =
N->getOpcode();
5734 EVT VT =
N->getValueType(0);
5745 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5748 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5774 X.getValueType() ==
Y.getValueType() &&
5775 hasOperation(Opcode,
X.getValueType())) {
5781 X.getValueType() ==
Y.getValueType() &&
5782 hasOperation(Opcode,
X.getValueType())) {
5815 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5818 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5832SDValue DAGCombiner::visitABD(SDNode *
N) {
5833 unsigned Opcode =
N->getOpcode();
5836 EVT VT =
N->getValueType(0);
5846 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5849 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5864 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5879 EVT SmallVT =
X.getScalarValueSizeInBits() >
Y.getScalarValueSizeInBits()
5882 if (!LegalOperations || hasOperation(Opcode, SmallVT)) {
5894 EVT SmallVT =
X.getValueType();
5895 if (!LegalOperations || hasOperation(Opcode, SmallVT)) {
5897 unsigned RelevantBits =
5904 const APInt &YConst =
C->getAsAPIntVal();
5911 if (RelevantBits <= Bits && TruncatingYIsCheap) {
5925SDValue DAGCombiner::SimplifyNodeWithTwoResults(SDNode *
N,
unsigned LoOp,
5928 bool HiExists =
N->hasAnyUseOfValue(1);
5929 if (!HiExists && (!LegalOperations ||
5932 return CombineTo(
N, Res, Res);
5936 bool LoExists =
N->hasAnyUseOfValue(0);
5937 if (!LoExists && (!LegalOperations ||
5940 return CombineTo(
N, Res, Res);
5944 if (LoExists && HiExists)
5950 AddToWorklist(
Lo.getNode());
5953 (!LegalOperations ||
5955 return CombineTo(
N, LoOpt, LoOpt);
5960 AddToWorklist(
Hi.getNode());
5963 (!LegalOperations ||
5965 return CombineTo(
N, HiOpt, HiOpt);
5971SDValue DAGCombiner::visitSMUL_LOHI(SDNode *
N) {
5977 EVT VT =
N->getValueType(0);
5993 unsigned SimpleSize =
Simple.getSizeInBits();
6005 return CombineTo(
N,
Lo,
Hi);
6012SDValue DAGCombiner::visitUMUL_LOHI(SDNode *
N) {
6018 EVT VT =
N->getValueType(0);
6033 return CombineTo(
N, Zero, Zero);
6039 return CombineTo(
N, N0, Zero);
6046 unsigned SimpleSize =
Simple.getSizeInBits();
6058 return CombineTo(
N,
Lo,
Hi);
6065SDValue DAGCombiner::visitMULO(SDNode *
N) {
6071 EVT CarryVT =
N->getValueType(1);
6092 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
6104 N->getVTList(), N0, N0);
6111 return CombineTo(
N,
And, Cmp);
6149 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3, CC);
6203 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
6204 if (!Opcode1 || Opcode0 == Opcode1)
6214 APInt MinCPlus1 = MinC + 1;
6215 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
6221 if (MaxC == 0 && MinC != 0 && MinCPlus1.
isPowerOf2()) {
6270 unsigned BW = (C1 + 1).exactLogBase2();
6284SDValue DAGCombiner::visitIMINMAX(SDNode *
N) {
6288 unsigned Opcode =
N->getOpcode();
6302 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
6306 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
6310 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
6321 if (IsSatBroken || IsOpIllegal) {
6323 if (
A.isUndef() ||
B.isUndef())
6336 if (HasKnownSameSign(N0, N1)) {
6339 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
6352 auto ReductionOpcode = [](
unsigned Opcode) {
6366 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
6367 SDLoc(
N), VT, N0, N1))
6375 return C0 > C1 ? N0 : N1;
6377 return C0 > C1 ? N1 : N0;
6386 const APInt &C1V = C1->getAPIntValue();
6405SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *
N) {
6408 unsigned LogicOpcode =
N->getOpcode();
6433 if (XVT !=
Y.getValueType())
6437 if ((VT.
isVector() || LegalOperations) &&
6447 SDNodeFlags LogicFlags;
6453 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6463 if (XVT !=
Y.getValueType())
6475 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6496 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6511 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6524 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6528 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6547 assert(
X.getValueType() ==
Y.getValueType() &&
6548 "Inputs to shuffles are not the same type");
6554 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6555 !SVN0->getMask().equals(SVN1->getMask()))
6591 SDValue LL, LR, RL, RR, N0CC, N1CC;
6592 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6593 !isSetCCEquivalent(N1, RL, RR, N1CC))
6597 "Unexpected operand types for bitwise logic op");
6600 "Unexpected operand types for setcc");
6616 if (LR == RR && CC0 == CC1 && IsInteger) {
6621 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6623 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6625 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6627 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6633 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6635 AddToWorklist(
Or.getNode());
6640 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6642 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6644 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6646 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6652 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6654 AddToWorklist(
And.getNode());
6668 AddToWorklist(
Add.getNode());
6689 auto MatchDiffPow2 = [&](ConstantSDNode *C0, ConstantSDNode *C1) {
6695 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6713 if (LL == RR && LR == RL) {
6720 if (LL == RL && LR == RR) {
6724 (!LegalOperations ||
6761 unsigned OrAndOpcode,
SelectionDAG &DAG,
bool isFMAXNUMFMINNUM_IEEE,
6762 bool isFMAXNUMFMINNUM) {
6773 isFMAXNUMFMINNUM_IEEE
6781 isFMAXNUMFMINNUM_IEEE
6799 isFMAXNUMFMINNUM_IEEE
6808 isFMAXNUMFMINNUM_IEEE
6819 (LogicOp->getOpcode() ==
ISD::AND || LogicOp->getOpcode() ==
ISD::OR) &&
6820 "Invalid Op to combine SETCC with");
6826 !
LHS->hasOneUse() || !
RHS->hasOneUse())
6833 LogicOp,
LHS.getNode(),
RHS.getNode());
6845 EVT VT = LogicOp->getValueType(0);
6868 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6874 SDValue CommonValue, Operand1, Operand2;
6882 }
else if (LHS1 == RHS1) {
6895 }
else if (RHS0 == LHS1) {
6912 bool IsSigned = isSignedIntSetCC(CC);
6916 bool IsOr = (LogicOp->getOpcode() ==
ISD::OR);
6925 LogicOp->getOpcode(), DAG, isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6931 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2, Flags);
6932 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue, CC, {},
6938 if (LHS0 == LHS1 && RHS0 == RHS1 && CCL == CCR &&
6942 return DAG.
getSetCC(
DL, VT, LHS0, RHS0, CCL);
6949 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6950 const APInt &APLhs = LHS1C->getAPIntValue();
6951 const APInt &APRhs = RHS1C->getAPIntValue();
6955 if (APLhs == (-APRhs) &&
6966 }
else if (TargetPreference &
6987 APInt Dif = MaxC - MinC;
7021 EVT CondVT =
Cond.getValueType();
7032 EVT OpVT =
T.getValueType();
7051 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
7068 APInt
ADDC = ADDI->getAPIntValue();
7069 APInt SRLC = SRLI->getAPIntValue();
7081 CombineTo(N0.
getNode(), NewAdd);
7094bool DAGCombiner::isAndLoadExtLoad(ConstantSDNode *AndC, LoadSDNode *LoadN,
7095 EVT LoadResultTy, EVT &ExtVT) {
7104 if (ExtVT == LoadedVT &&
7105 (!LegalOperations ||
7122 if (LegalOperations &&
7133bool DAGCombiner::isLegalNarrowLdSt(LSBaseSDNode *LDST,
7142 const unsigned ByteShAmt = ShAmt / 8;
7161 if (LdStMemVT.
bitsLT(MemVT))
7176 if (PtrType == MVT::Untyped || PtrType.
isExtended())
7183 if (!
SDValue(Load, 0).hasOneUse())
7186 if (LegalOperations &&
7188 Load->getAddressSpace(), ExtType,
false))
7196 if (
Load->getNumValues() > 2)
7215 if (LegalOperations &&
7217 Store->getAlign(),
Store->getAddressSpace()))
7223bool DAGCombiner::SearchForAndLoads(SDNode *
N,
7224 SmallVectorImpl<LoadSDNode*> &Loads,
7225 SmallPtrSetImpl<SDNode*> &NodesWithConsts,
7226 ConstantSDNode *Mask,
7227 SDNode *&NodeToMask) {
7231 if (
Op.getValueType().isVector())
7237 "Expected bitwise logic operation");
7238 if (!
C->getAPIntValue().isSubsetOf(
Mask->getAPIntValue()))
7243 if (!
Op.hasOneUse())
7246 switch(
Op.getOpcode()) {
7250 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
7268 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
7272 Op.getOperand(0).getValueType();
7283 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
7294 NodeToMask =
Op.getNode();
7297 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
7298 MVT VT =
SDValue(NodeToMask, i).getSimpleValueType();
7299 if (VT != MVT::Glue && VT != MVT::Other) {
7301 NodeToMask =
nullptr;
7313bool DAGCombiner::BackwardsPropagateMask(SDNode *
N) {
7318 if (!
Mask->getAPIntValue().isMask())
7326 SmallPtrSet<SDNode*, 2> NodesWithConsts;
7327 SDNode *FixupNode =
nullptr;
7328 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
7341 SDValue(FixupNode, 0), MaskOp);
7343 if (
And.getOpcode() == ISD ::AND)
7348 for (
auto *LogicN : NodesWithConsts) {
7354 if (LogicN->getOpcode() ==
ISD::AND &&
7373 for (
auto *Load : Loads) {
7378 if (
And.getOpcode() == ISD ::AND)
7381 SDValue NewLoad = reduceLoadWidth(
And.getNode());
7383 "Shouldn't be masking the load if it can't be narrowed");
7384 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
7397SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(SDNode *
N) {
7408 unsigned OuterShift;
7409 unsigned InnerShift;
7411 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
7414 OuterShift =
M->getOpcode();
7423 Y =
M->getOperand(1);
7430 else if (matchMask(N0))
7436 EVT VT =
N->getValueType(0);
7453 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
7463 bool FoundNot =
false;
7466 Src = Src.getOperand(0);
7472 Src = Src.getOperand(0);
7476 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
7480 EVT SrcVT = Src.getValueType();
7489 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
7493 Src = Src.getOperand(0);
7500 Src = Src.getOperand(0);
7524 EVT VT =
N->getValueType(0);
7550 unsigned LogicOpcode =
N->getOpcode();
7552 "Expected bitwise logic operation");
7554 if (!LogicOp.hasOneUse() || !ShiftOp.
hasOneUse())
7558 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7559 if (LogicOp.getOpcode() != LogicOpcode ||
7571 if (LogicOp.getOperand(0).getOpcode() == ShiftOpcode &&
7572 LogicOp.getOperand(0).getOperand(1) ==
Y) {
7574 Z = LogicOp.getOperand(1);
7575 }
else if (LogicOp.getOperand(1).getOpcode() == ShiftOpcode &&
7576 LogicOp.getOperand(1).getOperand(1) ==
Y) {
7578 Z = LogicOp.getOperand(0);
7583 EVT VT =
N->getValueType(0);
7587 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7598 unsigned LogicOpcode =
N->getOpcode();
7600 "Expected bitwise logic operation");
7601 if (LeftHand.
getOpcode() != LogicOpcode ||
7622 EVT VT =
N->getValueType(0);
7624 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7636 "Must be called with ISD::OR or ISD::AND node");
7650 EVT VT = M.getValueType();
7658SDValue DAGCombiner::visitAND(SDNode *
N) {
7682 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7699 if (BV0 && BV1 && !BV0->getSplatValue() && !BV1->getSplatValue() &&
7701 BV0->getOperand(0).getValueType() ==
7702 BV1->getOperand(0).getValueType()) {
7705 EVT EltVT = BV0->getOperand(0).getValueType();
7706 for (
unsigned I = 0;
I != NumElts; ++
I) {
7712 else if (C0 && C0->
isZero())
7714 else if (C1 && C1->isZero())
7718 else if (C1 && C1->isAllOnes())
7720 else if (BV0->getOperand(
I) == BV1->getOperand(
I))
7725 if (MergedOps.
size() == NumElts)
7734 EVT MemVT =
MLoad->getMemoryVT();
7745 MLoad->isExpandingLoad());
7746 CombineTo(
N, Frozen ? N0 : NewLoad);
7747 CombineTo(MLoad, NewLoad, NewLoad.
getValue(1));
7767 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7780 auto MatchSubset = [](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
7781 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7791 APInt
Mask = ~N1C->getAPIntValue();
7816 {N0Op0.getOperand(1)})) {
7849 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7850 APInt SplatValue, SplatUndef;
7851 unsigned SplatBitSize;
7858 const bool IsBigEndian =
false;
7860 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7861 HasAnyUndefs, EltBitWidth, IsBigEndian);
7865 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7868 SplatValue |= SplatUndef;
7875 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7876 Constant &= SplatValue.
extractBits(EltBitWidth, i * EltBitWidth);
7884 Load->getValueType(0),
Load->getMemoryVT(),
Load->getAlign(),
7893 switch (
Load->getExtensionType()) {
7894 default:
B =
false;
break;
7906 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7910 Load->getValueType(0), SDLoc(Load),
7911 Load->getChain(),
Load->getBasePtr(),
7912 Load->getOffset(),
Load->getMemoryVT(),
7913 Load->getMemOperand());
7915 if (
Load->getNumValues() == 3) {
7917 SDValue To[] = { NewLoad.getValue(0), NewLoad.getValue(1),
7918 NewLoad.getValue(2) };
7919 CombineTo(Load, To, 3,
true);
7921 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7931 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7958 EVT MemVT = GN0->getMemoryVT();
7961 if (
SDValue(GN0, 0).hasOneUse() &&
7964 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7965 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7968 DAG.
getVTList(VT, MVT::Other), MemVT,
DL,
Ops, GN0->getMemOperand(),
7971 CombineTo(
N, ZExtLoad);
7972 AddToWorklist(ZExtLoad.
getNode());
7985 if (
SDValue Res = reduceLoadWidth(
N))
7994 if (BackwardsPropagateMask(
N))
7998 if (
SDValue Combined = visitANDLike(N0, N1,
N))
8003 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8034 if (
SDValue Folded = foldBitwiseOpWithNeg(
N,
DL, VT))
8056 X.getOperand(0).getScalarValueSizeInBits() == 1)
8059 X.getOperand(0).getScalarValueSizeInBits() == 1)
8074 EVT MemVT = LN0->getMemoryVT();
8081 ((!LegalOperations && LN0->isSimple()) ||
8082 TLI.
isLoadLegal(VT, MemVT, LN0->getAlign(), LN0->getAddressSpace(),
8086 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
8100 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
8120 if (!
C->getAPIntValue().isMask(
8121 LHS.getOperand(0).getValueType().getScalarSizeInBits()))
8128 if (IsAndZeroExtMask(N0, N1) &&
8138 if (LegalOperations || VT.
isVector())
8151 bool DemandHighBits) {
8152 if (!LegalOperations)
8155 EVT VT =
N->getValueType(0);
8156 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
8162 bool LookPassAnd0 =
false;
8163 bool LookPassAnd1 =
false;
8178 LookPassAnd0 =
true;
8188 LookPassAnd1 =
true;
8214 LookPassAnd0 =
true;
8228 LookPassAnd1 =
true;
8237 if (OpSizeInBits > 16) {
8241 if (DemandHighBits && !LookPassAnd0)
8248 if (!LookPassAnd1) {
8249 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
8257 if (OpSizeInBits > 16) {
8272 if (!
N->hasOneUse())
8275 unsigned Opc =
N.getOpcode();
8293 unsigned MaskByteOffset;
8297 case 0xFF: MaskByteOffset = 0;
break;
8298 case 0xFF00: MaskByteOffset = 1;
break;
8307 case 0xFF0000: MaskByteOffset = 2;
break;
8308 case 0xFF000000: MaskByteOffset = 3;
break;
8313 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
8319 if (!
C ||
C->getZExtValue() != 8)
8327 if (!
C ||
C->getZExtValue() != 8)
8333 if (MaskByteOffset != 0 && MaskByteOffset != 2)
8336 if (!
C ||
C->getZExtValue() != 8)
8341 if (MaskByteOffset != 1 && MaskByteOffset != 3)
8344 if (!
C ||
C->getZExtValue() != 8)
8348 if (Parts[MaskByteOffset])
8363 if (!
C ||
C->getAPIntValue() != 16)
8365 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
8380 "MatchBSwapHWordOrAndAnd: expecting i32");
8390 if (!Mask0 || !Mask1)
8401 if (!ShiftAmt0 || !ShiftAmt1)
8421 if (!LegalOperations)
8424 EVT VT =
N->getValueType(0);
8442 SDNode *Parts[4] = {};
8462 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
8490 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
8499 if (
const ConstantSDNode *N0O1C =
8501 if (
const ConstantSDNode *N1O1C =
8505 const APInt &LHSMask = N0O1C->getAPIntValue();
8506 const APInt &RHSMask = N1O1C->getAPIntValue();
8540 auto peekThroughResize = [](
SDValue V) {
8542 return V->getOperand(0);
8546 SDValue N0Resized = peekThroughResize(N0);
8548 SDValue N1Resized = peekThroughResize(N1);
8553 if (N00 == N1Resized || N01 == N1Resized)
8560 if (peekThroughResize(NotOperand) == N1Resized)
8568 if (peekThroughResize(NotOperand) == N1Resized)
8589 auto peekThroughZext = [](
SDValue V) {
8591 return V->getOperand(0);
8631 if (S0 &&
S1 && S0->getZExtValue() < BW &&
S1->getZExtValue() < BW &&
8632 S0->getZExtValue() == (BW -
S1->getZExtValue())) {
8649 Lo.getScalarValueSizeInBits() == (BW / 2) &&
8650 Lo.getValueType() ==
Hi.getValueType()) {
8666SDValue DAGCombiner::visitOR(SDNode *
N) {
8687 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8703 if (BV0 && BV1 && !BV0->getSplatValue() && !BV1->getSplatValue() &&
8705 BV0->getOperand(0).getValueType() ==
8706 BV1->getOperand(0).getValueType()) {
8709 EVT EltVT = BV0->getOperand(0).getValueType();
8710 for (
unsigned I = 0;
I != NumElts; ++
I) {
8716 else if (C0 && C0->
isZero())
8718 else if (C1 && C1->isZero())
8722 else if (C1 && C1->isAllOnes())
8724 else if (BV0->getOperand(
I) == BV1->getOperand(
I))
8729 if (MergedOps.
size() == NumElts)
8743 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8744 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8745 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8746 bool CanFold =
true;
8748 SmallVector<int, 4>
Mask(NumElts, -1);
8750 for (
int i = 0; i != NumElts; ++i) {
8751 int M0 = SV0->getMaskElt(i);
8752 int M1 = SV1->getMaskElt(i);
8755 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8756 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8760 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8764 if (M0Zero == M1Zero) {
8769 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8775 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8784 return LegalShuffle;
8798 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8809 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8819 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8821 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8835 auto MatchIntersect = [](ConstantSDNode *C1, ConstantSDNode *C2) {
8855 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8859 if (
SDValue Rot = MatchRotate(N0, N1,
DL,
false))
8862 if (
SDValue Load = MatchLoadCombine(
N))
8872 if (
SDValue Combined = visitADDLike(
N))
8877 if (LegalOperations || VT.
isVector())
8892 Mask =
Op.getOperand(1);
8893 return Op.getOperand(0);
8936 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8964 bool IsMulOrDiv =
false;
8967 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8968 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8969 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8971 Opcode = NeededShift;
9021 if (Rem != 0 || ResultAmt != OppLHSAmt)
9027 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
9036 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
9090 unsigned MaskLoBits = 0;
9092 unsigned Bits =
Log2_64(EltSize);
9094 if (NegBits >= Bits) {
9117 if (PosBits >= MaskLoBits) {
9139 if ((Pos == NegOp1) ||
9163 return Width.
getLoBits(MaskLoBits) == 0;
9164 return Width == EltSize;
9174 SDValue InnerNeg,
bool FromAdd,
9175 bool HasPos,
unsigned PosOpcode,
9176 unsigned NegOpcode,
const SDLoc &
DL) {
9187 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
9188 HasPos ? Pos : Neg);
9201 SDValue InnerNeg,
bool FromAdd,
9202 bool HasPos,
unsigned PosOpcode,
9203 unsigned NegOpcode,
const SDLoc &
DL) {
9216 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
9217 HasPos ? Pos : Neg);
9262 EVT VT =
LHS.getValueType();
9267 bool HasROTL = hasOperation(
ISD::ROTL, VT);
9268 bool HasROTR = hasOperation(
ISD::ROTR, VT);
9269 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
9270 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
9281 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
9286 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
9289 MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL, FromAdd))
9303 if (!LHSShift && !RHSShift)
9318 RHSShift = NewRHSShift;
9323 LHSShift = NewLHSShift;
9326 if (!RHSShift || !LHSShift)
9351 auto MatchRotateSum = [EltSizeInBits](ConstantSDNode *
LHS,
9352 ConstantSDNode *
RHS) {
9353 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
9356 auto ApplyMasks = [&](
SDValue Res) {
9380 bool IsRotate = LHSShiftArg == RHSShiftArg;
9381 if (!IsRotate && !(HasFSHL || HasFSHR)) {
9390 if (CommonOp ==
Or.getOperand(0)) {
9392 Y =
Or.getOperand(1);
9395 if (CommonOp ==
Or.getOperand(1)) {
9397 Y =
Or.getOperand(0);
9404 if (matchOr(LHSShiftArg, RHSShiftArg)) {
9409 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
9418 return ApplyMasks(Res);
9431 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
9432 bool UseROTL = !LegalOperations || HasROTL;
9434 UseROTL ? LHSShiftAmt : RHSShiftAmt);
9436 bool UseFSHL = !LegalOperations || HasFSHL;
9438 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
9441 return ApplyMasks(Res);
9446 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
9455 SDValue LExtOp0 = LHSShiftAmt;
9456 SDValue RExtOp0 = RHSShiftAmt;
9469 if (IsRotate && (HasROTL || HasROTR)) {
9470 if (
SDValue TryL = MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt,
9471 LExtOp0, RExtOp0, FromAdd, HasROTL,
9475 if (
SDValue TryR = MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
9476 RExtOp0, LExtOp0, FromAdd, HasROTR,
9481 if (
SDValue TryL = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt,
9482 RHSShiftAmt, LExtOp0, RExtOp0, FromAdd,
9486 if (
SDValue TryR = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt,
9487 LHSShiftAmt, RExtOp0, LExtOp0, FromAdd,
9537static std::optional<SDByteProvider>
9539 std::optional<uint64_t> VectorIndex,
9540 unsigned StartingIndex = 0) {
9544 return std::nullopt;
9548 if (
Depth && !
Op.hasOneUse() &&
9549 (
Op.getOpcode() !=
ISD::LOAD || !
Op.getValueType().isVector()))
9550 return std::nullopt;
9554 if (
Op.getOpcode() !=
ISD::LOAD && VectorIndex.has_value())
9555 return std::nullopt;
9557 unsigned BitWidth =
Op.getScalarValueSizeInBits();
9559 return std::nullopt;
9561 assert(Index < ByteWidth &&
"invalid index requested");
9564 switch (
Op.getOpcode()) {
9569 return std::nullopt;
9573 return std::nullopt;
9575 if (
LHS->isConstantZero())
9577 if (
RHS->isConstantZero())
9579 return std::nullopt;
9584 return std::nullopt;
9586 uint64_t BitShift = ShiftOp->getZExtValue();
9588 if (BitShift % 8 != 0)
9589 return std::nullopt;
9595 return Index < ByteShift
9598 Depth + 1, VectorIndex, Index);
9605 if (NarrowBitWidth % 8 != 0)
9606 return std::nullopt;
9607 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9609 if (Index >= NarrowByteWidth)
9611 ? std::optional<SDByteProvider>(
9619 Depth + 1, VectorIndex, StartingIndex);
9623 return std::nullopt;
9625 VectorIndex =
OffsetOp->getZExtValue();
9629 if (NarrowBitWidth % 8 != 0)
9630 return std::nullopt;
9631 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9634 if (Index >= NarrowByteWidth)
9635 return std::nullopt;
9643 if (*VectorIndex * NarrowByteWidth > StartingIndex)
9644 return std::nullopt;
9645 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
9646 return std::nullopt;
9649 VectorIndex, StartingIndex);
9653 if (!L->isSimple() || L->isIndexed())
9654 return std::nullopt;
9656 unsigned NarrowBitWidth = L->getMemoryVT().getScalarSizeInBits();
9657 if (NarrowBitWidth % 8 != 0)
9658 return std::nullopt;
9659 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9664 if (Index >= NarrowByteWidth)
9666 ? std::optional<SDByteProvider>(
9670 unsigned BPVectorIndex = VectorIndex.value_or(0U);
9675 return std::nullopt;
9690 int64_t FirstOffset) {
9692 unsigned Width = ByteOffsets.
size();
9694 return std::nullopt;
9696 bool BigEndian =
true, LittleEndian =
true;
9697 for (
unsigned i = 0; i < Width; i++) {
9698 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9701 if (!BigEndian && !LittleEndian)
9702 return std::nullopt;
9705 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9712 switch (
Value.getOpcode()) {
9717 return Value.getOperand(0);
9744SDValue DAGCombiner::mergeTruncStores(StoreSDNode *
N) {
9755 EVT MemVT =
N->getMemoryVT();
9756 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9757 !
N->isSimple() ||
N->isIndexed())
9764 unsigned MaxWideNumBits = 64;
9765 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9774 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9778 Chain =
Store->getChain();
9779 if (MaxStores < Stores.
size())
9783 if (Stores.
size() < 2)
9788 unsigned NumStores = Stores.
size();
9789 unsigned WideNumBits = NumStores * NarrowNumBits;
9790 if (WideNumBits != 16 && WideNumBits != 32 && WideNumBits != 64)
9798 StoreSDNode *FirstStore =
nullptr;
9799 std::optional<BaseIndexOffset>
Base;
9800 for (
auto *Store : Stores) {
9819 if (ShiftAmtC % NarrowNumBits != 0)
9826 Offset = ShiftAmtC / NarrowNumBits;
9832 SourceValue = WideVal;
9833 else if (SourceValue != WideVal) {
9841 SourceValue = WideVal;
9850 int64_t ByteOffsetFromBase = 0;
9853 else if (!
Base->equalBaseIndex(Ptr, DAG, ByteOffsetFromBase))
9857 if (ByteOffsetFromBase < FirstOffset) {
9859 FirstOffset = ByteOffsetFromBase;
9865 OffsetMap[
Offset] = ByteOffsetFromBase;
9871 assert(FirstStore &&
"First store must be set");
9878 if (!Allowed || !
Fast)
9883 auto checkOffsets = [&](
bool MatchLittleEndian) {
9884 if (MatchLittleEndian) {
9885 for (
unsigned i = 0; i != NumStores; ++i)
9886 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9889 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9890 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9897 bool NeedBswap =
false;
9898 bool NeedRotate =
false;
9901 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9903 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9912 "Unexpected store value to merge");
9921 }
else if (NeedRotate) {
9922 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9966SDValue DAGCombiner::MatchLoadCombine(SDNode *
N) {
9968 "Can only match load combining against OR nodes");
9971 EVT VT =
N->getValueType(0);
9972 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9978 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9981 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9983 assert(LoadBitWidth % 8 == 0 &&
9984 "can only analyze providers for individual bytes not bit");
9985 unsigned LoadByteWidth = LoadBitWidth / 8;
9990 std::optional<BaseIndexOffset>
Base;
9993 SmallPtrSet<LoadSDNode *, 8> Loads;
9994 std::optional<SDByteProvider> FirstByteProvider;
10000 unsigned ZeroExtendedBytes = 0;
10001 for (
int i = ByteWidth - 1; i >= 0; --i) {
10008 if (
P->isConstantZero()) {
10011 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
10015 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
10022 else if (Chain != LChain)
10027 int64_t ByteOffsetFromBase = 0;
10036 if (
L->getMemoryVT().isVector()) {
10037 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
10038 if (LoadWidthInBit % 8 != 0)
10040 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
10041 Ptr.addToOffset(ByteOffsetFromVector);
10047 else if (!
Base->equalBaseIndex(Ptr, DAG, ByteOffsetFromBase))
10051 ByteOffsetFromBase += MemoryByteOffset(*
P);
10052 ByteOffsets[i] = ByteOffsetFromBase;
10055 if (ByteOffsetFromBase < FirstOffset) {
10056 FirstByteProvider =
P;
10057 FirstOffset = ByteOffsetFromBase;
10063 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
10064 "memory, so there must be at least one load which produces the value");
10065 assert(
Base &&
"Base address of the accessed memory location must be set");
10068 bool NeedsZext = ZeroExtendedBytes > 0;
10079 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
10083 assert(FirstByteProvider &&
"must be set");
10087 if (MemoryByteOffset(*FirstByteProvider) != 0)
10095 if (LegalOperations &&
10096 !TLI.
isLoadLegal(VT, MemVT, FirstLoad->getAlign(),
10097 FirstLoad->getAddressSpace(),
10106 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
10113 if (NeedsBswap && (LegalOperations || NeedsZext) &&
10119 if (NeedsBswap && NeedsZext && LegalOperations &&
10127 *FirstLoad->getMemOperand(), &
Fast);
10128 if (!Allowed || !
Fast)
10133 Chain, FirstLoad->getBasePtr(),
10134 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
10137 for (LoadSDNode *L : Loads)
10167SDValue DAGCombiner::unfoldMaskedMerge(SDNode *
N) {
10174 EVT VT =
N->getValueType(0);
10196 M =
And.getOperand(XorIdx ? 0 : 1);
10202 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
10203 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
10250SDValue DAGCombiner::visitXOR(SDNode *
N) {
10277 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10289 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10310 if (
SDValue Combined = visitADDLike(
N))
10318 isSetCCEquivalent(N0,
LHS,
RHS, CC,
true) &&
10320 N->use_begin()->getUser()->getOpcode() ==
ISD::AND)) {
10322 LHS.getValueType());
10323 if (!LegalOperations ||
10325 switch (N0Opcode) {
10341 CombineTo(
N, SetCC);
10343 recursivelyDeleteUnusedNodes(N0.
getNode());
10359 AddToWorklist(
V.getNode());
10368 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
10373 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10386 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10396 APInt NotYValue = ~YConst->getAPIntValue();
10412 AddToWorklist(NotX.
getNode());
10417 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
10421 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
10423 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
10460 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
10471 if (
SDValue MM = unfoldMaskedMerge(
N))
10540 if (!LogicOp.hasOneUse())
10543 unsigned LogicOpcode = LogicOp.getOpcode();
10549 unsigned ShiftOpcode = Shift->
getOpcode();
10552 assert(C1Node &&
"Expected a shift with constant operand");
10555 const APInt *&ShiftAmtVal) {
10556 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
10564 ShiftOp = V.getOperand(0);
10569 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
10574 bool Overflow =
false;
10575 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
10580 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
10588 const APInt *C0Val;
10589 if (matchFirstShift(LogicOp.getOperand(0),
X, C0Val))
10590 Y = LogicOp.getOperand(1);
10591 else if (matchFirstShift(LogicOp.getOperand(1),
X, C0Val))
10592 Y = LogicOp.getOperand(0);
10603 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
10613SDValue DAGCombiner::visitShiftByConstant(SDNode *
N) {
10633 switch (
LHS.getOpcode()) {
10657 if (!IsShiftByConstant && !IsCopyOrSelect)
10660 if (IsCopyOrSelect &&
N->hasOneUse())
10665 EVT VT =
N->getValueType(0);
10667 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
10670 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
10676SDValue DAGCombiner::distributeTruncateThroughAnd(SDNode *
N) {
10681 EVT TruncVT =
N->getValueType(0);
10682 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
10690 AddToWorklist(Trunc00.
getNode());
10691 AddToWorklist(Trunc01.
getNode());
10699SDValue DAGCombiner::visitRotate(SDNode *
N) {
10703 EVT VT =
N->getValueType(0);
10718 bool OutOfRange =
false;
10719 auto MatchOutOfRange = [Bitsize, &OutOfRange](ConstantSDNode *
C) {
10720 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
10728 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
10733 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
10744 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10745 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10757 bool SameSide = (
N->getOpcode() == NextOp);
10764 if (Norm1 && Norm2)
10766 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10768 {CombinedShift, BitsizeC});
10770 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10772 CombinedShiftNorm);
10779SDValue DAGCombiner::visitSHL(SDNode *
N) {
10796 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10819 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10829 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10835 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
10836 ConstantSDNode *
RHS) {
10837 APInt c1 =
LHS->getAPIntValue();
10838 APInt c2 =
RHS->getAPIntValue();
10840 return (c1 + c2).uge(OpSizeInBits);
10845 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
10846 ConstantSDNode *
RHS) {
10847 APInt c1 =
LHS->getAPIntValue();
10848 APInt c2 =
RHS->getAPIntValue();
10850 return (c1 + c2).ult(OpSizeInBits);
10872 auto MatchOutOfRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10873 ConstantSDNode *
RHS) {
10874 APInt c1 =
LHS->getAPIntValue();
10875 APInt c2 =
RHS->getAPIntValue();
10877 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10878 (c1 + c2).uge(OpSizeInBits);
10885 auto MatchInRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10886 ConstantSDNode *
RHS) {
10887 APInt c1 =
LHS->getAPIntValue();
10888 APInt c2 =
RHS->getAPIntValue();
10890 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10891 (c1 + c2).ult(OpSizeInBits);
10911 auto MatchEqual = [VT](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
10912 APInt c1 =
LHS->getAPIntValue();
10913 APInt c2 =
RHS->getAPIntValue();
10923 AddToWorklist(NewSHL.
getNode());
10929 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
10930 ConstantSDNode *
RHS) {
10931 const APInt &LHSC =
LHS->getAPIntValue();
10932 const APInt &RHSC =
RHS->getAPIntValue();
10933 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
11005 AddToWorklist(Shl0.
getNode());
11024 {Add.getOperand(1)})) {
11044 if (
SDValue NewSHL = visitShiftByConstant(
N))
11078 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap() &&
11091 APInt NewStep = C0 << ShlVal;
11106 "SRL or SRA node is required here!");
11115 SDValue ShiftOperand =
N->getOperand(0);
11130 if (!IsSignExt && !IsZeroExt)
11137 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
11142 if (!UShiftAmtSrc) {
11146 return UShiftAmt < NarrowVTSize;
11160 if (IsZeroExt && ShiftOperand.
hasOneUse() &&
11163 }
else if (IsSignExt && ShiftOperand.
hasOneUse() &&
11179 "Cannot have a multiply node with two different operand types.");
11190 if (ShiftAmt != NarrowVTSize)
11200 EVT TransformVT = NarrowVT;
11211 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
11218 unsigned Opcode =
N->getOpcode();
11223 EVT VT =
N->getValueType(0);
11242SDValue DAGCombiner::visitSRA(SDNode *
N) {
11264 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
11267 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
11279 auto SumOfShifts = [&](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
11280 APInt c1 =
LHS->getAPIntValue();
11281 APInt c2 =
RHS->getAPIntValue();
11283 APInt Sum = c1 + c2;
11284 unsigned ShiftSum =
11285 Sum.
uge(OpSizeInBits) ? (OpSizeInBits - 1) : Sum.getZExtValue();
11295 "Expected matchBinaryPredicate to return one element for "
11299 ShiftValue = ShiftValues[0];
11313 APInt Sum = C1 + C2;
11317 return DAG.
getNOT(
DL, NewShift, VT);
11341 if ((ShiftAmt > 0) &&
11351 N->getValueType(0), Trunc);
11368 if (ConstantSDNode *AddC =
11385 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
11402 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11419 if (LargeShift->getAPIntValue() == TruncBits) {
11440 if (
SDValue NewSRA = visitShiftByConstant(
N))
11449 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11458SDValue DAGCombiner::visitSRL(SDNode *
N) {
11475 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
11478 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
11489 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
11490 ConstantSDNode *
RHS) {
11491 APInt c1 =
LHS->getAPIntValue();
11492 APInt c2 =
RHS->getAPIntValue();
11494 return (c1 + c2).uge(OpSizeInBits);
11499 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
11500 ConstantSDNode *
RHS) {
11501 APInt c1 =
LHS->getAPIntValue();
11502 APInt c2 =
RHS->getAPIntValue();
11504 return (c1 + c2).ult(OpSizeInBits);
11524 if (c1 + OpSizeInBits == InnerShiftSize) {
11525 if (c1 + c2 >= InnerShiftSize)
11535 c1 + c2 < InnerShiftSize) {
11540 OpSizeInBits - c2),
11557 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
11558 ConstantSDNode *
RHS) {
11559 const APInt &LHSC =
LHS->getAPIntValue();
11560 const APInt &RHSC =
RHS->getAPIntValue();
11561 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
11603 AddToWorklist(SmallShift.
getNode());
11631 APInt UnknownBits = ~Known.Zero;
11632 if (UnknownBits == 0)
return DAG.
getConstant(1, SDLoc(N0), VT);
11647 AddToWorklist(
Op.getNode());
11656 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11686 if (N1C->
getZExtValue() == (NumElts - 1) * EltSizeInBits) {
11689 "Expected BUILD_VECTOR operand as wide as element type");
11705 if (
SDValue NewSRL = visitShiftByConstant(
N))
11709 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11736 if (
N->hasOneUse()) {
11737 SDNode *
User = *
N->user_begin();
11745 AddToWorklist(User);
11761 X.getScalarValueSizeInBits() == HalfBW &&
11762 Y.getScalarValueSizeInBits() == HalfBW) {
11764 (!LegalOperations ||
11770 (!LegalOperations ||
11788SDValue DAGCombiner::visitFunnelShift(SDNode *
N) {
11789 EVT VT =
N->getValueType(0);
11807 return IsFSHL ? N0 : N1;
11809 auto IsUndefOrZero = [](
SDValue V) {
11818 if (Cst->getAPIntValue().uge(
BitWidth)) {
11819 uint64_t RotAmt = Cst->getAPIntValue().urem(
BitWidth);
11820 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
11824 unsigned ShAmt = Cst->getZExtValue();
11826 return IsFSHL ? N0 : N1;
11832 if (IsUndefOrZero(N0))
11836 if (IsUndefOrZero(N1))
11850 "ShAmt must be in [1, BW-1] for the identity fold to be valid");
11852 unsigned C0Expected = IsFSHL ? ShAmt :
BitWidth - ShAmt;
11853 unsigned C1Expected = IsFSHL ?
BitWidth - ShAmt : ShAmt;
11876 if (
LHS &&
RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11877 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11878 (
LHS->hasNUsesOfValue(1, 0) ||
RHS->hasNUsesOfValue(1, 0)) &&
11887 RHS->getAddressSpace(), NewAlign,
11888 RHS->getMemOperand()->getFlags(), &
Fast) &&
11892 AddToWorklist(NewPtr.
getNode());
11894 VT,
DL,
RHS->getChain(), NewPtr,
11895 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11896 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11924 if (N0 == N1 && hasOperation(RotOpc, VT))
11925 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11934SDValue DAGCombiner::visitSHLSAT(SDNode *
N) {
11969SDValue DAGCombiner::foldABSToABD(SDNode *
N,
const SDLoc &
DL) {
11970 EVT SrcVT =
N->getValueType(0);
11973 N =
N->getOperand(0).getNode();
11975 EVT VT =
N->getValueType(0);
11982 SDValue AbsOp0 =
N->getOperand(0);
11987 auto IsNotMinSignedInt = [VT](ConstantSDNode *
C) {
11990 return !
C->getAPIntValue()
11992 .isMinSignedValue();
12008 auto CreateZextedAbd = [&](
unsigned AbdOpc) {
12017 bool AbsOpWillNSW =
12029 bool AbsOpWillNUW = !IsAdd && DAG.
SignBitIsZero(Op0) && Op1SignBitIsOne;
12031 if (hasOperation(
ISD::ABDU, VT) && AbsOpWillNUW)
12040 assert(!IsAdd &&
"Unexpected abs(add(x,y)) pattern");
12054 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
12055 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
12057 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
12067 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
12075SDValue DAGCombiner::visitABS(SDNode *
N) {
12077 EVT VT =
N->getValueType(0);
12110SDValue DAGCombiner::visitCLMUL(SDNode *
N) {
12111 unsigned Opcode =
N->getOpcode();
12114 EVT VT =
N->getValueType(0);
12124 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
12145SDValue DAGCombiner::visitBSWAP(SDNode *
N) {
12147 EVT VT =
N->getValueType(0);
12172 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
12173 ShAmt->getZExtValue() >= (BW / 2) && (ShAmt->getZExtValue() % 8) == 0 &&
12175 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
12177 if (uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
12193 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
12194 ShAmt->getZExtValue() % 8 == 0) {
12215 if (BW - (LZ + TZ) == 8) {
12220 if (!LegalOperations || hasOperation(
Opc, VT)) {
12222 SDNodeFlags
Flags =
12232SDValue DAGCombiner::visitBITREVERSE(SDNode *
N) {
12234 EVT VT =
N->getValueType(0);
12268 EVT VT = Src.getValueType();
12278 bool NeedAdd =
true;
12300SDValue DAGCombiner::visitCTLZ(SDNode *
N) {
12302 EVT VT =
N->getValueType(0);
12314 if (
SDValue V = foldCTLZToCTLS(N0,
DL))
12320SDValue DAGCombiner::visitCTLZ_ZERO_POISON(SDNode *
N) {
12322 EVT VT =
N->getValueType(0);
12330 if (
SDValue V = foldCTLZToCTLS(N0,
DL))
12336SDValue DAGCombiner::visitCTTZ(SDNode *
N) {
12338 EVT VT =
N->getValueType(0);
12353SDValue DAGCombiner::visitCTTZ_ZERO_POISON(SDNode *
N) {
12355 EVT VT =
N->getValueType(0);
12365SDValue DAGCombiner::visitCTPOP(SDNode *
N) {
12367 EVT VT =
N->getValueType(0);
12379 const APInt &Amt = AmtC->getAPIntValue();
12380 if (Amt.
ult(NumBits)) {
12414 EVT VT =
LHS.getValueType();
12418 return Flags.hasNoSignedZeros() &&
12420 (Flags.hasNoNaNs() ||
12470SDValue DAGCombiner::foldShiftToAvg(SDNode *
N,
const SDLoc &
DL) {
12471 const unsigned Opcode =
N->getOpcode();
12475 EVT VT =
N->getValueType(0);
12476 bool IsUnsigned = Opcode ==
ISD::SRL;
12483 SDNodeFlags
Flags =
12490 if (hasOperation(FloorISD, VT))
12497SDValue DAGCombiner::foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT) {
12498 unsigned Opc =
N->getOpcode();
12517 if ((
LHS == True &&
RHS == False) || (
LHS == False &&
RHS == True))
12523 True, DAG, LegalOperations, ForCodeSize);
12527 HandleSDNode NegTrueHandle(NegTrue);
12535 if (
LHS == NegTrue) {
12539 RHS, DAG, LegalOperations, ForCodeSize);
12541 HandleSDNode NegRHSHandle(NegRHS);
12542 if (NegRHS == False) {
12544 False, CC, TLI, DAG);
12564 EVT VT =
N->getValueType(0);
12566 VT !=
Cond.getOperand(0).getValueType())
12609SDValue DAGCombiner::foldSelectOfConstants(SDNode *
N) {
12613 EVT VT =
N->getValueType(0);
12614 EVT CondVT =
Cond.getValueType();
12625 if (CondVT != MVT::i1 || LegalOperations) {
12640 if (C1->
isZero() && C2->isOne()) {
12649 if (C1->
isOne() && C2->isZero() && CondVT == VT)
12660 assert(CondVT == MVT::i1 && !LegalOperations);
12663 if (C1->
isOne() && C2->isZero())
12671 if (C1->
isZero() && C2->isOne()) {
12678 if (C1->
isZero() && C2->isAllOnes()) {
12691 const APInt &C1Val = C1->getAPIntValue();
12692 const APInt &C2Val = C2->getAPIntValue();
12695 if (C1Val - 1 == C2Val) {
12701 if (C1Val + 1 == C2Val) {
12721 if (C2->isAllOnes()) {
12733template <
class MatchContextClass>
12737 N->getOpcode() == ISD::VP_SELECT) &&
12738 "Expected a (v)(vp.)select");
12740 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
12741 EVT VT =
N->getValueType(0);
12743 MatchContextClass matcher(DAG, TLI,
N);
12779 EVT VT =
N->getValueType(0);
12843 EVT VT =
LHS.getValueType();
12845 if (LegalOperations && !hasOperation(ABDOpc, VT))
12863 bool IsTypeLegalOrPromote =
12881 IsTypeLegalOrPromote)
12897 IsTypeLegalOrPromote)
12931SDValue DAGCombiner::visitSELECT(SDNode *
N) {
12935 EVT VT =
N->getValueType(0);
12938 SDNodeFlags
Flags =
N->getFlags();
12950 if (
SDValue V = foldSelectOfConstants(
N))
12954 if (SimplifySelectOps(
N, N1, N2))
12957 if (VT0 == MVT::i1) {
12966 bool normalizeToSequence =
12975 if (normalizeToSequence || !InnerSelect.
use_empty())
12977 InnerSelect, N2, Flags);
12980 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
12987 Cond1, N1, N2, Flags);
12988 if (normalizeToSequence || !InnerSelect.
use_empty())
12990 InnerSelect, Flags);
12993 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
13003 if (!normalizeToSequence) {
13009 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
13022 if (!normalizeToSequence) {
13028 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
13064 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2, CC))
13077 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
13097 (!LegalOperations &&
13105 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2, CC,
DL))
13108 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
13113 if (
SDValue UMin = foldSelectToUMin(Cond0, Cond1, N1, N2, CC,
DL))
13118 if (
SDValue BinOp = foldSelectOfBinops(
N))
13134 EVT VT =
N->getValueType(0);
13142 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
13151 for (
int i = 0; i < NumElems / 2; ++i) {
13152 if (
Cond->getOperand(i)->isUndef())
13155 if (BottomHalf ==
nullptr)
13157 else if (
Cond->getOperand(i).getNode() != BottomHalf)
13163 for (
int i = NumElems / 2; i < NumElems; ++i) {
13164 if (
Cond->getOperand(i)->isUndef())
13167 if (TopHalf ==
nullptr)
13169 else if (
Cond->getOperand(i).getNode() != TopHalf)
13173 assert(TopHalf && BottomHalf &&
13174 "One half of the selector was all UNDEFs and the other was all the "
13175 "same value. This should have been addressed before this function.");
13178 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
13179 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
13192 EVT VT = BasePtr.getValueType();
13196 SplatVal.getValueType() == VT) {
13202 if (Index.getOpcode() !=
ISD::ADD)
13229 Index = Index.getOperand(0);
13242 Index = Index.getOperand(0);
13249SDValue DAGCombiner::visitVPSCATTER(SDNode *
N) {
13280SDValue DAGCombiner::visitMSCATTER(SDNode *
N) {
13312SDValue DAGCombiner::visitMSTORE(SDNode *
N) {
13326 MST1->isSimple() && MST1->getBasePtr() == Ptr &&
13329 MST1->getMemoryVT().getStoreSize()) ||
13333 CombineTo(MST1, MST1->getChain());
13350 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
13354 Value.getValueType().isInteger() &&
13357 APInt TruncDemandedBits =
13384 Value.getOperand(0).getValueType());
13394SDValue DAGCombiner::visitVP_STRIDED_STORE(SDNode *
N) {
13399 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
13400 return DAG.
getStoreVP(SST->getChain(), SDLoc(
N), SST->getValue(),
13401 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
13402 SST->getVectorLength(), SST->getMemoryVT(),
13403 SST->getMemOperand(), SST->getAddressingMode(),
13404 SST->isTruncatingStore(), SST->isCompressingStore());
13409SDValue DAGCombiner::visitVECTOR_COMPRESS(SDNode *
N) {
13413 SDValue Passthru =
N->getOperand(2);
13416 bool HasPassthru = !Passthru.
isUndef();
13429 unsigned NumSelected = 0;
13431 for (
unsigned I = 0;
I < NumElmts; ++
I) {
13440 Ops.push_back(VecI);
13444 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
13450 Ops.push_back(Val);
13458SDValue DAGCombiner::visitVPGATHER(SDNode *
N) {
13486SDValue DAGCombiner::visitMGATHER(SDNode *
N) {
13499 return CombineTo(
N, PassThru, MGT->
getChain());
13518SDValue DAGCombiner::visitMLOAD(SDNode *
N) {
13534 return CombineTo(
N, NewLd, NewLd.
getValue(1));
13538 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
13544SDValue DAGCombiner::visitMHISTOGRAM(SDNode *
N) {
13554 EVT DataVT =
Index.getValueType();
13572SDValue DAGCombiner::visitPARTIAL_REDUCE_MLA(SDNode *
N) {
13573 if (
SDValue Res = foldPartialReduceMLAMulOp(
N))
13575 if (
SDValue Res = foldPartialReduceAdd(
N))
13591SDValue DAGCombiner::foldPartialReduceMLAMulOp(SDNode *
N) {
13610 bool IsMLS =
false;
13640 RHS.getValueType().getScalarType()));
13648 auto IsIntOrFPExtOpcode = [](
unsigned int Opcode) {
13652 unsigned LHSOpcode =
LHS->getOpcode();
13653 if (!IsIntOrFPExtOpcode(LHSOpcode))
13664 EVT OpVT =
Op.getValueType();
13675 EVT AccVT = Acc.getValueType();
13686 unsigned LHSBits =
LHS.getValueType().getScalarSizeInBits();
13703 ApplyPredicate(
C, LHSExtOp);
13704 return GetMLA(NewOpcode, Acc, LHSExtOp,
C);
13707 unsigned RHSOpcode =
RHS->getOpcode();
13708 if (!IsIntOrFPExtOpcode(RHSOpcode))
13733 EVT AccElemVT = Acc.getValueType().getVectorElementType();
13735 NewOpc !=
N->getOpcode())
13745 ApplyPredicate(RHSExtOp, LHSExtOp);
13746 return GetMLA(NewOpc, Acc, LHSExtOp, RHSExtOp);
13756SDValue DAGCombiner::foldPartialReduceAdd(SDNode *
N) {
13776 bool IsMLS =
false;
13790 if (Op1IsSigned != NodeIsSigned &&
13819 : DAG.
getNode(NewOpcode,
DL, AccVT, Acc, UnextOp1, Constant);
13822SDValue DAGCombiner::visitVP_STRIDED_LOAD(SDNode *
N) {
13827 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
13829 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
13830 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
13831 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
13832 SLD->getMemOperand(), SLD->isExpandingLoad());
13833 return CombineTo(
N, NewLd, NewLd.
getValue(1));
13840SDValue DAGCombiner::foldVSelectOfConstants(SDNode *
N) {
13844 EVT VT =
N->getValueType(0);
13845 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
13854 bool AllAddOne =
true;
13855 bool AllSubOne =
true;
13857 for (
unsigned i = 0; i != Elts; ++i) {
13880 if (AllAddOne || AllSubOne) {
13907SDValue DAGCombiner::visitVP_SELECT(SDNode *
N) {
13931 EVT CondVT =
Cond.getValueType();
13932 assert(CondVT.
isVector() &&
"Vector select expects a vector selector!");
13940 if (!IsTAllZero && !IsTAllOne && !IsFAllZero && !IsFAllOne)
13944 if (IsTAllZero && IsFAllZero) {
13953 Cond.getOperand(0).getValueType() == VT && VT.
isSimple() &&
13955 TValAPInt.
isOne() &&
13979 if (!IsTAllOne && !IsFAllZero &&
Cond.hasOneUse() &&
13983 if (IsTAllZero || IsFAllOne) {
13996 "Select condition no longer all-sign bits");
13999 if (IsTAllOne && IsFAllZero)
14028SDValue DAGCombiner::visitVSELECT(SDNode *
N) {
14032 EVT VT =
N->getValueType(0);
14065 bool isAbs =
false;
14084 AddToWorklist(Shift.
getNode());
14085 AddToWorklist(
Add.getNode());
14097 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT,
LHS,
RHS, N1, N2, CC))
14112 EVT NarrowVT =
LHS.getValueType();
14120 SetCCWidth < WideWidth &&
14136 DAG.
getSetCC(
DL, WideSetCCVT, WideLHS, WideRHS, CC);
14172 (OpLHS == CondLHS || OpRHS == CondLHS))
14175 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
14178 CondLHS == OpLHS) {
14182 auto MatchUADDSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
14183 return Cond->getAPIntValue() == ~Op->getAPIntValue();
14224 if (OpLHS ==
LHS) {
14239 auto MatchUSUBSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
14240 return (!
Op && !
Cond) ||
14242 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
14278 if (SimplifySelectOps(
N, N1, N2))
14298 if (
SDValue V = foldVSelectOfConstants(
N))
14314SDValue DAGCombiner::visitSELECT_CC(SDNode *
N) {
14335 AddToWorklist(
SCC.getNode());
14340 return SCCC->isZero() ? N3 : N2;
14344 if (
SCC->isUndef())
14350 SCC.getOperand(0),
SCC.getOperand(1), N2, N3,
14351 SCC.getOperand(2),
SCC->getFlags());
14356 if (SimplifySelectOps(
N, N2, N3))
14360 return SimplifySelectCC(
DL, N0, N1, N2, N3, CC);
14363SDValue DAGCombiner::visitSETCC(SDNode *
N) {
14368 N->hasOneUse() && (
N->user_begin()->getOpcode() ==
ISD::BRCOND ||
14372 EVT VT =
N->getValueType(0);
14379 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
14380 SDValue NewSetCC = rebuildSetCC(Combined);
14408 A.getOperand(0) ==
B.getOperand(0);
14412 B.getOperand(0) ==
A;
14415 bool IsRotate =
false;
14418 if (IsAndWithShift(N0, N1)) {
14420 ShiftOrRotate = N1;
14421 }
else if (IsAndWithShift(N1, N0)) {
14423 ShiftOrRotate = N0;
14424 }
else if (IsRotateWithOp(N0, N1)) {
14427 ShiftOrRotate = N1;
14428 }
else if (IsRotateWithOp(N1, N0)) {
14431 ShiftOrRotate = N0;
14434 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
14439 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
14442 if (CNode ==
nullptr)
14443 return std::nullopt;
14446 std::optional<APInt> AndCMask =
14447 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
14448 std::optional<APInt> ShiftCAmt =
14449 GetAPIntValue(ShiftOrRotate.getOperand(1));
14453 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
14454 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
14456 bool CanTransform = IsRotate;
14457 if (!CanTransform) {
14459 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
14461 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
14469 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
14471 if (CanTransform && NewShiftOpc != ShiftOpc) {
14473 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
14474 ShiftOrRotate.getOperand(1));
14481 NumBits - ShiftCAmt->getZExtValue())
14482 : APInt::getLowBitsSet(NumBits,
14483 NumBits - ShiftCAmt->getZExtValue());
14491 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
14499SDValue DAGCombiner::visitSETCCCARRY(SDNode *
N) {
14520 if (!
N.hasOneUse())
14549 unsigned Opcode =
N->getOpcode();
14551 EVT VT =
N->getValueType(0);
14554 "Expected EXTEND dag node in input!");
14596 unsigned Opcode =
N->getOpcode();
14598 EVT VT =
N->getValueType(0);
14601 "Expected EXTEND dag node in input!");
14607 return DAG.
getNode(Opcode,
DL, VT, N0);
14626 unsigned FoldOpc = Opcode;
14649 for (
unsigned i = 0; i != NumElts; ++i) {
14651 if (
Op.isUndef()) {
14662 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
14680 bool HasCopyToRegUses =
false;
14695 for (
unsigned i = 0; i != 2; ++i) {
14713 HasCopyToRegUses =
true;
14716 if (HasCopyToRegUses) {
14717 bool BothLiveOut =
false;
14720 BothLiveOut =
true;
14727 return !ExtendNodes.
empty();
14732void DAGCombiner::ExtendSetCCUses(
const SmallVectorImpl<SDNode *> &SetCCs,
14737 for (SDNode *SetCC : SetCCs) {
14740 for (
unsigned j = 0;
j != 2; ++
j) {
14741 SDValue SOp = SetCC->getOperand(j);
14742 if (SOp == OrigLoad)
14743 Ops.push_back(ExtLoad);
14748 Ops.push_back(SetCC->getOperand(2));
14754SDValue DAGCombiner::CombineExtLoad(SDNode *
N) {
14756 EVT DstVT =
N->getValueType(0);
14761 "Unexpected node type (not an extend)!");
14799 EVT SplitSrcVT = SrcVT;
14800 EVT SplitDstVT = DstVT;
14815 const unsigned NumSplits =
14822 for (
unsigned Idx = 0; Idx < NumSplits; Idx++) {
14823 const unsigned Offset = Idx * Stride;
14841 AddToWorklist(NewChain.
getNode());
14843 CombineTo(
N, NewValue);
14849 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
14850 CombineTo(N0.
getNode(), Trunc, NewChain);
14856SDValue DAGCombiner::CombineZExtLogicopShiftLoad(SDNode *
N) {
14858 EVT VT =
N->getValueType(0);
14859 EVT OrigVT =
N->getOperand(0).getValueType();
14881 EVT MemVT =
Load->getMemoryVT();
14903 Load->getChain(),
Load->getBasePtr(),
14904 Load->getMemoryVT(),
Load->getMemOperand());
14917 if (
SDValue(Load, 0).hasOneUse()) {
14921 Load->getValueType(0), ExtLoad);
14922 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
14926 recursivelyDeleteUnusedNodes(N0.
getNode());
14935SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(SDNode *Cast) {
14936 unsigned CastOpcode = Cast->
getOpcode();
14940 "Unexpected opcode for vector select narrowing/widening");
14980 bool LegalOperations,
SDNode *
N,
14994 EVT MemVT = OldExtLoad->getMemoryVT();
14995 if ((LegalOperations || !OldExtLoad->isSimple() || VT.
isVector()) &&
14996 !TLI.
isLoadLegal(VT, MemVT, OldExtLoad->getAlign(),
14997 OldExtLoad->getAddressSpace(), ExtLoadType,
false))
15002 OldExtLoad->getBasePtr(), MemVT,
15003 OldExtLoad->getMemOperand());
15010 DAG.
getValueType(OldExtLoad->getValueType(0).getScalarType()));
15028 bool NonNegZExt =
false) {
15035 (Frozen && !Load->hasNUsesOfValue(1, 0)))
15041 "Unexpected load type or opcode");
15058 !TLI.
isLoadLegal(VT, Load->getValueType(0), Load->getAlign(),
15059 Load->getAddressSpace(), ExtLoadType,
false))
15062 bool DoXform =
true;
15066 ExtOpc, SetCCs, TLI);
15075 unsigned OldBits,
unsigned NewBits,
15080 bool IsVariadic = Dbg->isVariadic();
15083 for (
unsigned I = 0,
E = Locs.
size();
I !=
E; ++
I) {
15088 if (
Op.getSDNode() == Old.getNode() &&
Op.getResNo() == Old.getResNo()) {
15112 for (
unsigned ArgNo : AffectedArgs)
15119 Dbg->getAdditionalDependencies(), Dbg->isIndirect(), Dbg->getDebugLoc(),
15120 Dbg->getOrder(), Dbg->isVariadic());
15122 Dbg->setIsInvalidated();
15123 Dbg->setIsEmitted();
15131 auto SalvageToOldLoadSize = [&](
SDValue Old,
SDValue New,
bool IsSigned) {
15136 unsigned VarBitsOld = Old.getValueSizeInBits();
15137 unsigned VarBitsNew = New.getValueSizeInBits();
15140 if (Dbg->isInvalidated())
15143 SalvageDbgValue(Dbg, Old, New, VarBitsOld, VarBitsNew, IsSigned);
15148 DAG.
getExtLoad(ExtLoadType,
DL, VT, Load->getChain(), Load->getBasePtr(),
15149 Load->getValueType(0), Load->getMemOperand());
15156 DAG.
getValueType(Load->getValueType(0).getScalarType()));
15158 Combiner.ExtendSetCCUses(SetCCs, N0, Res, ExtOpc);
15161 if (
N->getHasDebugValue()) {
15165 if (NoReplaceTrunc) {
15167 if (Load->getHasDebugValue()) {
15169 SalvageToOldLoadSize(OldLoadVal, ExtLoad, IsSigned);
15224 EVT MemoryVT = ALoad->getMemoryVT();
15225 if (!TLI.
isLoadLegal(VT, MemoryVT, ALoad->getAlign(),
15226 ALoad->getAddressSpace(), ExtLoadType,
true))
15234 EVT OrigVT = ALoad->getValueType(0);
15237 ExtLoadType,
SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(),
15238 ALoad->getBasePtr(), ALoad->getMemOperand()));
15248 bool LegalOperations) {
15260 EVT VT =
N->getValueType(0);
15261 EVT XVT =
X.getValueType();
15277 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
15283SDValue DAGCombiner::foldSextSetcc(SDNode *
N) {
15291 EVT VT =
N->getValueType(0);
15301 if (VT.
isVector() && !LegalOperations &&
15314 return DAG.
getSetCC(
DL, VT, N00, N01, CC, {},
15321 if (SVT == MatchingVecType) {
15338 auto IsFreeToExtend = [&](
SDValue V) {
15357 for (SDUse &Use :
V->uses()) {
15359 SDNode *
User =
Use.getUser();
15360 if (
Use.getResNo() != 0 || User == N0.
getNode())
15365 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
15371 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
15374 return DAG.
getSetCC(
DL, VT, Ext0, Ext1, CC, {},
15392 SDValue ExtTrueVal = (SetCCWidth == 1)
15396 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero, CC,
true))
15409 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero, Flags);
15416SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *
N) {
15418 EVT VT =
N->getValueType(0);
15422 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
15468 if (NarrowLoad.getNode() != N0.
getNode()) {
15469 CombineTo(N0.
getNode(), NarrowLoad);
15471 AddToWorklist(oye);
15479 unsigned OpBits =
Op.getScalarValueSizeInBits();
15485 if (OpBits == DestBits) {
15491 if (OpBits < DestBits) {
15500 Flags.setNoSignedWrap(
true);
15508 if (OpBits < DestBits)
15510 else if (OpBits > DestBits)
15530 if (
SDValue ExtLoad = CombineExtLoad(
N))
15566 bool NoReplaceTruncAnd = !N0.
hasOneUse();
15567 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
15570 if (NoReplaceTruncAnd) {
15573 CombineTo(N0.
getNode(), TruncAnd);
15575 if (NoReplaceTrunc) {
15580 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
15599 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15630 if (NewXor.getNode() == N0.
getNode()) {
15656 "Expected extend op");
15700SDValue DAGCombiner::visitZERO_EXTEND(SDNode *
N) {
15702 EVT VT =
N->getValueType(0);
15706 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
15737 APInt TruncatedBits =
15739 APInt(
Op.getScalarValueSizeInBits(), 0) :
15740 APInt::getBitsSet(
Op.getScalarValueSizeInBits(),
15741 N0.getScalarValueSizeInBits(),
15742 std::
min(
Op.getScalarValueSizeInBits(),
15745 SDValue ZExtOrTrunc = DAG.getZExtOrTrunc(Op, DL, VT);
15746 DAG.salvageDebugInfo(*N0.getNode());
15748 return ZExtOrTrunc;
15758 if (NarrowLoad.getNode() != N0.
getNode()) {
15759 CombineTo(N0.
getNode(), NarrowLoad);
15761 AddToWorklist(oye);
15769 if (
N->getFlags().hasNonNeg()) {
15777 if (OpBits == DestBits) {
15783 if (OpBits < DestBits) {
15793 Flags.setNoSignedWrap(
true);
15794 Flags.setNoUnsignedWrap(
true);
15806 AddToWorklist(
Op.getNode());
15810 return ZExtOrTrunc;
15816 AddToWorklist(
Op.getNode());
15852 if (
SDValue ExtLoad = CombineExtLoad(
N))
15873 bool DoXform =
true;
15880 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
15896 bool NoReplaceTruncAnd = !N0.
hasOneUse();
15897 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
15900 if (NoReplaceTruncAnd) {
15903 CombineTo(N0.
getNode(), TruncAnd);
15905 if (NoReplaceTrunc) {
15910 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
15919 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
15932 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
15935 if (!LegalOperations && VT.
isVector() &&
15967 if (
SDValue SCC = SimplifySelectCC(
15987 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
16008 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
16030SDValue DAGCombiner::visitANY_EXTEND(SDNode *
N) {
16032 EVT VT =
N->getValueType(0);
16066 if (NarrowLoad.getNode() != N0.
getNode()) {
16067 CombineTo(N0.
getNode(), NarrowLoad);
16069 AddToWorklist(oye);
16105 bool DoXform =
true;
16117 CombineTo(
N, ExtLoad);
16118 if (NoReplaceTrunc) {
16120 recursivelyDeleteUnusedNodes(LN0);
16124 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
16139 if (!LegalOperations ||
16145 CombineTo(
N, ExtLoad);
16147 recursivelyDeleteUnusedNodes(LN0);
16155 SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
16162 if (VT.
isVector() && !LegalOperations) {
16189 if (
SDValue SCC = SimplifySelectCC(
16205SDValue DAGCombiner::visitAssertExt(SDNode *
N) {
16206 unsigned Opcode =
N->getOpcode();
16230 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
16245 if (AssertVT.
bitsLT(BigA_AssertVT)) {
16263 if (AssertVT.
bitsLT(BigA_AssertVT) &&
16283SDValue DAGCombiner::visitAssertAlign(SDNode *
N) {
16293 std::max(AL, AAN->getAlign()));
16304 unsigned AlignShift =
Log2(AL);
16309 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
16310 if (LHSAlignShift < AlignShift)
16312 if (RHSAlignShift < AlignShift)
16323SDValue DAGCombiner::visitIS_FPCLASS(SDNode *
N) {
16326 EVT VT =
N->getValueType(0);
16355SDValue DAGCombiner::reduceLoadWidth(SDNode *
N) {
16356 unsigned Opc =
N->getOpcode();
16360 EVT VT =
N->getValueType(0);
16370 unsigned ShAmt = 0;
16375 unsigned ShiftedOffset = 0;
16395 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
16396 if (MemoryWidth <= ShAmt)
16407 LN->getExtensionType() != ExtType)
16416 unsigned ActiveBits = 0;
16417 if (
Mask.isMask()) {
16418 ActiveBits =
Mask.countr_one();
16419 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
16420 ShiftedOffset = ShAmt;
16441 if (!
SRL.hasOneUse())
16454 ShAmt = SRL1C->getZExtValue();
16455 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
16456 if (ShAmt >= MemoryWidth)
16481 SDNode *
Mask = *(
SRL->user_begin());
16484 unsigned Offset, ActiveBits;
16485 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
16486 if (ShiftMask.
isMask()) {
16492 LN->getAddressSpace(), ExtType,
false))
16502 LN->getAddressSpace(), ExtType,
false)) {
16510 N0 =
SRL.getOperand(0);
16518 unsigned ShLeftAmt = 0;
16522 ShLeftAmt = N01->getZExtValue();
16543 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
16549 if (FreezeNode && !FreezeNode.
hasOneUse() &&
16555 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
16556 unsigned LVTStoreBits =
16559 return LVTStoreBits - EVTStoreBits - ShAmt;
16564 unsigned PtrAdjustmentInBits =
16567 uint64_t PtrOff = PtrAdjustmentInBits / 8;
16573 AddToWorklist(NewPtr.
getNode());
16577 const MDNode *OldRanges = LN0->
getRanges();
16578 const MDNode *NewRanges =
nullptr;
16582 if (ShAmt == 0 && OldRanges) {
16590 ConstantRange TruncatedCR = CR.
truncate(BitSize);
16600 NewRanges = OldRanges;
16613 WorklistRemover DeadNodes(*
this);
16617 if (FreezeNode && !FreezeNode.
hasOneUse())
16634 if (ShLeftAmt != 0) {
16646 if (ShiftedOffset != 0) {
16660SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *
N) {
16663 EVT VT =
N->getValueType(0);
16694 if ((N00Bits <= ExtVTBits ||
16707 if ((N00Bits == ExtVTBits ||
16708 (!IsZext && (N00Bits < ExtVTBits ||
16710 (!LegalOperations ||
16735 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
16743 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
16747 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
16766 CombineTo(
N, ExtLoad);
16768 AddToWorklist(ExtLoad.
getNode());
16778 ((!LegalOperations && LN0->
isSimple()) &&
16784 CombineTo(
N, ExtLoad);
16800 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->
getMemOperand(),
16802 CombineTo(
N, Frozen ? N0 : ExtMaskedLoad);
16803 CombineTo(Ld, ExtMaskedLoad, ExtMaskedLoad.
getValue(1));
16810 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
16812 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
16813 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
16816 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL,
Ops, GN0->getMemOperand(),
16819 CombineTo(
N, ExtLoad);
16821 AddToWorklist(ExtLoad.
getNode());
16844 (!LegalOperations ||
16858 bool LegalOperations) {
16859 unsigned InregOpcode =
N->getOpcode();
16863 EVT VT =
N->getValueType(0);
16865 *DAG.
getContext(), Src.getValueType().getVectorElementType());
16868 "Expected EXTEND_VECTOR_INREG dag node in input!");
16877 Src = Src.getOperand(0);
16878 if (Src.getValueType() != SrcVT)
16884 return DAG.
getNode(Opcode,
DL, VT, Src);
16887SDValue DAGCombiner::visitEXTEND_VECTOR_INREG(SDNode *
N) {
16889 EVT VT =
N->getValueType(0);
16913SDValue DAGCombiner::visitTRUNCATE_USAT_U(SDNode *
N) {
16914 EVT VT =
N->getValueType(0);
16935 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16937 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16958 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16960 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16981 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16983 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
17006 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
17018 }
else if (Src.getOpcode() ==
ISD::UMIN) {
17030SDValue DAGCombiner::visitTRUNCATE(SDNode *
N) {
17032 EVT VT =
N->getValueType(0);
17047 return SaturatedTR;
17099 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
17101 EVT TrTy =
N->getValueType(0);
17106 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
17109 Src = Src.getOperand(0);
17116 EVT VecTy = Src.getOperand(0).getValueType();
17117 EVT ExTy = Src.getValueType();
17121 auto NewEltCnt = EltCnt * SizeRatio;
17126 SDValue EltNo = Src->getOperand(1);
17129 int Index = isLE ? (Elt * SizeRatio + EltOffset)
17130 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
17141 if (!LegalOperations ||
17164 AddToWorklist(Amt.
getNode());
17214 if (BuildVectEltTy == TruncVecEltTy) {
17218 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
17219 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
17221 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
17222 "Invalid number of elements");
17225 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
17226 i += TruncEltOffset)
17236 if (
SDValue Reduced = reduceLoadWidth(
N))
17259 unsigned NumDefs = 0;
17263 if (!
X.isUndef()) {
17280 if (NumDefs == 1) {
17281 assert(
V.getNode() &&
"The single defined operand is empty!");
17283 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
17289 AddToWorklist(
NV.getNode());
17304 (!LegalOperations ||
17332 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
17346 if (!LegalOperations && N0.
hasOneUse() &&
17363 Flags.setNoUnsignedWrap(
true);
17388 if (!LegalOperations && N0.
hasOneUse() &&
17429 if (!LegalOperations && N0.
hasOneUse() &&
17437 bool CanFold =
false;
17445 unsigned NeededBits = SrcBits - TruncBits;
17471SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *
N, EVT VT) {
17484 !LD1->hasOneUse() || !LD2->hasOneUse() ||
17485 LD1->getAddressSpace() != LD2->getAddressSpace())
17488 unsigned LD1Fast = 0;
17489 EVT LD1VT = LD1->getValueType(0);
17494 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
17495 return DAG.
getLoad(VT, SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
17496 LD1->getPointerInfo(), LD1->getAlign());
17507SDValue DAGCombiner::foldBitcastedFPLogic(SDNode *
N, SelectionDAG &DAG,
17511 EVT VT =
N->getValueType(0);
17548 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op, EVT VT) {
17562 IsBitCastOrFree(LogicOp0, VT)) {
17565 NumFPLogicOpsConv++;
17574SDValue DAGCombiner::visitBITCAST(SDNode *
N) {
17576 EVT VT =
N->getValueType(0);
17601 if (!LegalOperations ||
17607 if (
C.getNode() !=
N)
17620 auto IsFreeBitcast = [VT](
SDValue V) {
17622 V.getOperand(0).getValueType() == VT) ||
17635 auto CastLoad = [
this, &VT](
SDValue N0,
const SDLoc &
DL) {
17652 if ((LegalOperations || !LN0->
isSimple()) &&
17662 if (
const MDNode *MD = LN0->
getRanges()) {
17674 if (
SDValue NewLd = CastLoad(N0, SDLoc(
N)))
17681 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
17701 AddToWorklist(NewConv.
getNode());
17704 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
17711 AddToWorklist(FlipBit.
getNode());
17718 AddToWorklist(
Hi.getNode());
17720 AddToWorklist(FlipBit.
getNode());
17724 AddToWorklist(FlipBits.
getNode());
17754 AddToWorklist(
X.getNode());
17758 if (OrigXWidth < VTWidth) {
17760 AddToWorklist(
X.getNode());
17761 }
else if (OrigXWidth > VTWidth) {
17766 X.getValueType(),
X,
17768 X.getValueType()));
17769 AddToWorklist(
X.getNode());
17771 AddToWorklist(
X.getNode());
17774 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
17777 AddToWorklist(Cst.
getNode());
17779 AddToWorklist(
X.getNode());
17781 AddToWorklist(XorResult.
getNode());
17785 SDLoc(XorResult)));
17786 AddToWorklist(XorResult64.
getNode());
17789 DAG.
getConstant(SignBit, SDLoc(XorResult64), MVT::i64));
17790 AddToWorklist(FlipBit.
getNode());
17793 AddToWorklist(FlipBits.
getNode());
17799 AddToWorklist(
X.getNode());
17804 AddToWorklist(Cst.
getNode());
17812 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
17835 auto PeekThroughBitcast = [&](
SDValue Op) {
17837 Op.getOperand(0).getValueType() == VT)
17854 SmallVector<int, 8> NewMask;
17856 for (
int i = 0; i != MaskScale; ++i)
17857 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
17862 return LegalShuffle;
17868SDValue DAGCombiner::visitBUILD_PAIR(SDNode *
N) {
17869 EVT VT =
N->getValueType(0);
17870 return CombineConsecutiveLoads(
N, VT);
17873SDValue DAGCombiner::visitFREEZE(SDNode *
N) {
17887 assert(
N->getOperand(0) == FrozenN0 &&
"Expected cycle in DAG");
17917 bool AllowMultipleMaybePoisonOperands =
17945 SmallSet<SDValue, 8> MaybePoisonOperands;
17946 SmallVector<unsigned, 8> MaybePoisonOperandNumbers;
17951 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
17952 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
17953 if (IsNewMaybePoisonOperand)
17954 MaybePoisonOperandNumbers.
push_back(OpNo);
17955 if (!HadMaybePoisonOperands)
17957 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
17966 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
17977 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
17979 if (MaybePoisonOperand.
isUndef())
17986 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
17990 MaybePoisonOperand);
18026 SDNodeFlags SrcFlags = N0->
getFlags();
18027 SDNodeFlags SafeFlags;
18041 N->getFlags().hasAllowContract();
18045template <
class MatchContextClass>
18046SDValue DAGCombiner::visitFADDForFMACombine(SDNode *
N) {
18049 EVT VT =
N->getValueType(0);
18051 MatchContextClass matcher(DAG, TLI,
N);
18054 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
18059 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
18063 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
18067 if (!HasFMAD && !HasFMA)
18070 bool AllowFusionGlobally =
18073 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
18099 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
18110 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
18117 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
18129 bool CanReassociate =
N->getFlags().hasAllowReassociation();
18130 if (CanReassociate) {
18135 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
18141 while (
E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
18146 SDValue CDE = matcher.getNode(PreferredFusedOpcode, SL, VT,
C,
D,
E);
18165 return matcher.getNode(
18166 PreferredFusedOpcode, SL, VT,
18179 return matcher.getNode(
18180 PreferredFusedOpcode, SL, VT,
18192 return matcher.getNode(
18193 PreferredFusedOpcode, SL, VT,
X,
Y,
18194 matcher.getNode(PreferredFusedOpcode, SL, VT,
18198 if (isFusedOp(N0)) {
18219 return matcher.getNode(
18220 PreferredFusedOpcode, SL, VT,
18223 matcher.getNode(PreferredFusedOpcode, SL, VT,
18229 if (isFusedOp(N00)) {
18243 if (isFusedOp(N1)) {
18264 if (isFusedOp(N10)) {
18281template <
class MatchContextClass>
18282SDValue DAGCombiner::visitFSUBForFMACombine(SDNode *
N) {
18285 EVT VT =
N->getValueType(0);
18287 MatchContextClass matcher(DAG, TLI,
N);
18290 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
18295 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
18299 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
18303 if (!HasFMAD && !HasFMA)
18306 const SDNodeFlags
Flags =
N->getFlags();
18307 bool AllowFusionGlobally =
18311 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
18320 bool NoSignedZero =
Flags.hasNoSignedZeros();
18327 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
18333 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
18344 return matcher.getNode(
18345 PreferredFusedOpcode, SL, VT,
18346 matcher.getNode(
ISD::FNEG, SL, VT, YZ.getOperand(0)),
18347 YZ.getOperand(1),
X);
18357 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
18360 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
18364 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
18367 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
18376 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
18377 matcher.getNode(
ISD::FNEG, SL, VT, N00), N01,
18378 matcher.getNode(
ISD::FNEG, SL, VT, N1));
18390 return matcher.getNode(
18391 PreferredFusedOpcode, SL, VT,
18394 matcher.getNode(
ISD::FNEG, SL, VT, N1));
18406 return matcher.getNode(
18407 PreferredFusedOpcode, SL, VT,
18428 return matcher.getNode(
18431 PreferredFusedOpcode, SL, VT,
18452 return matcher.getNode(
18455 PreferredFusedOpcode, SL, VT,
18472 if (
Aggressive &&
N->getFlags().hasAllowReassociation()) {
18473 bool CanFuse =
N->getFlags().hasAllowContract();
18476 if (CanFuse && isFusedOp(N0) &&
18477 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
18479 return matcher.getNode(
18481 matcher.
getNode(PreferredFusedOpcode, SL, VT,
18489 if (CanFuse && isFusedOp(N1) &&
18490 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
18495 PreferredFusedOpcode, SL, VT,
18498 matcher.
getNode(PreferredFusedOpcode, SL, VT,
18499 matcher.getNode(
ISD::FNEG, SL, VT, N20), N21, N0));
18504 if (isFusedOp(N0) && N0->
hasOneUse()) {
18508 if (isContractableAndReassociableFMUL(N020) &&
18511 return matcher.getNode(
18514 PreferredFusedOpcode, SL, VT,
18517 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
18530 if (isFusedOp(N00)) {
18532 if (isContractableAndReassociableFMUL(N002) &&
18535 return matcher.getNode(
18536 PreferredFusedOpcode, SL, VT,
18540 PreferredFusedOpcode, SL, VT,
18543 matcher.getNode(
ISD::FNEG, SL, VT, N1)));
18553 if (isContractableAndReassociableFMUL(N120) &&
18559 PreferredFusedOpcode, SL, VT,
18563 PreferredFusedOpcode, SL, VT,
18581 if (isContractableAndReassociableFMUL(N102) &&
18587 PreferredFusedOpcode, SL, VT,
18592 PreferredFusedOpcode, SL, VT,
18606SDValue DAGCombiner::visitFMULForFMADistributiveCombine(SDNode *
N) {
18609 EVT VT =
N->getValueType(0);
18619 if (!
FAdd->getFlags().hasNoInfs())
18630 bool HasFMAD = LegalOperations && TLI.
isFMADLegal(DAG,
N);
18633 if (!HasFMAD && !HasFMA)
18645 if (
C->isExactlyValue(+1.0))
18646 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
18648 if (
C->isExactlyValue(-1.0))
18649 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
18656 if (
SDValue FMA = FuseFADD(N0, N1))
18658 if (
SDValue FMA = FuseFADD(N1, N0))
18668 if (C0->isExactlyValue(+1.0))
18669 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
18672 if (C0->isExactlyValue(-1.0))
18673 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
18678 if (C1->isExactlyValue(+1.0))
18679 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
18681 if (C1->isExactlyValue(-1.0))
18682 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
18689 if (
SDValue FMA = FuseFSUB(N0, N1))
18691 if (
SDValue FMA = FuseFSUB(N1, N0))
18697SDValue DAGCombiner::visitVP_FADD(SDNode *
N) {
18698 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18701 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
18703 AddToWorklist(Fused.getNode());
18709SDValue DAGCombiner::visitFADD(SDNode *
N) {
18714 EVT VT =
N->getValueType(0);
18716 SDNodeFlags
Flags =
N->getFlags();
18717 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18727 if (N0CFP && !N1CFP)
18732 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18737 if (N1C && N1C->
isZero())
18741 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18747 N1, DAG, LegalOperations, ForCodeSize))
18753 N0, DAG, LegalOperations, ForCodeSize))
18760 return C &&
C->isExactlyValue(-2.0);
18764 if (isFMulNegTwo(N0)) {
18770 if (isFMulNegTwo(N1)) {
18781 if (
Flags.hasNoNaNs() && AllowNewConst) {
18794 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
18812 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
18833 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
18880 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros()) {
18883 VT, N0, N1, Flags))
18888 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
18890 AddToWorklist(Fused.getNode());
18896SDValue DAGCombiner::visitSTRICT_FADD(SDNode *
N) {
18900 EVT VT =
N->getValueType(0);
18901 EVT ChainVT =
N->getValueType(1);
18903 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18908 N1, DAG, LegalOperations, ForCodeSize)) {
18910 {Chain, N0, NegN1});
18916 N0, DAG, LegalOperations, ForCodeSize)) {
18918 {Chain, N1, NegN0});
18923SDValue DAGCombiner::visitFSUB(SDNode *
N) {
18928 EVT VT =
N->getValueType(0);
18930 const SDNodeFlags
Flags =
N->getFlags();
18931 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18942 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18945 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18949 if (N1CFP && N1CFP->
isZero()) {
18957 if (
Flags.hasNoNaNs())
18962 if (N0CFP && N0CFP->
isZero()) {
18979 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
18995 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
18996 AddToWorklist(Fused.getNode());
19018SDValue DAGCombiner::combineFMulOrFDivWithIntPow2(SDNode *
N) {
19019 EVT VT =
N->getValueType(0);
19025 std::optional<int> Mantissa;
19026 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
19027 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
19044 auto IsFPConstValid = [
N, MaxExpChange, &Mantissa](ConstantFPSDNode *CFP) {
19045 if (CFP ==
nullptr)
19048 const APFloat &APF = CFP->getValueAPF();
19056 int CurExp =
ilogb(APF);
19059 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
19062 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
19070 Mantissa = ThisMantissa;
19072 return *Mantissa == ThisMantissa && ThisMantissa > 0;
19079 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
19107 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
19112SDValue DAGCombiner::visitFMUL(SDNode *
N) {
19116 EVT VT =
N->getValueType(0);
19118 const SDNodeFlags
Flags =
N->getFlags();
19119 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19135 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
19138 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
19141 if (
Flags.hasAllowReassociation()) {
19167 VT, N0, N1, Flags))
19191 HandleSDNode NegN0Handle(NegN0);
19201 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
19212 if (TrueOpnd && FalseOpnd &&
19233 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
19237 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
19246 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
19247 AddToWorklist(Fused.getNode());
19253 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
19259template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(SDNode *
N) {
19266 EVT VT =
N->getValueType(0);
19269 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19270 MatchContextClass matcher(DAG, TLI,
N);
19285 HandleSDNode NegN0Handle(NegN0);
19293 if (
N->getFlags().hasNoNaNs() &&
N->getFlags().hasNoInfs()) {
19294 if (
N->getFlags().hasNoSignedZeros() ||
19296 if (N0CFP && N0CFP->
isZero())
19298 if (N1CFP && N1CFP->
isZero())
19307 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
19312 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
19314 bool CanReassociate =
N->getFlags().hasAllowReassociation();
19315 if (CanReassociate) {
19320 return matcher.getNode(
19329 return matcher.getNode(
19339 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
19344 AddToWorklist(RHSNeg.
getNode());
19345 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
19359 if (CanReassociate) {
19361 if (N1CFP && N0 == N2) {
19379 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
19384SDValue DAGCombiner::visitFMAD(SDNode *
N) {
19388 EVT VT =
N->getValueType(0);
19398SDValue DAGCombiner::visitFMULADD(SDNode *
N) {
19402 EVT VT =
N->getValueType(0);
19420SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *
N) {
19424 const SDNodeFlags
Flags =
N->getFlags();
19425 if (LegalDAG || !
Flags.hasAllowReciprocal())
19440 unsigned NumElts = 1;
19441 EVT VT =
N->getValueType(0);
19445 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
19450 SetVector<SDNode *>
Users;
19451 for (
auto *U : N1->
users()) {
19452 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
19454 if (
U->getOperand(1).getOpcode() ==
ISD::FSQRT &&
19455 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
19456 U->getFlags().hasAllowReassociation() &&
19457 U->getFlags().hasNoSignedZeros())
19462 if (
U->getFlags().hasAllowReciprocal())
19469 if ((
Users.size() * NumElts) < MinUses)
19477 for (
auto *U :
Users) {
19478 SDValue Dividend =
U->getOperand(0);
19479 if (Dividend != FPOne) {
19481 Reciprocal, Flags);
19482 CombineTo(U, NewNode);
19483 }
else if (U != Reciprocal.
getNode()) {
19486 CombineTo(U, Reciprocal);
19492SDValue DAGCombiner::visitFDIV(SDNode *
N) {
19495 EVT VT =
N->getValueType(0);
19497 SDNodeFlags
Flags =
N->getFlags();
19498 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19509 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
19512 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
19529 (!LegalOperations ||
19539 if (
Flags.hasAllowReciprocal()) {
19548 N1AllowReciprocal) {
19581 A =
Y.getOperand(0);
19594 recursivelyDeleteUnusedNodes(AAZ.
getNode());
19603 AddToWorklist(Div.
getNode());
19610 if (
Flags.hasNoInfs())
19611 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
19617 Flags.hasAllowReassociation())
19629 HandleSDNode NegN0Handle(NegN0);
19637 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
19643SDValue DAGCombiner::visitFREM(SDNode *
N) {
19646 EVT VT =
N->getValueType(0);
19647 SDNodeFlags
Flags =
N->getFlags();
19648 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19658 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
19686SDValue DAGCombiner::visitFSQRT(SDNode *
N) {
19687 SDNodeFlags
Flags =
N->getFlags();
19691 if (!
Flags.hasApproximateFuncs() || !
Flags.hasNoInfs())
19699 SelectionDAG::FlagInserter FlagInserter(DAG, Flags);
19704 return buildSqrtEstimate(N0, Flags);
19719 if (YTy == MVT::f128)
19736SDValue DAGCombiner::visitFCOPYSIGN(SDNode *
N) {
19739 EVT VT =
N->getValueType(0);
19777SDValue DAGCombiner::visitFPOW(SDNode *
N) {
19781 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19787 EVT VT =
N->getValueType(0);
19789 if ((ScalarVT == MVT::f32 &&
19791 (ScalarVT == MVT::f64 &&
19799 SDNodeFlags
Flags =
N->getFlags();
19800 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
19801 !
Flags.hasApproximateFuncs())
19823 if (ExponentIs025 || ExponentIs075) {
19831 SDNodeFlags
Flags =
N->getFlags();
19834 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
19835 !
Flags.hasApproximateFuncs())
19872 EVT VT =
N->getValueType(0);
19878 assert(IsSigned || IsUnsigned);
19883 if (IsSigned && !IsSignedZeroSafe)
19887 if (IsUnsigned && !IsSignedZeroSafe && !TLI.
isFAbsFree(VT))
19895 constexpr unsigned MaxClamps = 2;
19899 SDValue IntVal =
N->getOperand(0);
19900 for (
unsigned Level = 0; Level < MaxClamps; ++Level) {
19901 if (!IntVal.hasOneUse() ||
19902 (IntVal.getOpcode() != MinOp && IntVal.getOpcode() != MaxOp))
19907 IntConst = IntConstNode->getAPIntValue();
19917 !IsExact ||
static_cast<const APInt &
>(RoundTrip) != IntConst)
19919 bool IsMin = IntVal.getOpcode() == MinOp;
19921 IntVal = IntVal.getOperand(0);
19926 if (IntVal.getOpcode() != FPToIntOp ||
19927 IntVal.getOperand(0).getValueType() != VT)
19930 SDValue Result = IntVal.getOperand(0);
19931 if (IsUnsigned && !IsSignedZeroSafe && TLI.
isFAbsFree(VT))
19935 for (
const ClampInfo &Clamp :
reverse(Clamps)) {
19936 unsigned FPClampOp =
19940 Result = DAG.
getNode(FPClampOp,
DL, VT, Result, Clamp.Constant);
19945SDValue DAGCombiner::visitSINT_TO_FP(SDNode *
N) {
19947 EVT VT =
N->getValueType(0);
19999SDValue DAGCombiner::visitUINT_TO_FP(SDNode *
N) {
20001 EVT VT =
N->getValueType(0);
20045 EVT VT =
N->getValueType(0);
20051 EVT SrcVT = Src.getValueType();
20066 unsigned ActualSize = std::min(InputSize, OutputSize);
20075 return DAG.
getNode(ExtOp,
DL, VT, Src);
20084SDValue DAGCombiner::visitFP_TO_SINT(SDNode *
N) {
20086 EVT VT =
N->getValueType(0);
20100SDValue DAGCombiner::visitFP_TO_UINT(SDNode *
N) {
20102 EVT VT =
N->getValueType(0);
20116SDValue DAGCombiner::visitXROUND(SDNode *
N) {
20118 EVT VT =
N->getValueType(0);
20134SDValue DAGCombiner::visitFP_ROUND(SDNode *
N) {
20137 EVT VT =
N->getValueType(0);
20150 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
20172 if ((
N->getFlags().hasAllowContract() &&
20190 AddToWorklist(Tmp.
getNode());
20194 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
20204 EVT VT =
N->getValueType(0);
20206 unsigned NarrowingOp;
20207 switch (
N->getOpcode()) {
20237SDValue DAGCombiner::visitFP_EXTEND(SDNode *
N) {
20238 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
20240 EVT VT =
N->getValueType(0);
20244 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
20264 if (
In.getValueType() == VT)
return In;
20278 CombineTo(
N, ExtLoad);
20288 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
20292 return CastEliminated;
20297SDValue DAGCombiner::visitFCEIL(SDNode *
N) {
20299 EVT VT =
N->getValueType(0);
20308SDValue DAGCombiner::visitFTRUNC(SDNode *
N) {
20310 EVT VT =
N->getValueType(0);
20334SDValue DAGCombiner::visitFFREXP(SDNode *
N) {
20343SDValue DAGCombiner::visitFFLOOR(SDNode *
N) {
20345 EVT VT =
N->getValueType(0);
20354SDValue DAGCombiner::visitFNEG(SDNode *
N) {
20356 EVT VT =
N->getValueType(0);
20357 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
20380 if (
SDValue Cast = foldSignChangeInBitcast(
N))
20386SDValue DAGCombiner::visitFMinMax(SDNode *
N) {
20389 EVT VT =
N->getValueType(0);
20390 const SDNodeFlags
Flags =
N->getFlags();
20391 unsigned Opc =
N->getOpcode();
20396 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
20405 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0);
20419 if (PropAllNaNsToQNaNs || (AF.
isSignaling() && PropOnlySNaNsToQNaNs)) {
20424 return N->getOperand(0);
20437 (!PropAllNaNsToQNaNs ||
Flags.hasNoNaNs()))
20438 return N->getOperand(1);
20446 if (IsMin != AF.
isNegative() && (PropAllNaNsToQNaNs ||
Flags.hasNoNaNs()))
20447 return N->getOperand(0);
20455 if (
SDValue SD = reassociateReduction(
20459 Opc, SDLoc(
N), VT, N0, N1, Flags))
20465SDValue DAGCombiner::visitFABS(SDNode *
N) {
20467 EVT VT =
N->getValueType(0);
20477 if (
SDValue Cast = foldSignChangeInBitcast(
N))
20483SDValue DAGCombiner::visitBRCOND(SDNode *
N) {
20510 bool Updated =
false;
20522 return True || False;
20526 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
20533 S1 =
S1->getOperand(0);
20564 HandleSDNode ChainHandle(Chain);
20565 if (
SDValue NewN1 = rebuildSetCC(N1))
20567 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
20576 (
N.getOperand(0).hasOneUse() &&
20577 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
20580 N =
N.getOperand(0);
20628 HandleSDNode XORHandle(
N);
20629 SDValue Tmp = visitXOR(
N.getNode());
20636 N = XORHandle.getValue();
20648 bool Equal =
false;
20658 EVT SetCCVT =
N.getValueType();
20667 return DAG.
getSetCC(SDLoc(
N), SetCCVT, Op0, Op1, CC);
20676SDValue DAGCombiner::visitBR_CC(SDNode *
N) {
20688 CondLHS, CondRHS, CC->
get(), SDLoc(
N),
20703 bool &IsLoad,
bool &IsMasked,
SDValue &Ptr,
20706 if (LD->isIndexed())
20708 EVT VT = LD->getMemoryVT();
20711 Ptr = LD->getBasePtr();
20713 if (ST->isIndexed())
20715 EVT VT = ST->getMemoryVT();
20718 Ptr = ST->getBasePtr();
20721 if (LD->isIndexed())
20723 EVT VT = LD->getMemoryVT();
20727 Ptr = LD->getBasePtr();
20730 if (ST->isIndexed())
20732 EVT VT = ST->getMemoryVT();
20736 Ptr = ST->getBasePtr();
20750bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *
N) {
20754 bool IsLoad =
true;
20755 bool IsMasked =
false;
20777 bool Swapped =
false;
20806 if (Val == BasePtr)
20815 SmallPtrSet<const SDNode *, 32> Visited;
20825 for (SDUse &Use :
BasePtr->uses()) {
20828 if (
Use.getUser() == Ptr.
getNode() || Use != BasePtr)
20841 SDValue Op1 =
Use.getUser()->getOperand((
Use.getOperandNo() + 1) & 1);
20860 bool RealUse =
false;
20862 for (SDNode *User : Ptr->
users()) {
20896 WorklistRemover DeadNodes(*
this);
20905 deleteAndRecombine(
N);
20911 for (SDNode *OtherUse : OtherUses) {
20912 unsigned OffsetIdx = 1;
20913 if (OtherUse->getOperand(OffsetIdx).getNode() ==
BasePtr.getNode())
20915 assert(OtherUse->getOperand(!OffsetIdx).getNode() ==
BasePtr.getNode() &&
20916 "Expected BasePtr operand");
20930 const APInt &Offset0 = CN->getAPIntValue();
20931 const APInt &Offset1 =
Offset->getAsAPIntVal();
20932 int X0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
20933 int Y0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
20937 unsigned Opcode = (Y0 * Y1 < 0) ?
ISD::SUB : ISD::
ADD;
20939 APInt CNV = Offset0;
20940 if (X0 < 0) CNV = -CNV;
20941 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
20942 else CNV = CNV - Offset1;
20944 SDLoc
DL(OtherUse);
20951 DAG.
getNode(Opcode,
DL, OtherUse->getValueType(0), NewOp1, NewOp2);
20953 deleteAndRecombine(OtherUse);
20958 deleteAndRecombine(Ptr.
getNode());
20959 AddToWorklist(
Result.getNode());
20991 bool IsLoad =
true;
20992 bool IsMasked =
false;
20995 IsMasked, OtherPtr, TLI)) {
21015 bool &IsMasked,
SDValue &Ptr,
21021 IsMasked, Ptr, TLI) ||
21033 if (U.getResNo() != Ptr.
getResNo())
21059bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *
N) {
21063 bool IsLoad =
true;
21064 bool IsMasked =
false;
21085 ++PostIndexedNodes;
21089 WorklistRemover DeadNodes(*
this);
21098 deleteAndRecombine(
N);
21102 Result.getValue(IsLoad ? 1 : 0));
21103 deleteAndRecombine(
Op);
21108SDValue DAGCombiner::SplitIndexingFromLoad(LoadSDNode *LD) {
21119 "Cannot split out indexing using opaque target constants");
21135bool DAGCombiner::getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val) {
21137 EVT STMemType =
ST->getMemoryVT();
21138 if (STType == STMemType)
21159bool DAGCombiner::extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val) {
21160 EVT LDMemType =
LD->getMemoryVT();
21161 EVT LDType =
LD->getValueType(0);
21163 "Attempting to extend value of non-matching type");
21164 if (LDType == LDMemType)
21167 switch (
LD->getExtensionType()) {
21185StoreSDNode *DAGCombiner::getUniqueStoreFeeding(LoadSDNode *LD,
21193 StoreSDNode *
ST =
nullptr;
21203 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
21206 GatherAllAliases(Store, Chain, Aliases);
21207 if (Aliases.
empty() ||
21208 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
21217 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
21225SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
21231 StoreSDNode *
ST = getUniqueStoreFeeding(LD,
Offset);
21233 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
21236 EVT LDType =
LD->getValueType(0);
21237 EVT LDMemType =
LD->getMemoryVT();
21238 EVT STMemType =
ST->getMemoryVT();
21239 EVT STType =
ST->getValue().getValueType();
21263 int64_t OrigOffset =
Offset;
21276 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
21282 if (
LD->isIndexed()) {
21287 SDValue Idx = SplitIndexingFromLoad(LD);
21289 return CombineTo(LD,
Ops, 3);
21291 return CombineTo(LD, Val, Chain);
21298 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
21301 return ReplaceLd(LD,
ST->getValue(), Chain);
21309 SDLoc(ST), STType);
21311 return ReplaceLd(LD, Val, Chain);
21330 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
21335 if (!getTruncatedStoreValue(ST, Val))
21339 if (STMemType != LDMemType) {
21340 if (LdMemSize == StMemSize) {
21346 *
LD->getMemOperand()))
21366 unsigned ExtIdx = 0;
21382 if (!extendLoadedValueToExtension(LD, Val))
21384 return ReplaceLd(LD, Val, Chain);
21389 deleteAndRecombine(Val.
getNode());
21393SDValue DAGCombiner::visitLOAD(SDNode *
N) {
21402 if (
LD->isSimple()) {
21403 if (
N->getValueType(1) == MVT::Other) {
21405 if (!
N->hasAnyUseOfValue(0)) {
21413 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
21415 WorklistRemover DeadNodes(*
this);
21417 AddUsersToWorklist(Chain.
getNode());
21418 if (
N->use_empty())
21419 deleteAndRecombine(
N);
21425 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
21433 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
21436 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
21437 Index = SplitIndexingFromLoad(LD);
21440 AddUsersToWorklist(
N);
21444 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
21445 dbgs() <<
" and 2 other values\n");
21446 WorklistRemover DeadNodes(*
this);
21450 deleteAndRecombine(
N);
21458 if (
auto V = ForwardStoreValueToDirectLoad(LD))
21465 if (*Alignment >
LD->getAlign() &&
21466 isAligned(*Alignment,
LD->getSrcValueOffset())) {
21468 LD->getExtensionType(), SDLoc(
N),
LD->getValueType(0), Chain, Ptr,
21469 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
21470 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
21478 if (
LD->isUnindexed()) {
21480 SDValue BetterChain = FindBetterChain(LD, Chain);
21483 if (Chain != BetterChain) {
21488 ReplLoad = DAG.
getLoad(
N->getValueType(0), SDLoc(LD),
21489 BetterChain, Ptr,
LD->getMemOperand());
21491 ReplLoad = DAG.
getExtLoad(
LD->getExtensionType(), SDLoc(LD),
21492 LD->getValueType(0),
21493 BetterChain, Ptr,
LD->getMemoryVT(),
21494 LD->getMemOperand());
21499 MVT::Other, Chain, ReplLoad.
getValue(1));
21502 return CombineTo(
N, ReplLoad.
getValue(0), Token);
21507 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
21512 if (SliceUpLoad(
N))
21532struct LoadedSlice {
21536 bool ForCodeSize =
false;
21539 unsigned Loads = 0;
21540 unsigned Truncates = 0;
21541 unsigned CrossRegisterBanksCopies = 0;
21542 unsigned ZExts = 0;
21543 unsigned Shift = 0;
21545 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
21548 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
21549 : ForCodeSize(ForCodeSize), Loads(1) {
21550 EVT TruncType =
LS.Inst->getValueType(0);
21551 EVT LoadedType =
LS.getLoadedType();
21552 if (TruncType != LoadedType &&
21553 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
21561 void addSliceGain(
const LoadedSlice &LS) {
21563 const TargetLowering &TLI =
LS.DAG->getTargetLoweringInfo();
21570 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
21571 ++CrossRegisterBanksCopies;
21575 Loads +=
RHS.Loads;
21576 Truncates +=
RHS.Truncates;
21577 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
21578 ZExts +=
RHS.ZExts;
21579 Shift +=
RHS.Shift;
21584 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
21585 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
21586 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
21594 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
21595 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
21598 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
21599 return ExpensiveOpsLHS < ExpensiveOpsRHS;
21600 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
21601 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
21616 LoadSDNode *Origin;
21625 LoadedSlice(SDNode *Inst =
nullptr, LoadSDNode *Origin =
nullptr,
21626 unsigned Shift = 0, SelectionDAG *DAG =
nullptr)
21627 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
21632 APInt getUsedBits()
const {
21637 assert(Origin &&
"No original load to compare against.");
21639 assert(Inst &&
"This slice is not bound to an instruction");
21641 "Extracted slice is bigger than the whole type!");
21643 UsedBits.setAllBits();
21644 UsedBits = UsedBits.zext(
BitWidth);
21645 UsedBits <<= Shift;
21650 unsigned getLoadedSize()
const {
21651 unsigned SliceSize = getUsedBits().popcount();
21652 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
21653 return SliceSize / 8;
21658 EVT getLoadedType()
const {
21659 assert(DAG &&
"Missing context");
21667 uint64_t
Offset = getOffsetFromBase();
21674 bool isLegal()
const {
21676 if (!Origin || !Inst || !DAG)
21686 EVT SliceType = getLoadedType();
21697 if (PtrType == MVT::Untyped || PtrType.
isExtended())
21710 if (TruncateType != SliceType &&
21720 uint64_t getOffsetFromBase()
const {
21721 assert(DAG &&
"Missing context.");
21723 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
21724 uint64_t
Offset = Shift / 8;
21727 "The size of the original loaded type is not a multiple of a"
21732 "Invalid shift amount for given loaded size");
21745 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
21749 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
21750 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
21753 EVT ArithType =
BaseAddr.getValueType();
21760 EVT SliceType = getLoadedType();
21770 if (SliceType != FinalType)
21780 bool canMergeExpensiveCrossRegisterBankCopy()
const {
21786 assert(DAG &&
"Missing context");
21788 EVT ResVT =
User->getValueType(0);
21789 const TargetRegisterClass *ResRC =
21791 const TargetRegisterClass *ArgRC =
21793 User->getOperand(0)->isDivergent());
21802 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
21807 unsigned IsFast = 0;
21848 const LoadedSlice &Second) {
21850 "Unable to match different memory origins.");
21852 assert((UsedBits & Second.getUsedBits()) == 0 &&
21853 "Slices are not supposed to overlap.");
21854 UsedBits |= Second.getUsedBits();
21863 LoadedSlice::Cost &GlobalLSCost) {
21864 unsigned NumberOfSlices = LoadedSlices.
size();
21866 if (NumberOfSlices < 2)
21871 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
21872 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
21873 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
21875 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
21878 const LoadedSlice *
First =
nullptr;
21879 const LoadedSlice *Second =
nullptr;
21880 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
21883 Second = &LoadedSlices[CurrSlice];
21890 EVT LoadedType =
First->getLoadedType();
21893 if (LoadedType != Second->getLoadedType())
21897 Align RequiredAlignment;
21898 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
21904 if (
First->getAlign() < RequiredAlignment)
21911 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
21912 --GlobalLSCost.Loads;
21929 const APInt &UsedBits,
bool ForCodeSize) {
21930 unsigned NumberOfSlices = LoadedSlices.
size();
21932 return NumberOfSlices > 1;
21935 if (NumberOfSlices != 2)
21943 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
21945 OrigCost.Loads = 1;
21946 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
21947 const LoadedSlice &LS = LoadedSlices[CurrSlice];
21949 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
21950 GlobalSlicingCost += SliceCost;
21954 OrigCost.addSliceGain(LS);
21959 return OrigCost > GlobalSlicingCost;
21968bool DAGCombiner::SliceUpLoad(SDNode *
N) {
21974 !
LD->getValueType(0).isInteger())
21980 if (
LD->getValueType(0).isScalableVector())
21985 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
21992 for (SDUse &U :
LD->uses()) {
21994 if (
U.getResNo() != 0)
21997 SDNode *
User =
U.getUser();
21998 unsigned Shift = 0;
22003 Shift =
User->getConstantOperandVal(1);
22016 unsigned Width =
User->getValueSizeInBits(0);
22021 LoadedSlice
LS(User, LD, Shift, &DAG);
22022 APInt CurrentUsedBits =
LS.getUsedBits();
22025 if ((CurrentUsedBits & UsedBits) != 0)
22028 UsedBits |= CurrentUsedBits;
22049 for (
const LoadedSlice &LS : LoadedSlices) {
22051 CombineTo(
LS.Inst, SliceInst,
true);
22055 "It takes more than a zext to get to the loaded slice!!");
22062 AddToWorklist(Chain.
getNode());
22069static std::pair<unsigned, unsigned>
22071 std::pair<unsigned, unsigned> Result(0, 0);
22081 if (LD->getBasePtr() != Ptr)
return Result;
22084 if (V.getValueType() != MVT::i16 &&
22085 V.getValueType() != MVT::i32 &&
22086 V.getValueType() != MVT::i64)
22094 if (NotMaskLZ & 7)
return Result;
22096 if (NotMaskTZ & 7)
return Result;
22097 if (NotMaskLZ == 64)
return Result;
22104 if (V.getValueType() != MVT::i64 && NotMaskLZ)
22105 NotMaskLZ -= 64-V.getValueSizeInBits();
22107 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
22108 switch (MaskedBytes) {
22112 default:
return Result;
22117 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
22124 SDValue(LD, 1).hasOneUse()) {
22126 if (!LD->isOperandOf(Chain.
getNode()))
22131 Result.first = MaskedBytes;
22132 Result.second = NotMaskTZ/8;
22143 unsigned NumBytes = MaskInfo.first;
22144 unsigned ByteShift = MaskInfo.second;
22150 ByteShift*8, (ByteShift+NumBytes)*8);
22159 bool UseTruncStore;
22160 if (DC->isTypeLegal(VT))
22161 UseTruncStore =
false;
22165 UseTruncStore =
true;
22191 StOffset = ByteShift;
22219SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *
N) {
22221 if (!
ST->isSimple())
22227 EVT VT =
Value.getValueType();
22229 if (
ST->isTruncatingStore() || VT.
isVector())
22235 !
Value.hasOneUse())
22244 std::pair<unsigned, unsigned> MaskedLoad;
22246 if (MaskedLoad.first)
22248 Value.getOperand(1), ST,
this))
22253 if (MaskedLoad.first)
22255 Value.getOperand(0), ST,
this))
22269 if (
LD->getBasePtr() != Ptr ||
22270 LD->getPointerInfo().getAddrSpace() !=
22271 ST->getPointerInfo().getAddrSpace())
22280 if (Imm == 0 ||
Imm.isAllOnes())
22285 unsigned BitsPerByteMask = 7u;
22286 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
22287 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
22315 unsigned ShAmt = 0;
22316 uint64_t PtrOff = 0;
22317 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
22321 if (ShAmt + NewBW < MSB)
22326 ? VTStoreSize - NewBW - ShAmt
22328 PtrOff = PtrAdjustmentInBits / 8;
22331 unsigned IsFast = 0;
22334 LD->getAddressSpace(), NewAlign,
22335 LD->getMemOperand()->getFlags(), &IsFast) &&
22340 if (ShAmt + NewBW > VTStoreSize)
22343 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
22350 DAG.
getLoad(NewVT, SDLoc(N0),
LD->getChain(), NewPtr,
22351 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
22352 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
22356 DAG.
getStore(Chain, SDLoc(
N), NewVal, NewPtr,
22357 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
22359 AddToWorklist(NewPtr.
getNode());
22360 AddToWorklist(NewLD.
getNode());
22361 AddToWorklist(NewVal.
getNode());
22362 WorklistRemover DeadNodes(*
this);
22374SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *
N) {
22378 Value.hasOneUse()) {
22380 EVT VT =
LD->getMemoryVT();
22382 LD->isNonTemporal() ||
ST->isNonTemporal() ||
22383 LD->getPointerInfo().getAddrSpace() != 0 ||
22384 ST->getPointerInfo().getAddrSpace() != 0)
22394 unsigned FastLD = 0, FastST = 0;
22401 *
LD->getMemOperand(), &FastLD) ||
22403 *
ST->getMemOperand(), &FastST) ||
22404 !FastLD || !FastST)
22408 LD->getBasePtr(),
LD->getMemOperand());
22411 ST->getBasePtr(),
ST->getMemOperand());
22413 AddToWorklist(NewLD.
getNode());
22414 AddToWorklist(NewST.
getNode());
22415 WorklistRemover DeadNodes(*
this);
22437bool DAGCombiner::isMulAddWithConstProfitable(SDNode *MulNode,
SDValue AddNode,
22446 for (SDNode *User : ConstNode->
users()) {
22447 if (User == MulNode)
22455 if (
User->getOperand(0) == ConstNode)
22456 OtherOp =
User->getOperand(1).getNode();
22458 OtherOp =
User->getOperand(0).getNode();
22470 if (OtherOp == MulVar)
22497SDValue DAGCombiner::getMergeStoreChains(SmallVectorImpl<MemOpLink> &StoreNodes,
22498 unsigned NumStores) {
22500 SmallPtrSet<const SDNode *, 8> Visited;
22501 SDLoc StoreDL(StoreNodes[0].MemNode);
22503 for (
unsigned i = 0; i < NumStores; ++i) {
22504 Visited.
insert(StoreNodes[i].MemNode);
22508 for (
unsigned i = 0; i < NumStores; ++i) {
22509 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
22510 Chains.
push_back(StoreNodes[i].MemNode->getChain());
22513 assert(!Chains.
empty() &&
"Chain should have generated a chain");
22518 const Value *UnderlyingObj =
nullptr;
22519 for (
const auto &MemOp : StoreNodes) {
22520 const MachineMemOperand *MMO = MemOp.MemNode->getMemOperand();
22531 if (UnderlyingObj && UnderlyingObj != Obj)
22534 if (!UnderlyingObj)
22535 UnderlyingObj =
Obj;
22541bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
22542 SmallVectorImpl<MemOpLink> &StoreNodes, EVT MemVT,
unsigned NumStores,
22543 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
22548 assert((!UseTrunc || !UseVector) &&
22549 "This optimization cannot emit a vector truncating store");
22552 SDLoc
DL(StoreNodes[0].MemNode);
22555 unsigned SizeInBits = NumStores * ElementSizeBits;
22558 std::optional<MachineMemOperand::Flags>
Flags;
22560 for (
unsigned I = 0;
I != NumStores; ++
I) {
22576 unsigned Elts = NumStores * NumMemElts;
22584 if (IsConstantSrc) {
22586 for (
unsigned I = 0;
I != NumStores; ++
I) {
22605 .zextOrTrunc(ElementSizeBits),
22606 SDLoc(
C), IntMemVT);
22615 DL, StoreTy, BuildVector);
22618 for (
unsigned i = 0; i < NumStores; ++i) {
22642 Val = DAG.
getNode(OpC, SDLoc(Val), MemVT, Vec, Idx);
22645 Ops.push_back(Val);
22656 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
22658 APInt StoreInt(SizeInBits, 0);
22663 for (
unsigned i = 0; i < NumStores; ++i) {
22664 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
22669 StoreInt <<= ElementSizeBits;
22671 StoreInt |=
C->getAPIntValue()
22672 .zextOrTrunc(ElementSizeBits)
22673 .zextOrTrunc(SizeInBits);
22675 StoreInt |=
C->getValueAPF()
22677 .zextOrTrunc(ElementSizeBits)
22678 .zextOrTrunc(SizeInBits);
22695 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22696 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
22697 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
22711 FirstInChain->
getAlign(), *Flags, AAInfo);
22713 EVT LegalizedStoredValTy =
22715 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
22718 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
22719 LegalizedStoredValTy);
22721 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
22730 for (
unsigned i = 0; i < NumStores; ++i)
22731 CombineTo(StoreNodes[i].MemNode, NewStore);
22733 AddToWorklist(NewChain.
getNode());
22738DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
22739 SmallVectorImpl<MemOpLink> &StoreNodes) {
22744 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
22748 StoreSource StoreSrc = getStoreSource(Val);
22749 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
22753 BaseIndexOffset LBasePtr;
22755 if (StoreSrc == StoreSource::Load) {
22760 if (MemVT != LoadVT)
22770 auto CandidateMatch = [&](StoreSDNode *
Other, BaseIndexOffset &Ptr,
22771 int64_t &
Offset) ->
bool {
22774 if (!
Other->isSimple() ||
Other->isIndexed())
22784 :
Other->getMemoryVT() != MemVT;
22785 switch (StoreSrc) {
22786 case StoreSource::Load: {
22794 if (LoadVT != OtherLd->getMemoryVT())
22797 if (!OtherLd->hasNUsesOfValue(1, 0))
22801 if (!OtherLd->isSimple() || OtherLd->isIndexed())
22809 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
22813 case StoreSource::Constant:
22816 if (getStoreSource(OtherBC) != StoreSource::Constant)
22819 case StoreSource::Extract:
22821 if (
Other->isTruncatingStore())
22854 if (ChainsWithoutMergeableStores.
contains(RootNode))
22859 auto OverLimitInDependenceCheck = [&](SDNode *StoreNode,
22860 SDNode *RootNode) ->
bool {
22861 auto RootCount = StoreRootCountMap.
find(StoreNode);
22862 return RootCount != StoreRootCountMap.
end() &&
22863 RootCount->second.first == RootNode &&
22867 auto TryToAddCandidate = [&](SDUse &
Use) {
22869 if (
Use.getOperandNo() != 0)
22872 BaseIndexOffset Ptr;
22874 if (CandidateMatch(OtherStore, Ptr, PtrDiff) &&
22875 !OverLimitInDependenceCheck(OtherStore, RootNode))
22876 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
22880 unsigned NumNodesExplored = 0;
22881 const unsigned MaxSearchNodes = 1024;
22883 RootNode = Ldn->getChain().getNode();
22885 if (ChainsWithoutMergeableStores.
contains(RootNode))
22888 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
22889 SDNode *
User =
I->getUser();
22891 for (SDUse &U2 :
User->uses())
22892 TryToAddCandidate(U2);
22896 TryToAddCandidate(*
I);
22901 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
22902 TryToAddCandidate(*
I);
22911bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
22912 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumStores,
22913 SDNode *RootNode) {
22919 SmallPtrSet<const SDNode *, 32> Visited;
22927 while (!Worklist.
empty()) {
22929 if (!Visited.
insert(
N).second)
22938 unsigned int Max = 1024 + Visited.
size();
22940 for (
unsigned i = 0; i < NumStores; ++i) {
22941 SDNode *
N = StoreNodes[i].MemNode;
22962 for (
unsigned i = 0; i < NumStores; ++i)
22968 if (Visited.
size() >= Max) {
22969 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
22970 if (RootCount.first == RootNode)
22971 RootCount.second++;
22973 RootCount = {RootNode, 1};
22980bool DAGCombiner::hasCallInLdStChain(StoreSDNode *St, LoadSDNode *Ld) {
22981 SmallPtrSet<const SDNode *, 32> Visited;
22985 while (!Worklist.
empty()) {
22987 if (!Visited.
insert(Node).second ||
Node->getNumOperands() == 0)
22990 switch (
Node->getOpcode()) {
23003 assert(
Node->getOperand(0).getValueType() == MVT::Other &&
23004 "Invalid chain type");
23013DAGCombiner::getConsecutiveStores(SmallVectorImpl<MemOpLink> &StoreNodes,
23014 int64_t ElementSizeBytes)
const {
23017 size_t StartIdx = 0;
23018 while ((StartIdx + 1 < StoreNodes.
size()) &&
23019 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
23020 StoreNodes[StartIdx + 1].OffsetFromBase)
23024 if (StartIdx + 1 >= StoreNodes.
size())
23033 unsigned NumConsecutiveStores = 1;
23034 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
23037 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
23038 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
23039 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
23041 NumConsecutiveStores = i + 1;
23043 if (NumConsecutiveStores > 1)
23044 return NumConsecutiveStores;
23052bool DAGCombiner::tryStoreMergeOfConstants(
23053 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
23054 EVT MemVT, SDNode *RootNode,
bool AllowVectors) {
23059 bool MadeChange =
false;
23062 while (NumConsecutiveStores >= 2) {
23063 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
23066 unsigned LastLegalType = 1;
23067 unsigned LastLegalVectorType = 1;
23068 bool LastIntegerTrunc =
false;
23069 bool NonZero =
false;
23070 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
23071 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
23074 bool IsElementZero =
false;
23076 IsElementZero =
C->isZero();
23078 IsElementZero =
C->getConstantFPValue()->isNullValue();
23080 IsElementZero =
true;
23081 if (IsElementZero) {
23082 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
23083 FirstZeroAfterNonZero = i;
23085 NonZero |= !IsElementZero;
23088 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
23090 unsigned IsFast = 0;
23102 LastIntegerTrunc =
false;
23103 LastLegalType = i + 1;
23107 EVT LegalizedStoredValTy =
23110 FirstStoreAlign, FirstStoreAS) &&
23116 LastIntegerTrunc =
true;
23117 LastLegalType = i + 1;
23126 unsigned Elts = (i + 1) * NumMemElts;
23133 LastLegalVectorType = i + 1;
23137 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
23138 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
23139 bool UseTrunc = LastIntegerTrunc && !UseVector;
23151 unsigned NumSkip = 1;
23152 while ((NumSkip < NumConsecutiveStores) &&
23153 (NumSkip < FirstZeroAfterNonZero) &&
23154 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
23158 NumConsecutiveStores -= NumSkip;
23163 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
23166 NumConsecutiveStores -= NumElem;
23170 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
23172 UseVector, UseTrunc);
23176 NumConsecutiveStores -= NumElem;
23181bool DAGCombiner::tryStoreMergeOfExtracts(
23182 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
23183 EVT MemVT, SDNode *RootNode) {
23187 bool MadeChange =
false;
23190 while (NumConsecutiveStores >= 2) {
23191 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
23194 unsigned NumStoresToMerge = 1;
23195 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
23197 unsigned Elts = (i + 1) * NumMemElts;
23199 unsigned IsFast = 0;
23210 NumStoresToMerge = i + 1;
23215 if (NumStoresToMerge < 2) {
23222 unsigned NumSkip = 1;
23223 while ((NumSkip < NumConsecutiveStores) &&
23224 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
23228 NumConsecutiveStores -= NumSkip;
23233 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
23236 StoreNodes.
begin() + NumStoresToMerge);
23237 NumConsecutiveStores -= NumStoresToMerge;
23241 MadeChange |= mergeStoresOfConstantsOrVecElts(
23242 StoreNodes, MemVT, NumStoresToMerge,
false,
23245 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
23246 NumConsecutiveStores -= NumStoresToMerge;
23251bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl<MemOpLink> &StoreNodes,
23252 unsigned NumConsecutiveStores, EVT MemVT,
23253 SDNode *RootNode,
bool AllowVectors,
23254 bool IsNonTemporalStore,
23255 bool IsNonTemporalLoad) {
23260 bool MadeChange =
false;
23267 BaseIndexOffset LdBasePtr;
23269 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
23276 int64_t LdOffset = 0;
23277 if (LdBasePtr.
getBase().getNode()) {
23279 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
23287 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
23290 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
23291 Align RequiredAlignment;
23292 bool NeedRotate =
false;
23293 if (LoadNodes.
size() == 2) {
23297 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
23303 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
23304 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
23306 if (Offset0 - Offset1 == ElementSizeBytes &&
23313 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
23322 unsigned LastConsecutiveLoad = 1;
23325 unsigned LastLegalVectorType = 1;
23326 unsigned LastLegalIntegerType = 1;
23327 bool isDereferenceable =
true;
23328 bool DoIntegerTruncate =
false;
23329 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
23331 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
23333 if (LoadNodes[i].MemNode->getChain() != LoadChain)
23336 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
23337 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
23339 LastConsecutiveLoad = i;
23341 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
23342 isDereferenceable =
false;
23345 unsigned Elts = (i + 1) * NumMemElts;
23352 unsigned IsFastSt = 0;
23353 unsigned IsFastLd = 0;
23367 LastLegalVectorType = i + 1;
23371 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
23382 LastLegalIntegerType = i + 1;
23383 DoIntegerTruncate =
false;
23389 FirstStoreAlign, FirstStoreAS) &&
23407 LastLegalIntegerType = i + 1;
23408 DoIntegerTruncate =
true;
23416 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
23417 unsigned LastLegalType =
23418 std::max(LastLegalVectorType, LastLegalIntegerType);
23422 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
23423 NumElem = std::min(LastLegalType, NumElem);
23434 unsigned NumSkip = 1;
23435 while ((NumSkip < LoadNodes.
size()) &&
23436 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
23437 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
23441 NumConsecutiveStores -= NumSkip;
23446 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
23450 NumConsecutiveStores -= NumElem;
23459 unsigned Elts = NumElem * NumMemElts;
23462 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
23472 NumConsecutiveStores -= NumElem;
23476 SDLoc LoadDL(LoadNodes[0].MemNode);
23477 SDLoc StoreDL(StoreNodes[0].MemNode);
23482 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
23483 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
23484 AddToWorklist(NewStoreChain.
getNode());
23489 if (IsNonTemporalLoad)
23501 if (UseVectorTy || !DoIntegerTruncate) {
23507 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
23509 "Unexpected type for rotate-able load pair");
23516 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
23518 : MachinePointerInfo(FirstStoreAS),
23519 FirstStoreAlign, StMMOFlags);
23526 FirstLoadAlign, LdMMOFlags);
23528 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
23530 : MachinePointerInfo(FirstStoreAS),
23531 JointMemOpVT, FirstInChain->
getAlign(),
23536 for (
unsigned i = 0; i < NumElem; ++i) {
23544 for (
unsigned i = 0; i < NumElem; ++i) {
23545 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
23546 CombineTo(StoreNodes[i].MemNode, NewStore);
23548 recursivelyDeleteUnusedNodes(Val.
getNode());
23554 NumConsecutiveStores -= NumElem;
23559bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
23576 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
23582 const StoreSource StoreSrc = getStoreSource(StoredVal);
23583 if (StoreSrc == StoreSource::Unknown)
23588 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
23591 if (StoreNodes.
size() < 2)
23597 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
23601 Attribute::NoImplicitFloat);
23603 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
23613 bool MadeChange =
false;
23614 while (StoreNodes.
size() > 1) {
23615 unsigned NumConsecutiveStores =
23616 getConsecutiveStores(StoreNodes, ElementSizeBytes);
23618 if (NumConsecutiveStores == 0)
23622 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
23623 switch (StoreSrc) {
23624 case StoreSource::Constant:
23625 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
23626 MemVT, RootNode, AllowVectors);
23629 case StoreSource::Extract:
23630 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
23634 case StoreSource::Load:
23635 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
23636 MemVT, RootNode, AllowVectors,
23637 IsNonTemporalStore, IsNonTemporalLoad);
23647 ChainsWithoutMergeableStores.
insert(RootNode);
23652SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST,
SDValue BetterChain) {
23657 if (
ST->isTruncatingStore()) {
23659 ST->getBasePtr(),
ST->getMemoryVT(),
23660 ST->getMemOperand());
23662 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
23663 ST->getMemOperand());
23668 MVT::Other,
ST->getChain(), ReplStore);
23671 AddToWorklist(Token.
getNode());
23674 return CombineTo(ST, Token,
false);
23677SDValue DAGCombiner::replaceStoreOfFPConstant(StoreSDNode *ST) {
23708 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
23711 bitcastToAPInt().getZExtValue(), SDLoc(CFP),
23713 return DAG.
getStore(Chain,
DL, Tmp, Ptr,
ST->getMemOperand());
23718 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
23722 getZExtValue(), SDLoc(CFP), MVT::i64);
23724 Ptr,
ST->getMemOperand());
23739 AAMDNodes AAInfo =
ST->getAAInfo();
23742 ST->getBaseAlign(), MMOFlags, AAInfo);
23745 ST->getPointerInfo().getWithOffset(4),
23746 ST->getBaseAlign(), MMOFlags, AAInfo);
23760SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
23775 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
23789 ST->getAlign(),
ST->getMemOperand()->getFlags(),
23794 MachinePointerInfo PointerInfo(
ST->getAddressSpace());
23800 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
23802 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
23810 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
23811 ST->getMemOperand()->getFlags());
23814SDValue DAGCombiner::visitATOMIC_STORE(SDNode *
N) {
23818 EVT MemVT =
ST->getMemoryVT();
23837 SDValue StoredVal = Store->getValue();
23838 SDValue StorePtr = Store->getBasePtr();
23839 SDValue StoreOffset = Store->getOffset();
23840 EVT VT = Store->getMemoryVT();
23847 unsigned AddrSpace = Store->getAddressSpace();
23848 Align Alignment = Store->getAlign();
23855 SDValue Mask, OtherVec, LoadCh;
23874 Load->getAddressSpace() != AddrSpace)
23877 if (!Store->getChain().reachesChainWithoutSideEffects(LoadCh))
23881 Mask = DAG.
getNOT(Dl, Mask, Mask.getValueType());
23883 return DAG.
getMaskedStore(Store->getChain(), Dl, OtherVec, StorePtr,
23884 StoreOffset, Mask, VT, Store->getMemOperand(),
23885 Store->getAddressingMode());
23888SDValue DAGCombiner::visitSTORE(SDNode *
N) {
23897 ST->isUnindexed()) {
23898 EVT SVT =
Value.getOperand(0).getValueType();
23905 if (((!LegalOperations &&
ST->isSimple()) ||
23908 DAG, *
ST->getMemOperand())) {
23910 ST->getMemOperand());
23915 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
23922 if (*Alignment >
ST->getAlign() &&
23923 isAligned(*Alignment,
ST->getSrcValueOffset())) {
23926 ST->getMemoryVT(), *Alignment,
23927 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
23937 if (
SDValue NewST = TransformFPLoadStorePair(
N))
23941 if (
SDValue Store = mergeTruncStores(ST))
23944 if (
ST->isUnindexed()) {
23947 if (findBetterNeighborChains(ST)) {
23952 Chain =
ST->getChain();
23956 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
23957 Value.getValueType().isInteger() &&
23964 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
23967 ST->getMemOperand());
23969 APInt TruncDemandedBits =
23971 ST->getMemoryVT().getScalarSizeInBits());
23975 AddToWorklist(
Value.getNode());
23991 return DAG.
getTruncStore(Chain, SDLoc(
N), Shorter, Ptr,
ST->getMemoryVT(),
23992 ST->getMemOperand());
23997 if (!Cst->isOpaque()) {
23998 const APInt &CValue = Cst->getAPIntValue();
23999 APInt NewVal = CValue & TruncDemandedBits;
24000 if (NewVal != CValue) {
24004 ST->getMemoryVT(),
ST->getMemOperand());
24018 ST->isUnindexed() &&
ST->isSimple() &&
24029 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
24034 if (
ST->isUnindexed() &&
ST->isSimple() &&
24035 ST1->isUnindexed() && ST1->isSimple()) {
24037 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
24038 ST->getAddressSpace() == ST1->getAddressSpace()) {
24045 !ST1->getBasePtr().isUndef() &&
24046 ST->getAddressSpace() == ST1->getAddressSpace()) {
24051 if (
ST->getMemoryVT().isScalableVector() ||
24052 ST1->getMemoryVT().isScalableVector()) {
24053 if (ST1->getBasePtr() == Ptr &&
24055 ST->getMemoryVT().getStoreSize())) {
24056 CombineTo(ST1, ST1->getChain());
24066 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
24068 ST1->getMemoryVT().getFixedSizeInBits())) {
24069 CombineTo(ST1, ST1->getChain());
24081 Value->hasOneUse() &&
ST->isUnindexed() &&
24083 ST->getMemoryVT(),
ST->getAlign(),
24084 ST->getAddressSpace(), LegalOperations)) {
24086 ST->getMemoryVT(),
ST->getMemOperand());
24097 bool Changed = mergeConsecutiveStores(ST);
24107 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
24116 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
24124 return MaskedStore;
24126 return ReduceLoadOpStoreWidth(
N);
24129SDValue DAGCombiner::visitLIFETIME_END(SDNode *
N) {
24131 const BaseIndexOffset LifetimeEndBase(
N->getOperand(1),
SDValue(), 0,
false);
24135 while (!Chains.
empty()) {
24154 if (!
ST->isSimple() ||
ST->isIndexed())
24156 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
24165 if (LifetimeEndBase.contains(
24169 dbgs() <<
"\nwithin LIFETIME_END of : ";
24170 LifetimeEndBase.dump();
dbgs() <<
"\n");
24171 CombineTo(ST,
ST->getChain());
24208SDValue DAGCombiner::splitMergedValStore(StoreSDNode *ST) {
24214 if (!
ST->isSimple())
24247 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
24248 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
24250 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
24251 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
24257 ?
Lo.getOperand(0).getValueType()
24258 :
Lo.getValueType();
24260 ?
Hi.getOperand(0).getValueType()
24261 :
Hi.getValueType();
24267 AAMDNodes AAInfo =
ST->getAAInfo();
24278 ST->getBaseAlign(), MMOFlags, AAInfo);
24283 St0,
DL,
Hi, Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
24284 ST->getBaseAlign(), MMOFlags, AAInfo);
24295 unsigned InsIndex) {
24304 int ElementOffset = -1;
24313 while (!ArgWorkList.
empty()) {
24316 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
24318 if (ArgVal == InsertVal0) {
24319 ElementOffset = ArgOffset;
24325 int CurrentArgOffset =
24329 CurrentArgOffset -= Step;
24335 assert(CurrentArgOffset == ArgOffset);
24341 if (ElementOffset == -1) {
24342 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
24344 ElementOffset = Mask.size();
24348 NewMask.
assign(Mask.begin(), Mask.end());
24350 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
24351 "NewMask[InsIndex] is out of bound");
24360SDValue DAGCombiner::mergeInsertEltWithShuffle(SDNode *
N,
unsigned InsIndex) {
24362 "Expected extract_vector_elt");
24363 SDValue InsertVal =
N->getOperand(1);
24374 SmallVector<int, 16> NewMask(Mask);
24379 return LegalShuffle;
24390SDValue DAGCombiner::combineInsertEltToShuffle(SDNode *
N,
unsigned InsIndex) {
24392 "Expected extract_vector_elt");
24410 if (NumSrcElts == 1)
24413 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
24420 SmallVector<int, 16>
Mask(NumMaskVals);
24421 for (
unsigned i = 0; i != NumMaskVals; ++i) {
24422 if (i / NumSrcElts == InsIndex)
24423 Mask[i] = (i % NumSrcElts) + NumMaskVals;
24438 ConcatOps[0] = SubVec;
24444 AddToWorklist(PaddedSubV.
getNode());
24445 AddToWorklist(DestVecBC.
getNode());
24446 AddToWorklist(Shuf.
getNode());
24453SDValue DAGCombiner::combineInsertEltToLoad(SDNode *
N,
unsigned InsIndex) {
24454 EVT VT =
N->getValueType(0);
24466 return InsIndex == P.index() || P.value() < 0 ||
24467 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
24468 (InsIndex == VT.getVectorNumElements() - 1 &&
24469 P.value() == (int)P.index() + 1);
24475 unsigned Extend = 0;
24479 Extend =
Scalar.getOpcode();
24497 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
24498 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
24501 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
24506 if (InsIndex == 0) {
24517 unsigned IsFast = 0;
24521 NewAlign,
VecLoad->getMemOperand()->getFlags(),
24528 SDValue Ptr = ScalarLoad->getBasePtr();
24532 MachinePointerInfo PtrInfo =
24533 InsIndex == 0 ? ScalarLoad->getPointerInfo()
24534 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
24537 ScalarLoad->getChain(), Ptr, PtrInfo, NewAlign);
24543SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *
N) {
24580 if (!IsByteSized) {
24587 auto IsTypeDefaultHandled = [
this](EVT VT) {
24595 if (IsTypeDefaultHandled(OldVT) && IsTypeDefaultHandled(VT)) {
24604 unsigned NumDynamic = 1;
24616 if (NumDynamic > 1) {
24632 PtrInfo, SmallestAlign);
24656 DAG.
getLoad(VT,
DL, Store, StackPtr, PtrInfo, SmallestAlign);
24671 unsigned Elt = IndexC->getZExtValue();
24674 if (NumElts == 1) {
24692 if (Elt < OtherElt) {
24696 AddToWorklist(NewOp.
getNode());
24702 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
24705 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
24708 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
24719 auto AddBuildVectorOp = [&](SmallVectorImpl<SDValue> &
Ops,
SDValue Elt,
24724 EVT EltVT = Elt.getValueType();
24725 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
24732 auto CanonicalizeBuildVector = [&](SmallVectorImpl<SDValue> &
Ops,
24733 bool FreezeUndef =
false) {
24734 assert(
Ops.size() == NumElts &&
"Unexpected vector size");
24750 for (
SDValue CurVec = InVec; CurVec;) {
24752 if (CurVec.isUndef())
24753 return CanonicalizeBuildVector(
Ops);
24757 return CanonicalizeBuildVector(
Ops,
true);
24761 for (
unsigned I = 0;
I != NumElts; ++
I)
24762 AddBuildVectorOp(
Ops, CurVec.getOperand(
I),
I);
24763 return CanonicalizeBuildVector(
Ops);
24768 AddBuildVectorOp(
Ops, CurVec.getOperand(0), 0);
24769 return CanonicalizeBuildVector(
Ops);
24775 if (CurIdx->getAPIntValue().ult(NumElts)) {
24776 unsigned Idx = CurIdx->getZExtValue();
24777 AddBuildVectorOp(
Ops, CurVec.getOperand(1), Idx);
24781 return CanonicalizeBuildVector(
Ops);
24783 CurVec = CurVec->getOperand(0);
24795 bool Merged =
true;
24799 SmallVector<int, 16> NewMask;
24804 Mask = std::move(NewMask);
24813 if (!LegalOperations) {
24826 unsigned MaskOpcode) {
24828 for (
unsigned I = 0;
I != NumElts; ++
I) {
24836 CurVec = DAG.
getFreeze(CurVec, InsertedEltMask,
24838 return DAG.
getNode(MaskOpcode,
DL, VT, CurVec,
24858 for (
unsigned I = 0;
I != NumElts; ++
I)
24865 for (
unsigned I = 0;
I != NumElts; ++
I)
24869 return CanonicalizeBuildVector(
Ops);
24879 const SDLoc &
DL,
bool LegalTypes) {
24908 if (!IsExtractFree(Op0) && !IsExtractFree(Op1))
24922 if (ResVT != MVT::i1 &&
24947bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
24969 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
24973 EVT ScalarVT =
N->getValueType(0);
24989 Entry(Entry &&) =
default;
24990 Entry(SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
24991 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
24994 Entry(
const Entry &) =
delete;
24995 Entry &operator=(
const Entry &) =
delete;
24996 Entry &operator=(Entry &&) =
delete;
25002 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
25005 while (!Worklist.
empty()) {
25012 bool ProducerIsLeaf =
false;
25014 for (SDNode *User :
E.Producer->users()) {
25015 switch (
User->getOpcode()) {
25023 User->getValueSizeInBits(0));
25030 User->getOperand(0).getNode() ==
E.Producer && ShAmtC) {
25033 unsigned ShAmt = ShAmtC->getZExtValue();
25034 Worklist.
emplace_back(User,
E.BitPos + ShAmt,
E.NumBits - ShAmt);
25041 ProducerIsLeaf =
true;
25049 if (ProducerIsLeaf)
25053 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
25056 if (NewVecEltBitWidth == VecEltBitWidth)
25066 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &
E) {
25067 return (
unsigned)
E.NumBits == NewVecEltBitWidth &&
25068 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
25069 E.BitPos % NewVecEltBitWidth == 0;
25081 if (LegalOperations &&
25087 for (
const Entry &
E : Leafs) {
25088 SDLoc
DL(
E.Producer);
25089 unsigned NewIndex =
E.BitPos / NewVecEltBitWidth;
25091 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
25094 CombineTo(
E.Producer, V);
25100SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *
N) {
25103 EVT ScalarVT =
N->getValueType(0);
25116 AddUsersToWorklist(VecOp.
getNode());
25151 "BUILD_VECTOR used for scalable vectors");
25152 unsigned IndexVal =
25160 if (ScalarVT == InEltVT)
25200 unsigned ExtractIndex = IndexC->getZExtValue();
25202 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
25215 EVT XVT =
X.getValueType();
25217 "Extract element and scalar to vector can't change element type "
25218 "from FP to integer.");
25219 unsigned XBitWidth =
X.getValueSizeInBits();
25220 unsigned Scale = XBitWidth / VecEltBitWidth;
25221 BCTruncElt = IsLE ? 0 : Scale - 1;
25226 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
25227 assert(XBitWidth % VecEltBitWidth == 0 &&
25228 "Scalar bitwidth must be a multiple of vector element bitwidth");
25230 if (ExtractIndex != BCTruncElt) {
25231 unsigned ShiftIndex =
25232 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
25252 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
25260 if (OrigElt < (
int)NumElts) {
25264 OrigElt -= NumElts;
25285 if (!LegalOperations ||
25297 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
25298 Use->getOperand(0) == VecOp &&
25299 isa<ConstantSDNode>(Use->getOperand(1));
25302 for (SDNode *User : VecOp->
users()) {
25304 if (CstElt->getAPIntValue().ult(NumElts))
25305 DemandedElts.
setBit(CstElt->getZExtValue());
25324 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
25330 bool BCNumEltsChanged =
false;
25345 BCNumEltsChanged =
true;
25351 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
25355 if (VecLoad &&
VecLoad->isSimple()) {
25357 ScalarVT, SDLoc(
N), VecVT, Index, VecLoad, DAG)) {
25366 if (!LegalOperations || !IndexC)
25372 int Elt = IndexC->getZExtValue();
25373 LoadSDNode *LN0 =
nullptr;
25396 if (BCNumEltsChanged)
25400 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
25405 if (!VecOp.hasOneUse())
25408 VecOp = VecOp.getOperand(0);
25411 LN0 = cast<LoadSDNode>(VecOp);
25412 Elt = (Idx < (int)NumElts) ? Idx : Idx - (int)NumElts;
25413 Index = DAG.getConstant(Elt, DL, Index.getValueType());
25431 Index.getValueType());
25459SDValue DAGCombiner::reduceBuildVecExtToExtBuildVec(SDNode *
N) {
25469 unsigned NumInScalars =
N->getNumOperands();
25471 EVT VT =
N->getValueType(0);
25478 EVT SourceType = MVT::Other;
25479 bool AllAnyExt =
true;
25481 for (
unsigned i = 0; i != NumInScalars; ++i) {
25484 if (
In.isUndef())
continue;
25490 if (!ZeroExt && !AnyExt) {
25491 SourceType = MVT::Other;
25496 EVT InTy =
In.getOperand(0).getValueType();
25499 if (SourceType == MVT::Other)
25502 else if (InTy != SourceType) {
25504 SourceType = MVT::Other;
25509 AllAnyExt &= AnyExt;
25517 SourceType != MVT::Other &&
25533 assert(ElemRatio > 1 &&
"Invalid element size ratio");
25541 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
25545 Cast.
isUndef()) &&
"Invalid cast opcode");
25551 unsigned Index = isLE ? (i * ElemRatio) :
25552 (i * ElemRatio + (ElemRatio - 1));
25554 assert(Index <
Ops.size() &&
"Invalid index");
25561 "Invalid vector size");
25581SDValue DAGCombiner::reduceBuildVecTruncToBitCast(SDNode *
N) {
25584 EVT VT =
N->getValueType(0);
25602 unsigned NumInScalars =
N->getNumOperands();
25605 auto PeekThroughBitcast = [](
SDValue Op) {
25607 return Op.getOperand(0);
25613 for (
unsigned i = 0; i != NumInScalars; ++i) {
25614 SDValue In = PeekThroughBitcast(
N->getOperand(i));
25616 if (
In.isUndef())
continue;
25621 In = PeekThroughBitcast(
In.getOperand(0));
25632 SDValue part = PeekThroughBitcast(
In.getOperand(0));
25636 }
else if (Src != part) {
25641 SDValue ShiftAmtVal =
In.getOperand(1);
25645 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
25648 if (ShiftAmt != i * ScalarTypeBitsize)
25654 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
25660SDValue DAGCombiner::createBuildVecShuffle(
const SDLoc &
DL, SDNode *
N,
25661 ArrayRef<int> VectorMask,
25663 unsigned LeftIdx,
bool DidSplitVec) {
25664 EVT VT =
N->getValueType(0);
25669 unsigned ShuffleNumElems = NumElems;
25679 assert(InVT2Size <= InVT1Size &&
25680 "Inputs must be sorted to be in non-increasing vector size order.");
25684 if (InVT1 != VT || InVT2 != VT) {
25685 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
25688 unsigned NumConcats = VTSize / InVT1Size;
25689 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
25691 ConcatOps[0] = VecIn1;
25692 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getPOISON(InVT1);
25695 }
else if (InVT1Size == VTSize * 2) {
25707 Vec2Offset = NumElems;
25709 assert(InVT2Size <= InVT1Size &&
25710 "Second input is not going to be larger than the first one.");
25716 if (LegalOperations &&
25723 if (InVT1 != InVT2) {
25728 ShuffleNumElems = NumElems * 2;
25730 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
25732 ConcatOps[0] = VecIn2;
25734 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
25742 assert(InVT2Size <= InVT1Size &&
25743 "Second input is not going to be larger than the first one.");
25752 if (InVT1 != InVT2) {
25755 ShuffleNumElems = InVT1Size / VTSize * NumElems;
25766 SmallVector<int, 8>
Mask(ShuffleNumElems, -1);
25771 for (
unsigned i = 0; i != NumElems; ++i) {
25772 if (VectorMask[i] <= 0)
25775 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
25776 if (VectorMask[i] == (
int)LeftIdx) {
25777 Mask[i] = ExtIndex;
25778 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
25779 Mask[i] = Vec2Offset + ExtIndex;
25792 if (ShuffleNumElems > NumElems)
25805 for (
int i = 0; i != NumBVOps; ++i) {
25837 if (DestSize % SrcSize != 0 ||
25843 int ZextRatio = DestSize / SrcSize;
25844 int NumMaskElts = NumBVOps * ZextRatio;
25846 for (
int i = 0; i != NumMaskElts; ++i) {
25847 if (i / ZextRatio == ZextElt) {
25868 ZeroVec, ShufMask, DAG);
25875template <
typename R,
typename T>
25879 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
25880 return std::distance(
Range.begin(),
I);
25886SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *
N) {
25888 EVT VT =
N->getValueType(0);
25901 bool UsesZeroVector =
false;
25902 unsigned NumElems =
N->getNumOperands();
25910 SmallVector<int, 8> VectorMask(NumElems, -1);
25916 unsigned OneConstExtractIndex = ~0
u;
25919 unsigned NumExtracts = 0;
25921 for (
unsigned i = 0; i != NumElems; ++i) {
25931 UsesZeroVector =
true;
25941 SDValue ExtractedFromVec =
Op.getOperand(0);
25948 if (ExtractIdx->getAsAPIntVal().uge(
25957 OneConstExtractIndex = ExtractIdx->getZExtValue();
25965 Idx = VecIn.
size();
25969 VectorMask[i] = Idx;
25973 if (VecIn.
size() < 2)
25980 bool DidSplitVec =
false;
25981 if (VecIn.
size() == 2) {
25990 if (NumExtracts == 1 &&
25996 unsigned MaxIndex = 0;
25997 unsigned NearestPow2 = 0;
26000 SmallVector<unsigned, 8> IndexVec(NumElems, 0);
26002 for (
unsigned i = 0; i < NumElems; i++) {
26003 if (VectorMask[i] <= 0)
26005 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
26006 IndexVec[i] =
Index;
26007 MaxIndex = std::max(MaxIndex, Index);
26011 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
26012 NumElems * 2 < NearestPow2) {
26013 unsigned SplitSize = NearestPow2 / 2;
26026 DidSplitVec =
true;
26028 for (
unsigned i = 0; i < NumElems; i++) {
26029 if (VectorMask[i] <= 0)
26031 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
26044 b.getValueType().getVectorNumElements();
26049 for (
int &SourceVectorIndex : VectorMask) {
26050 if (SourceVectorIndex <= 0)
26052 unsigned Idx =
getFirstIndexOf(SortedVecIn, VecIn[SourceVectorIndex]);
26053 assert(Idx > 0 && Idx < SortedVecIn.size() &&
26054 VecIn[SourceVectorIndex] == SortedVecIn[Idx] &&
"Remapping failure");
26055 SourceVectorIndex = Idx;
26058 VecIn = std::move(SortedVecIn);
26076 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
26077 unsigned LeftIdx = 2 *
In + 1;
26078 SDValue VecLeft = VecIn[LeftIdx];
26080 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
26082 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
26083 VecRight, LeftIdx, DidSplitVec))
26091 if (UsesZeroVector)
26096 if (Shuffles.
size() == 1)
26097 return Shuffles[0];
26100 for (
int &Vec : VectorMask)
26102 Vec = Shuffles.
size() - 1;
26104 Vec = (Vec - 1) / 2;
26118 if (Shuffles.
size() % 2)
26121 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
26126 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
26129 SmallVector<int, 8>
Mask(NumElems, -1);
26131 ArrayRef<int> LMask;
26133 L.use_empty() &&
L.getOperand(1).isUndef() &&
26134 L.getOperand(0).getValueType() ==
L.getValueType();
26135 if (IsLeftShuffle) {
26137 L =
L.getOperand(0);
26140 ArrayRef<int> RMask;
26142 R.use_empty() &&
R.getOperand(1).isUndef() &&
26143 R.getOperand(0).getValueType() ==
R.getValueType();
26144 if (IsRightShuffle) {
26146 R =
R.getOperand(0);
26148 for (
unsigned I = 0;
I != NumElems; ++
I) {
26149 if (VectorMask[
I] ==
Left) {
26153 VectorMask[
I] =
In;
26154 }
else if (VectorMask[
I] ==
Right) {
26156 if (IsRightShuffle)
26157 Mask[
I] = RMask[
I] + NumElems;
26158 VectorMask[
I] =
In;
26165 return Shuffles[0];
26171SDValue DAGCombiner::convertBuildVecExtToExt(SDNode *
N) {
26172 if (LegalOperations)
26175 EVT VT =
N->getValueType(0);
26177 bool FoundZeroExtend =
false;
26178 bool FoundSignExtend =
false;
26180 auto checkElem = [&](
SDValue Op) -> int64_t {
26181 unsigned Opc =
Op.getOpcode();
26189 return C->getZExtValue();
26197 int64_t
Offset = checkElem(Op0);
26201 unsigned NumElems =
N->getNumOperands();
26203 EVT InSVT =
In.getValueType().getScalarType();
26211 for (
unsigned i = 1; i != NumElems; ++i) {
26212 if ((
Offset + i) != checkElem(
N->getOperand(i)))
26217 if (FoundZeroExtend && FoundSignExtend)
26221 if (FoundSignExtend)
26223 else if (FoundZeroExtend)
26229 return DAG.
getNode(ExtOpc,
DL, VT, In);
26239SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(SDNode *
N) {
26248 EVT VT =
N->getValueType(0);
26249 EVT OpVT =
N->getOperand(0).getValueType();
26263 unsigned ActiveBits = 0;
26269 unsigned OpActiveBits =
26270 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
26271 if (OpActiveBits == 0) {
26272 KnownZeroOps.setBit(
I.index());
26280 if (
I.index() != 0)
26286 unsigned CurrActiveBits =
26287 Op.getOperand(0).getValueSizeInBits().getFixedValue();
26288 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
26289 ActiveBits = CurrActiveBits;
26291 if (2 * ActiveBits > EltBitwidth)
26296 if (ActiveBits == 0)
26301 EVT NewScalarIntVT, NewIntVT;
26302 std::optional<unsigned> Factor;
26307 assert(2 * ActiveBits <= EltBitwidth &&
26308 "We know that half or less bits of the element are active.");
26309 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
26310 if (EltBitwidth % Scale != 0)
26312 unsigned ChunkBitwidth = EltBitwidth / Scale;
26313 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
26316 Scale *
N->getNumOperands());
26318 (LegalOperations &&
26336 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
26337 unsigned SrcOpIdx =
I.index();
26338 if (KnownZeroOps[SrcOpIdx]) {
26339 NewOps.
append(*Factor, ZeroOp);
26345 NewOps.
append(*Factor - 1, ZeroOp);
26353SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *
N) {
26354 EVT VT =
N->getValueType(0);
26368 if (!LegalOperations) {
26374 EVT SrcVT =
Splat.getValueType();
26390 if (!LegalTypes && (
N->getNumOperands() > 1)) {
26392 auto checkElem = [&](
SDValue Op) -> uint64_t {
26400 int Offset = checkElem(Op0);
26401 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
26402 if (
Offset + i != checkElem(
N->getOperand(i))) {
26412 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
26418 if (
SDValue V = convertBuildVecExtToExt(
N))
26421 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
26424 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
26427 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
26430 if (
SDValue V = reduceBuildVecToShuffle(
N))
26437 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
26446 EVT OpVT =
N->getOperand(0).getValueType();
26453 EVT VT =
N->getValueType(0);
26462 !
Op.getOperand(0).getValueType().isVector())
26463 Ops.push_back(
Op.getOperand(0));
26464 else if (
Op.isUndef())
26471 EVT LastOpVT =
Ops.back().getValueType();
26473 AnyFPVT = LastOpVT;
26481 if (AnyFPVT !=
EVT()) {
26484 if (
Op.getValueType() == SVT)
26503 EVT VT =
N->getValueType(0);
26513 if (!FirstConcat) {
26514 SubVT =
Op.getOperand(0).getValueType();
26520 if (SubVT !=
Op.getOperand(0).getValueType())
26523 assert(FirstConcat &&
"Concat of all-undefs found");
26527 if (
Op.isUndef()) {
26531 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
26541 EVT VT =
N->getValueType(0);
26542 EVT OpVT =
N->getOperand(0).getValueType();
26558 if (
Op.isUndef()) {
26559 Mask.append((
unsigned)NumOpElts, -1);
26568 int ExtIdx =
Op.getConstantOperandVal(1);
26577 Mask.append((
unsigned)NumOpElts, -1);
26588 if (0 == (NumExtElts % NumElts))
26589 ExtIdx /= (NumExtElts / NumElts);
26590 else if (0 == (NumElts % NumExtElts))
26591 ExtIdx *= (NumElts / NumExtElts);
26596 if (SV0.
isUndef() || SV0 == ExtVec) {
26598 for (
int i = 0; i != NumOpElts; ++i)
26599 Mask.push_back(i + ExtIdx);
26600 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
26602 for (
int i = 0; i != NumOpElts; ++i)
26603 Mask.push_back(i + ExtIdx + NumElts);
26615 unsigned CastOpcode =
N->getOperand(0).getOpcode();
26616 switch (CastOpcode) {
26632 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
26640 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
26641 Op.getOperand(0).getValueType() != SrcVT)
26649 EVT VT =
N->getValueType(0);
26653 switch (CastOpcode) {
26673 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
26681 bool LegalOperations) {
26682 EVT VT =
N->getValueType(0);
26683 EVT OpVT =
N->getOperand(0).getValueType();
26688 if (
N->getNumOperands() != 2)
26693 (LegalOperations &&
26705 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
26708 return !Op.isUndef() &&
26709 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
26730 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
26731 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
26738 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
26739 if (
Op.getNode() == SVN) {
26760 std::array<SDValue, 2> ShufOps;
26761 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
26763 SDValue &NewShufOp = std::get<1>(
I);
26769 ShufOpParts[0] = ShufOp;
26780 bool LegalOperations) {
26781 EVT VT =
N->getValueType(0);
26799SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *
N) {
26801 if (
N->getNumOperands() == 1)
26805 EVT VT =
N->getValueType(0);
26811 [](
const SDValue &
Op) { return Op.isUndef(); })) {
26813 assert(
In.getValueType().isVector() &&
"Must concat vectors");
26823 !(LegalDAG &&
In.getValueType().isScalableVector())) {
26824 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
26836 EVT SVT =
Scalar.getValueType().getVectorElementType();
26837 if (SVT ==
Scalar.getOperand(0).getValueType())
26842 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
26853 EVT SclTy =
Scalar.getValueType();
26863 if (VNTNumElms < 2)
26879 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
26890 bool FoundMinVT =
false;
26893 EVT OpSVT =
Op.getOperand(0).getValueType();
26894 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
26897 assert(FoundMinVT &&
"Concat vector type mismatch");
26901 EVT OpVT =
Op.getValueType();
26910 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
26912 for (
unsigned i = 0; i != NumElts; ++i)
26920 "Concat vector type mismatch");
26947 N, DAG, TLI, LegalTypes, LegalOperations))
26957 unsigned PartNumElem =
26958 N->getOperand(0).getValueType().getVectorMinNumElements();
26960 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
26971 if (SingleSource.
getNode()) {
26972 if (
Op.getOperand(0) != SingleSource)
26975 SingleSource =
Op.getOperand(0);
26985 unsigned IdentityIndex = i * PartNumElem;
26986 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
26991 return SingleSource;
26996SDValue DAGCombiner::visitVECTOR_INTERLEAVE(SDNode *
N) {
27007 Ops.append(
N->op_values().begin(),
N->op_values().end());
27008 return CombineTo(
N, &
Ops);
27015 V.getOperand(1).getValueType() == SubVT &&
27016 V.getConstantOperandAPInt(2) == Index) {
27017 return V.getOperand(1);
27020 V.getOperand(0).getValueType() == SubVT &&
27023 return V.getOperand(SubIdx);
27029 unsigned Index,
const SDLoc &
DL,
27031 bool LegalOperations) {
27033 unsigned BinOpcode = BinOp.
getOpcode();
27039 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
27050 if (!Sub0 || !Sub1)
27063 bool LegalOperations) {
27084 if (
C &&
C->getValueAPF().isNegZero())
27097 "Extract index is not a multiple of the vector length.");
27102 if (WideWidth % NarrowWidth != 0)
27107 unsigned NarrowingRatio = WideWidth / NarrowWidth;
27109 if (WideNumElts % NarrowingRatio != 0)
27114 WideNumElts / NarrowingRatio);
27126 BinOp.
hasOneUse() && Src->hasOneUse()) {
27140 if (NarrowingRatio != 2)
27155 return V.getOperand(ConcatOpNum);
27161 if (SubVecL || SubVecR) {
27213 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
27214 "multiple of the result's element count");
27218 std::optional<unsigned> ByteOffset;
27220 ByteOffset =
Offset.getFixedValue();
27232 if (
Offset.isScalable()) {
27256 bool LegalOperations) {
27258 EVT WideVT = Src.getValueType();
27264 if (!WideShuffleVector)
27268 if (!WideShuffleVector->hasOneUse())
27273 if (LegalOperations &&
27278 assert((Index % NumEltsExtracted) == 0 &&
27279 "Extract index is not a multiple of the output vector length.");
27284 NewMask.
reserve(NumEltsExtracted);
27286 DemandedSubvectors;
27289 for (
int M : WideShuffleVector->getMask().slice(Index, NumEltsExtracted)) {
27290 assert((M >= -1) && (M < (2 * WideNumElts)) &&
27291 "Out-of-bounds shuffle mask?");
27300 int WideShufOpIdx = M / WideNumElts;
27302 int OpEltIdx = M % WideNumElts;
27304 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
27305 "Shuffle mask vector decomposition failure.");
27308 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
27310 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
27312 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
27313 "Shuffle mask subvector decomposition failure.");
27315 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
27316 WideShufOpIdx * WideNumElts) == M &&
27317 "Shuffle mask full decomposition failure.");
27319 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
27321 if (
Op.isUndef()) {
27327 const std::pair<SDValue, int> DemandedSubvector =
27328 std::make_pair(
Op, OpSubvecIdx);
27330 if (DemandedSubvectors.insert(DemandedSubvector)) {
27331 if (DemandedSubvectors.size() > 2)
27334 int Index = NumEltsExtracted * OpSubvecIdx;
27342 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
27343 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
27345 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
27348 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
27349 assert(DemandedSubvectors.size() <= 2 &&
27350 "Should have ended up demanding at most two subvectors.");
27353 if (DemandedSubvectors.empty())
27359 any_of(NewMask, [](
int M) {
return M < 0; }))
27360 for (
auto &DemandedSubvector : DemandedSubvectors)
27361 if (DemandedSubvector.second != 0)
27373 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
27374 &DemandedSubvector : DemandedSubvectors) {
27376 int Index = NumEltsExtracted * DemandedSubvector.second;
27379 DemandedSubvector.first, IndexC));
27382 "Should end up with either one or two ops");
27385 if (NewOps.
size() == 1)
27391SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *
N) {
27392 EVT NVT =
N->getValueType(0);
27394 uint64_t ExtIdx =
N->getConstantOperandVal(1);
27412 V.getConstantOperandVal(1)) &&
27432 unsigned InsIdx =
V.getConstantOperandVal(2);
27434 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
27437 V.getValueType().isFixedLengthVector())
27445 V.getOperand(0).getValueType().isVector() &&
27450 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
27451 if ((SrcNumElts % DestNumElts) == 0) {
27452 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
27459 V.getOperand(0), NewIndex);
27463 if ((DestNumElts % SrcNumElts) == 0) {
27464 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
27466 ElementCount NewExtEC =
27469 if ((ExtIdx % DestSrcRatio) == 0) {
27470 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
27477 V.getOperand(0), NewIndex);
27485 V.getOperand(0), NewIndex);
27495 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
27497 "Concat and extract subvector do not change element type");
27500 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
27506 return V.getOperand(ConcatOpIdx);
27514 ConcatSrcNumElts % ExtNumElts == 0) {
27515 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
27516 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
27517 "Trying to extract from >1 concat operand?");
27518 assert(NewExtIdx % ExtNumElts == 0 &&
27519 "Extract index is not a multiple of the input vector length.");
27522 V.getOperand(ConcatOpIdx), NewIndexC);
27527 NVT, V, ExtIdx,
DL, DAG, LegalOperations))
27538 EVT InVT =
V.getValueType();
27542 if (ExtractSize % EltSize == 0) {
27543 unsigned NumElems = ExtractSize / EltSize;
27546 NumElems == 1 ? EltVT
27554 if (NumElems == 1) {
27555 SDValue Src =
V->getOperand(IdxVal);
27556 if (EltVT != Src.getValueType())
27572 EVT SmallVT =
V.getOperand(1).getValueType();
27573 if (NVT.
bitsEq(SmallVT)) {
27579 uint64_t InsIdx =
V.getConstantOperandVal(2);
27587 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
27595 if (!
V.getValueType().isScalableVector() &&
27597 return Use->getOpcode() == ISD::EXTRACT_SUBVECTOR &&
27598 Use->getOperand(0) == V;
27600 unsigned NumElts =
V.getValueType().getVectorNumElements();
27602 for (SDNode *User :
V->users()) {
27603 unsigned ExtIdx =
User->getConstantOperandVal(1);
27604 unsigned NumSubElts =
User->getValueType(0).getVectorNumElements();
27605 DemandedElts.
setBits(ExtIdx, ExtIdx + NumSubElts);
27639 unsigned HalfNumElts = NumElts / 2;
27642 for (
unsigned i = 0; i != NumElts; ++i) {
27646 if ((Mask[i] % NumElts) >= HalfNumElts)
27648 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (int)HalfNumElts;
27649 if (i < HalfNumElts)
27652 Mask1[i - HalfNumElts] = M;
27675 EVT VT =
N->getValueType(0);
27686 unsigned NumConcats = NumElts / NumElemsPerConcat;
27688 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
27693 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
27694 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
27698 Mask.slice(0, NumElemsPerConcat));
27705 for (
unsigned I = 0;
I != NumConcats; ++
I) {
27706 unsigned Begin =
I * NumElemsPerConcat;
27707 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
27716 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
27717 if (IsUndefMaskElt(SubMask[i]))
27719 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
27721 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
27726 assert(0 <=
OpIdx &&
"Unknown concat_vectors op");
27780 bool IsSplat =
false;
27784 if (
SDValue Splat0 = BV0->getSplatValue())
27785 IsSplat = (Splat0 == BV1->getSplatValue());
27789 for (
int M : SVN->
getMask()) {
27792 int Idx = M < (int)NumElts ? M : M - NumElts;
27793 SDValue &S = (M < (int)NumElts ? N0 : N1);
27810 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
27821 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
27837 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)> Match,
27839 bool LegalOperations) {
27844 return std::nullopt;
27852 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
27854 if (NumElts % Scale != 0)
27868 return std::nullopt;
27877 bool LegalOperations) {
27887 Mask = SVN->
getMask()](
unsigned Scale) {
27888 for (
unsigned i = 0; i != NumElts; ++i) {
27891 if ((i % Scale) == 0 && Mask[i] == (
int)(i / Scale))
27903 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
27915 bool LegalOperations) {
27916 bool LegalTypes =
true;
27928 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
27929 for (
int &Indice : Mask) {
27933 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
27934 Fn(Indice,
OpIdx, OpEltIdx);
27939 std::array<APInt, 2> OpsDemandedElts;
27940 for (
APInt &OpDemandedElts : OpsDemandedElts)
27942 ForEachDecomposedIndice(
27943 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
27944 OpsDemandedElts[
OpIdx].setBit(OpEltIdx);
27948 std::array<APInt, 2> OpsKnownZeroElts;
27949 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
27957 bool HadZeroableElts =
false;
27958 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
27959 int &Indice,
int OpIdx,
int OpEltIdx) {
27960 if (OpsKnownZeroElts[
OpIdx][OpEltIdx]) {
27962 HadZeroableElts =
true;
27970 if (!HadZeroableElts)
27978 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
27979 int Prescale = Mask.size() / ScaledMask.
size();
27981 NumElts = ScaledMask.
size();
27982 EltSizeInBits *= Prescale;
27994 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
27995 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
27996 "Unexpected mask scaling factor.");
27998 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
27999 SrcElt != NumSrcElts; ++SrcElt) {
28002 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
28003 Mask = Mask.drop_front(MaskChunk.
size());
28006 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
28011 [](
int Indice) { return Indice == -2; }))
28014 assert(Mask.empty() &&
"Did not process the whole mask?");
28019 for (
bool Commuted : {
false,
true}) {
28024 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
28060 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
28062 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
28067 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
28068 for (
unsigned i = 0; i != NumElts; ++i) {
28071 if ((i * Scale) < NumElts && Mask[i] == (
int)(i * Scale))
28081 if (EltSizeInBits != ExtSrcSizeInBits)
28088 if (isTruncate(ExtScale))
28111 APInt DemandedElts(NumElts, 0);
28112 for (
int Idx : Shuf->
getMask()) {
28115 assert((
unsigned)Idx < NumElts &&
"Out-of-bounds shuffle indice?");
28116 DemandedElts.
setBit(Idx);
28118 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
28123 std::optional<unsigned> MinNonUndefIdx;
28124 for (
int Idx : Shuf->
getMask()) {
28125 if (Idx < 0 || UndefElts[Idx])
28127 MinNonUndefIdx = std::min<unsigned>(Idx, MinNonUndefIdx.value_or(~0U));
28129 if (!MinNonUndefIdx)
28131 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
28133 for (
int &Idx : SplatMask) {
28138 Idx = UndefElts[Idx] ? -1 : *MinNonUndefIdx;
28140 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
28158 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
28176 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
28178 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
28179 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
28180 SplatMask[UserMask[i]] != -1)
28184 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
28190 for (
int Idx : ShufMask)
28191 NewMask.
push_back(Idx == -1 ? -1 : SplatMask[Idx]);
28203 bool LegalOperations) {
28220 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
28221 (LegalOperations &&
28224 int Factor = VTLanes / InLanes;
28252 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
28257 unsigned NumElts = OuterMask.
size();
28258 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
28260 int SplatIndex = -1;
28261 for (
unsigned i = 0; i != NumElts; ++i) {
28263 int OuterMaskElt = OuterMask[i];
28264 if (OuterMaskElt == -1)
28268 int InnerMaskElt = InnerMask[OuterMaskElt];
28269 if (InnerMaskElt == -1)
28273 if (SplatIndex == -1)
28274 SplatIndex = InnerMaskElt;
28277 if (SplatIndex != InnerMaskElt)
28280 CombinedMask[i] = InnerMaskElt;
28284 "Expected a splat mask");
28288 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
28293 InnerShuf->getOperand(1), CombinedMask);
28301 int MaskSize = Mask.size();
28302 int EltFromOp0 = -1;
28307 for (
int i = 0; i != MaskSize; ++i) {
28308 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
28310 if (EltFromOp0 != -1)
28313 }
else if (Mask[i] != i + MaskSize) {
28324SDValue DAGCombiner::replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf) {
28328 SmallVector<int, 16> CommutedMask(Mask);
28332 if (ShufOp0Index == -1) {
28336 if (ShufOp0Index == -1)
28340 Mask = CommutedMask;
28348 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)
Mask.size() &&
28349 "Shuffle mask value must be from operand 0");
28367 Op1, Elt, NewInsIndex);
28374 Mask[ShufOp0Index] == 0) {
28377 Op1, Elt, NewInsIndex);
28395 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
28399 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
28403 if (Mask0[Mask[i]] != Mask0[i])
28411SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *
N) {
28412 EVT VT =
N->getValueType(0);
28438 SmallVector<int, 8> NewMask;
28439 for (
unsigned i = 0; i != NumElts; ++i) {
28441 if (Idx >= (
int)NumElts) {
28451 if (
SDValue InsElt = replaceShuffleOfInsert(SVN))
28491 if (Idx->getAPIntValue() == SplatIndex)
28517 SDValue ConvInput =
V->getOperand(0);
28524 assert(
V->getNumOperands() == NumElts &&
28525 "BUILD_VECTOR has wrong number of operands");
28527 bool AllSame =
true;
28528 for (
unsigned i = 0; i != NumElts; ++i) {
28529 if (!
V->getOperand(i).isUndef()) {
28530 Base =
V->getOperand(i);
28535 if (!
Base.getNode())
28537 for (
unsigned i = 0; i != NumElts; ++i) {
28538 if (
V->getOperand(i) !=
Base) {
28549 SDValue Splatted =
V->getOperand(SplatIndex);
28553 for (
unsigned i = 0; i != NumElts; ++i) {
28562 if (
V->getValueType(0) != VT)
28601 int HalfNumElts = (int)NumElts / 2;
28602 SmallVector<int, 8> NewMask;
28603 for (
unsigned i = 0; i != NumElts; ++i) {
28605 if (Idx >= HalfNumElts) {
28606 assert(Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
28607 Idx -= HalfNumElts;
28628 EVT SubVT =
RHS.getOperand(0).getValueType();
28629 int NumSubVecs =
RHS.getNumOperands();
28631 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
28636 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
28641 SmallVector<int> InsertionMask(NumElts);
28642 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
28643 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
28645 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
28648 std::iota(InsertionMask.begin() + SubIdx,
28649 InsertionMask.begin() + SubIdx + NumSubElts,
28650 NumElts + (SubVec * NumSubElts));
28653 bool MatchingShuffle =
true;
28654 for (
int i = 0; i != (int)NumElts; ++i) {
28655 int ExpectIdx = InsertionMask[i];
28656 int ActualIdx =
Mask[i];
28657 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
28658 MatchingShuffle =
false;
28663 if (MatchingShuffle)
28672 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
28675 SmallVector<int> CommuteMask(Mask);
28677 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
28685 bool IsInLaneMask =
true;
28687 SmallVector<int, 16> ClearMask(NumElts, -1);
28690 for (
int I = 0;
I != (int)NumElts; ++
I) {
28694 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
28695 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
28697 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
28698 Demanded.
setBit(M % NumElts);
28702 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
28717 for (
int I = 0;
I != (int)NumElts; ++
I)
28719 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
28756 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
28767 SmallVector<int, 8> InnerMask;
28768 SmallVector<int, 8> OuterMask;
28773 SmallVector<int, 8> NewMask;
28774 for (
int M : OuterMask)
28775 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
28806 auto MergeInnerShuffle =
28807 [NumElts, &VT](
bool Commute, ShuffleVectorSDNode *SVN,
28808 ShuffleVectorSDNode *OtherSVN,
SDValue N1,
28810 SmallVectorImpl<int> &
Mask) ->
bool {
28813 if (OtherSVN->isSplat())
28819 for (
unsigned i = 0; i != NumElts; ++i) {
28820 int Idx = SVN->getMaskElt(i);
28823 Mask.push_back(Idx);
28828 Idx = (Idx < (int)NumElts) ? (Idx + NumElts) : (Idx - NumElts);
28831 if (Idx < (
int)NumElts) {
28834 Idx = OtherSVN->getMaskElt(Idx);
28837 Mask.push_back(Idx);
28840 CurrentVec = (Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
28849 Mask.push_back(-1);
28855 Idx = Idx % NumElts;
28856 if (!SV0.getNode() || SV0 == CurrentVec) {
28860 Mask.push_back(Idx);
28863 if (!SV1.getNode() || SV1 == CurrentVec) {
28867 Mask.push_back(Idx + NumElts);
28874 int InnerIdx = CurrentSVN->getMaskElt(Idx);
28875 if (InnerIdx < 0) {
28876 Mask.push_back(-1);
28879 SDValue InnerVec = (InnerIdx < (int)NumElts)
28880 ? CurrentSVN->getOperand(0)
28881 : CurrentSVN->getOperand(1);
28883 Mask.push_back(-1);
28886 InnerIdx %= NumElts;
28887 if (InnerVec == SV0) {
28888 Mask.push_back(InnerIdx);
28891 if (InnerVec == SV1) {
28892 Mask.push_back(InnerIdx + NumElts);
28911 if (TLI.isShuffleMaskLegal(Mask, VT))
28916 return TLI.isShuffleMaskLegal(Mask, VT);
28928 assert(N1->getOperand(0).getValueType() == VT &&
28929 "Shuffle types don't match");
28931 SDValue SV0 = N1->getOperand(0);
28932 SDValue SV1 = N1->getOperand(1);
28933 bool HasSameOp0 = N0 == SV0;
28934 bool IsSV1Undef = SV1.
isUndef();
28935 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
28956 for (
int i = 0; i != 2; ++i) {
28958 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
28962 assert(OtherSV->getOperand(0).getValueType() == VT &&
28963 "Shuffle types don't match");
28966 SmallVector<int, 4>
Mask;
28967 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
28985 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
28987 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode()) &&
28988 N0.
getResNo() == N1.getResNo()))) {
28993 SDValue Op11 = N1.isUndef() ? N1 : N1.getOperand(1);
29004 SmallVectorImpl<int> &
Mask,
bool LeftOp,
29006 SDValue InnerN = Commute ? N1 : N0;
29007 SDValue Op0 = LeftOp ? Op00 : Op01;
29008 SDValue Op1 = LeftOp ? Op10 : Op11;
29015 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
29017 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
29023 bool MergedLeft =
false;
29025 SmallVector<int, 4> LeftMask;
29026 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
29027 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
29030 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
29031 LeftSV0 = Op00, LeftSV1 = Op10;
29034 bool MergedRight =
false;
29036 SmallVector<int, 4> RightMask;
29037 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
29038 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
29039 MergedRight =
true;
29041 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
29042 RightSV0 = Op01, RightSV1 = Op11;
29045 if (MergedLeft || MergedRight) {
29049 LeftSV1 ? LeftSV1 : DAG.
getPOISON(VT), LeftMask);
29052 RightSV1 ? RightSV1 : DAG.
getPOISON(VT), RightMask);
29074SDValue DAGCombiner::visitSCALAR_TO_VECTOR(SDNode *
N) {
29075 EVT VT =
N->getValueType(0);
29085 unsigned Opcode =
Scalar.getOpcode();
29087 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
29088 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
29089 Scalar.getOperand(0).getValueType() == VecEltVT &&
29090 Scalar.getOperand(1).getValueType() == VecEltVT &&
29091 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
29092 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
29097 for (
int i : {0, 1}) {
29108 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
29123 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
29127 if (VecEltVT !=
Scalar.getValueType() &&
29141 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
29143 SmallVector<int, 8>
Mask(SrcNumElts, -1);
29144 Mask[0] = ExtIndexC->getZExtValue();
29145 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
29146 SrcVT, SDLoc(
N), SrcVec, DAG.
getPOISON(SrcVT), Mask, DAG);
29152 return LegalShuffle;
29155 if (VTNumElts != SrcNumElts) {
29167SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *
N) {
29168 EVT VT =
N->getValueType(0);
29172 uint64_t InsIdx =
N->getConstantOperandVal(2);
29196 InsIdx + SubVecNumElts);
29293 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
29305 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
29328 if (InsIdx < OtherIdx) {
29332 AddToWorklist(NewOp.
getNode());
29346 Ops[InsIdx / Factor] = N1;
29357SDValue DAGCombiner::visitFP_TO_FP16(SDNode *
N) {
29367SDValue DAGCombiner::visitFP16_TO_FP(SDNode *
N) {
29368 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
29369 auto Op =
N->getOpcode();
29371 "opcode should be FP16_TO_FP or BF16_TO_FP.");
29384 return CastEliminated;
29390 N->getValueType(0), {N0});
29394SDValue DAGCombiner::visitFP_TO_BF16(SDNode *
N) {
29404SDValue DAGCombiner::visitBF16_TO_FP(SDNode *
N) {
29406 return visitFP16_TO_FP(
N);
29409SDValue DAGCombiner::visitVECREDUCE(SDNode *
N) {
29412 unsigned Opcode =
N->getOpcode();
29430 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
29431 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
29433 return DAG.
getNode(NewOpcode, SDLoc(
N),
N->getValueType(0), N0);
29446 return DAG.
getNode(Opcode, SDLoc(
N),
N->getValueType(0), Subvec);
29465SDValue DAGCombiner::visitVP_FSUB(SDNode *
N) {
29466 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
29469 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
29470 AddToWorklist(Fused.getNode());
29476SDValue DAGCombiner::visitVPOp(SDNode *
N) {
29478 if (
N->getOpcode() == ISD::VP_GATHER)
29479 if (
SDValue SD = visitVPGATHER(
N))
29482 if (
N->getOpcode() == ISD::VP_SCATTER)
29483 if (
SDValue SD = visitVPSCATTER(
N))
29486 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
29487 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
29490 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
29491 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
29497 bool AreAllEltsDisabled =
false;
29501 AreAllEltsDisabled |=
29505 if (!AreAllEltsDisabled) {
29506 switch (
N->getOpcode()) {
29508 return visitVP_FADD(
N);
29510 return visitVP_FSUB(
N);
29512 return visitFMA<VPMatchContext>(
N);
29513 case ISD::VP_SELECT:
29514 return visitVP_SELECT(
N);
29516 return visitMUL<VPMatchContext>(
N);
29527 return DAG.
getUNDEF(
N->getValueType(0));
29532 if (MemSD->writeMem())
29533 return MemSD->getChain();
29534 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
29544SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *
N) {
29551 LoadSDNode *LdNode =
nullptr;
29552 for (
auto *U : Ptr->
users()) {
29556 if (LdNode && LdNode != Ld)
29569 StoreSDNode *StNode =
nullptr;
29570 for (SDUse &U : LdNode->
uses()) {
29571 if (
U.getResNo() == 0) {
29590 CombineTo(StNode, Res,
false);
29594SDValue DAGCombiner::visitSET_FPENV_MEM(SDNode *
N) {
29600 StoreSDNode *StNode =
nullptr;
29601 for (
auto *U : Ptr->
users()) {
29605 if (StNode && StNode != St)
29638SDValue DAGCombiner::XformToShuffleWithZero(SDNode *
N) {
29641 EVT VT =
N->getValueType(0);
29648 if (LegalOperations)
29654 EVT RVT =
RHS.getValueType();
29655 unsigned NumElts =
RHS.getNumOperands();
29660 auto BuildClearMask = [&](
int Split) {
29661 int NumSubElts = NumElts *
Split;
29664 SmallVector<int, 8> Indices;
29665 for (
int i = 0; i != NumSubElts; ++i) {
29666 int EltIdx = i /
Split;
29667 int SubIdx = i %
Split;
29683 Bits->extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
29685 *
Bits =
Bits->extractBits(NumSubBits, SubIdx * NumSubBits);
29687 if (
Bits->isAllOnes())
29689 else if (*Bits == 0)
29698 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
29712 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
29714 if (
SDValue S = BuildClearMask(Split))
29723 const SDLoc &
DL,
bool LegalTypes) {
29726 unsigned Opcode =
N->getOpcode();
29727 EVT VT =
N->getValueType(0);
29734 int Index0, Index1;
29741 if (!Src0 || !Src1 || Index0 != Index1 ||
29768 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
29783SDValue DAGCombiner::SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL) {
29784 EVT VT =
N->getValueType(0);
29785 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
29787 unsigned Opcode =
N->getOpcode();
29818SDValue DAGCombiner::SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL) {
29819 EVT VT =
N->getValueType(0);
29820 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
29824 unsigned Opcode =
N->getOpcode();
29825 SDNodeFlags
Flags =
N->getFlags();
29837 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
29838 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
29841 RHS.getOperand(0), Flags);
29853 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
29862 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
29878 LHS.getOperand(2) ==
RHS.getOperand(2) &&
29883 EVT NarrowVT =
X.getValueType();
29884 if (NarrowVT ==
Y.getValueType() &&
29886 LegalOperations)) {
29899 return Op.isUndef() ||
29900 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
29909 if (ConcatWithConstantOrUndef(
LHS) && ConcatWithConstantOrUndef(
RHS) &&
29911 EVT NarrowVT =
LHS.getOperand(0).getValueType();
29912 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
29914 unsigned NumOperands =
LHS.getNumOperands();
29916 for (
unsigned i = 0; i != NumOperands; ++i) {
29919 RHS.getOperand(i)));
29935 "First argument must be a SetCC node!");
29943 if (
SCC.getNode()) {
29950 SCC.getOperand(0),
SCC.getOperand(1),
29951 SCC.getOperand(4), Flags);
29952 AddToWorklist(
SETCC.getNode());
29953 return DAG.
getSelect(SDLoc(SCC),
SCC.getValueType(), SETCC,
29954 SCC.getOperand(2),
SCC.getOperand(3), Flags);
29967bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect,
SDValue LHS,
29977 const ConstantFPSDNode *
Zero =
nullptr;
29988 CmpLHS =
Cmp.getOperand(0);
29992 if (Zero &&
Zero->isZero() &&
29996 CombineTo(TheSelect, Sqrt);
30006 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
30019 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
30057 SmallPtrSet<const SDNode *, 32> Visited;
30063 Visited.
insert(TheSelect);
30127 MMOFlags &= ~MachineMemOperand::MOInvariant;
30129 MMOFlags &= ~MachineMemOperand::MODereferenceable;
30133 LLD->
getChain(), Addr, MachinePointerInfo(AddrSpace),
30134 Alignment, MMOFlags);
30141 MachinePointerInfo(AddrSpace), LLD->
getMemoryVT(), Alignment,
30146 CombineTo(TheSelect, Load);
30150 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
30151 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
30192 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
30193 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
30197 AddToWorklist(Shift.
getNode());
30199 if (XType.
bitsGT(AType)) {
30201 AddToWorklist(Shift.
getNode());
30205 Shift = DAG.
getNOT(
DL, Shift, AType);
30217 AddToWorklist(Shift.
getNode());
30219 if (XType.
bitsGT(AType)) {
30221 AddToWorklist(Shift.
getNode());
30225 Shift = DAG.
getNOT(
DL, Shift, AType);
30231SDValue DAGCombiner::foldSelectOfBinops(SDNode *
N) {
30285SDValue DAGCombiner::foldSignChangeInBitcast(SDNode *
N) {
30287 EVT VT =
N->getValueType(0);
30295 EVT IntVT =
Int.getValueType();
30309 SignMask = ~SignMask;
30315 SignMask = ~SignMask;
30320 AddToWorklist(
Int.getNode());
30328SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
30344 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
30345 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
30350 if (!TV->hasOneUse() && !FV->hasOneUse())
30354 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
30371 AddToWorklist(
Cond.getNode());
30373 AddToWorklist(CstOffset.
getNode());
30375 AddToWorklist(CPIdx.
getNode());
30385 bool NotExtCompare) {
30387 if (N2 == N3)
return N2;
30398 AddToWorklist(
SCC.getNode());
30402 return !(SCCC->isZero()) ? N2 : N3;
30407 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3, CC))
30410 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3, CC))
30423 if (ConstAndRHS && ConstAndRHS->getAPIntValue().isPowerOf2()) {
30425 const APInt &AndMask = ConstAndRHS->getAPIntValue();
30443 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
30444 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
30446 if ((Fold || Swap) &&
30459 if (NotExtCompare && N2C->isOne())
30468 SCC = DAG.
getSetCC(SDLoc(N0), MVT::i1, N0, N1, CC);
30472 AddToWorklist(
SCC.getNode());
30473 AddToWorklist(Temp.
getNode());
30478 unsigned ShCt = N2C->getAPIntValue().logBase2();
30509 N0 ==
Count.getOperand(0) &&
30516 N0 ==
Count.getOperand(0) &&
30525 if (!NotExtCompare && N1C && N2C && N3C &&
30526 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
30539 if (CC ==
ISD::SETGT && N1C && N2C && N3C && N1C->isAllOnes() &&
30540 N2C->isOne() && N3C->isAllOnes() &&
30555 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3, CC,
DL))
30584 const auto IsSrc = [&](
SDValue V) {
30595 while (!Worklist.
empty()) {
30597 if (!V.hasOneUse() && (Src && Src != V))
30600 if (V.getOpcode() ==
ISD::OR) {
30617 PartsMask |= (RootMask << ShiftAmtVal);
30622 PartsMask |= RootMask;
30640 bool foldBooleans) {
30641 TargetLowering::DAGCombinerInfo
30642 DagCombineInfo(DAG, Level,
false,
this);
30661SDValue DAGCombiner::BuildSDIV(SDNode *
N) {
30669 for (SDNode *
N : Built)
30679SDValue DAGCombiner::BuildSDIVPow2(SDNode *
N) {
30690 for (SDNode *
N : Built)
30702SDValue DAGCombiner::BuildUDIV(SDNode *
N) {
30710 for (SDNode *
N : Built)
30720SDValue DAGCombiner::BuildSREMPow2(SDNode *
N) {
30731 for (SDNode *
N : Built)
30751 bool AssumeNonZero) {
30754 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
30756 switch (V.getOpcode()) {
30759 V = V.getOperand(0);
30770 Op = PeekThroughCastsAndTrunc(
Op);
30776 if (
C->isZero() ||
C->isOpaque())
30779 if (
C->getAPIntValue().isPowerOf2()) {
30796 for (
const APInt &Pow2 : Pow2Constants)
30805 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
30810 ToCast = ToCast.getOperand(0);
30811 EVT CurVT = ToCast.getValueType();
30812 if (NewVT == CurVT)
30824 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
30827 Depth + 1, AssumeNonZero))
30829 CastToVT(VT,
Op.getOperand(1)));
30855 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
30864 bool KnownNonZero,
bool InexpensiveOnly,
30865 std::optional<EVT> OutVT) {
30866 EVT VT = OutVT ? *OutVT :
V.getValueType();
30867 SDValue InexpensiveLogBase2 =
30870 return InexpensiveLogBase2;
30887 SDNodeFlags Flags) {
30892 EVT VT =
Op.getValueType();
30900 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
30907 AddToWorklist(Est.getNode());
30915 for (
int i = 0; i < Iterations; ++i) {
30918 if (i == Iterations - 1) {
30920 AddToWorklist(MulEst.
getNode());
30924 AddToWorklist(NewEst.
getNode());
30927 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
30928 AddToWorklist(NewEst.
getNode());
30931 AddToWorklist(NewEst.
getNode());
30934 AddToWorklist(Est.getNode());
30939 AddToWorklist(Est.getNode());
30955 unsigned Iterations,
bool Reciprocal) {
30966 for (
unsigned i = 0; i < Iterations; ++i) {
30986 unsigned Iterations,
bool Reciprocal) {
30998 for (
unsigned i = 0; i < Iterations; ++i) {
31007 if (Reciprocal || (i + 1) < Iterations) {
31025 SDNodeFlags Flags) {
31030 EVT VT =
Op.getValueType();
31038 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
31045 bool UseOneConstNR =
false;
31049 AddToWorklist(Est.
getNode());
31051 if (Iterations > 0)
31052 Est = UseOneConstNR
31053 ? buildSqrtNROneConst(
Op, Est, Iterations, Reciprocal)
31054 : buildSqrtNRTwoConst(
Op, Est, Iterations, Reciprocal);
31074 return buildSqrtEstimateImpl(
Op,
true, Flags);
31078 return buildSqrtEstimateImpl(
Op,
false, Flags);
31082bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1)
const {
31084 struct MemUseCharacteristics {
31089 LocationSize NumBytes;
31090 MachineMemOperand *MMO;
31093 auto getCharacteristics = [
this](SDNode *
N) -> MemUseCharacteristics {
31099 ? -1 *
C->getSExtValue()
31101 TypeSize
Size = LSN->getMemoryVT().getStoreSize();
31102 return {LSN->isVolatile(), LSN->isAtomic(),
31103 LSN->getBasePtr(),
Offset ,
31113 (MachineMemOperand *)
nullptr};
31121 (MachineMemOperand *)
nullptr};
31124 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
31125 MUC1 = getCharacteristics(Op1);
31128 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
31129 MUC0.Offset == MUC1.Offset)
31133 if (MUC0.IsVolatile && MUC1.IsVolatile)
31138 if (MUC0.IsAtomic && MUC1.IsAtomic)
31141 if (MUC0.MMO && MUC1.MMO) {
31142 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
31143 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
31149 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
31150 MUC0.Offset != 0) ||
31151 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
31163 if (!MUC0.MMO || !MUC1.MMO)
31169 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
31170 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
31178 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
31179 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
31180 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
31181 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
31182 LocationSize Size0 = MUC0.NumBytes;
31183 LocationSize Size1 = MUC1.NumBytes;
31185 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
31191 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
31192 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
31196 if ((OffAlign0 +
static_cast<int64_t
>(
31198 (OffAlign1 +
static_cast<int64_t
>(
31212 if (
UseAA && BatchAA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
31215 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
31216 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
31218 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
31223 LocationSize Loc0 =
31225 LocationSize Loc1 =
31228 MemoryLocation(MUC0.MMO->getValue(), Loc0,
31229 UseTBAA ? MUC0.MMO->getAAInfo() : AAMDNodes()),
31230 MemoryLocation(MUC1.MMO->getValue(), Loc1,
31231 UseTBAA ? MUC1.MMO->getAAInfo() : AAMDNodes())))
31241void DAGCombiner::GatherAllAliases(SDNode *
N,
SDValue OriginalChain,
31242 SmallVectorImpl<SDValue> &Aliases) {
31244 SmallPtrSet<SDNode *, 16> Visited;
31252 unsigned Depth = 0;
31255 auto ImproveChain = [&](
SDValue &
C) ->
bool {
31256 switch (
C.getOpcode()) {
31267 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
31269 C =
C.getOperand(0);
31278 C =
C.getOperand(0);
31287 C =
C.getOperand(0);
31300 while (!Chains.
empty()) {
31334 if (ImproveChain(Chain)) {
31356 GatherAllAliases(
N, OldChain, Aliases);
31359 if (Aliases.
empty())
31363 if (Aliases.
size() == 1)
31383bool DAGCombiner::parallelizeChainedStores(StoreSDNode *St) {
31385 StoreSDNode *STChain = St;
31390 using IMap = llvm::IntervalMap<int64_t, std::monostate, 8,
31391 IntervalMapHalfOpenInfo<int64_t>>;
31400 if (!
BasePtr.getBase().getNode())
31404 if (
BasePtr.getBase().isUndef())
31422 if (Chain->getMemoryVT().isScalableVector())
31426 if (!
SDValue(Chain, 0)->hasOneUse())
31429 if (!Chain->isSimple() || Chain->isIndexed())
31438 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
31446 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
31455 if (ChainedStores.
empty())
31462 for (
unsigned I = ChainedStores.
size();
I;) {
31463 StoreSDNode *S = ChainedStores[--
I];
31464 SDValue BetterChain = FindBetterChain(S, NewChain);
31468 ChainedStores[
I] = S;
31472 SDValue BetterChain = FindBetterChain(St, NewChain);
31487 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
31488 return ST->getOperand(0) != NewChain;
31490 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
31500 AddToWorklist(
Op.getNode());
31501 AddToWorklist(STChain);
31505bool DAGCombiner::findBetterNeighborChains(StoreSDNode *St) {
31512 if (!
BasePtr.getBase().getNode())
31516 if (
BasePtr.getBase().isUndef())
31520 if (parallelizeChainedStores(St))
31525 if (St->
getChain() != BetterChain) {
31526 replaceStoreChain(St, BetterChain);
31536 DAGCombiner(*
this, BatchAA, OptLevel).Run(Level);
static bool mayAlias(MachineInstr &MIa, SmallVectorImpl< MachineInstr * > &MemInsns, AliasAnalysis *AA)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > UseAA("aarch64-use-aa", cl::init(true), cl::desc("Enable the use of AA during codegen."))
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL, const TargetLowering &TLI)
For the instruction sequence of store below, F and I values are bundled together as an i64 value befo...
static unsigned bigEndianByteAt(const unsigned ByteWidth, const unsigned I)
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
static bool canFoldInAddressingMode(GLoadStore *MI, const TargetLowering &TLI, MachineRegisterInfo &MRI)
Return true if 'MI' is a load or a store that may be fold it's address operand into the load / store ...
static unsigned littleEndianByteAt(const unsigned ByteWidth, const unsigned I)
static bool isAnyConstantBuildVector(SDValue V, bool NoOpaques=false)
static cl::opt< bool > EnableShrinkLoadReplaceStoreWithStore("combiner-shrink-load-replace-store-with-store", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable load/<replace bytes>/store with " "a narrower store"))
static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0, unsigned ExtOpc, SmallVectorImpl< SDNode * > &ExtendNodes, const TargetLowering &TLI)
static cl::opt< unsigned > TokenFactorInlineLimit("combiner-tokenfactor-inline-limit", cl::Hidden, cl::init(2048), cl::desc("Limit the number of operands to inline for Token Factors"))
static SDValue tryToFoldExtOfLoad(SelectionDAG &DAG, DAGCombiner &Combiner, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc, bool NonNegZExt=false)
static SDValue ConvertSelectToConcatVector(SDNode *N, SelectionDAG &DAG)
static SDNode * getBuildPairElt(SDNode *N, unsigned i)
static SDValue foldExtractSubvectorFromShuffleVector(EVT NarrowVT, SDValue Src, unsigned Index, const SDLoc &DL, SelectionDAG &DAG, bool LegalOperations)
Given EXTRACT_SUBVECTOR(VECTOR_SHUFFLE(Op0, Op1, Mask)), try to produce VECTOR_SHUFFLE(EXTRACT_SUBVEC...
static SDValue foldToMaskedStore(StoreSDNode *Store, SelectionDAG &DAG, const SDLoc &Dl)
static SDValue foldBitOrderCrossLogicOp(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalTypes)
Try to fold a sext/zext/aext dag node into a ConstantSDNode or a build_vector of constants.
static unsigned getMinMaxOpcodeForClamp(bool IsMin, SDValue Operand1, SDValue Operand2, SelectionDAG &DAG, const TargetLowering &TLI)
Returns an appropriate FP min/max opcode for clamping operations.
static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift, SDValue ExtractFrom, SDValue &Mask, const SDLoc &DL)
Helper function for visitOR to extract the needed side of a rotate idiom from a shl/srl/mul/udiv.
static bool getCombineLoadStoreParts(SDNode *N, unsigned Inc, unsigned Dec, bool &IsLoad, bool &IsMasked, SDValue &Ptr, const TargetLowering &TLI)
bool refineUniformBase(SDValue &BasePtr, SDValue &Index, bool IndexIsScaled, SelectionDAG &DAG, const SDLoc &DL)
static SDValue narrowExtractedVectorLoad(EVT VT, SDValue Src, unsigned Index, const SDLoc &DL, SelectionDAG &DAG)
If we are extracting a subvector from a wide vector load, convert to a narrow load to eliminate the e...
static SDValue scalarizeExtractedBinOp(SDNode *ExtElt, SelectionDAG &DAG, const SDLoc &DL, bool LegalTypes)
Transform a vector binary operation into a scalar binary operation by moving the math/logic after an ...
static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG)
static SDValue foldAddSubMasked1(bool IsAdd, SDValue N0, SDValue N1, SelectionDAG &DAG, const SDLoc &DL)
Given the operands of an add/sub operation, see if the 2nd operand is a masked 0/1 whose source opera...
static bool mergeEltWithShuffle(SDValue &X, SDValue &Y, ArrayRef< int > Mask, SmallVectorImpl< int > &NewMask, SDValue Elt, unsigned InsIndex)
static SDValue simplifyShuffleOfShuffle(ShuffleVectorSDNode *Shuf)
If we have a unary shuffle of a shuffle, see if it can be folded away completely.
static unsigned getMinMaxOpcodeForCompareFold(SDValue Operand1, SDValue Operand2, bool SetCCNoNaNs, ISD::CondCode CC, unsigned OrAndOpcode, SelectionDAG &DAG, bool isFMAXNUMFMINNUM_IEEE, bool isFMAXNUMFMINNUM)
static bool canSplitIdx(LoadSDNode *LD)
static SDValue ShrinkLoadReplaceStoreWithStore(const std::pair< unsigned, unsigned > &MaskInfo, SDValue IVal, StoreSDNode *St, DAGCombiner *DC)
Check to see if IVal is something that provides a value as specified by MaskInfo.
static cl::opt< bool > StressLoadSlicing("combiner-stress-load-slicing", cl::Hidden, cl::desc("Bypass the profitability model of load slicing"), cl::init(false))
Hidden option to stress test load slicing, i.e., when this option is enabled, load slicing bypasses m...
static cl::opt< bool > UseTBAA("combiner-use-tbaa", cl::Hidden, cl::init(true), cl::desc("Enable DAG combiner's use of TBAA"))
static void adjustCostForPairing(SmallVectorImpl< LoadedSlice > &LoadedSlices, LoadedSlice::Cost &GlobalLSCost)
Adjust the GlobalLSCost according to the target paring capabilities and the layout of the slices.
static SDValue combineCarryDiamond(SelectionDAG &DAG, const TargetLowering &TLI, SDValue N0, SDValue N1, SDNode *N)
static cl::opt< bool > DisableCombines("combiner-disabled", cl::Hidden, cl::init(false), cl::desc("Disable the DAG combiner"))
static SDValue foldExtendVectorInregToExtendOfSubvector(SDNode *N, const SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG, bool LegalOperations)
static SDValue narrowExtractedVectorBinOp(EVT VT, SDValue Src, unsigned Index, const SDLoc &DL, SelectionDAG &DAG, bool LegalOperations)
If we are extracting a subvector produced by a wide binary operator try to use a narrow binary operat...
static bool isCompatibleLoad(SDValue N, unsigned ExtOpcode)
Check if N satisfies: N is used once.
static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned, const SelectionDAG &DAG)
Return true if divmod libcall is available.
static SDValue widenCtPop(SDNode *Extend, SelectionDAG &DAG, const SDLoc &DL)
Given an extending node with a pop-count operand, if the target does not support a pop-count in the n...
static SDValue foldLogicTreeOfShifts(SDNode *N, SDValue LeftHand, SDValue RightHand, SelectionDAG &DAG)
Given a tree of logic operations with shape like (LOGIC (LOGIC (X, Y), LOGIC (Z, Y))) try to match an...
static SDValue partitionShuffleOfConcats(SDNode *N, SelectionDAG &DAG)
static SDValue takeInexpensiveLog2(SelectionDAG &DAG, const SDLoc &DL, EVT VT, SDValue Op, unsigned Depth, bool AssumeNonZero)
static SDValue combineSelectAsExtAnd(SDValue Cond, SDValue T, SDValue F, const SDLoc &DL, SelectionDAG &DAG)
static bool areUsedBitsDense(const APInt &UsedBits)
Check that all bits set in UsedBits form a dense region, i.e., UsedBits looks like 0....
static SDValue foldMaskedMerge(SDNode *Node, SelectionDAG &DAG, const TargetLowering &TLI, const SDLoc &DL)
Fold "masked merge" expressions like (m & x) | (~m & y) and its DeMorgan variant (~m | x) & (m | y) i...
static SDValue getInputChainForNode(SDNode *N)
Given a node, return its input chain if it has one, otherwise return a null sd operand.
static ElementCount numVectorEltsOrZero(EVT T)
static SDValue foldSelectWithIdentityConstant(SDNode *N, SelectionDAG &DAG, bool ShouldCommuteOperands)
This inverts a canonicalization in IR that replaces a variable select arm with an identity constant.
static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG)
static SDValue tryToFoldExtOfExtload(SelectionDAG &DAG, DAGCombiner &Combiner, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType)
static SDValue foldAndToUsubsat(SDNode *N, SelectionDAG &DAG, const SDLoc &DL)
For targets that support usubsat, match a bit-hack form of that operation that ends in 'and' and conv...
static cl::opt< bool > CombinerGlobalAA("combiner-global-alias-analysis", cl::Hidden, cl::desc("Enable DAG combiner's use of IR alias analysis"))
static bool isConstantSplatVectorMaskForType(SDNode *N, EVT ScalarTy)
static SDValue formSplatFromShuffles(ShuffleVectorSDNode *OuterShuf, SelectionDAG &DAG)
Combine shuffle of shuffle of the form: shuf (shuf X, undef, InnerMask), undef, OuterMask --> splat X...
static bool isDivisorPowerOfTwo(SDValue Divisor)
static bool matchRotateHalf(const SelectionDAG &DAG, SDValue Op, SDValue &Shift, SDValue &Mask)
Match "(X shl/srl V1) & V2" where V2 may not be present.
static SDValue combineConcatVectorOfExtracts(SDNode *N, SelectionDAG &DAG)
static bool isLegalToCombineMinNumMaxNum(SelectionDAG &DAG, SDValue LHS, SDValue RHS, const SDNodeFlags Flags, const TargetLowering &TLI)
static SDValue combineShuffleOfBitcast(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static std::optional< EVT > canCombineShuffleToExtendVectorInreg(unsigned Opcode, EVT VT, std::function< bool(unsigned)> Match, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalTypes, bool LegalOperations)
static SDValue PerformUMinFpToSatCombine(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, SelectionDAG &DAG)
static SDValue combineShuffleToAnyExtendVectorInreg(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static SDValue foldAddSubOfSignBit(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
Try to fold a 'not' shifted sign-bit with add/sub with constant operand into a shift and add with a d...
static SDValue stripTruncAndExt(SDValue Value)
static SDValue combineUADDO_CARRYDiamond(DAGCombiner &Combiner, SelectionDAG &DAG, SDValue X, SDValue Carry0, SDValue Carry1, SDNode *N)
If we are facing some sort of diamond carry propagation pattern try to break it up to generate someth...
static SDValue foldShuffleOfConcatUndefs(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
Try to convert a wide shuffle of concatenated vectors into 2 narrow shuffles followed by concatenatio...
static SDValue combineShuffleOfSplatVal(ShuffleVectorSDNode *Shuf, SelectionDAG &DAG)
static auto getFirstIndexOf(R &&Range, const T &Val)
static SDValue getSubVectorSrc(SDValue V, unsigned Index, EVT SubVT)
static std::pair< unsigned, unsigned > CheckForMaskedLoad(SDValue V, SDValue Ptr, SDValue Chain)
Check to see if V is (and load (ptr), imm), where the load is having specific bytes cleared out.
static int getShuffleMaskIndexOfOneElementFromOp0IntoOp1(ArrayRef< int > Mask)
If the shuffle mask is taking exactly one element from the first vector operand and passing through a...
static bool shouldConvertSelectOfConstantsToMath(const SDValue &Cond, EVT VT, const TargetLowering &TLI)
static cl::opt< bool > EnableStoreMerging("combiner-store-merging", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable merging multiple stores " "into a wider store"))
static bool isContractableFMUL(const TargetOptions &Options, SDValue N)
static cl::opt< bool > MaySplitLoadIndex("combiner-split-load-index", cl::Hidden, cl::init(true), cl::desc("DAG combiner may split indexing from loads"))
static bool areSlicesNextToEachOther(const LoadedSlice &First, const LoadedSlice &Second)
Check whether or not First and Second are next to each other in memory.
static SDValue stripConstantMask(const SelectionDAG &DAG, SDValue Op, SDValue &Mask)
static bool arebothOperandsNotSNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static bool isBSwapHWordPair(SDValue N, MutableArrayRef< SDNode * > Parts)
static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static bool CanCombineFCOPYSIGN_EXTEND_ROUND(EVT XTy, EVT YTy)
copysign(x, fp_extend(y)) -> copysign(x, y) copysign(x, fp_round(y)) -> copysign(x,...
static cl::opt< bool > ReduceLoadOpStoreWidthForceNarrowingProfitable("combiner-reduce-load-op-store-width-force-narrowing-profitable", cl::Hidden, cl::init(false), cl::desc("DAG combiner force override the narrowing profitable check when " "reducing the width of load/op/store sequences"))
static SDValue getTruncatedUSUBSAT(EVT DstVT, EVT SrcVT, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
static SDValue foldToSaturated(SDNode *N, EVT &VT, SDValue &Src, EVT &SrcVT, SDLoc &DL, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue FoldIntToFPToInt(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue foldSubCtlzNot(SDNode *N, SelectionDAG &DAG)
static SDNode * getPostIndexedLoadStoreOp(SDNode *N, bool &IsLoad, bool &IsMasked, SDValue &Ptr, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue extractBooleanFlip(SDValue V, SelectionDAG &DAG, const TargetLowering &TLI, bool Force)
Flips a boolean if it is cheaper to compute.
static bool isTruncateOf(SelectionDAG &DAG, SDValue N, SDValue &Op, KnownBits &Known)
static SDValue tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, bool LegalOperations, SDNode *N, SDValue N0, ISD::LoadExtType ExtLoadType, ISD::NodeType ExtOpc)
static SDValue combineOrOfSetCCToUSUBOCarry(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue combineConcatVectorOfShuffleAndItsOperands(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalTypes, bool LegalOperations)
bool refineIndexType(SDValue &Index, ISD::MemIndexType &IndexType, EVT DataVT, SelectionDAG &DAG)
static SDValue foldRemainderIdiom(SDNode *N, SelectionDAG &DAG, const SDLoc &DL)
static SDValue combineMinNumMaxNumImpl(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode CC, const TargetLowering &TLI, SelectionDAG &DAG)
static SDValue combineShiftOfShiftedLogic(SDNode *Shift, SelectionDAG &DAG)
If we have a shift-by-constant of a bitwise logic op that itself has a shift-by-constant operand with...
static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG)
static void zeroExtendToMatch(APInt &LHS, APInt &RHS, unsigned Offset=0)
static SDValue combineShiftToMULH(SDNode *N, const SDLoc &DL, SelectionDAG &DAG, const TargetLowering &TLI)
static ConstantSDNode * getAsNonOpaqueConstant(SDValue N)
If N is a ConstantSDNode with isOpaque() == false return it casted to a ConstantSDNode pointer else n...
static bool arebothOperandsNotNan(SDValue Operand1, SDValue Operand2, SelectionDAG &DAG)
static SDValue detectUSatUPattern(SDValue In, EVT VT)
Detect patterns of truncation with unsigned saturation:
static SDValue PerformMinMaxFpToSatCombine(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, SelectionDAG &DAG)
static SDValue combineConcatVectorOfSplats(SDNode *N, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalTypes, bool LegalOperations)
static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1, SDNode *N)
OR combines for which the commuted variant will be tried as well.
static SDValue detectSSatUPattern(SDValue In, EVT VT, SelectionDAG &DAG, const SDLoc &DL)
Detect patterns of truncation with unsigned saturation:
static SDValue combineShuffleToZeroExtendVectorInReg(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI, bool LegalOperations)
static cl::opt< bool > EnableReduceLoadOpStoreWidth("combiner-reduce-load-op-store-width", cl::Hidden, cl::init(true), cl::desc("DAG combiner enable reducing the width of load/op/store " "sequence"))
static bool shouldCombineToPostInc(SDNode *N, SDValue Ptr, SDNode *PtrUse, SDValue &BasePtr, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue combineVSelectWithAllOnesOrZeros(SDValue Cond, SDValue TVal, SDValue FVal, const TargetLowering &TLI, SelectionDAG &DAG, const SDLoc &DL)
static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, SelectionDAG &DAG, bool IsRotate, bool FromAdd)
static SDValue foldExtendedSignBitTest(SDNode *N, SelectionDAG &DAG, bool LegalOperations)
static SDValue combineConcatVectorOfCasts(SDNode *N, SelectionDAG &DAG)
static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG)
Try to replace shift/logic that tests if a bit is clear with mask + setcc.
static bool areBitwiseNotOfEachother(SDValue Op0, SDValue Op1)
static SDValue combineShuffleOfScalars(ShuffleVectorSDNode *SVN, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue combineConcatVectorOfScalars(SDNode *N, SelectionDAG &DAG)
static SDValue scalarizeBinOpOfSplats(SDNode *N, SelectionDAG &DAG, const SDLoc &DL, bool LegalTypes)
If a vector binop is performed on splat values, it may be profitable to extract, scalarize,...
static SDValue foldVSelectToSignBitSplatMask(SDNode *N, SelectionDAG &DAG)
static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static SDValue combineConcatVectorOfConcatVectors(SDNode *N, SelectionDAG &DAG)
static SDValue tryToFoldExtOfAtomicLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, SDValue N0, ISD::LoadExtType ExtLoadType)
static SDValue matchBSwapHWordOrAndAnd(const TargetLowering &TLI, SelectionDAG &DAG, SDNode *N, SDValue N0, SDValue N1, EVT VT)
static SDValue tryToFoldExtendSelectLoad(SDNode *N, const TargetLowering &TLI, SelectionDAG &DAG, const SDLoc &DL, CombineLevel Level)
Fold (sext (select c, load x, load y)) -> (select c, sextload x, sextload y) (zext (select c,...
static SDValue getAsCarry(const TargetLowering &TLI, SDValue V, bool ForceCarryReconstruction=false)
static SDValue matchMergedBFX(SDValue Root, SelectionDAG &DAG, const TargetLowering &TLI)
static SDValue foldSelectOfConstantsUsingSra(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
If a (v)select has a condition value that is a sign-bit test, try to smear the condition operand sign...
static unsigned getPPCf128HiElementSelector(const SelectionDAG &DAG)
static SDValue detectSSatSPattern(SDValue In, EVT VT)
Detect patterns of truncation with signed saturation: (truncate (smin (smax (x, signed_min_of_dest_ty...
static SDValue combineTruncationShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG)
static SDValue tryFoldToZero(const SDLoc &DL, const TargetLowering &TLI, EVT VT, SelectionDAG &DAG, bool LegalOperations)
static cl::opt< unsigned > StoreMergeDependenceLimit("combiner-store-merge-dependence-limit", cl::Hidden, cl::init(10), cl::desc("Limit the number of times for the same StoreNode and RootNode " "to bail out in store merging dependence check"))
static SDValue eliminateFPCastPair(SDNode *N)
static cl::opt< bool > EnableTopologicalSorting("combiner-topological-sorting", cl::Hidden, cl::init(false), cl::desc("DAG combiner nodes consistently processed in topological order"))
static cl::opt< std::string > CombinerAAOnlyFunc("combiner-aa-only-func", cl::Hidden, cl::desc("Only use DAG-combiner alias analysis in this" " function"))
static SDValue foldLogicOfShifts(SDNode *N, SDValue LogicOp, SDValue ShiftOp, SelectionDAG &DAG)
Given a bitwise logic operation N with a matching bitwise logic operand, fold a pattern where 2 of th...
ByteProvider< SDNode * > SDByteProvider
Recursively traverses the expression calculating the origin of the requested byte of the given value.
static bool isSlicingProfitable(SmallVectorImpl< LoadedSlice > &LoadedSlices, const APInt &UsedBits, bool ForCodeSize)
Check the profitability of all involved LoadedSlice.
static SDValue narrowInsertExtractVectorBinOp(EVT SubVT, SDValue BinOp, unsigned Index, const SDLoc &DL, SelectionDAG &DAG, bool LegalOperations)
static bool isBSwapHWordElement(SDValue N, MutableArrayRef< SDNode * > Parts)
Return true if the specified node is an element that makes up a 32-bit packed halfword byteswap.
static SDValue isSaturatingMinMax(SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC, unsigned &BW, bool &Unsigned, SelectionDAG &DAG)
static SDValue foldBoolSelectToLogic(SDNode *N, const SDLoc &DL, SelectionDAG &DAG)
static std::optional< SDByteProvider > calculateByteProvider(SDValue Op, unsigned Index, unsigned Depth, std::optional< uint64_t > VectorIndex, unsigned StartingIndex=0)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
static bool isSigned(unsigned Opcode)
static MaybeAlign getAlign(Value *Ptr)
iv Induction Variable Users
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
static Value * simplifyDivRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, const SimplifyQuery &Q, unsigned MaxRecurse)
Check for common or similar folds of integer division or integer remainder.
This file implements a coalescing interval map for small objects.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isUndef(const MachineInstr &MI)
Register const TargetRegisterInfo * TRI
This file provides utility analysis objects describing memory locations.
MachineInstr unsigned OpIdx
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
const SmallVectorImpl< MachineOperand > & Cond
Contains matchers for matching SelectionDAG nodes and values.
static bool isSimple(Instruction *I)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
static cl::opt< bool > UseTBAA("use-tbaa-in-sched-mi", cl::Hidden, cl::init(true), cl::desc("Enable use of TBAA during MI DAG construction"))
static cl::opt< unsigned > MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192), cl::desc("DAG combiner limit number of steps when searching DAG " "for predecessor nodes"))
This file implements a set that has insertion order iteration characteristics.
This file implements the SmallBitVector class.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file describes how to lower LLVM code to machine code.
static constexpr int Concat[]
static constexpr roundingMode rmTowardZero
static LLVM_ABI ExponentType semanticsMinExponent(const fltSemantics &)
static constexpr roundingMode rmNearestTiesToEven
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
static LLVM_ABI bool isIEEELikeFP(const fltSemantics &)
opStatus
IEEE-754R 7: Default exception handling.
static LLVM_ABI unsigned int semanticsIntSizeInBits(const fltSemantics &, bool)
static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)
Factory for QNaN values.
opStatus divide(const APFloat &RHS, roundingMode RM)
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
const fltSemantics & getSemantics() const
APFloat makeQuiet() const
Assuming this is an IEEE-754 NaN value, quiet its signaling bit.
opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM)
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() const
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
LLVM_ABI APInt umul_ov(const APInt &RHS, bool &Overflow) const
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
LLVM_ABI APInt getLoBits(unsigned numBits) const
Compute an APInt containing numBits lowbits from this APInt.
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
void setBitsFrom(unsigned loBit)
Set the top bits starting from loBit.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
APInt abs() const
Get the absolute value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool ugt(const APInt &RHS) const
Unsigned greater than comparison.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit)
Get a value with a block of bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
bool isNegative() const
Determine sign of this APInt.
bool intersects(const APInt &RHS) const
This operation tests if there are any pairs of corresponding bits between this APInt and RHS that are...
int32_t exactLogBase2() const
bool sle(const APInt &RHS) const
Signed less or equal comparison.
LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const
unsigned countr_zero() const
Count the number of trailing zero bits.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
unsigned countl_zero() const
The APInt version of std::countl_zero.
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
unsigned countLeadingZeros() const
void flipAllBits()
Toggle every bit to its opposite value.
unsigned logBase2() const
bool isShiftedMask() const
Return true if this APInt value contains a non-empty sequence of ones with the remainder zero.
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
bool getBoolValue() const
Convert APInt to a boolean value.
LLVM_ABI APInt srem(const APInt &RHS) const
Function for signed remainder operation.
LLVM_ABI APInt smul_ov(const APInt &RHS, bool &Overflow) const
bool isMask(unsigned numBits) const
bool isMaxSignedValue() const
Determine if this is the largest signed value.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
void setBits(unsigned loBit, unsigned hiBit)
Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
LLVM_ABI APInt extractBits(unsigned numBits, unsigned bitPosition) const
Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
bool sge(const APInt &RHS) const
Signed greater or equal comparison.
bool isOne() const
Determine if this is a value of 1.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
int64_t getSExtValue() const
Get sign extended value.
void lshrInPlace(unsigned ShiftAmt)
Logical right-shift this APInt by ShiftAmt in place.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
An arbitrary precision integer that knows its signedness.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
static LLVM_ABI BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
static LLVM_ABI bool computeAliasing(const SDNode *Op0, const LocationSize NumBytes0, const SDNode *Op1, const LocationSize NumBytes1, const SelectionDAG &DAG, bool &IsAlias)
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
LLVM_ABI bool isConstant() const
Represents known origin of an individual byte in combine pattern.
static ByteProvider getConstantZero()
static ByteProvider getSrc(std::optional< SDNode * > Val, int64_t ByteOffset, int64_t VectorOffset)
ISD::CondCode get() const
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
const APFloat & getValueAPF() const
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
bool isNegative() const
Return true if the value is negative.
bool isZero() const
Return true if the value is positive or negative zero.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI APInt getUnsignedMin() const
Return the smallest unsigned value contained in the ConstantRange.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI APInt getSignedMin() const
Return the smallest signed value contained in the ConstantRange.
LLVM_ABI ConstantRange truncate(uint32_t BitWidth, unsigned NoWrapKind=0) const
Return a new range in the specified integer type, which must be strictly smaller than the current typ...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI APInt getUnsignedMax() const
Return the largest unsigned value contained in the ConstantRange.
LLVM_ABI APInt getSignedMax() const
Return the largest signed value contained in the ConstantRange.
uint32_t getBitWidth() const
Get the bit width of this ConstantRange.
bool isMinSignedValue() const
const ConstantInt * getConstantIntValue() const
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This is an important base class in LLVM.
static LLVM_ABI ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed)
Returns the ops for a zero- or sign-extension in a DIExpression.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
static LLVM_ABI const DIExpression * convertToVariadicExpression(const DIExpression *Expr)
If Expr is a non-variadic expression (i.e.
static LLVM_ABI DIExpression * appendExt(const DIExpression *Expr, unsigned FromSize, unsigned ToSize, bool Signed)
Append a zero- or sign-extension to Expr.
bool isLittleEndian() const
Layout endianness...
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
static bool shouldExecute(CounterInfo &Counter)
iterator find(const_arg_type_t< KeyT > Val)
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr bool isScalar() const
Exactly one element.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
AttributeList getAttributes() const
Return the attribute list for this Function.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
const_iterator find(KeyT x) const
find - Return an iterator pointing to the first interval ending at or after x, or end().
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
static LocationSize precise(uint64_t Value)
static constexpr LocationSize beforeOrAfterPointer()
Any location before or after the base pointer (but still within the underlying object).
TypeSize getValue() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static MVT getIntegerVT(unsigned BitWidth)
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
A description of a memory reference used in the backend.
const PseudoSourceValue * getPseudoValue() const
void clearRanges()
Unset the tracked range metadata.
Flags
Flags values. These may be or'd together.
@ MODereferenceable
The memory access is dereferenceable (i.e., doesn't trap).
@ MONonTemporal
The memory access is non-temporal.
Flags getFlags() const
Return the raw flags of the source value,.
const Value * getValue() const
Return the base address of the memory access.
const SDValue & getPassThru() const
ISD::LoadExtType getExtensionType() const
const SDValue & getIndex() const
bool isIndexScaled() const
const SDValue & getScale() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getInc() const
const SDValue & getScale() const
const SDValue & getMask() const
const SDValue & getIntID() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
ISD::MemIndexType getIndexType() const
This class is used to represent an MLOAD node.
const SDValue & getBasePtr() const
bool isExpandingLoad() const
ISD::LoadExtType getExtensionType() const
const SDValue & getMask() const
const SDValue & getPassThru() const
const SDValue & getOffset() const
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
This class is used to represent an MSTORE node.
bool isCompressingStore() const
Returns true if the op does a compression to the vector before storing.
const SDValue & getOffset() const
const SDValue & getBasePtr() const
const SDValue & getMask() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
unsigned getAddressSpace() const
Return the address space for the associated pointer.
Align getBaseAlign() const
Returns alignment and volatility of the memory access.
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getBasePtr() const
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isNonTemporal() const
bool isDereferenceable() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > take_back(size_t N=1) const
Return a copy of *this with only the last N elements.
MutableArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Holds the information for a single machine location through SDISel; either an SDNode,...
static SDDbgOperand fromNode(SDNode *Node, unsigned ResNo)
@ SDNODE
Value is the result of an expression.
Holds the information from a dbg_value node through SDISel.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
const APInt & getAsAPIntVal() const
Helper method returns the APInt value of a ConstantSDNode.
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
LLVM_ABI bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< value_op_iterator > op_values() const
iterator_range< use_iterator > uses()
SDNodeFlags getFlags() const
size_t use_size() const
Return the number of uses of this node.
TypeSize getValueSizeInBits(unsigned ResNo) const
Returns MVT::getSizeInBits(getValueType(ResNo)).
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
SDVTList getVTList() const
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
LLVM_ABI bool isOperandOf(const SDNode *N) const
Return true if this node is an operand of N.
const APInt & getConstantOperandAPInt(unsigned Num) const
Helper method returns the APInt of a ConstantSDNode operand.
std::optional< APInt > bitcastToAPInt() const
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const
Return true if there are any use of the indicated value.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
iterator_range< user_iterator > users()
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
static use_iterator use_end()
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
LLVM_ABI bool reachesChainWithoutSideEffects(SDValue Dest, unsigned Depth=2) const
Return true if this operand (which must be a chain) reaches the specified operand without crossing an...
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
bool use_empty() const
Return true if there are no nodes using value ResNo of Node.
const APInt & getConstantOperandAPInt(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
unsigned getNumOperands() const
Targets can subclass this to parameterize the SelectionDAG lowering and instruction selection process...
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
bool willNotOverflowAdd(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the addition of 2 nodes can never overflow.
LLVM_ABI Align getReducedAlign(EVT VT, bool UseABI)
In most cases this function returns the ABI alignment for a given type, except for illegal vector typ...
LLVM_ABI SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT, unsigned Opcode)
Convert Op, which must be of integer type, to the integer type VT, by either any/sign/zero-extending ...
LLVM_ABI SDValue getSplatSourceVector(SDValue V, int &SplatIndex)
If V is a splatted value, return the source vector and its splat index.
LLVM_ABI unsigned ComputeMaxSignificantBits(SDValue Op, unsigned Depth=0) const
Get the upper bound on bit size for this Value Op as a signed integer.
const SDValue & getRoot() const
Return the root tag of the SelectionDAG.
LLVM_ABI SDValue getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, ISD::LoadExtType ExtTy)
LLVM_ABI SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl, SDNodeFlags Flags={})
Constant fold a setcc to true or false.
bool isKnownNeverSNaN(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
LLVM_ABI std::optional< bool > isBoolConstant(SDValue N) const
Check if a value \op N is a constant using the target's BooleanContent for its type.
const TargetSubtargetInfo & getSubtarget() const
LLVM_ABI ConstantRange computeConstantRange(SDValue Op, bool ForSigned, unsigned Depth=0) const
Determine the possible constant range of an integer or vector of integers.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL)
LLVM_ABI SDValue getSplatValue(SDValue V, bool LegalTypes=false)
If V is a splat vector, return its scalar source operand by extracting that element from the source v...
LLVM_ABI SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI void ExtractVectorElements(SDValue Op, SmallVectorImpl< SDValue > &Args, unsigned Start=0, unsigned Count=0, EVT EltVT=EVT())
Append the extracted elements from Start to Count out of the vector Op in Args.
LLVM_ABI SDValue getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO)
LLVM_ABI SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags, bool AllowCommute=false)
Get the specified node if it's already available, or else return NULL.
LLVM_ABI SDValue getFreeze(SDValue V)
Return a freeze using the SDLoc of the value operand.
LLVM_ABI SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
LLVM_ABI SDValue makeEquivalentMemoryOrdering(SDValue OldChain, SDValue NewMemOpChain)
If an existing load has uses of its chain, create a token factor node with that chain and the new mem...
LLVM_ABI bool isConstantIntBuildVectorOrConstantInt(SDValue N, bool AllowOpaques=true) const
Test whether the given value is a constant int or similar node.
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
LLVM_ABI SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
LLVM_ABI SDValue getVScale(const SDLoc &DL, EVT VT, APInt MulImm)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
LLVM_ABI void Combine(CombineLevel Level, BatchAAResults *BatchAA, CodeGenOptLevel OptLevel)
This iterates over the nodes in the SelectionDAG, folding certain types of nodes together,...
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
static LLVM_ABI unsigned getHasPredecessorMaxSteps()
LLVM_ABI bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
SDValue getExtractSubvector(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Return the VT typed sub-vector of Vec at Idx.
LLVM_ABI bool cannotBeOrderedNegativeFP(SDValue Op) const
Test whether the given float value is known to be positive.
LLVM_ABI SDValue getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
LLVM_ABI SDValue getAssertAlign(const SDLoc &DL, SDValue V, Align A)
Return an AssertAlignSDNode.
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI bool canIgnoreSignBitOfZero(const SDUse &Use) const
Check if a use of a float value is insensitive to signed zeros.
LLVM_ABI bool SignBitIsZeroFP(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero, for a floating-point value.
SDValue getInsertSubvector(const SDLoc &DL, SDValue Vec, SDValue SubVec, unsigned Idx)
Insert SubVec at the Idx element of Vec.
LLVM_ABI SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal)
Returns a vector of type ResVT whose elements contain the linear sequence <0, Step,...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool willNotOverflowSub(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the sub of 2 nodes can never overflow.
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
static constexpr unsigned MaxRecursionDepth
bool isGuaranteedNotToBePoison(SDValue Op, unsigned Depth=0) const
Return true if this function can prove that Op is never poison.
LLVM_ABI SDValue getIndexedMaskedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
LLVM_ABI APInt computeVectorKnownZeroElements(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
For each demanded element of a vector, see if it is known to be zero.
LLVM_ABI void AddDbgValue(SDDbgValue *DB, bool isParameter)
Add a dbg_value SDNode.
LLVM_ABI std::pair< EVT, EVT > GetSplitDestVTs(const EVT &VT) const
Compute the VTs needed for the low/hi parts of a type which is split (or expanded) into two not neces...
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
LLVM_ABI SDValue getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
SDValue getBuildVector(EVT VT, const SDLoc &DL, ArrayRef< SDValue > Ops)
Return an ISD::BUILD_VECTOR node.
LLVM_ABI bool isSplatValue(SDValue V, const APInt &DemandedElts, APInt &UndefElts, unsigned Depth=0) const
Test whether V has a splatted value for all the demanded elements.
LLVM_ABI void DeleteNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDDbgValue * getDbgValueList(DIVariable *Var, DIExpression *Expr, ArrayRef< SDDbgOperand > Locs, ArrayRef< SDNode * > Dependencies, bool IsIndirect, const DebugLoc &DL, unsigned O, bool IsVariadic)
Creates a SDDbgValue node from a list of locations.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getNegative(SDValue Val, const SDLoc &DL, EVT VT)
Create negative operation as (SUB 0, Val).
LLVM_ABI std::optional< unsigned > getValidShiftAmount(SDValue V, const APInt &DemandedElts, unsigned Depth=0) const
If a SHL/SRA/SRL node V has a uniform shift amount that is less than the element bit-width of the shi...
LLVM_ABI SDValue simplifySelect(SDValue Cond, SDValue TVal, SDValue FVal)
Try to simplify a select/vselect into 1 of its operands or a constant.
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
LLVM_ABI bool isConstantFPBuildVectorOrConstantFP(SDValue N) const
Test whether the given value is a constant FP or similar node.
const DataLayout & getDataLayout() const
SDValue getPartialReduceMLS(unsigned Opc, const SDLoc &DL, SDValue Acc, SDValue LHS, SDValue RHS)
Get an expression that implements a partial multiply-subtract reduction.
LLVM_ABI SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl< SDValue > &Vals)
Creates a new TokenFactor containing Vals.
LLVM_ABI bool LegalizeOp(SDNode *N, SmallSetVector< SDNode *, 16 > &UpdatedNodes)
Transforms a SelectionDAG node and any operands to it into a node that is compatible with the target ...
LLVM_ABI bool doesNodeExist(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops)
Check if a node exists without modifying its flags.
LLVM_ABI bool areNonVolatileConsecutiveLoads(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const
Return true if loads are next to each other and can be merged.
LLVM_ABI SDValue getMaskedHistogram(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
bool willNotOverflowMul(bool IsSigned, SDValue N0, SDValue N1) const
Determine if the result of the mul of 2 nodes can never overflow.
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV)
Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to the shuffle node in input but with swa...
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getSplatVector(EVT VT, const SDLoc &DL, SDValue Op)
LLVM_ABI MaybeAlign InferPtrAlign(SDValue Ptr) const
Infer alignment of a load / store address.
LLVM_ABI bool SignBitIsZero(SDValue Op, unsigned Depth=0) const
Return true if the sign bit of Op is known to be zero.
LLVM_ABI void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
bool isConstantValueOfAnyType(SDValue N) const
LLVM_ABI bool canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts, UndefPoisonKind Kind=UndefPoisonKind::UndefOrPoison, bool ConsiderFlags=true, unsigned Depth=0) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI KnownFPClass computeKnownFPClass(SDValue Op, FPClassTest InterestedClasses, unsigned Depth=0) const
Determine floating-point class information about Op.
LLVM_ABI bool isIdentityElement(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo, unsigned Depth=0) const
Returns true if V is an identity element of Opc with Flags.
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, UndefPoisonKind Kind=UndefPoisonKind::UndefOrPoison, unsigned Depth=0) const
Return true if this function can prove that Op is never poison and, Kind can be used to track poison ...
LLVM_ABI bool isKnownNeverZero(SDValue Op, unsigned Depth=0) const
Test whether the given SDValue is known to contain non-zero value(s).
LLVM_ABI SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
LLVM_ABI SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDValue > Ops, SDNodeFlags Flags=SDNodeFlags())
LLVM_ABI SDValue getSetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO)
LLVM_ABI SDValue getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT)
Convert Op, which must be of integer type, to the integer type VT, by using an extension appropriate ...
LLVM_ABI SDValue getMaskedStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Base, SDValue Offset, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, bool IsTruncating=false, bool IsCompressing=false)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
iterator_range< allnodes_iterator > allnodes()
const LibcallLoweringInfo & getLibcalls() const
LLVM_ABI SDValue getLoadVP(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL, MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment, MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo, const MDNode *Ranges=nullptr, bool IsExpanding=false)
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType)
LLVM_ABI SDValue getValueType(EVT)
ArrayRef< SDDbgValue * > GetDbgValues(const SDNode *SD) const
Get the debug values which reference the given SDNode.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI unsigned AssignTopologicalOrder()
Topological-sort the AllNodes list and a assign a unique node id for each node in the DAG based on th...
LLVM_ABI bool isKnownNeverNaN(SDValue Op, const APInt &DemandedElts, bool SNaN=false, unsigned Depth=0) const
Test whether the given SDValue (or all elements of it, if it is a vector) is known to never be NaN in...
LLVM_ABI SDValue FoldConstantBuildVector(BuildVectorSDNode *BV, const SDLoc &DL, EVT DstEltVT)
Fold BUILD_VECTOR of constants/undefs to the destination type BUILD_VECTOR of constants/undefs elemen...
LLVM_ABI SDValue getIndexedMaskedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool MaskedVectorIsZero(SDValue Op, const APInt &DemandedElts, unsigned Depth=0) const
Return true if 'Op' is known to be zero in DemandedElts.
LLVM_ABI SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT)
Create a true or false constant of type VT using the target's BooleanContent for type OpVT.
LLVM_ABI SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI OverflowKind computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the unsigned addition of 2 nodes can overflow.
SDValue getPOISON(EVT VT)
Return a POISON node. POISON does not have a useful SDLoc.
SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)
Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.
bool isSafeToSpeculativelyExecuteNode(const SDNode *N) const
Check if the provided node is save to speculatively executed given its current arguments.
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI SDValue getCondCode(ISD::CondCode Cond)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVM_ABI bool isKnownToBeAPowerOfTwoFP(SDValue Val, unsigned Depth=0) const
Test if the given fp value is known to be an integer power-of-2, either positive or negative.
LLVMContext * getContext() const
LLVM_ABI SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y, SDNodeFlags Flags)
Try to simplify a floating-point binary operation into 1 of its operands or a constant.
const SDValue & setRoot(SDValue N)
Set the current root tag of the SelectionDAG.
LLVM_ABI bool isKnownToBeAPowerOfTwo(SDValue Val, bool OrZero=false, unsigned Depth=0) const
Test if the given value is known to have exactly one bit set.
LLVM_ABI bool isUndef(unsigned Opcode, ArrayRef< SDValue > Ops)
Return true if the result of this operation is always undefined.
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
LLVM_ABI SDValue getIndexedLoad(SDValue OrigLoad, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Base, SDValue Offset, SDValue Mask, SDValue Src0, EVT MemVT, MachineMemOperand *MMO, ISD::MemIndexedMode AM, ISD::LoadExtType, bool IsExpanding=false)
DenormalMode getDenormalMode(EVT VT) const
Return the current function's default denormal handling kind for the given floating point type.
SDValue getSplat(EVT VT, const SDLoc &DL, SDValue Op)
Returns a node representing a splat of one value into all lanes of the provided vector type.
static unsigned getOpcode_EXTEND(unsigned Opcode)
Convert *_EXTEND_VECTOR_INREG to *_EXTEND opcode.
LLVM_ABI bool isADDLike(SDValue Op, bool NoWrap=false) const
Return true if the specified operand is an ISD::OR or ISD::XOR node that can be treated as an ISD::AD...
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue simplifyShift(SDValue X, SDValue Y)
Try to simplify a shift into 1 of its operands or a constant.
LLVM_ABI void transferDbgValues(SDValue From, SDValue To, unsigned OffsetInBits=0, unsigned SizeInBits=0, bool InvalidateDbg=true)
Transfer debug values from one node to another, while optionally generating fragment expressions for ...
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
LLVM_ABI SDValue getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl, ArrayRef< SDValue > Ops, MachineMemOperand *MMO, ISD::MemIndexType IndexType, bool IsTruncating=false)
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
static LLVM_ABI bool isIdentityMask(ArrayRef< int > Mask, int NumSrcElts)
Return true if this shuffle mask chooses elements from exactly one source vector without lane crossin...
This SDNode is used to implement the code generator support for the llvm IR shufflevector instruction...
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
static void commuteMask(MutableArrayRef< int > Mask)
Change values in a shuffle permute mask assuming the two vector operands have swapped position.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
const SDValue & getValue() const
bool isTruncatingStore() const
Return true if the op does a truncation before store.
virtual bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF, EVT) const
Return true if an FMA operation is faster than a pair of fmul and fadd instructions.
bool isOperationExpand(unsigned Op, EVT VT) const
Return true if the specified operation is illegal on this target or unlikely to be made legal with cu...
virtual bool preferSextInRegOfTruncate(EVT TruncVT, EVT VT, EVT ExtVT) const
virtual bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const
Return true if it is profitable to transform an integer multiplication-by-constant into simpler opera...
virtual bool hasAndNot(SDValue X) const
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
virtual bool isShuffleMaskLegal(ArrayRef< int >, EVT) const
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
virtual bool enableAggressiveFMAFusion(EVT VT) const
Return true if target always benefits from combining into FMA for a given value type.
bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
SDValue promoteTargetBoolean(SelectionDAG &DAG, SDValue Bool, EVT ValVT) const
Promote the given target boolean to a target boolean of the given type.
virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset=std::nullopt) const
Return true if it is profitable to reduce a load to a smaller type.
virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const
Use bitwise logic to make pairs of compares more efficient.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const
Return true if folding a vector load into ExtVal (a sign, zero, or any extend node) is profitable.
unsigned getMaximumLegalStoreInBits() const
Return maximum known-legal store size, which can be guaranteed for scalable vectors.
int getRecipEstimateSqrtEnabled(EVT VT, MachineFunction &MF) const
Return a ReciprocalEstimate enum value for a square root of the given type based on the function's at...
virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const
Return true if sign-extension from FromTy to ToTy is cheaper than zero-extension.
virtual MachineMemOperand::Flags getTargetMMOFlags(const Instruction &I) const
This callback is used to inspect load/store instructions and add target-specific MachineMemOperand fl...
virtual bool isZExtFree(Type *FromTy, Type *ToTy) const
Return true if any actual instruction that defines a value of type FromTy implicitly zero-extends the...
virtual bool isFPExtFoldable(const MachineInstr &MI, unsigned Opcode, LLT DestTy, LLT SrcTy) const
Return true if an fpext operation input to an Opcode operation is free (for instance,...
virtual bool hasBitTest(SDValue X, SDValue Y) const
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
EVT getLegalTypeToTransformTo(LLVMContext &Context, EVT VT) const
Perform getTypeToTransformTo repeatedly until a legal type is obtained.
virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: fold (conv (load x)) -> (load (conv*)x) On arch...
virtual bool areTwoSDNodeTargetMMOFlagsMergeable(const MemSDNode &NodeX, const MemSDNode &NodeY) const
Return true if it is valid to merge the TargetMMOFlags in two SDNodes.
virtual bool isCommutativeBinOp(unsigned Opcode) const
Returns true if the opcode is a commutative binary operation.
virtual bool isFPImmLegal(const APFloat &, EVT, bool ForCodeSize=false) const
Returns true if the target can instruction select the specified FP immediate natively.
virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const
Return true if extraction of a scalar element from the given vector type at the given index is cheap.
virtual bool optimizeFMulOrFDivAsShiftAddBitcast(SDNode *N, SDValue FPConst, SDValue IntPow2) const
virtual bool shouldNormalizeToSelectSequence(LLVMContext &Context, EVT VT) const
Returns true if we should normalize select(N0&N1, X, Y) => select(N0, select(N1, X,...
virtual bool preferScalarizeSplat(SDNode *N) const
bool isIndexedMaskedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool allowsMisalignedMemoryAccesses(EVT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *=nullptr) const
Determine if the target supports unaligned memory accesses.
bool isOperationCustom(unsigned Op, EVT VT) const
Return true if the operation uses custom lowering, regardless of whether the type is legal or not.
virtual bool reduceSelectOfFPConstantLoads(EVT CmpOpVT) const
Return true if it is profitable to convert a select of FP constants into a constant pool load whose a...
bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const
When splitting a value of the specified type into parts, does the Lo or Hi part come first?
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const
Returns the type for the shift amount of a shift opcode.
virtual bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
virtual bool isMulAddWithConstProfitable(SDValue AddNode, SDValue ConstNode) const
Return true if it may be profitable to transform (mul (add x, c1), c2) -> (add (mul x,...
bool isPartialReduceMLALegalOrCustom(unsigned Opc, EVT AccVT, EVT InputVT) const
Return true if a PARTIAL_REDUCE_U/SMLA node with the specified types is legal or custom for this targ...
virtual bool isFsqrtCheap(SDValue X, SelectionDAG &DAG) const
Return true if SQRT(X) shouldn't be replaced with X*RSQRT(X).
int getDivRefinementSteps(EVT VT, MachineFunction &MF) const
Return the refinement step count for a division of the given type based on the function's attributes.
virtual bool isTruncateFree(Type *FromTy, Type *ToTy) const
Return true if it's free to truncate a value of type FromTy to type ToTy.
virtual bool shouldAvoidTransformToShift(EVT VT, unsigned Amount) const
Return true if creating a shift of the type by the given amount is not profitable.
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const
For types supported by the target, this is an identity function.
virtual bool shouldFoldSelectWithSingleBitTest(EVT VT, const APInt &AndMask) const
BooleanContent getBooleanContents(bool isVec, bool isFloat) const
For targets without i1 registers, this gives the nature of the high-bits of boolean values held in ty...
virtual bool shouldReassociateReduction(unsigned RedOpc, EVT VT) const
bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const
Return true if the specified condition code is legal for a comparison of the specified types on this ...
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
virtual bool shouldFoldConstantShiftPairToMask(const SDNode *N) const
Return true if it is profitable to fold a pair of shifts into a mask.
int getRecipEstimateDivEnabled(EVT VT, MachineFunction &MF) const
Return a ReciprocalEstimate enum value for a division of the given type based on the function's attri...
virtual bool preferIncOfAddToSubOfNot(EVT VT) const
These two forms are equivalent: sub y, (xor x, -1) add (add x, 1), y The variant with two add's is IR...
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
unsigned getMaxDivRemBitWidthSupported() const
Returns the size in bits of the maximum div/rem the backend supports.
virtual bool isLegalAddImmediate(int64_t) const
Return true if the specified immediate is legal add immediate, that is the target has add instruction...
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
virtual bool canTransformPtrArithOutOfBounds(const Function &F, EVT PtrVT) const
True if the target allows transformations of in-bounds pointer arithmetic that cause out-of-bounds in...
virtual bool canCombineTruncStore(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace, bool LegalOnly) const
virtual bool isProfitableToCombineMinNumMaxNum(EVT VT) const
virtual bool isFNegFree(EVT VT) const
Return true if an fneg operation is free to the point where it is never worthwhile to replace it with...
virtual bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X, SDValue Y) const
Return true if pulling a binary operation into a select with an identity constant is profitable.
@ ZeroOrOneBooleanContent
@ UndefinedBooleanContent
@ ZeroOrNegativeOneBooleanContent
virtual bool isIntDivCheap(EVT VT, AttributeList Attr) const
Return true if integer divide is usually cheaper than a sequence of several shifts,...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
bool isPredictableSelectExpensive() const
Return true if selects are only cheaper than branches if the branch is unlikely to be predicted right...
virtual bool mergeStoresAfterLegalization(EVT MemVT) const
Allow store merging for the specified type after legalization in addition to before legalization.
virtual bool shouldMergeStoreOfLoadsOverCall(EVT, EVT) const
Returns true if it's profitable to allow merging store of loads when there are functions calls betwee...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
unsigned getGatherAllAliasesMaxDepth() const
virtual bool storeOfVectorConstantIsCheap(bool IsZero, EVT MemVT, unsigned NumElem, unsigned AddrSpace) const
Return true if it is expected to be cheaper to do a store of vector constant with the given size and ...
virtual bool isNarrowingProfitable(SDNode *N, EVT SrcVT, EVT DestVT) const
Return true if it's profitable to narrow operations of type SrcVT to DestVT.
virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const
Return true if it is cheaper to split the store of a merged int val from a pair of smaller values int...
virtual bool isBinOp(unsigned Opcode) const
Return true if the node is a math/logic binary operator.
virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const
There are two ways to clear extreme bits (either low or high): Mask: x & (-1 << y) (the instcombine c...
bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, const MachineFunction &MF) const
Returns if it's reasonable to merge stores to MemVT size.
virtual bool preferABDSToABSWithNSW(EVT VT) const
bool isTruncStoreLegal(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace) const
Return true if the specified store with truncation is legal on this target.
AndOrSETCCFoldKind
Enum of different potentially desirable ways to fold (and/or (setcc ...), (setcc ....
virtual bool shouldScalarizeBinop(SDValue VecOp) const
Try to convert an extract element of a vector binary operation into an extract element followed by a ...
virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, const SelectionDAG &DAG, const MachineMemOperand &MMO) const
Return true if the following transform is beneficial: (store (y (conv x)), y*)) -> (store x,...
bool isIndexedMaskedStoreLegal(unsigned IdxMode, EVT VT) const
Return true if the specified indexed load is legal on this target.
virtual bool isVectorClearMaskLegal(ArrayRef< int >, EVT) const
Similar to isShuffleMaskLegal.
LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const
Return pair that represents the legalization kind (first) that needs to happen to EVT (second) in ord...
bool hasTargetDAGCombine(ISD::NodeType NT) const
If true, the target has custom DAG combine transformations that it can perform for the specified node...
virtual bool shouldSplatInsEltVarIndex(EVT) const
Return true if inserting a scalar into a variable element of an undef vector is more efficiently hand...
NegatibleCost
Enum that specifies when a float negation is beneficial.
LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const
Return how we should legalize values of this type, either it is already legal (return 'Legal') or we ...
int getSqrtRefinementSteps(EVT VT, MachineFunction &MF) const
Return the refinement step count for a square root of the given type based on the function's attribut...
virtual unsigned preferedOpcodeForCmpEqPiecesOfOperand(EVT VT, unsigned ShiftOpc, bool MayTransformRotate, const APInt &ShiftOrRotateAmt, const std::optional< APInt > &AndMask) const
virtual bool isFMADLegal(const MachineInstr &MI, LLT Ty) const
Returns true if MI can be combined with another instruction to form TargetOpcode::G_FMAD.
virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const
virtual bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const
bool isLoadLegal(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace, unsigned ExtType, bool Atomic) const
Return true if the specified load with extension is legal on this target.
bool isLoadLegalOrCustom(EVT ValVT, EVT MemVT, Align Alignment, unsigned AddrSpace, unsigned ExtType, bool Atomic) const
Return true if the specified load with extension is legal or custom on this target.
virtual bool isFAbsFree(EVT VT) const
Return true if an fabs operation is free to the point where it is never worthwhile to replace it with...
LegalizeAction getOperationAction(unsigned Op, EVT VT) const
Return how this operation should be treated: either it is legal, needs to be promoted to a larger siz...
virtual bool generateFMAsInMachineCombiner(EVT VT, CodeGenOptLevel OptLevel) const
virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AddrSpace, Instruction *I=nullptr) const
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
virtual bool hasPairedLoad(EVT, Align &) const
Return true if the target supplies and combines to a paired load two loaded values of type LoadedType...
virtual bool convertSelectOfConstantsToMath(EVT VT) const
Return true if a select of constants (select Cond, C1, C2) should be transformed into simple math ops...
bool isOperationLegalOrCustomOrPromote(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const
Should we generate fp_to_si_sat and fp_to_ui_sat from type FPVT to type VT from min(max(fptoi)) satur...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual SDValue getSqrtEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps, bool &UseOneConstNR, bool Reciprocal) const
Hooks for building estimates in place of slower divisions and square roots.
bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, APInt &KnownUndef, APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Vector Op.
virtual bool isReassocProfitable(SelectionDAG &DAG, SDValue N0, SDValue N1) const
SDValue getCheaperOrNeutralNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, const NegatibleCost CostThreshold=NegatibleCost::Neutral, unsigned Depth=0) const
virtual bool isTargetCanonicalSelect(SDNode *N) const
Return true if the given select/vselect should be considered canonical and not be transformed.
SDValue getCheaperNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, unsigned Depth=0) const
This is the helper function to return the newly negated expression only when the cost is cheaper.
SDValue SimplifyMultipleUseDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth=0) const
More limited version of SimplifyDemandedBits that can be used to "lookthrough" ops that don't contrib...
SDValue expandABS(SDNode *N, SelectionDAG &DAG, bool IsNegative=false) const
Expand ABS nodes.
virtual bool IsDesirableToPromoteOp(SDValue, EVT &) const
This method query the target whether it is beneficial for dag combiner to promote the specified node.
SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, bool IsAfterLegalTypes, SmallVectorImpl< SDNode * > &Created) const
Given an ISD::SDIV node expressing a divide by constant, return a DAG expression to select that will ...
virtual bool isTypeDesirableForOp(unsigned, EVT VT) const
Return true if the target has native support for the specified value type and it is 'desirable' to us...
SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, bool IsAfterLegalTypes, SmallVectorImpl< SDNode * > &Created) const
Given an ISD::UDIV node expressing a divide by constant, return a DAG expression to select that will ...
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG, bool LegalOps, bool OptForSize, NegatibleCost &Cost, unsigned Depth=0) const
Return the newly negated expression if the cost is not expensive and set the cost in Cost to indicate...
SDValue buildLegalVectorShuffle(EVT VT, const SDLoc &DL, SDValue N0, SDValue N1, MutableArrayRef< int > Mask, SelectionDAG &DAG) const
Tries to build a legal vector shuffle using the provided parameters or equivalent variations.
virtual SDValue getRecipEstimate(SDValue Operand, SelectionDAG &DAG, int Enabled, int &RefinementSteps) const
Return a reciprocal estimate value for the input operand.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
TargetLowering(const TargetLowering &)=delete
bool isConstFalseVal(SDValue N) const
Return if the N is a constant or constant vector equal to the false value from getBooleanContents().
virtual SDValue getSqrtResultForDenormInput(SDValue Operand, SelectionDAG &DAG) const
Return a target-dependent result if the input operand is not suitable for use with a square root esti...
virtual bool getPostIndexedAddressParts(SDNode *, SDNode *, SDValue &, SDValue &, ISD::MemIndexedMode &, SelectionDAG &) const
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, bool foldBooleans, DAGCombinerInfo &DCI, const SDLoc &dl) const
Try to simplify a setcc built with the specified operands and cc.
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
Return true if folding a constant offset with the given GlobalAddress is legal.
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual bool isDesirableToCommuteWithShift(const SDNode *N, CombineLevel Level) const
Return true if it is profitable to move this shift by a constant amount through its operand,...
virtual bool useTopologicalSorting() const
virtual unsigned combineRepeatedFPDivisors() const
Indicate whether this target prefers to combine FDIVs with the same divisor.
virtual AndOrSETCCFoldKind isDesirableToCombineLogicOpOfSETCC(const SDNode *LogicOp, const SDNode *SETCC0, const SDNode *SETCC1) const
virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, const DenormalMode &Mode, SDNodeFlags Flags={}) const
Return a target-dependent comparison result if the input operand is suitable for use with a square ro...
virtual bool getPreIndexedAddressParts(SDNode *, SDValue &, SDValue &, ISD::MemIndexedMode &, SelectionDAG &) const
Returns true by value, base pointer and offset pointer and addressing mode by reference if the node's...
SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index, const SDNodeFlags PtrArithFlags=SDNodeFlags()) const
Get a pointer to vector element Idx located in memory for a vector of type VecVT starting at a base a...
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue getInboundsVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index) const
Get a pointer to vector element Idx located in memory for a vector of type VecVT starting at a base a...
virtual SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Targets may override this function to provide custom SDIV lowering for power-of-2 denominators.
SDValue scalarizeExtractedVectorLoad(EVT ResultVT, const SDLoc &DL, EVT InVecVT, SDValue EltNo, LoadSDNode *OriginalLoad, SelectionDAG &DAG) const
Replace an extraction of a load with a narrowed load.
virtual SDValue BuildSREMPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, SmallVectorImpl< SDNode * > &Created) const
Targets may override this function to provide custom SREM lowering for power-of-2 denominators.
virtual bool isDesirableToTransformToIntegerOp(unsigned, EVT) const
Return true if it is profitable for dag combiner to transform a floating point op of specified opcode...
unsigned NoSignedZerosFPMath
NoSignedZerosFPMath - This flag is enabled when the -enable-no-signed-zeros-fp-math is specified on t...
virtual bool useAA() const
Enable use of alias analysis during code generation (during MI scheduling, DAGCombine,...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI const fltSemantics & getFltSemantics() const
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
const SDValue & getScale() const
ISD::MemIndexType getIndexType() const
How is Index applied to BasePtr when computing addresses.
const SDValue & getVectorLength() const
const SDValue & getIndex() const
const SDValue & getBasePtr() const
bool isIndexScaled() const
const SDValue & getMask() const
const SDValue & getValue() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
iterator_range< user_iterator > users()
int getNumOccurrences() const
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
constexpr ScalarTy getFixedValue() const
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const
We do not provide the '/' operator here because division for polynomial types does not work in the sa...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const APInt & smin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be signed.
const APInt & smax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be signed.
const APInt & umin(const APInt &A, const APInt &B)
Determine the smaller of two APInts considered to be unsigned.
const APInt & umax(const APInt &A, const APInt &B)
Determine the larger of two APInts considered to be unsigned.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, EVT Type)
Return the result of a logical AND between different comparisons of identical values: ((X op1 Y) & (X...
LLVM_ABI bool isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are ~0 ...
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ PTRADD
PTRADD represents pointer arithmetic semantics, for targets that opt in using shouldPreservePtrArith(...
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ COND_LOOP
COND_LOOP is a conditional branch to self, used for implementing efficient conditional traps.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ SMULFIX
RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on 2 integers with the same...
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ FMAD
FMAD - Perform a * b + c, while getting the same result as the separately rounded operations.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ SMULFIXSAT
Same as the corresponding unsaturated fixed point instructions, but the result is clamped between the...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
@ VECREDUCE_FMAX
FMIN/FMAX nodes can have flags, for NaN/NoNaN variants.
@ FADD
Simple binary floating point operators.
@ VECREDUCE_FMAXIMUM
FMINIMUM/FMAXIMUM nodes propatate NaNs and signed zeroes using the llvm.minimum and llvm....
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
@ SIGN_EXTEND_VECTOR_INREG
SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register sign-extension of the low ...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ FMULADD
FMULADD - Performs a * b + c, with, or without, intermediate rounding.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ CLMUL
Carry-less multiplication operations.
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ SIGN_EXTEND
Conversion operators.
@ AVGCEILS
AVGCEILS/AVGCEILU - Rounding averaging add - Add two integers using an integer of type i[N+2],...
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ VECREDUCE_FADD
These reductions have relaxed evaluation order semantics, and have a single vector operand.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
@ VECTOR_INTERLEAVE
VECTOR_INTERLEAVE(VEC1, VEC2, ...) - Returns N vectors from N input vectors, where N is the factor to...
@ STEP_VECTOR
STEP_VECTOR(IMM) - Returns a scalable vector whose lanes are comprised of a linear sequence of unsign...
@ FCANONICALIZE
Returns platform specific canonical encoding of a floating point number.
@ IS_FPCLASS
Performs a check of floating point class property, defined by IEEE-754.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
@ UNDEF
UNDEF - An undefined node.
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ CTLS
Count leading redundant sign bits.
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ AssertNoFPClass
AssertNoFPClass - These nodes record if a register contains a float value that is known to be not som...
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ FMINNUM_IEEE
FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimumNumber or maximumNumber on two values,...
@ EntryToken
EntryToken - This is the marker used to indicate the start of a region.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ VSCALE
VSCALE(IMM) - Returns the runtime scaling factor used to calculate the number of elements within a sc...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ SSHLSAT
RESULT = [US]SHLSAT(LHS, RHS) - Perform saturation left shift.
@ SMULO
Same for multiplication.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
@ LIFETIME_START
This corresponds to the llvm.lifetime.
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ MGATHER
Masked gather and scatter - load and store operations for a vector of random addresses with additiona...
@ HANDLENODE
HANDLENODE node - Used as a handle for various purposes.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ TargetConstant
TargetConstant* - Like Constant*, but the DAG does not do any folding, simplification,...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ GET_FPENV_MEM
Gets the current floating-point environment.
@ CARRY_FALSE
CARRY_FALSE - This node is used when folding other nodes, like ADDC/SUBC, which indicate the carry re...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FADD
Constrained versions of the binary floating point operators.
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ CTTZ_ZERO_POISON
Bit counting operators with a poisoned result for zero inputs.
@ FFREXP
FFREXP - frexp, extract fractional and exponent component of a floating-point value.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ VECTOR_COMPRESS
VECTOR_COMPRESS(Vec, Mask, Passthru) consecutively place vector elements based on mask e....
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ EXPERIMENTAL_VECTOR_HISTOGRAM
Experimental vector histogram intrinsic Operands: Input Chain, Inc, Mask, Base, Index,...
@ FP_TO_SINT_SAT
FP_TO_[US]INT_SAT - Convert floating point value in operand 0 to a signed or unsigned scalar integer ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BRCOND
BRCOND - Conditional branch.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ SET_FPENV_MEM
Sets the current floating point environment.
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ TRUNCATE_SSAT_S
TRUNCATE_[SU]SAT_[SU] - Truncate for saturated operand [SU] located in middle, prefix for SAT means i...
@ ABDS
ABDS/ABDU - Absolute difference - Return the absolute difference between two numbers interpreted as s...
@ SADDO_CARRY
Carry-using overflow-aware nodes for multiple precision addition and subtraction.
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isIndexTypeSigned(MemIndexType IndexType)
bool isExtVecInRegOpcode(unsigned Opcode)
LLVM_ABI NodeType getOppositeSignednessMinMaxOpcode(unsigned MinMaxOpc)
Given a MinMaxOpc of ISD::(U|S)MIN or ISD::(U|S)MAX, returns the corresponding opcode with the opposi...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
bool matchUnaryFpPredicate(SDValue Op, std::function< bool(ConstantFPSDNode *)> Match, bool AllowUndefs=false)
Hook for matching ConstantFPSDNode predicate.
bool isFPEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with floati...
bool isExtOpcode(unsigned Opcode)
LLVM_ABI bool isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly=false)
Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where all of the elements are 0 o...
LLVM_ABI bool isVPBinaryOp(unsigned Opcode)
Whether this is a vector-predicated binary operation opcode.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isBitwiseLogicOp(unsigned Opcode)
Whether this is bitwise logic opcode.
LLVM_ABI std::optional< unsigned > getVPMaskIdx(unsigned Opcode)
The operand position of the vector mask.
bool isUNINDEXEDLoad(const SDNode *N)
Returns true if the specified node is an unindexed load.
LLVM_ABI std::optional< unsigned > getVPExplicitVectorLengthIdx(unsigned Opcode)
The operand position of the explicit vector length parameter.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI bool allOperandsUndef(const SDNode *N)
Return true if the node has at least one operand and all operands of the specified node are ISD::UNDE...
LLVM_ABI bool isFreezeUndef(const SDNode *N)
Return true if the specified node is FREEZE(UNDEF).
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
MemIndexType
MemIndexType enum - This enum defines how to interpret MGATHER/SCATTER's index parameter when calcula...
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
LLVM_ABI NodeType getInverseMinMaxOpcode(unsigned MinMaxOpc)
Given a MinMaxOpc of ISD::(U|S)MIN or ISD::(U|S)MAX, returns ISD::(U|S)MAX and ISD::(U|S)MIN,...
LLVM_ABI bool matchBinaryPredicate(SDValue LHS, SDValue RHS, std::function< bool(ConstantSDNode *, ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTypeMismatch=false)
Attempt to match a binary predicate against a pair of scalar/splat constants or every element of a pa...
LLVM_ABI bool isVPReduction(unsigned Opcode)
Whether this is a vector-predicated reduction opcode.
bool matchUnaryPredicate(SDValue Op, std::function< bool(ConstantSDNode *)> Match, bool AllowUndefs=false, bool AllowTruncation=false)
Hook for matching ConstantSDNode predicate.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LLVM_ABI bool isBuildVectorOfConstantFPSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantFPSDNode or undef.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
LLVM_ABI CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, EVT Type)
Return the result of a logical OR between different comparisons of identical values: ((X op1 Y) | (X ...
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
m_Intrinsic_Ty< Opnd0 >::Ty m_BitReverse(const Opnd0 &Op0)
BinaryOp_match< LHS, RHS, Instruction::URem > m_URem(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
match_deferred< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
IntrinsicID_match m_VScale()
Matches a call to llvm.vscale().
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
MaxMin_match< ICmpInst, LHS, RHS, smin_pred_ty > m_SMin(const LHS &L, const RHS &R)
CastInst_match< OpTy, FPToUIInst > m_FPToUI(const OpTy &Op)
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
OneOps_match< OpTy, Instruction::Load > m_Load(const OpTy &Op)
Matches LoadInst.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
MaxMin_match< ICmpInst, LHS, RHS, umax_pred_ty > m_UMax(const LHS &L, const RHS &R)
SelectLike_match< CondTy, LTy, RTy > m_SelectLike(const CondTy &C, const LTy &TrueC, const RTy &FalseC)
Matches a value that behaves like a boolean-controlled select, i.e.
CastOperator_match< OpTy, Instruction::BitCast > m_BitCast(const OpTy &Op)
Matches BitCast.
MaxMin_match< ICmpInst, LHS, RHS, smax_pred_ty > m_SMax(const LHS &L, const RHS &R)
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
m_Intrinsic_Ty< Opnd0, Opnd1 >::Ty m_Ctlz(const Opnd0 &Op0, const Opnd1 &Op1)
BinaryOp_match< LHS, RHS, Instruction::SRem > m_SRem(const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Or > m_Or(const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
BinOpPred_match< LHS, RHS, is_bitwiselogic_op > m_BitwiseLogic(const LHS &L, const RHS &R)
Matches bitwise logic operations.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
MaxMin_match< ICmpInst, LHS, RHS, umin_pred_ty > m_UMin(const LHS &L, const RHS &R)
LLVM_ABI Libcall getCBRT(EVT RetVT)
getCBRT - Return the CBRT_* value for the given types, or UNKNOWN_LIBCALL if there is none.
auto m_SelectCCLike(const LTy &L, const RTy &R, const TTy &T, const FTy &F, const CCTy &CC)
BinaryOpc_match< LHS, RHS > m_Srl(const LHS &L, const RHS &R)
auto m_SpecificVT(EVT RefVT, const Pattern &P)
Match a specific ValueType.
Opcode_match m_SpecificOpc(unsigned Opcode)
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
BinaryOpc_match< LHS, RHS, true > m_Clmul(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
auto m_UMaxLike(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Abs(const Opnd &Op)
Or< Preds... > m_AnyOf(const Preds &...preds)
And< Preds... > m_AllOf(const Preds &...preds)
TernaryOpc_match< T0_P, T1_P, T2_P > m_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
ReassociatableOpc_match< PatternTs... > m_ReassociatableAdd(const PatternTs &...Patterns)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
auto m_Node(unsigned Opcode, const OpndPreds &...preds)
auto m_SMaxLike(const LHS &L, const RHS &R)
SpecificNeg_match m_SpecificNeg(SDValue V)
Match a negation of a specific value V, either as sub(0, V) or as constant(s) that are the negation o...
TernaryOpc_match< T0_P, T1_P, T2_P > m_VSelect(const T0_P &Cond, const T1_P &T, const T2_P &F)
bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P)
UnaryOpc_match< Opnd > m_UnaryOp(unsigned Opc, const Opnd &Op)
auto m_SMinLike(const LHS &L, const RHS &R)
CondCode_match m_SpecificCondCode(ISD::CondCode CC)
Match a conditional code SDNode with a specific ISD::CondCode.
ReassociatableOpc_match< PatternTs... > m_ReassociatableAnd(const PatternTs &...Patterns)
NUses_match< 1, Value_match > m_OneUse()
CondCode_match m_CondCode()
Match any conditional code SDNode.
Not(const Pred &P) -> Not< Pred >
TernaryOpc_match< T0_P, T1_P, T2_P, true, false > m_c_SetCC(const T0_P &LHS, const T1_P &RHS, const T2_P &CC)
bool sd_context_match(SDValue N, const MatchContext &Ctx, Pattern &&P)
ConstantInt_match m_ConstInt()
Match any integer constants or splat of an integer constant.
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool operator<(int64_t V1, const APSInt &V2)
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
SDValue peekThroughFreeze(SDValue V)
Return the non-frozen source operand of V if it exists.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI bool isAllOnesOrAllOnesSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant -1 integer or a splatted vector of a constant -1 integer (with...
LLVM_ABI SDValue getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs)
If V is a bitwise not, returns the inverted operand.
@ Undef
Value of the register doesn't matter.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
LLVM_ABI llvm::SmallVector< int, 16 > createUnaryMask(ArrayRef< int > Mask, unsigned NumElts)
Given a shuffle mask for a binary shuffle, create the equivalent shuffle mask assuming both operands ...
bool isIntOrFPConstant(SDValue V)
Return true if V is either a integer or FP constant.
bool operator!=(uint64_t V1, const APInt &V2)
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
bool operator>=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
LLVM_ABI bool isOneOrOneSplatFP(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant floating-point value, or a splatted vector of a constant float...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool widenShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Try to transform a shuffle mask by replacing elements with the scaled index for an equivalent mask of...
int ilogb(const APFloat &Arg)
Returns the exponent of the internal representation of the APFloat.
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
LLVM_ABI bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI bool isMinSignedConstant(SDValue V)
Returns true if V is a constant min signed integer value.
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI bool isConstantOrConstantVector(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowFP=true, bool AllowOpaqueConstants=true)
Return true if the specified instruction is known to be a constant, or a vector of constants.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
bool operator>(int64_t V1, const APSInt &V2)
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
auto reverse(ContainerTy &&C)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
detail::ValueMatchesPoly< M > HasValue(M Matcher)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI SDValue peekThroughTruncates(SDValue V)
Return the non-truncated source operand of V if it exists.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
FunctionAddr VTableAddr Count
LLVM_ABI SDValue peekThroughOneUseBitcasts(SDValue V)
Return the non-bitcasted and one-use source operand of V if it exists.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
LLVM_ABI bool isOneOrOneSplat(SDValue V, bool AllowUndefs=false)
Return true if the value is a constant 1 integer or a splatted vector of a constant 1 integer (with n...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI void narrowShuffleMaskElts(int Scale, ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Replace each shuffle mask index with the scaled sequential indices for an equivalent mask of narrowed...
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
constexpr T AbsoluteDifference(U X, V Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr unsigned BitWidth
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isZeroOrZeroSplat(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant 0 integer or a splatted vector of a constant 0 integer (with n...
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
LLVM_ABI void getShuffleMaskWithWidestElts(ArrayRef< int > Mask, SmallVectorImpl< int > &ScaledMask)
Repetitively apply widenShuffleMaskElts() for as long as it succeeds, to get the shuffle mask with wi...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI bool isZeroOrZeroSplatFP(SDValue N, bool AllowUndefs=false)
Return true if the value is a constant (+/-)0.0 floating-point value or a splatted vector thereof (wi...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool operator<=(int64_t V1, const APSInt &V2)
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
LLVM_ABI int getSplatIndex(ArrayRef< int > Mask)
If all non-negative Mask elements are the same value, return that value.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
LLVM_ABI AAMDNodes concat(const AAMDNodes &Other) const
Determine the best AAMDNodes after concatenating two different locations together.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool knownBitsLE(EVT VT) const
Return true if we know at compile time this has fewer than or the same bits as VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
EVT changeTypeToInteger() const
Return the type converted to an equivalently sized integer or vector with integer element type.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isByteSized() const
Return true if the bit size is a multiple of 8.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
EVT changeVectorElementCount(LLVMContext &Context, ElementCount EC) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element coun...
bool isScalableVT() const
Return true if the type is a scalable type.
bool isFixedLengthVector() const
EVT getRoundIntegerType(LLVMContext &Context) const
Rounds the bit-width of the given integer EVT up to the nearest power of two (and at least to eight),...
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
bool bitsGE(EVT VT) const
Return true if this has no less bits than VT.
bool bitsEq(EVT VT) const
Return true if this has the same number of bits as VT.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
bool isRound() const
Return true if the size is a power-of-two number of bytes.
bool isScalableVector() const
Return true if this is a vector type where the runtime length is machine dependent.
bool knownBitsGE(EVT VT) const
Return true if we know at compile time this has more than or the same bits as VT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isExtended() const
Test if the given EVT is extended (as opposed to being simple).
EVT changeElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
LLVM_ABI const fltSemantics & getFltSemantics() const
Returns an APFloat semantics tag appropriate for the value type.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool isZeroSized() const
Test if the given EVT has zero size, this will fail if called on a scalable type.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isNonNegative() const
Returns true if this value is known to be non-negative.
bool isZero() const
Returns true if value is all zero.
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
bool isConstant() const
Returns true if we know the value of all bits.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
unsigned countMinLeadingZeros() const
Returns the minimum number of leading zero bits.
bool isNegative() const
Returns true if this value is known to be negative.
bool isAllOnes() const
Returns true if value is all one bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
FPClassTest KnownFPClasses
Floating-point classes the value could be one of.
This class contains a discriminated union of information about pointers in memory operands,...
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
These are IR-level optimization flags that may be propagated to SDNodes.
void setAllowContract(bool b)
bool hasNoUnsignedWrap() const
void setAllowReassociation(bool b)
void setAllowReciprocal(bool b)
bool hasAllowContract() const
bool hasApproximateFuncs() const
void setApproximateFuncs(bool b)
bool hasNoSignedWrap() const
bool hasAllowReciprocal() const
bool hasAllowReassociation() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
Clients of various APIs that cause global effects on the DAG can optionally implement this interface.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
LLVM_ABI void AddToWorklist(SDNode *N)
LLVM_ABI bool recursivelyDeleteUnusedNodes(SDNode *N)
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
LLVM_ABI void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...