85#define DEBUG_TYPE "dagcombine"
87STATISTIC(NodesCombined ,
"Number of dag nodes combined");
88STATISTIC(PreIndexedNodes ,
"Number of pre-indexed nodes created");
89STATISTIC(PostIndexedNodes,
"Number of post-indexed nodes created");
90STATISTIC(OpsNarrowed ,
"Number of load/op/store narrowed");
91STATISTIC(LdStFP2Int ,
"Number of fp load/store pairs transformed to int");
93STATISTIC(NumFPLogicOpsConv,
"Number of logic ops converted to fp ops");
96 "Controls whether a DAG combine is performed for a node");
100 cl::desc(
"Enable DAG combiner's use of IR alias analysis"));
104 cl::desc(
"Enable DAG combiner's use of TBAA"));
109 cl::desc(
"Only use DAG-combiner alias analysis in this"
117 cl::desc(
"Bypass the profitability model of load slicing"),
122 cl::desc(
"DAG combiner may split indexing from loads"));
126 cl::desc(
"DAG combiner enable merging multiple stores "
127 "into a wider store"));
131 cl::desc(
"Limit the number of operands to inline for Token Factors"));
135 cl::desc(
"Limit the number of times for the same StoreNode and RootNode "
136 "to bail out in store merging dependence check"));
140 cl::desc(
"DAG combiner enable reducing the width of load/op/store "
143 "combiner-reduce-load-op-store-width-force-narrowing-profitable",
145 cl::desc(
"DAG combiner force override the narrowing profitable check when "
146 "reducing the width of load/op/store sequences"));
150 cl::desc(
"DAG combiner enable load/<replace bytes>/store with "
151 "a narrower store"));
155 cl::desc(
"Disable the DAG combiner"));
165 bool LegalDAG =
false;
166 bool LegalOperations =
false;
167 bool LegalTypes =
false;
169 bool DisableGenericCombines;
205 void AddUsersToWorklist(
SDNode *
N) {
211 void AddToWorklistWithUsers(SDNode *
N) {
212 AddUsersToWorklist(
N);
219 void clearAddedDanglingWorklistEntries() {
221 while (!PruningList.empty()) {
222 auto *
N = PruningList.pop_back_val();
224 recursivelyDeleteUnusedNodes(
N);
228 SDNode *getNextWorklistEntry() {
230 clearAddedDanglingWorklistEntries();
234 while (!
N && !Worklist.empty()) {
235 N = Worklist.pop_back_val();
239 assert(
N->getCombinerWorklistIndex() >= 0 &&
240 "Found a worklist entry without a corresponding map entry!");
242 N->setCombinerWorklistIndex(-2);
252 : DAG(
D), TLI(
D.getTargetLoweringInfo()),
253 STI(
D.getSubtarget().getSelectionDAGInfo()), OptLevel(OL),
255 ForCodeSize = DAG.shouldOptForSize();
256 DisableGenericCombines =
259 MaximumLegalStoreInBits = 0;
263 if (EVT(VT).
isSimple() && VT != MVT::Other &&
264 TLI.isTypeLegal(EVT(VT)) &&
265 VT.getSizeInBits().getKnownMinValue() >= MaximumLegalStoreInBits)
266 MaximumLegalStoreInBits = VT.getSizeInBits().getKnownMinValue();
269 void ConsiderForPruning(SDNode *
N) {
271 PruningList.insert(
N);
276 void AddToWorklist(SDNode *
N,
bool IsCandidateForPruning =
true,
277 bool SkipIfCombinedBefore =
false) {
279 "Deleted Node added to Worklist");
283 if (
N->getOpcode() == ISD::HANDLENODE)
286 if (SkipIfCombinedBefore &&
N->getCombinerWorklistIndex() == -2)
289 if (IsCandidateForPruning)
290 ConsiderForPruning(
N);
292 if (
N->getCombinerWorklistIndex() < 0) {
293 N->setCombinerWorklistIndex(Worklist.size());
294 Worklist.push_back(
N);
299 void removeFromWorklist(SDNode *
N) {
300 PruningList.remove(
N);
301 StoreRootCountMap.erase(
N);
303 int WorklistIndex =
N->getCombinerWorklistIndex();
307 if (WorklistIndex < 0)
311 Worklist[WorklistIndex] =
nullptr;
312 N->setCombinerWorklistIndex(-1);
315 void deleteAndRecombine(SDNode *
N);
316 bool recursivelyDeleteUnusedNodes(SDNode *
N);
324 return CombineTo(
N, &Res, 1, AddTo);
331 return CombineTo(
N, To, 2, AddTo);
334 SDValue CombineTo(SDNode *
N, SmallVectorImpl<SDValue> *To,
336 return CombineTo(
N, To->
data(), To->
size(), AddTo);
339 void CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO);
342 unsigned MaximumLegalStoreInBits;
348 unsigned BitWidth =
Op.getScalarValueSizeInBits();
350 return SimplifyDemandedBits(
Op, DemandedBits);
353 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits) {
354 EVT VT =
Op.getValueType();
358 return SimplifyDemandedBits(
Op, DemandedBits, DemandedElts,
false);
364 bool SimplifyDemandedVectorElts(
SDValue Op) {
366 if (
Op.getValueType().isScalableVector())
369 unsigned NumElts =
Op.getValueType().getVectorNumElements();
371 return SimplifyDemandedVectorElts(
Op, DemandedElts);
374 bool SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
375 const APInt &DemandedElts,
376 bool AssumeSingleUse =
false);
377 bool SimplifyDemandedVectorElts(
SDValue Op,
const APInt &DemandedElts,
378 bool AssumeSingleUse =
false);
380 bool CombineToPreIndexedLoadStore(SDNode *
N);
381 bool CombineToPostIndexedLoadStore(SDNode *
N);
382 SDValue SplitIndexingFromLoad(LoadSDNode *LD);
383 bool SliceUpLoad(SDNode *
N);
389 StoreSDNode *getUniqueStoreFeeding(LoadSDNode *LD, int64_t &
Offset);
391 SDValue ForwardStoreValueToDirectLoad(LoadSDNode *LD);
392 bool getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val);
393 bool extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val);
395 void ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad);
404 SDValue foldShiftToAvg(SDNode *
N,
const SDLoc &
DL);
406 SDValue foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT);
424 SDValue visitTokenFactor(SDNode *
N);
425 SDValue visitMERGE_VALUES(SDNode *
N);
429 SDNode *LocReference);
440 SDValue visitUADDO_CARRY(SDNode *
N);
441 SDValue visitSADDO_CARRY(SDNode *
N);
447 SDValue visitUSUBO_CARRY(SDNode *
N);
448 SDValue visitSSUBO_CARRY(SDNode *
N);
449 template <
class MatchContextClass>
SDValue visitMUL(SDNode *
N);
470 SDValue SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL);
471 SDValue SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL);
475 SDValue visitFunnelShift(SDNode *
N);
482 SDValue visitCTLZ_ZERO_UNDEF(SDNode *
N);
484 SDValue visitCTTZ_ZERO_UNDEF(SDNode *
N);
492 SDValue visitSIGN_EXTEND(SDNode *
N);
493 SDValue visitZERO_EXTEND(SDNode *
N);
496 SDValue visitAssertAlign(SDNode *
N);
497 SDValue visitSIGN_EXTEND_INREG(SDNode *
N);
498 SDValue visitEXTEND_VECTOR_INREG(SDNode *
N);
500 SDValue visitTRUNCATE_USAT_U(SDNode *
N);
507 SDValue visitSTRICT_FADD(SDNode *
N);
510 template <
class MatchContextClass>
SDValue visitFMA(SDNode *
N);
518 SDValue visitFCANONICALIZE(SDNode *
N);
538 SDValue replaceStoreOfFPConstant(StoreSDNode *ST);
539 SDValue replaceStoreOfInsertLoad(StoreSDNode *ST);
541 bool refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(SDNode *
N);
544 SDValue visitATOMIC_STORE(SDNode *
N);
545 SDValue visitLIFETIME_END(SDNode *
N);
546 SDValue visitINSERT_VECTOR_ELT(SDNode *
N);
547 SDValue visitEXTRACT_VECTOR_ELT(SDNode *
N);
548 SDValue visitBUILD_VECTOR(SDNode *
N);
549 SDValue visitCONCAT_VECTORS(SDNode *
N);
550 SDValue visitVECTOR_INTERLEAVE(SDNode *
N);
551 SDValue visitEXTRACT_SUBVECTOR(SDNode *
N);
552 SDValue visitVECTOR_SHUFFLE(SDNode *
N);
553 SDValue visitSCALAR_TO_VECTOR(SDNode *
N);
554 SDValue visitINSERT_SUBVECTOR(SDNode *
N);
555 SDValue visitVECTOR_COMPRESS(SDNode *
N);
561 SDValue visitPARTIAL_REDUCE_MLA(SDNode *
N);
564 SDValue visitVP_STRIDED_LOAD(SDNode *
N);
565 SDValue visitVP_STRIDED_STORE(SDNode *
N);
572 SDValue visitGET_FPENV_MEM(SDNode *
N);
573 SDValue visitSET_FPENV_MEM(SDNode *
N);
575 template <
class MatchContextClass>
576 SDValue visitFADDForFMACombine(SDNode *
N);
577 template <
class MatchContextClass>
578 SDValue visitFSUBForFMACombine(SDNode *
N);
579 SDValue visitFMULForFMADistributiveCombine(SDNode *
N);
581 SDValue XformToShuffleWithZero(SDNode *
N);
582 bool reassociationCanBreakAddressingModePattern(
unsigned Opc,
588 SDValue N1, SDNodeFlags Flags);
590 SDValue N1, SDNodeFlags Flags);
591 SDValue reassociateReduction(
unsigned RedOpc,
unsigned Opc,
const SDLoc &
DL,
593 SDNodeFlags Flags = SDNodeFlags());
595 SDValue visitShiftByConstant(SDNode *
N);
597 SDValue foldSelectOfConstants(SDNode *
N);
598 SDValue foldVSelectOfConstants(SDNode *
N);
599 SDValue foldBinOpIntoSelect(SDNode *BO);
601 SDValue hoistLogicOpWithSameOpcodeHands(SDNode *
N);
605 bool NotExtCompare =
false);
606 SDValue convertSelectOfFPConstantsToLoadOffset(
609 SDValue foldSignChangeInBitcast(SDNode *
N);
612 SDValue foldSelectOfBinops(SDNode *
N);
616 SDValue foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL);
617 SDValue foldABSToABD(SDNode *
N,
const SDLoc &
DL);
622 SDValue unfoldMaskedMerge(SDNode *
N);
623 SDValue unfoldExtremeBitClearingToShifts(SDNode *
N);
625 const SDLoc &
DL,
bool foldBooleans);
629 SDValue &CC,
bool MatchStrict =
false)
const;
630 bool isOneUseSetCC(
SDValue N)
const;
632 SDValue foldAddToAvg(SDNode *
N,
const SDLoc &
DL);
633 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 convertBuildVecZextToZext(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;
1071 return !(Const->isOpaque() && NoOpaques);
1074 unsigned BitWidth =
N.getScalarValueSizeInBits();
1079 if (!Const || Const->getAPIntValue().getBitWidth() !=
BitWidth ||
1080 (Const->isOpaque() && NoOpaques))
1102bool DAGCombiner::reassociationCanBreakAddressingModePattern(
unsigned Opc,
1128 int64_t ScalableOffset = N1.
getOpcode() == ISD::VSCALE
1130 : (N1.
getOperand(0).getConstantOperandVal(0) *
1135 ScalableOffset = -ScalableOffset;
1136 if (
all_of(
N->users(), [&](SDNode *Node) {
1137 if (auto *LoadStore = dyn_cast<MemSDNode>(Node);
1138 LoadStore && LoadStore->getBasePtr().getNode() == N) {
1139 TargetLoweringBase::AddrMode AM;
1140 AM.HasBaseReg = true;
1141 AM.ScalableOffset = ScalableOffset;
1142 EVT VT = LoadStore->getMemoryVT();
1143 unsigned AS = LoadStore->getAddressSpace();
1144 Type *AccessTy = VT.getTypeForEVT(*DAG.getContext());
1145 return TLI.isLegalAddressingMode(DAG.getDataLayout(), AM, AccessTy,
1160 const APInt &C2APIntVal = C2->getAPIntValue();
1168 const APInt &C1APIntVal = C1->getAPIntValue();
1169 const APInt CombinedValueIntVal = C1APIntVal + C2APIntVal;
1172 const int64_t CombinedValue = CombinedValueIntVal.
getSExtValue();
1174 for (SDNode *Node :
N->users()) {
1179 TargetLoweringBase::AddrMode AM;
1181 AM.
BaseOffs = C2APIntVal.getSExtValue();
1183 unsigned AS =
LoadStore->getAddressSpace();
1199 for (SDNode *Node :
N->users()) {
1206 TargetLoweringBase::AddrMode AM;
1208 AM.
BaseOffs = C2APIntVal.getSExtValue();
1210 unsigned AS =
LoadStore->getAddressSpace();
1223SDValue DAGCombiner::reassociateOpsCommutative(
unsigned Opc,
const SDLoc &
DL,
1225 SDNodeFlags Flags) {
1235 SDNodeFlags NewFlags;
1237 Flags.hasNoUnsignedWrap())
1245 return DAG.
getNode(
Opc,
DL, VT, N00, OpNode, NewFlags);
1253 return DAG.
getNode(
Opc,
DL, VT, OpNode, N01, NewFlags);
1263 if (N1 == N00 || N1 == N01)
1309 if (CC1 == CC00 && CC1 != CC01) {
1313 if (CC1 == CC01 && CC1 != CC00) {
1327 SDValue N1, SDNodeFlags Flags) {
1333 if (!
Flags.hasAllowReassociation() || !
Flags.hasNoSignedZeros())
1336 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N0, N1, Flags))
1338 if (
SDValue Combined = reassociateOpsCommutative(
Opc,
DL, N1, N0, Flags))
1346SDValue DAGCombiner::reassociateReduction(
unsigned RedOpc,
unsigned Opc,
1348 SDValue N1, SDNodeFlags Flags) {
1354 SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
1376 A.getValueType() ==
C.getValueType() &&
1377 hasOperation(
Opc,
A.getValueType()) &&
1385 SelectionDAG::FlagInserter FlagsInserter(
1396SDValue DAGCombiner::CombineTo(SDNode *
N,
const SDValue *To,
unsigned NumTo,
1398 assert(
N->getNumValues() == NumTo &&
"Broken CombineTo call!");
1402 dbgs() <<
" and " << NumTo - 1 <<
" other values\n");
1403 for (
unsigned i = 0, e = NumTo; i !=
e; ++i)
1405 N->getValueType(i) == To[i].getValueType()) &&
1406 "Cannot combine value to value of different type!");
1408 WorklistRemover DeadNodes(*
this);
1412 for (
unsigned i = 0, e = NumTo; i !=
e; ++i) {
1414 AddToWorklistWithUsers(To[i].
getNode());
1422 deleteAndRecombine(
N);
1427CommitTargetLoweringOpt(
const TargetLowering::TargetLoweringOpt &TLO) {
1440 recursivelyDeleteUnusedNodes(TLO.
Old.
getNode());
1445bool DAGCombiner::SimplifyDemandedBits(
SDValue Op,
const APInt &DemandedBits,
1446 const APInt &DemandedElts,
1447 bool AssumeSingleUse) {
1448 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1455 AddToWorklist(
Op.getNode());
1457 CommitTargetLoweringOpt(TLO);
1464bool DAGCombiner::SimplifyDemandedVectorElts(
SDValue Op,
1465 const APInt &DemandedElts,
1466 bool AssumeSingleUse) {
1467 TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations);
1468 APInt KnownUndef, KnownZero;
1470 TLO, 0, AssumeSingleUse))
1474 AddToWorklist(
Op.getNode());
1476 CommitTargetLoweringOpt(TLO);
1480void DAGCombiner::ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad) {
1482 EVT VT =
Load->getValueType(0);
1491 AddToWorklist(Trunc.
getNode());
1492 recursivelyDeleteUnusedNodes(Load);
1500 EVT MemVT =
LD->getMemoryVT();
1502 :
LD->getExtensionType();
1505 LD->getChain(),
LD->getBasePtr(),
1506 MemVT,
LD->getMemOperand());
1509 unsigned Opc =
Op.getOpcode();
1513 if (
SDValue Op0 = SExtPromoteOperand(
Op.getOperand(0), PVT))
1517 if (
SDValue Op0 = ZExtPromoteOperand(
Op.getOperand(0), PVT))
1535 EVT OldVT =
Op.getValueType();
1537 bool Replace =
false;
1538 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1541 AddToWorklist(NewOp.
getNode());
1544 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1550 EVT OldVT =
Op.getValueType();
1552 bool Replace =
false;
1553 SDValue NewOp = PromoteOperand(
Op, PVT, Replace);
1556 AddToWorklist(NewOp.
getNode());
1559 ReplaceLoadWithPromotedLoad(
Op.getNode(), NewOp.
getNode());
1567 if (!LegalOperations)
1570 EVT VT =
Op.getValueType();
1576 unsigned Opc =
Op.getOpcode();
1584 assert(PVT != VT &&
"Don't know what type to promote to!");
1588 bool Replace0 =
false;
1590 SDValue NN0 = PromoteOperand(N0, PVT, Replace0);
1592 bool Replace1 =
false;
1594 SDValue NN1 = PromoteOperand(N1, PVT, Replace1);
1606 Replace1 &= (N0 != N1) && !N1->
hasOneUse();
1609 CombineTo(
Op.getNode(), RV);
1635 if (!LegalOperations)
1638 EVT VT =
Op.getValueType();
1644 unsigned Opc =
Op.getOpcode();
1652 assert(PVT != VT &&
"Don't know what type to promote to!");
1656 bool Replace =
false;
1659 N0 = SExtPromoteOperand(N0, PVT);
1661 N0 = ZExtPromoteOperand(N0, PVT);
1663 N0 = PromoteOperand(N0, PVT, Replace);
1674 ReplaceLoadWithPromotedLoad(
Op.getOperand(0).getNode(), N0.
getNode());
1684 if (!LegalOperations)
1687 EVT VT =
Op.getValueType();
1693 unsigned Opc =
Op.getOpcode();
1701 assert(PVT != VT &&
"Don't know what type to promote to!");
1706 return DAG.
getNode(
Op.getOpcode(), SDLoc(
Op), VT,
Op.getOperand(0));
1711bool DAGCombiner::PromoteLoad(
SDValue Op) {
1712 if (!LegalOperations)
1718 EVT VT =
Op.getValueType();
1724 unsigned Opc =
Op.getOpcode();
1732 assert(PVT != VT &&
"Don't know what type to promote to!");
1735 SDNode *
N =
Op.getNode();
1737 EVT MemVT =
LD->getMemoryVT();
1739 :
LD->getExtensionType();
1741 LD->getChain(),
LD->getBasePtr(),
1742 MemVT,
LD->getMemOperand());
1751 AddToWorklist(
Result.getNode());
1752 recursivelyDeleteUnusedNodes(
N);
1765bool DAGCombiner::recursivelyDeleteUnusedNodes(SDNode *
N) {
1766 if (!
N->use_empty())
1769 SmallSetVector<SDNode *, 16> Nodes;
1776 if (
N->use_empty()) {
1777 for (
const SDValue &ChildN :
N->op_values())
1778 Nodes.
insert(ChildN.getNode());
1780 removeFromWorklist(
N);
1785 }
while (!Nodes.
empty());
1800 WorklistInserter AddNodes(*
this);
1808 for (SDNode &Node : DAG.
allnodes())
1809 AddToWorklist(&Node,
Node.use_empty());
1814 HandleSDNode Dummy(DAG.
getRoot());
1817 while (SDNode *
N = getNextWorklistEntry()) {
1821 if (recursivelyDeleteUnusedNodes(
N))
1824 WorklistRemover DeadNodes(*
this);
1829 SmallSetVector<SDNode *, 16> UpdatedNodes;
1832 for (SDNode *LN : UpdatedNodes)
1833 AddToWorklistWithUsers(LN);
1845 for (
const SDValue &ChildN :
N->op_values())
1846 AddToWorklist(ChildN.getNode(),
true,
1857 ChainsWithoutMergeableStores.
clear();
1868 "Node was deleted but visit returned new node!");
1876 N->getNumValues() == 1 &&
"Type mismatch");
1886 AddToWorklistWithUsers(RV.
getNode());
1892 recursivelyDeleteUnusedNodes(
N);
1896 DAG.
setRoot(Dummy.getValue());
1900SDValue DAGCombiner::visit(SDNode *
N) {
1902 switch (
N->getOpcode()) {
1907 case ISD::PTRADD:
return visitPTRADD(
N);
1929 case ISD::MUL:
return visitMUL<EmptyMatchContext>(
N);
1987 case ISD::BITCAST:
return visitBITCAST(
N);
1993 case ISD::FMA:
return visitFMA<EmptyMatchContext>(
N);
1998 case ISD::FSQRT:
return visitFSQRT(
N);
2000 case ISD::FPOW:
return visitFPOW(
N);
2008 case ISD::LLRINT:
return visitXROUND(
N);
2010 case ISD::FP_EXTEND:
return visitFP_EXTEND(
N);
2011 case ISD::FNEG:
return visitFNEG(
N);
2012 case ISD::FABS:
return visitFABS(
N);
2013 case ISD::FFLOOR:
return visitFFLOOR(
N);
2018 case ISD::FMINIMUMNUM:
2019 case ISD::FMAXIMUMNUM:
return visitFMinMax(
N);
2020 case ISD::FCEIL:
return visitFCEIL(
N);
2021 case ISD::FTRUNC:
return visitFTRUNC(
N);
2022 case ISD::FFREXP:
return visitFFREXP(
N);
2023 case ISD::BRCOND:
return visitBRCOND(
N);
2024 case ISD::BR_CC:
return visitBR_CC(
N);
2025 case ISD::LOAD:
return visitLOAD(
N);
2026 case ISD::STORE:
return visitSTORE(
N);
2027 case ISD::ATOMIC_STORE:
return visitATOMIC_STORE(
N);
2037 case ISD::MGATHER:
return visitMGATHER(
N);
2038 case ISD::MLOAD:
return visitMLOAD(
N);
2039 case ISD::MSCATTER:
return visitMSCATTER(
N);
2040 case ISD::MSTORE:
return visitMSTORE(
N);
2041 case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM:
return visitMHISTOGRAM(
N);
2042 case ISD::PARTIAL_REDUCE_SMLA:
2043 case ISD::PARTIAL_REDUCE_UMLA:
2044 case ISD::PARTIAL_REDUCE_SUMLA:
2045 return visitPARTIAL_REDUCE_MLA(
N);
2047 case ISD::LIFETIME_END:
return visitLIFETIME_END(
N);
2048 case ISD::FP_TO_FP16:
return visitFP_TO_FP16(
N);
2049 case ISD::FP16_TO_FP:
return visitFP16_TO_FP(
N);
2050 case ISD::FP_TO_BF16:
return visitFP_TO_BF16(
N);
2051 case ISD::BF16_TO_FP:
return visitBF16_TO_FP(
N);
2053 case ISD::GET_FPENV_MEM:
return visitGET_FPENV_MEM(
N);
2054 case ISD::SET_FPENV_MEM:
return visitSET_FPENV_MEM(
N);
2056 case ISD::VECREDUCE_FADD:
2057 case ISD::VECREDUCE_FMUL:
2058 case ISD::VECREDUCE_ADD:
2059 case ISD::VECREDUCE_MUL:
2060 case ISD::VECREDUCE_AND:
2061 case ISD::VECREDUCE_OR:
2062 case ISD::VECREDUCE_XOR:
2063 case ISD::VECREDUCE_SMAX:
2064 case ISD::VECREDUCE_SMIN:
2065 case ISD::VECREDUCE_UMAX:
2066 case ISD::VECREDUCE_UMIN:
2067 case ISD::VECREDUCE_FMAX:
2068 case ISD::VECREDUCE_FMIN:
2069 case ISD::VECREDUCE_FMAXIMUM:
2070 case ISD::VECREDUCE_FMINIMUM:
return visitVECREDUCE(
N);
2071#define BEGIN_REGISTER_VP_SDNODE(SDOPC, ...) case ISD::SDOPC:
2072#include "llvm/IR/VPIntrinsics.def"
2073 return visitVPOp(
N);
2079SDValue DAGCombiner::combine(SDNode *
N) {
2084 if (!DisableGenericCombines)
2090 "Node was deleted but visit returned NULL!");
2096 TargetLowering::DAGCombinerInfo
2097 DagCombineInfo(DAG, Level,
false,
this);
2105 switch (
N->getOpcode()) {
2113 RV = PromoteIntBinOp(
SDValue(
N, 0));
2118 RV = PromoteIntShiftOp(
SDValue(
N, 0));
2154 if (
unsigned NumOps =
N->getNumOperands()) {
2155 if (
N->getOperand(0).getValueType() == MVT::Other)
2156 return N->getOperand(0);
2157 if (
N->getOperand(
NumOps-1).getValueType() == MVT::Other)
2158 return N->getOperand(
NumOps-1);
2159 for (
unsigned i = 1; i <
NumOps-1; ++i)
2160 if (
N->getOperand(i).getValueType() == MVT::Other)
2161 return N->getOperand(i);
2166SDValue DAGCombiner::visitFCANONICALIZE(SDNode *
N) {
2167 SDValue Operand =
N->getOperand(0);
2179SDValue DAGCombiner::visitTokenFactor(SDNode *
N) {
2182 if (
N->getNumOperands() == 2) {
2184 return N->getOperand(0);
2186 return N->getOperand(1);
2201 AddToWorklist(*(
N->user_begin()));
2205 SmallPtrSet<SDNode*, 16> SeenOps;
2213 for (
unsigned i = 0; i < TFs.
size(); ++i) {
2218 for (
unsigned j = i;
j < TFs.
size();
j++)
2219 Ops.emplace_back(TFs[j], 0);
2226 SDNode *TF = TFs[i];
2229 switch (
Op.getOpcode()) {
2247 if (SeenOps.
insert(
Op.getNode()).second)
2258 for (
unsigned i = 1, e = TFs.
size(); i < e; i++)
2259 AddToWorklist(TFs[i]);
2269 SmallVector<unsigned, 8> OpWorkCount;
2270 SmallPtrSet<SDNode *, 16> SeenChains;
2271 bool DidPruneOps =
false;
2273 unsigned NumLeftToConsider = 0;
2275 Worklist.
push_back(std::make_pair(
Op.getNode(), NumLeftToConsider++));
2279 auto AddToWorklist = [&](
unsigned CurIdx, SDNode *
Op,
unsigned OpNumber) {
2285 unsigned OrigOpNumber = 0;
2286 while (OrigOpNumber <
Ops.size() &&
Ops[OrigOpNumber].getNode() !=
Op)
2289 "expected to find TokenFactor Operand");
2291 for (
unsigned i = CurIdx + 1; i < Worklist.
size(); ++i) {
2292 if (Worklist[i].second == OrigOpNumber) {
2293 Worklist[i].second = OpNumber;
2296 OpWorkCount[OpNumber] += OpWorkCount[OrigOpNumber];
2297 OpWorkCount[OrigOpNumber] = 0;
2298 NumLeftToConsider--;
2301 if (SeenChains.
insert(
Op).second) {
2302 OpWorkCount[OpNumber]++;
2307 for (
unsigned i = 0; i < Worklist.
size() && i < 1024; ++i) {
2309 if (NumLeftToConsider <= 1)
2311 auto CurNode = Worklist[i].first;
2312 auto CurOpNumber = Worklist[i].second;
2313 assert((OpWorkCount[CurOpNumber] > 0) &&
2314 "Node should not appear in worklist");
2315 switch (CurNode->getOpcode()) {
2321 NumLeftToConsider++;
2324 for (
const SDValue &
Op : CurNode->op_values())
2325 AddToWorklist(i,
Op.getNode(), CurOpNumber);
2327 case ISD::LIFETIME_START:
2328 case ISD::LIFETIME_END:
2331 AddToWorklist(i, CurNode->getOperand(0).getNode(), CurOpNumber);
2335 AddToWorklist(i, MemNode->getChain().getNode(), CurOpNumber);
2338 OpWorkCount[CurOpNumber]--;
2339 if (OpWorkCount[CurOpNumber] == 0)
2340 NumLeftToConsider--;
2354 if (SeenChains.
count(
Op.getNode()) == 0)
2368SDValue DAGCombiner::visitMERGE_VALUES(SDNode *
N) {
2369 WorklistRemover DeadNodes(*
this);
2375 AddUsersToWorklist(
N);
2380 }
while (!
N->use_empty());
2381 deleteAndRecombine(
N);
2389 return Const !=
nullptr && !Const->isOpaque() ? Const :
nullptr;
2399 Op =
N->getOperand(0);
2401 if (
N->getFlags().hasNoUnsignedWrap())
2406 if (
N.getValueType().getScalarType() != MVT::i1 ||
2423 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2425 VT = LD->getMemoryVT();
2426 AS = LD->getAddressSpace();
2428 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2430 VT = ST->getMemoryVT();
2431 AS = ST->getAddressSpace();
2433 if (LD->isIndexed() || LD->getBasePtr().getNode() !=
N)
2435 VT = LD->getMemoryVT();
2436 AS = LD->getAddressSpace();
2438 if (ST->isIndexed() || ST->getBasePtr().getNode() !=
N)
2440 VT = ST->getMemoryVT();
2441 AS = ST->getAddressSpace();
2447 if (
N->isAnyAdd()) {
2456 }
else if (
N->getOpcode() ==
ISD::SUB) {
2478 bool ShouldCommuteOperands) {
2484 if (ShouldCommuteOperands)
2498 unsigned Opcode =
N->getOpcode();
2499 EVT VT =
N->getValueType(0);
2504 unsigned OpNo = ShouldCommuteOperands ? 0 : 1;
2524SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) {
2527 "Unexpected binary operator");
2539 unsigned SelOpNo = 0;
2576 bool CanFoldNonConst =
2582 if (!CanFoldNonConst &&
2591 if (CanFoldNonConst) {
2610 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CT, CBO});
2615 : DAG.FoldConstantArithmetic(BinOpcode,
DL, VT, {CF, CBO});
2626 "Expecting add or sub");
2631 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2632 SDValue C = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2633 SDValue Z = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2639 if (Z.getOperand(0).getValueType() != MVT::i1)
2651 EVT VT =
C.getValueType();
2659SDValue DAGCombiner::foldSubToAvg(SDNode *
N,
const SDLoc &
DL) {
2664 if ((!LegalOperations || hasOperation(
ISD::AVGCEILU, VT)) &&
2669 if ((!LegalOperations || hasOperation(
ISD::AVGCEILS, VT)) &&
2680SDValue DAGCombiner::visitPTRADD(SDNode *
N) {
2690 "PTRADD with different operand types is not supported");
2701 !reassociationCanBreakAddressingModePattern(ISD::PTRADD,
DL,
N, N0, N1)) {
2712 if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) {
2717 AddToWorklist(
Add.getNode());
2741 if (
const GlobalAddressSDNode *GA =
2756 AddToWorklist(Inner.
getNode());
2778 SDNodeFlags CommonFlags =
N->getFlags() & N1->
getFlags();
2786 if (ZIsConstant != YIsConstant) {
2790 AddToWorklist(Inner.
getNode());
2800 bool TransformCannotBreakAddrMode =
none_of(
N->users(), [&](SDNode *User) {
2801 return canFoldInAddressingMode(N, User, DAG, TLI);
2804 if (TransformCannotBreakAddrMode)
2816 "Expecting add or sub");
2820 bool IsAdd =
N->getOpcode() ==
ISD::ADD;
2821 SDValue ConstantOp = IsAdd ?
N->getOperand(1) :
N->getOperand(0);
2822 SDValue ShiftOp = IsAdd ?
N->getOperand(0) :
N->getOperand(1);
2844 {ConstantOp, DAG.getConstant(1, DL, VT)})) {
2846 Not.getOperand(0), ShAmt);
2862SDValue DAGCombiner::visitADDLike(SDNode *
N) {
2888 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
2920 if ((!LegalOperations ||
2923 X.getScalarValueSizeInBits() == 1) {
2939 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
2943 if (!reassociationCanBreakAddressingModePattern(
ISD::ADD,
DL,
N, N0, N1)) {
2977 reassociateReduction(ISD::VECREDUCE_ADD,
ISD::ADD,
DL, VT, N0, N1))
3030 auto MatchUSUBSAT = [](ConstantSDNode *
Max, ConstantSDNode *
Op) {
3031 return (!Max && !
Op) ||
3032 (
Max &&
Op &&
Max->getAPIntValue() == (-
Op->getAPIntValue()));
3073 !
N->getFlags().hasNoSignedWrap()))) {
3094 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3098 if (
N->getFlags().hasNoUnsignedWrap() &&
3102 if (
N->getFlags().hasNoSignedWrap() &&
3111 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3119 (CA * CM + CB->getAPIntValue()).getSExtValue())) {
3125 if (
N->getFlags().hasNoUnsignedWrap() &&
3130 if (
N->getFlags().hasNoSignedWrap() &&
3141 DAG.
getConstant(CA * CM + CB->getAPIntValue(),
DL, VT), Flags);
3146 if (
SDValue Combined = visitADDLikeCommutative(N0, N1,
N))
3149 if (
SDValue Combined = visitADDLikeCommutative(N1, N0,
N))
3156SDValue DAGCombiner::foldAddToAvg(SDNode *
N,
const SDLoc &
DL) {
3175SDValue DAGCombiner::visitADD(SDNode *
N) {
3181 if (
SDValue Combined = visitADDLike(
N))
3190 if (
SDValue V = MatchRotate(N0, N1, SDLoc(
N),
true))
3224 APInt NewStep = C0 + C1;
3234 APInt NewStep = SV0 + SV1;
3242SDValue DAGCombiner::visitADDSAT(SDNode *
N) {
3243 unsigned Opcode =
N->getOpcode();
3261 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
3265 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
3285 bool ForceCarryReconstruction =
false) {
3291 V = V.getOperand(0);
3296 if (ForceCarryReconstruction)
3300 V = V.getOperand(0);
3304 if (ForceCarryReconstruction && V.getValueType() == MVT::i1)
3311 if (V.getResNo() != 1)
3318 EVT VT = V->getValueType(0);
3362 SDNode *LocReference) {
3364 SDLoc
DL(LocReference);
3426 if (TN->
getVT() == MVT::i1) {
3443 DAG.
getVTList(VT, Carry.getValueType()), N0,
3449SDValue DAGCombiner::visitADDC(SDNode *
N) {
3456 if (!
N->hasAnyUseOfValue(1))
3496 return V.getOperand(0);
3502SDValue DAGCombiner::visitADDO(SDNode *
N) {
3508 EVT CarryVT =
N->getValueType(1);
3512 if (!
N->hasAnyUseOfValue(1))
3519 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
3544 if (
SDValue Combined = visitUADDOLike(N0, N1,
N))
3547 if (
SDValue Combined = visitUADDOLike(N1, N0,
N))
3578SDValue DAGCombiner::visitADDE(SDNode *
N) {
3597SDValue DAGCombiner::visitUADDO_CARRY(SDNode *
N) {
3611 if (!LegalOperations ||
3621 AddToWorklist(CarryExt.
getNode());
3627 if (
SDValue Combined = visitUADDO_CARRYLike(N0, N1, CarryIn,
N))
3630 if (
SDValue Combined = visitUADDO_CARRYLike(N1, N0, CarryIn,
N))
3777 EVT CarryOutType =
N->getValueType(0);
3793 unsigned CarryInOperandNum =
3795 if (Opcode ==
ISD::USUBO && CarryInOperandNum != 1)
3886SDValue DAGCombiner::visitSADDO_CARRY(SDNode *
N) {
3900 if (!LegalOperations ||
3905 if (
SDValue Combined = visitSADDO_CARRYLike(N0, N1, CarryIn,
N))
3908 if (
SDValue Combined = visitSADDO_CARRYLike(N1, N0, CarryIn,
N))
3920 "Illegal truncation");
3944SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *
N,
const SDLoc &
DL) {
3946 !(!LegalOperations || hasOperation(
ISD::USUBSAT, DstVT)))
3949 EVT SubVT =
N->getValueType(0);
4017template <
class MatchContextClass>
4040 if ((
BitWidth - Src.getValueType().getScalarSizeInBits()) != BitWidthDiff)
4050 if (!(AndMask.
isMask(AndMaskWidth) && XorMask.
countr_one() >= AndMaskWidth))
4073 DivRem.getResNo() == 0 && DivRem.getOperand(0) == Sub0 &&
4074 DivRem.getOperand(1) == MaybeY) {
4075 return SDValue(DivRem.getNode(), 1);
4085 if (
SDValue Res = CheckAndFoldMulCase(Mul0, Mul1))
4088 if (
SDValue Res = CheckAndFoldMulCase(Mul1, Mul0))
4126SDValue DAGCombiner::visitSUB(SDNode *
N) {
4146 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4173 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4196 if (
N->getFlags().hasNoUnsignedWrap())
4202 if (
N->getFlags().hasNoSignedWrap())
4228 if (hasOperation(NewOpc, VT))
4373 if (!reassociationCanBreakAddressingModePattern(
ISD::SUB,
DL,
N, N0, N1) &&
4411 if ((!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4421 if (GA->getGlobal() == GB->getGlobal())
4422 return DAG.
getConstant((uint64_t)GA->getOffset() - GB->getOffset(),
4429 if (TN->
getVT() == MVT::i1) {
4482 DAG.
getVTList(VT, Carry.getValueType()), NegX, Zero,
4490 if (!C0->isOpaque()) {
4491 const APInt &C0Val = C0->getAPIntValue();
4492 const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero;
4493 if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes))
4499 if ((!LegalOperations || hasOperation(
ISD::ABDS, VT)) &&
4511 if ((!LegalOperations || hasOperation(
ISD::ABDU, VT)) &&
4525SDValue DAGCombiner::visitSUBSAT(SDNode *
N) {
4526 unsigned Opcode =
N->getOpcode();
4547 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4566SDValue DAGCombiner::visitSUBC(SDNode *
N) {
4573 if (!
N->hasAnyUseOfValue(1))
4594SDValue DAGCombiner::visitSUBO(SDNode *
N) {
4600 EVT CarryVT =
N->getValueType(1);
4604 if (!
N->hasAnyUseOfValue(1))
4636SDValue DAGCombiner::visitSUBE(SDNode *
N) {
4648SDValue DAGCombiner::visitUSUBO_CARRY(SDNode *
N) {
4655 if (!LegalOperations ||
4663SDValue DAGCombiner::visitSSUBO_CARRY(SDNode *
N) {
4670 if (!LegalOperations ||
4680SDValue DAGCombiner::visitMULFIX(SDNode *
N) {
4693 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0, Scale);
4702template <
class MatchContextClass>
SDValue DAGCombiner::visitMUL(SDNode *
N) {
4708 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
4709 MatchContextClass Matcher(DAG, TLI,
N);
4724 bool N1IsConst =
false;
4725 bool N1IsOpaqueConst =
false;
4732 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
4737 "Splat APInt should be element width");
4747 if (N1IsConst && ConstValue1.
isZero())
4751 if (N1IsConst && ConstValue1.
isOne())
4755 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
4759 if (N1IsConst && ConstValue1.
isAllOnes())
4765 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
4769 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap());
4771 return Matcher.getNode(
ISD::SHL,
DL, VT, N0, Trunc, Flags);
4777 unsigned Log2Val = (-ConstValue1).logBase2();
4781 return Matcher.getNode(
4792 SDVTList LoHiVT = DAG.
getVTList(VT, VT);
4795 if (LoHi->hasAnyUseOfValue(1))
4798 if (LoHi->hasAnyUseOfValue(1))
4819 if (!UseVP && N1IsConst &&
4825 APInt MulC = ConstValue1.
abs();
4827 unsigned TZeros = MulC == 2 ? 0 : MulC.
countr_zero();
4829 if ((MulC - 1).isPowerOf2())
4831 else if ((MulC + 1).isPowerOf2())
4836 MathOp ==
ISD::ADD ? (MulC - 1).logBase2() : (MulC + 1).logBase2();
4839 "multiply-by-constant generated out of bounds shift");
4843 TZeros ? DAG.
getNode(MathOp,
DL, VT, Shl,
4885 return Matcher.getNode(
4892 if (!UseVP && N0.
getOpcode() == ISD::VSCALE && NC1) {
4903 APInt NewStep = C0 * MulVal;
4909 if (!UseVP && (!LegalOperations || hasOperation(
ISD::ABS, VT)) &&
4923 SmallBitVector ClearMask;
4925 auto IsClearMask = [&ClearMask](ConstantSDNode *
V) {
4926 if (!V ||
V->isZero()) {
4940 for (
unsigned I = 0;
I != NumElts; ++
I)
4957 reassociateReduction(ISD::VECREDUCE_MUL,
ISD::MUL,
DL, VT, N0, N1))
4971 EVT NodeType =
Node->getValueType(0);
4972 if (!NodeType.isSimple())
4974 switch (NodeType.getSimpleVT().SimpleTy) {
4975 default:
return false;
4976 case MVT::i8: LC=
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
4977 case MVT::i16: LC=
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
4978 case MVT::i32: LC=
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
4979 case MVT::i64: LC=
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
4980 case MVT::i128: LC=
isSigned ? RTLIB::SDIVREM_I128:RTLIB::UDIVREM_I128;
break;
4987SDValue DAGCombiner::useDivRem(SDNode *Node) {
4988 if (
Node->use_empty())
4991 unsigned Opcode =
Node->getOpcode();
4996 EVT VT =
Node->getValueType(0);
5010 unsigned OtherOpcode = 0;
5024 for (SDNode *User : Op0->
users()) {
5031 unsigned UserOpc =
User->getOpcode();
5032 if ((UserOpc == Opcode || UserOpc == OtherOpcode || UserOpc == DivRemOpc) &&
5033 User->getOperand(0) == Op0 &&
5034 User->getOperand(1) == Op1) {
5036 if (UserOpc == OtherOpcode) {
5038 combined = DAG.
getNode(DivRemOpc, SDLoc(Node), VTs, Op0, Op1);
5039 }
else if (UserOpc == DivRemOpc) {
5042 assert(UserOpc == Opcode);
5047 CombineTo(User, combined);
5049 CombineTo(User, combined.
getValue(1));
5058 EVT VT =
N->getValueType(0);
5061 unsigned Opc =
N->getOpcode();
5080 if (N0C && N0C->
isZero())
5100SDValue DAGCombiner::visitSDIV(SDNode *
N) {
5103 EVT VT =
N->getValueType(0);
5113 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5130 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5138 if (
SDValue V = visitSDIVLike(N0, N1,
N)) {
5145 if (!
N->getFlags().hasExact()) {
5148 AddToWorklist(
Mul.getNode());
5149 AddToWorklist(
Sub.getNode());
5150 CombineTo(RemNode,
Sub);
5171 if (
C->isZero() ||
C->isOpaque())
5173 if (
C->getAPIntValue().isPowerOf2())
5175 if (
C->getAPIntValue().isNegatedPowerOf2())
5185 EVT VT =
N->getValueType(0);
5210 AddToWorklist(Sign.
getNode());
5216 AddToWorklist(
Add.getNode());
5227 Sra = DAG.
getSelect(
DL, VT, IsOneOrAllOnes, N0, Sra);
5252SDValue DAGCombiner::visitUDIV(SDNode *
N) {
5255 EVT VT =
N->getValueType(0);
5265 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5279 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5282 if (
SDValue V = visitUDIVLike(N0, N1,
N)) {
5289 if (!
N->getFlags().hasExact()) {
5292 AddToWorklist(
Mul.getNode());
5293 AddToWorklist(
Sub.getNode());
5294 CombineTo(RemNode,
Sub);
5319 EVT VT =
N->getValueType(0);
5323 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5324 AddToWorklist(LogBase2.getNode());
5328 AddToWorklist(Trunc.
getNode());
5337 if (
SDValue LogBase2 = BuildLogBase2(N10,
DL)) {
5338 AddToWorklist(LogBase2.getNode());
5342 AddToWorklist(Trunc.
getNode());
5344 AddToWorklist(
Add.getNode());
5371SDValue DAGCombiner::visitREM(SDNode *
N) {
5372 unsigned Opcode =
N->getOpcode();
5375 EVT VT =
N->getValueType(0);
5397 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
5410 AddToWorklist(
Add.getNode());
5421 AddToWorklist(
Add.getNode());
5438 if (
SDValue OptimizedRem = buildOptimizedSREM(N0, N1,
N))
5439 return OptimizedRem;
5443 isSigned ? visitSDIVLike(N0, N1,
N) : visitUDIVLike(N0, N1,
N);
5446 unsigned DivOpcode = isSigned ? ISD::SDIV : ISD::UDIV;
5447 if (SDNode *DivNode = DAG.getNodeIfExists(DivOpcode, N->getVTList(),
5449 CombineTo(DivNode, OptimizedDiv);
5452 AddToWorklist(OptimizedDiv.
getNode());
5453 AddToWorklist(
Mul.getNode());
5460 return DivRem.getValue(1);
5483SDValue DAGCombiner::visitMULHS(SDNode *
N) {
5486 EVT VT =
N->getValueType(0);
5499 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5542SDValue DAGCombiner::visitMULHU(SDNode *
N) {
5545 EVT VT =
N->getValueType(0);
5558 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5582 if (
SDValue LogBase2 = BuildLogBase2(N1,
DL)) {
5597 unsigned SimpleSize =
Simple.getSizeInBits();
5618SDValue DAGCombiner::visitAVG(SDNode *
N) {
5619 unsigned Opcode =
N->getOpcode();
5622 EVT VT =
N->getValueType(0);
5633 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5636 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5662 X.getValueType() ==
Y.getValueType() &&
5663 hasOperation(Opcode,
X.getValueType())) {
5669 X.getValueType() ==
Y.getValueType() &&
5670 hasOperation(Opcode,
X.getValueType())) {
5703 if (IsSigned &&
Add->getFlags().hasNoSignedWrap())
5706 if (!IsSigned &&
Add->getFlags().hasNoUnsignedWrap())
5720SDValue DAGCombiner::visitABD(SDNode *
N) {
5721 unsigned Opcode =
N->getOpcode();
5724 EVT VT =
N->getValueType(0);
5734 return DAG.
getNode(Opcode,
DL,
N->getVTList(), N1, N0);
5737 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
5752 (!LegalOperations || hasOperation(
ISD::ABS, VT)))
5770SDValue DAGCombiner::SimplifyNodeWithTwoResults(SDNode *
N,
unsigned LoOp,
5773 bool HiExists =
N->hasAnyUseOfValue(1);
5774 if (!HiExists && (!LegalOperations ||
5777 return CombineTo(
N, Res, Res);
5781 bool LoExists =
N->hasAnyUseOfValue(0);
5782 if (!LoExists && (!LegalOperations ||
5785 return CombineTo(
N, Res, Res);
5789 if (LoExists && HiExists)
5795 AddToWorklist(
Lo.getNode());
5798 (!LegalOperations ||
5800 return CombineTo(
N, LoOpt, LoOpt);
5805 AddToWorklist(
Hi.getNode());
5808 (!LegalOperations ||
5810 return CombineTo(
N, HiOpt, HiOpt);
5816SDValue DAGCombiner::visitSMUL_LOHI(SDNode *
N) {
5822 EVT VT =
N->getValueType(0);
5838 unsigned SimpleSize =
Simple.getSizeInBits();
5850 return CombineTo(
N,
Lo,
Hi);
5857SDValue DAGCombiner::visitUMUL_LOHI(SDNode *
N) {
5863 EVT VT =
N->getValueType(0);
5878 return CombineTo(
N, Zero, Zero);
5884 return CombineTo(
N, N0, Zero);
5891 unsigned SimpleSize =
Simple.getSizeInBits();
5903 return CombineTo(
N,
Lo,
Hi);
5910SDValue DAGCombiner::visitMULO(SDNode *
N) {
5916 EVT CarryVT =
N->getValueType(1);
5937 return DAG.
getNode(
N->getOpcode(),
DL,
N->getVTList(), N1, N0);
5949 N->getVTList(), N0, N0);
5956 return CombineTo(
N,
And, Cmp);
5994 unsigned Opcode0 = isSignedMinMax(N0, N1, N2, N3, CC);
6048 unsigned Opcode1 = isSignedMinMax(N00, N01, N02, N03, N0CC);
6049 if (!Opcode1 || Opcode0 == Opcode1)
6059 APInt MinCPlus1 = MinC + 1;
6060 if (-MaxC == MinCPlus1 && MinCPlus1.
isPowerOf2()) {
6066 if (MaxC == 0 && MinC != 0 && MinCPlus1.
isPowerOf2()) {
6117 unsigned BW = (C1 + 1).exactLogBase2();
6133SDValue DAGCombiner::visitIMINMAX(SDNode *
N) {
6137 unsigned Opcode =
N->getOpcode();
6153 return C0 > C1 ? N0 : N1;
6155 return C0 > C1 ? N1 : N0;
6161 return DAG.
getNode(Opcode,
DL, VT, N1, N0);
6165 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
6169 if (
SDValue RMINMAX = reassociateOps(Opcode,
DL, N0, N1,
N->getFlags()))
6189 return DAG.
getNode(AltOpcode,
DL, VT, N0, N1);
6201 auto ReductionOpcode = [](
unsigned Opcode) {
6204 return ISD::VECREDUCE_SMIN;
6206 return ISD::VECREDUCE_SMAX;
6208 return ISD::VECREDUCE_UMIN;
6210 return ISD::VECREDUCE_UMAX;
6215 if (
SDValue SD = reassociateReduction(ReductionOpcode(Opcode), Opcode,
6216 SDLoc(
N), VT, N0, N1))
6228SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *
N) {
6231 unsigned LogicOpcode =
N->getOpcode();
6256 if (XVT !=
Y.getValueType())
6260 if ((VT.
isVector() || LegalOperations) &&
6270 SDNodeFlags LogicFlags;
6276 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6286 if (XVT !=
Y.getValueType())
6298 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6319 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6334 return DAG.
getNode(HandOpcode,
DL, VT, Logic0, Logic1, S);
6347 if (XVT.
isInteger() && XVT ==
Y.getValueType() &&
6351 return DAG.
getNode(HandOpcode,
DL, VT, Logic);
6370 assert(
X.getValueType() ==
Y.getValueType() &&
6371 "Inputs to shuffles are not the same type");
6377 if (!SVN0->hasOneUse() || !SVN1->hasOneUse() ||
6378 !SVN0->getMask().equals(SVN1->getMask()))
6414 SDValue LL, LR, RL, RR, N0CC, N1CC;
6415 if (!isSetCCEquivalent(N0, LL, LR, N0CC) ||
6416 !isSetCCEquivalent(N1, RL, RR, N1CC))
6420 "Unexpected operand types for bitwise logic op");
6423 "Unexpected operand types for setcc");
6439 if (LR == RR && CC0 == CC1 && IsInteger) {
6444 bool AndEqZero = IsAnd && CC1 ==
ISD::SETEQ && IsZero;
6446 bool AndGtNeg1 = IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6448 bool OrNeZero = !IsAnd && CC1 ==
ISD::SETNE && IsZero;
6450 bool OrLtZero = !IsAnd && CC1 ==
ISD::SETLT && IsZero;
6456 if (AndEqZero || AndGtNeg1 || OrNeZero || OrLtZero) {
6458 AddToWorklist(
Or.getNode());
6463 bool AndEqNeg1 = IsAnd && CC1 ==
ISD::SETEQ && IsNeg1;
6465 bool AndLtZero = IsAnd && CC1 ==
ISD::SETLT && IsZero;
6467 bool OrNeNeg1 = !IsAnd && CC1 ==
ISD::SETNE && IsNeg1;
6469 bool OrGtNeg1 = !IsAnd && CC1 ==
ISD::SETGT && IsNeg1;
6475 if (AndEqNeg1 || AndLtZero || OrNeNeg1 || OrGtNeg1) {
6477 AddToWorklist(
And.getNode());
6491 AddToWorklist(
Add.getNode());
6512 auto MatchDiffPow2 = [&](ConstantSDNode *C0, ConstantSDNode *C1) {
6518 return !C0->
isOpaque() && !C1->isOpaque() && (CMax - CMin).isPowerOf2();
6536 if (LL == RR && LR == RL) {
6543 if (LL == RL && LR == RR) {
6547 (!LegalOperations ||
6570 bool isFMAXNUMFMINNUM_IEEE,
6571 bool isFMAXNUMFMINNUM) {
6582 isFMAXNUMFMINNUM_IEEE
6590 isFMAXNUMFMINNUM_IEEE
6606 return isFMAXNUMFMINNUM ? ISD::FMINNUM
6608 isFMAXNUMFMINNUM_IEEE
6615 return isFMAXNUMFMINNUM ? ISD::FMAXNUM
6617 isFMAXNUMFMINNUM_IEEE
6628 (LogicOp->getOpcode() ==
ISD::AND || LogicOp->getOpcode() ==
ISD::OR) &&
6629 "Invalid Op to combine SETCC with");
6635 !
LHS->hasOneUse() || !
RHS->hasOneUse())
6640 LogicOp,
LHS.getNode(),
RHS.getNode());
6652 EVT VT = LogicOp->getValueType(0);
6666 bool isFMAXNUMFMINNUM_IEEE = TLI.
isOperationLegal(ISD::FMAXNUM_IEEE, OpVT) &&
6675 (isFMAXNUMFMINNUM_IEEE || isFMAXNUMFMINNUM))) &&
6681 SDValue CommonValue, Operand1, Operand2;
6689 }
else if (LHS1 == RHS1) {
6702 }
else if (RHS0 == LHS1) {
6719 bool IsSigned = isSignedIntSetCC(CC);
6723 bool IsOr = (LogicOp->getOpcode() ==
ISD::OR);
6731 DAG, isFMAXNUMFMINNUM_IEEE, isFMAXNUMFMINNUM);
6735 DAG.
getNode(NewOpcode,
DL, OpVT, Operand1, Operand2);
6736 return DAG.
getSetCC(
DL, VT, MinMaxValue, CommonValue, CC);
6741 if (LHS0 == LHS1 && RHS0 == RHS1 && CCL == CCR &&
6745 return DAG.
getSetCC(
DL, VT, LHS0, RHS0, CCL);
6752 LHS0 == RHS0 && LHS1C && RHS1C && OpVT.
isInteger()) {
6753 const APInt &APLhs = LHS1C->getAPIntValue();
6754 const APInt &APRhs = RHS1C->getAPIntValue();
6758 if (APLhs == (-APRhs) &&
6769 }
else if (TargetPreference &
6790 APInt Dif = MaxC - MinC;
6824 EVT CondVT =
Cond.getValueType();
6835 EVT OpVT =
T.getValueType();
6854 if (
SDValue V = foldLogicOfSetCCs(
true, N0, N1,
DL))
6871 APInt
ADDC = ADDI->getAPIntValue();
6872 APInt SRLC = SRLI->getAPIntValue();
6884 CombineTo(N0.
getNode(), NewAdd);
6897bool DAGCombiner::isAndLoadExtLoad(ConstantSDNode *AndC, LoadSDNode *LoadN,
6898 EVT LoadResultTy, EVT &ExtVT) {
6907 if (ExtVT == LoadedVT &&
6908 (!LegalOperations ||
6924 if (LegalOperations &&
6934bool DAGCombiner::isLegalNarrowLdSt(LSBaseSDNode *LDST,
6943 const unsigned ByteShAmt = ShAmt / 8;
6962 if (LdStMemVT.
bitsLT(MemVT))
6977 if (PtrType == MVT::Untyped || PtrType.
isExtended())
6984 if (!
SDValue(Load, 0).hasOneUse())
6987 if (LegalOperations &&
6996 if (
Load->getNumValues() > 2)
7015 if (LegalOperations &&
7022bool DAGCombiner::SearchForAndLoads(SDNode *
N,
7023 SmallVectorImpl<LoadSDNode*> &Loads,
7024 SmallPtrSetImpl<SDNode*> &NodesWithConsts,
7025 ConstantSDNode *Mask,
7026 SDNode *&NodeToMask) {
7030 if (
Op.getValueType().isVector())
7036 "Expected bitwise logic operation");
7037 if (!
C->getAPIntValue().isSubsetOf(
Mask->getAPIntValue()))
7042 if (!
Op.hasOneUse())
7045 switch(
Op.getOpcode()) {
7049 if (isAndLoadExtLoad(Mask, Load,
Load->getValueType(0), ExtVT) &&
7067 unsigned ActiveBits =
Mask->getAPIntValue().countr_one();
7071 Op.getOperand(0).getValueType();
7082 if (!SearchForAndLoads(
Op.getNode(), Loads, NodesWithConsts, Mask,
7093 NodeToMask =
Op.getNode();
7096 for (
unsigned i = 0, e = NodeToMask->
getNumValues(); i < e; ++i) {
7097 MVT VT =
SDValue(NodeToMask, i).getSimpleValueType();
7098 if (VT != MVT::Glue && VT != MVT::Other) {
7100 NodeToMask =
nullptr;
7112bool DAGCombiner::BackwardsPropagateMask(SDNode *
N) {
7117 if (!
Mask->getAPIntValue().isMask())
7125 SmallPtrSet<SDNode*, 2> NodesWithConsts;
7126 SDNode *FixupNode =
nullptr;
7127 if (SearchForAndLoads(
N, Loads, NodesWithConsts, Mask, FixupNode)) {
7140 SDValue(FixupNode, 0), MaskOp);
7142 if (
And.getOpcode() == ISD ::AND)
7147 for (
auto *LogicN : NodesWithConsts) {
7153 if (LogicN->getOpcode() ==
ISD::AND &&
7172 for (
auto *Load : Loads) {
7177 if (
And.getOpcode() == ISD ::AND)
7180 SDValue NewLoad = reduceLoadWidth(
And.getNode());
7182 "Shouldn't be masking the load if it can't be narrowed");
7183 CombineTo(Load, NewLoad, NewLoad.
getValue(1));
7196SDValue DAGCombiner::unfoldExtremeBitClearingToShifts(SDNode *
N) {
7207 unsigned OuterShift;
7208 unsigned InnerShift;
7210 auto matchMask = [&OuterShift, &InnerShift, &
Y](
SDValue M) ->
bool {
7213 OuterShift =
M->getOpcode();
7222 Y =
M->getOperand(1);
7229 else if (matchMask(N0))
7235 EVT VT =
N->getValueType(0);
7252 SDValue And0 =
And->getOperand(0), And1 =
And->getOperand(1);
7262 bool FoundNot =
false;
7265 Src = Src.getOperand(0);
7271 Src = Src.getOperand(0);
7275 if (Src.getOpcode() !=
ISD::SRL || !Src.hasOneUse())
7279 EVT SrcVT = Src.getValueType();
7288 if (!ShiftAmtC || !ShiftAmtC->getAPIntValue().ult(
BitWidth))
7292 Src = Src.getOperand(0);
7299 Src = Src.getOperand(0);
7323 EVT VT =
N->getValueType(0);
7349 unsigned LogicOpcode =
N->getOpcode();
7351 "Expected bitwise logic operation");
7353 if (!LogicOp.hasOneUse() || !ShiftOp.
hasOneUse())
7357 unsigned ShiftOpcode = ShiftOp.
getOpcode();
7358 if (LogicOp.getOpcode() != LogicOpcode ||
7370 if (LogicOp.getOperand(0).getOpcode() == ShiftOpcode &&
7371 LogicOp.getOperand(0).getOperand(1) ==
Y) {
7373 Z = LogicOp.getOperand(1);
7374 }
else if (LogicOp.getOperand(1).getOpcode() == ShiftOpcode &&
7375 LogicOp.getOperand(1).getOperand(1) ==
Y) {
7377 Z = LogicOp.getOperand(0);
7382 EVT VT =
N->getValueType(0);
7386 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift, Z);
7397 unsigned LogicOpcode =
N->getOpcode();
7399 "Expected bitwise logic operation");
7400 if (LeftHand.
getOpcode() != LogicOpcode ||
7421 EVT VT =
N->getValueType(0);
7423 return DAG.
getNode(LogicOpcode,
DL, VT, CombinedShifts, W);
7435 "Must be called with ISD::OR or ISD::AND node");
7449 EVT VT = M.getValueType();
7457SDValue DAGCombiner::visitAND(SDNode *
N) {
7481 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
7498 EVT LoadVT = MLoad->getMemoryVT();
7504 uint64_t ElementSize =
7506 if (
Splat->getAPIntValue().isMask(ElementSize)) {
7508 ExtVT,
DL, MLoad->getChain(), MLoad->getBasePtr(),
7509 MLoad->getOffset(), MLoad->getMask(), MLoad->getPassThru(),
7510 LoadVT, MLoad->getMemOperand(), MLoad->getAddressingMode(),
7512 bool LoadHasOtherUsers = !N0.
hasOneUse();
7513 CombineTo(
N, NewLoad);
7514 if (LoadHasOtherUsers)
7535 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
7544 reassociateReduction(ISD::VECREDUCE_AND,
ISD::AND,
DL, VT, N0, N1))
7548 auto MatchSubset = [](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
7549 return RHS->getAPIntValue().isSubsetOf(
LHS->getAPIntValue());
7559 APInt
Mask = ~N1C->getAPIntValue();
7584 {N0Op0.getOperand(1)})) {
7617 unsigned EltBitWidth =
Vector->getValueType(0).getScalarSizeInBits();
7618 APInt SplatValue, SplatUndef;
7619 unsigned SplatBitSize;
7626 const bool IsBigEndian =
false;
7628 Vector->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
7629 HasAnyUndefs, EltBitWidth, IsBigEndian);
7633 if (IsSplat && (SplatBitSize % EltBitWidth) == 0) {
7636 SplatValue |= SplatUndef;
7643 for (
unsigned i = 0, n = (SplatBitSize / EltBitWidth); i < n; ++i)
7644 Constant &= SplatValue.
extractBits(EltBitWidth, i * EltBitWidth);
7652 Load->getValueType(0),
7653 Load->getMemoryVT());
7661 switch (
Load->getExtensionType()) {
7662 default:
B =
false;
break;
7674 CombineTo(
N, (N0.
getNode() == Load) ? NewLoad : N0);
7678 Load->getValueType(0), SDLoc(Load),
7679 Load->getChain(),
Load->getBasePtr(),
7680 Load->getOffset(),
Load->getMemoryVT(),
7681 Load->getMemOperand());
7683 if (
Load->getNumValues() == 3) {
7685 SDValue To[] = { NewLoad.getValue(0), NewLoad.getValue(1),
7686 NewLoad.getValue(2) };
7687 CombineTo(Load, To, 3,
true);
7689 CombineTo(Load, NewLoad.getValue(0), NewLoad.getValue(1));
7699 if (
SDValue Shuffle = XformToShuffleWithZero(
N))
7708 EVT ExtVT =
Ext->getValueType(0);
7726 EVT MemVT = GN0->getMemoryVT();
7729 if (
SDValue(GN0, 0).hasOneUse() &&
7732 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
7733 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
7736 DAG.
getVTList(VT, MVT::Other), MemVT,
DL,
Ops, GN0->getMemOperand(),
7739 CombineTo(
N, ZExtLoad);
7740 AddToWorklist(ZExtLoad.
getNode());
7749 if (
SDValue Res = reduceLoadWidth(
N))
7757 if (BackwardsPropagateMask(
N))
7761 if (
SDValue Combined = visitANDLike(N0, N1,
N))
7766 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
7797 if (
SDValue Folded = foldBitwiseOpWithNeg(
N,
DL, VT))
7819 X.getOperand(0).getScalarValueSizeInBits() == 1)
7822 X.getOperand(0).getScalarValueSizeInBits() == 1)
7837 EVT MemVT = LN0->getMemoryVT();
7844 ((!LegalOperations && LN0->isSimple()) ||
7848 LN0->getBasePtr(), MemVT, LN0->getMemOperand());
7862 if (
SDValue Shifts = unfoldExtremeBitClearingToShifts(
N))
7882 if (!
C->getAPIntValue().isMask(
7883 LHS.getOperand(0).getValueType().getFixedSizeInBits()))
7890 if (IsAndZeroExtMask(N0, N1))
7899 if (LegalOperations || VT.
isVector())
7912 bool DemandHighBits) {
7913 if (!LegalOperations)
7916 EVT VT =
N->getValueType(0);
7917 if (VT != MVT::i64 && VT != MVT::i32 && VT != MVT::i16)
7923 bool LookPassAnd0 =
false;
7924 bool LookPassAnd1 =
false;
7939 LookPassAnd0 =
true;
7949 LookPassAnd1 =
true;
7975 LookPassAnd0 =
true;
7989 LookPassAnd1 =
true;
7998 if (OpSizeInBits > 16) {
8002 if (DemandHighBits && !LookPassAnd0)
8009 if (!LookPassAnd1) {
8010 unsigned HighBit = DemandHighBits ? OpSizeInBits : 24;
8018 if (OpSizeInBits > 16) {
8033 if (!
N->hasOneUse())
8036 unsigned Opc =
N.getOpcode();
8054 unsigned MaskByteOffset;
8058 case 0xFF: MaskByteOffset = 0;
break;
8059 case 0xFF00: MaskByteOffset = 1;
break;
8068 case 0xFF0000: MaskByteOffset = 2;
break;
8069 case 0xFF000000: MaskByteOffset = 3;
break;
8074 if (MaskByteOffset == 0 || MaskByteOffset == 2) {
8080 if (!
C ||
C->getZExtValue() != 8)
8088 if (!
C ||
C->getZExtValue() != 8)
8094 if (MaskByteOffset != 0 && MaskByteOffset != 2)
8097 if (!
C ||
C->getZExtValue() != 8)
8102 if (MaskByteOffset != 1 && MaskByteOffset != 3)
8105 if (!
C ||
C->getZExtValue() != 8)
8109 if (Parts[MaskByteOffset])
8124 if (!
C ||
C->getAPIntValue() != 16)
8126 Parts[0] = Parts[1] =
N.getOperand(0).getOperand(0).getNode();
8141 "MatchBSwapHWordOrAndAnd: expecting i32");
8151 if (!Mask0 || !Mask1)
8162 if (!ShiftAmt0 || !ShiftAmt1)
8182 if (!LegalOperations)
8185 EVT VT =
N->getValueType(0);
8203 SDNode *Parts[4] = {};
8223 if (Parts[0] != Parts[1] || Parts[0] != Parts[2] || Parts[0] != Parts[3])
8251 if (
SDValue V = foldLogicOfSetCCs(
false, N0, N1,
DL))
8260 if (
const ConstantSDNode *N0O1C =
8262 if (
const ConstantSDNode *N1O1C =
8266 const APInt &LHSMask = N0O1C->getAPIntValue();
8267 const APInt &RHSMask = N1O1C->getAPIntValue();
8301 auto peekThroughResize = [](
SDValue V) {
8303 return V->getOperand(0);
8307 SDValue N0Resized = peekThroughResize(N0);
8309 SDValue N1Resized = peekThroughResize(N1);
8314 if (N00 == N1Resized || N01 == N1Resized)
8321 if (peekThroughResize(NotOperand) == N1Resized)
8329 if (peekThroughResize(NotOperand) == N1Resized)
8350 auto peekThroughZext = [](
SDValue V) {
8352 return V->getOperand(0);
8374 Lo.getScalarValueSizeInBits() == (BW / 2) &&
8375 Lo.getValueType() ==
Hi.getValueType()) {
8391SDValue DAGCombiner::visitOR(SDNode *
N) {
8412 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
8434 if ((ZeroN00 != ZeroN01) && (ZeroN10 != ZeroN11)) {
8435 assert((!ZeroN00 || !ZeroN01) &&
"Both inputs zero!");
8436 assert((!ZeroN10 || !ZeroN11) &&
"Both inputs zero!");
8437 bool CanFold =
true;
8439 SmallVector<int, 4>
Mask(NumElts, -1);
8441 for (
int i = 0; i != NumElts; ++i) {
8442 int M0 = SV0->getMaskElt(i);
8443 int M1 = SV1->getMaskElt(i);
8446 bool M0Zero =
M0 < 0 || (ZeroN00 == (
M0 < NumElts));
8447 bool M1Zero =
M1 < 0 || (ZeroN10 == (
M1 < NumElts));
8451 if ((M0Zero &&
M1 < 0) || (M1Zero &&
M0 < 0))
8455 if (M0Zero == M1Zero) {
8460 assert((
M0 >= 0 ||
M1 >= 0) &&
"Undef index!");
8466 Mask[i] = M1Zero ?
M0 % NumElts : (
M1 % NumElts) + NumElts;
8475 return LegalShuffle;
8489 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
8500 if (
SDValue Combined = visitORLike(N0, N1,
DL))
8507 if (
SDValue BSwap = MatchBSwapHWord(
N, N0, N1))
8509 if (
SDValue BSwap = MatchBSwapHWordLow(
N, N0, N1))
8518 reassociateReduction(ISD::VECREDUCE_OR,
ISD::OR,
DL, VT, N0, N1))
8523 auto MatchIntersect = [](ConstantSDNode *C1, ConstantSDNode *C2) {
8543 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
8547 if (
SDValue Rot = MatchRotate(N0, N1,
DL,
false))
8550 if (
SDValue Load = MatchLoadCombine(
N))
8560 if (
SDValue Combined = visitADDLike(
N))
8565 if (LegalOperations || VT.
isVector())
8580 Mask =
Op.getOperand(1);
8581 return Op.getOperand(0);
8624 assert(OppShift && ExtractFrom &&
"Empty SDValue");
8652 bool IsMulOrDiv =
false;
8655 auto SelectOpcode = [&](
unsigned NeededShift,
unsigned MulOrDivVariant) {
8656 IsMulOrDiv = ExtractFrom.
getOpcode() == MulOrDivVariant;
8657 if (!IsMulOrDiv && ExtractFrom.
getOpcode() != NeededShift)
8659 Opcode = NeededShift;
8709 if (Rem != 0 || ResultAmt != OppLHSAmt)
8715 if (OppLHSAmt != ExtractFromAmt - NeededShiftAmt.
zextOrTrunc(
8724 return DAG.
getNode(Opcode,
DL, ResVT, OppShiftLHS, NewShiftNode);
8778 unsigned MaskLoBits = 0;
8780 unsigned Bits =
Log2_64(EltSize);
8782 if (NegBits >= Bits) {
8805 if (PosBits >= MaskLoBits) {
8827 if ((Pos == NegOp1) ||
8851 return Width.
getLoBits(MaskLoBits) == 0;
8852 return Width == EltSize;
8862 SDValue InnerNeg,
bool FromAdd,
8863 bool HasPos,
unsigned PosOpcode,
8864 unsigned NegOpcode,
const SDLoc &
DL) {
8875 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, Shifted,
8876 HasPos ? Pos : Neg);
8889 SDValue InnerNeg,
bool FromAdd,
8890 bool HasPos,
unsigned PosOpcode,
8891 unsigned NegOpcode,
const SDLoc &
DL) {
8904 return DAG.
getNode(HasPos ? PosOpcode : NegOpcode,
DL, VT, N0, N1,
8905 HasPos ? Pos : Neg);
8950 EVT VT =
LHS.getValueType();
8955 bool HasROTL = hasOperation(
ISD::ROTL, VT);
8956 bool HasROTR = hasOperation(
ISD::ROTR, VT);
8957 bool HasFSHL = hasOperation(
ISD::FSHL, VT);
8958 bool HasFSHR = hasOperation(
ISD::FSHR, VT);
8969 if (LegalOperations && !HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
8974 LHS.getOperand(0).getValueType() ==
RHS.getOperand(0).getValueType()) {
8977 MatchRotate(
LHS.getOperand(0),
RHS.getOperand(0),
DL, FromAdd))
8991 if (!LHSShift && !RHSShift)
9006 RHSShift = NewRHSShift;
9011 LHSShift = NewLHSShift;
9014 if (!RHSShift || !LHSShift)
9039 auto MatchRotateSum = [EltSizeInBits](ConstantSDNode *
LHS,
9040 ConstantSDNode *
RHS) {
9041 return (
LHS->getAPIntValue() +
RHS->getAPIntValue()) == EltSizeInBits;
9044 auto ApplyMasks = [&](
SDValue Res) {
9068 bool IsRotate = LHSShiftArg == RHSShiftArg;
9069 if (!IsRotate && !(HasFSHL || HasFSHR)) {
9078 if (CommonOp ==
Or.getOperand(0)) {
9080 Y =
Or.getOperand(1);
9083 if (CommonOp ==
Or.getOperand(1)) {
9085 Y =
Or.getOperand(0);
9092 if (matchOr(LHSShiftArg, RHSShiftArg)) {
9097 }
else if (matchOr(RHSShiftArg, LHSShiftArg)) {
9106 return ApplyMasks(Res);
9119 if (IsRotate && (HasROTL || HasROTR || !(HasFSHL || HasFSHR))) {
9120 bool UseROTL = !LegalOperations || HasROTL;
9122 UseROTL ? LHSShiftAmt : RHSShiftAmt);
9124 bool UseFSHL = !LegalOperations || HasFSHL;
9126 RHSShiftArg, UseFSHL ? LHSShiftAmt : RHSShiftAmt);
9129 return ApplyMasks(Res);
9134 if (!HasROTL && !HasROTR && !HasFSHL && !HasFSHR)
9143 SDValue LExtOp0 = LHSShiftAmt;
9144 SDValue RExtOp0 = RHSShiftAmt;
9157 if (IsRotate && (HasROTL || HasROTR)) {
9158 if (
SDValue TryL = MatchRotatePosNeg(LHSShiftArg, LHSShiftAmt, RHSShiftAmt,
9159 LExtOp0, RExtOp0, FromAdd, HasROTL,
9163 if (
SDValue TryR = MatchRotatePosNeg(RHSShiftArg, RHSShiftAmt, LHSShiftAmt,
9164 RExtOp0, LExtOp0, FromAdd, HasROTR,
9169 if (
SDValue TryL = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, LHSShiftAmt,
9170 RHSShiftAmt, LExtOp0, RExtOp0, FromAdd,
9174 if (
SDValue TryR = MatchFunnelPosNeg(LHSShiftArg, RHSShiftArg, RHSShiftAmt,
9175 LHSShiftAmt, RExtOp0, LExtOp0, FromAdd,
9225static std::optional<SDByteProvider>
9227 std::optional<uint64_t> VectorIndex,
9228 unsigned StartingIndex = 0) {
9232 return std::nullopt;
9236 if (
Depth && !
Op.hasOneUse() &&
9237 (
Op.getOpcode() != ISD::LOAD || !
Op.getValueType().isVector()))
9238 return std::nullopt;
9242 if (
Op.getOpcode() != ISD::LOAD && VectorIndex.has_value())
9243 return std::nullopt;
9245 unsigned BitWidth =
Op.getScalarValueSizeInBits();
9247 return std::nullopt;
9249 assert(Index < ByteWidth &&
"invalid index requested");
9252 switch (
Op.getOpcode()) {
9257 return std::nullopt;
9261 return std::nullopt;
9263 if (
LHS->isConstantZero())
9265 if (
RHS->isConstantZero())
9267 return std::nullopt;
9272 return std::nullopt;
9274 uint64_t BitShift = ShiftOp->getZExtValue();
9276 if (BitShift % 8 != 0)
9277 return std::nullopt;
9283 return Index < ByteShift
9286 Depth + 1, VectorIndex, Index);
9293 if (NarrowBitWidth % 8 != 0)
9294 return std::nullopt;
9295 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9297 if (Index >= NarrowByteWidth)
9299 ? std::optional<SDByteProvider>(
9307 Depth + 1, VectorIndex, StartingIndex);
9311 return std::nullopt;
9313 VectorIndex =
OffsetOp->getZExtValue();
9317 if (NarrowBitWidth % 8 != 0)
9318 return std::nullopt;
9319 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9322 if (Index >= NarrowByteWidth)
9323 return std::nullopt;
9331 if (*VectorIndex * NarrowByteWidth > StartingIndex)
9332 return std::nullopt;
9333 if ((*VectorIndex + 1) * NarrowByteWidth <= StartingIndex)
9334 return std::nullopt;
9337 VectorIndex, StartingIndex);
9341 if (!L->isSimple() || L->isIndexed())
9342 return std::nullopt;
9344 unsigned NarrowBitWidth = L->getMemoryVT().getScalarSizeInBits();
9345 if (NarrowBitWidth % 8 != 0)
9346 return std::nullopt;
9347 uint64_t NarrowByteWidth = NarrowBitWidth / 8;
9352 if (Index >= NarrowByteWidth)
9354 ? std::optional<SDByteProvider>(
9358 unsigned BPVectorIndex = VectorIndex.value_or(0U);
9363 return std::nullopt;
9378 int64_t FirstOffset) {
9380 unsigned Width = ByteOffsets.
size();
9382 return std::nullopt;
9384 bool BigEndian =
true, LittleEndian =
true;
9385 for (
unsigned i = 0; i < Width; i++) {
9386 int64_t CurrentByteOffset = ByteOffsets[i] - FirstOffset;
9389 if (!BigEndian && !LittleEndian)
9390 return std::nullopt;
9393 assert((BigEndian != LittleEndian) &&
"It should be either big endian or"
9400 switch (
Value.getOpcode()) {
9405 return Value.getOperand(0);
9432SDValue DAGCombiner::mergeTruncStores(StoreSDNode *
N) {
9443 EVT MemVT =
N->getMemoryVT();
9444 if (!(MemVT == MVT::i8 || MemVT == MVT::i16 || MemVT == MVT::i32) ||
9445 !
N->isSimple() ||
N->isIndexed())
9452 unsigned MaxWideNumBits = 64;
9453 unsigned MaxStores = MaxWideNumBits / NarrowNumBits;
9462 if (
Store->getMemoryVT() != MemVT || !
Store->isSimple() ||
9466 Chain =
Store->getChain();
9467 if (MaxStores < Stores.
size())
9471 if (Stores.
size() < 2)
9476 unsigned NumStores = Stores.
size();
9477 unsigned WideNumBits = NumStores * NarrowNumBits;
9478 if (WideNumBits != 16 && WideNumBits != 32 && WideNumBits != 64)
9486 StoreSDNode *FirstStore =
nullptr;
9487 std::optional<BaseIndexOffset>
Base;
9488 for (
auto *Store : Stores) {
9507 if (ShiftAmtC % NarrowNumBits != 0)
9514 Offset = ShiftAmtC / NarrowNumBits;
9520 SourceValue = WideVal;
9521 else if (SourceValue != WideVal) {
9529 SourceValue = WideVal;
9538 int64_t ByteOffsetFromBase = 0;
9541 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9545 if (ByteOffsetFromBase < FirstOffset) {
9547 FirstOffset = ByteOffsetFromBase;
9553 OffsetMap[
Offset] = ByteOffsetFromBase;
9559 assert(FirstStore &&
"First store must be set");
9566 if (!Allowed || !
Fast)
9571 auto checkOffsets = [&](
bool MatchLittleEndian) {
9572 if (MatchLittleEndian) {
9573 for (
unsigned i = 0; i != NumStores; ++i)
9574 if (OffsetMap[i] != i * (NarrowNumBits / 8) + FirstOffset)
9577 for (
unsigned i = 0, j = NumStores - 1; i != NumStores; ++i, --
j)
9578 if (OffsetMap[j] != i * (NarrowNumBits / 8) + FirstOffset)
9585 bool NeedBswap =
false;
9586 bool NeedRotate =
false;
9589 if (NarrowNumBits == 8 && checkOffsets(Layout.
isBigEndian()))
9591 else if (NumStores == 2 && checkOffsets(Layout.
isBigEndian()))
9600 "Unexpected store value to merge");
9609 }
else if (NeedRotate) {
9610 assert(WideNumBits % 2 == 0 &&
"Unexpected type for rotate");
9654SDValue DAGCombiner::MatchLoadCombine(SDNode *
N) {
9656 "Can only match load combining against OR nodes");
9659 EVT VT =
N->getValueType(0);
9660 if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
9666 assert(
P.hasSrc() &&
"Must be a memory byte provider");
9669 unsigned LoadBitWidth =
Load->getMemoryVT().getScalarSizeInBits();
9671 assert(LoadBitWidth % 8 == 0 &&
9672 "can only analyze providers for individual bytes not bit");
9673 unsigned LoadByteWidth = LoadBitWidth / 8;
9678 std::optional<BaseIndexOffset>
Base;
9681 SmallPtrSet<LoadSDNode *, 8> Loads;
9682 std::optional<SDByteProvider> FirstByteProvider;
9688 unsigned ZeroExtendedBytes = 0;
9689 for (
int i = ByteWidth - 1; i >= 0; --i) {
9696 if (
P->isConstantZero()) {
9699 if (++ZeroExtendedBytes != (ByteWidth -
static_cast<unsigned>(i)))
9703 assert(
P->hasSrc() &&
"provenance should either be memory or zero");
9710 else if (Chain != LChain)
9715 int64_t ByteOffsetFromBase = 0;
9724 if (
L->getMemoryVT().isVector()) {
9725 unsigned LoadWidthInBit =
L->getMemoryVT().getScalarSizeInBits();
9726 if (LoadWidthInBit % 8 != 0)
9728 unsigned ByteOffsetFromVector =
P->SrcOffset * LoadWidthInBit / 8;
9729 Ptr.addToOffset(ByteOffsetFromVector);
9735 else if (!
Base->equalBaseIndex(
Ptr, DAG, ByteOffsetFromBase))
9739 ByteOffsetFromBase += MemoryByteOffset(*
P);
9740 ByteOffsets[i] = ByteOffsetFromBase;
9743 if (ByteOffsetFromBase < FirstOffset) {
9744 FirstByteProvider =
P;
9745 FirstOffset = ByteOffsetFromBase;
9751 assert(!Loads.
empty() &&
"All the bytes of the value must be loaded from "
9752 "memory, so there must be at least one load which produces the value");
9753 assert(
Base &&
"Base address of the accessed memory location must be set");
9756 bool NeedsZext = ZeroExtendedBytes > 0;
9767 if (LegalOperations &&
9775 ArrayRef(ByteOffsets).drop_back(ZeroExtendedBytes), FirstOffset);
9779 assert(FirstByteProvider &&
"must be set");
9783 if (MemoryByteOffset(*FirstByteProvider) != 0)
9792 bool NeedsBswap = IsBigEndianTarget != *IsBigEndian;
9799 if (NeedsBswap && (LegalOperations || NeedsZext) &&
9805 if (NeedsBswap && NeedsZext && LegalOperations &&
9813 *FirstLoad->getMemOperand(), &
Fast);
9814 if (!Allowed || !
Fast)
9819 Chain, FirstLoad->getBasePtr(),
9820 FirstLoad->getPointerInfo(), MemVT, FirstLoad->getAlign());
9823 for (LoadSDNode *L : Loads)
9853SDValue DAGCombiner::unfoldMaskedMerge(SDNode *
N) {
9860 EVT VT =
N->getValueType(0);
9882 M =
And.getOperand(XorIdx ? 0 : 1);
9888 if (!matchAndXor(N0, 0, N1) && !matchAndXor(N0, 1, N1) &&
9889 !matchAndXor(N1, 0, N0) && !matchAndXor(N1, 1, N0))
9936SDValue DAGCombiner::visitXOR(SDNode *
N) {
9963 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
9975 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
9984 reassociateReduction(ISD::VECREDUCE_XOR,
ISD::XOR,
DL, VT, N0, N1))
9996 if (
SDValue Combined = visitADDLike(
N))
10004 isSetCCEquivalent(N0,
LHS,
RHS, CC,
true) &&
10006 N->use_begin()->getUser()->getOpcode() ==
ISD::AND)) {
10008 LHS.getValueType());
10009 if (!LegalOperations ||
10011 switch (N0Opcode) {
10027 CombineTo(
N, SetCC);
10029 recursivelyDeleteUnusedNodes(N0.
getNode());
10045 AddToWorklist(
V.getNode());
10054 if (isOneUseSetCC(N01) || isOneUseSetCC(N00)) {
10059 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10072 return DAG.
getNode(NewOpcode,
DL, VT, N00, N01);
10082 APInt NotYValue = ~YConst->getAPIntValue();
10098 AddToWorklist(NotX.
getNode());
10103 if (!LegalOperations || hasOperation(
ISD::ABS, VT)) {
10107 SDValue A0 =
A.getOperand(0), A1 =
A.getOperand(1);
10109 if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0))
10146 if (
SDValue V = hoistLogicOpWithSameOpcodeHands(
N))
10157 if (
SDValue MM = unfoldMaskedMerge(
N))
10226 if (!LogicOp.hasOneUse())
10229 unsigned LogicOpcode = LogicOp.getOpcode();
10235 unsigned ShiftOpcode = Shift->
getOpcode();
10238 assert(C1Node &&
"Expected a shift with constant operand");
10241 const APInt *&ShiftAmtVal) {
10242 if (V.getOpcode() != ShiftOpcode || !V.hasOneUse())
10250 ShiftOp = V.getOperand(0);
10255 if (ShiftAmtVal->getBitWidth() != C1Val.
getBitWidth())
10260 bool Overflow =
false;
10261 APInt NewShiftAmt = C1Val.
uadd_ov(*ShiftAmtVal, Overflow);
10266 if (NewShiftAmt.
uge(V.getScalarValueSizeInBits()))
10274 const APInt *C0Val;
10275 if (matchFirstShift(LogicOp.getOperand(0),
X, C0Val))
10276 Y = LogicOp.getOperand(1);
10277 else if (matchFirstShift(LogicOp.getOperand(1),
X, C0Val))
10278 Y = LogicOp.getOperand(0);
10289 return DAG.
getNode(LogicOpcode,
DL, VT, NewShift1, NewShift2,
10299SDValue DAGCombiner::visitShiftByConstant(SDNode *
N) {
10319 switch (
LHS.getOpcode()) {
10343 if (!IsShiftByConstant && !IsCopyOrSelect)
10346 if (IsCopyOrSelect &&
N->hasOneUse())
10351 EVT VT =
N->getValueType(0);
10353 N->getOpcode(),
DL, VT, {LHS.getOperand(1), N->getOperand(1)})) {
10356 return DAG.
getNode(
LHS.getOpcode(),
DL, VT, NewShift, NewRHS);
10362SDValue DAGCombiner::distributeTruncateThroughAnd(SDNode *
N) {
10367 EVT TruncVT =
N->getValueType(0);
10368 if (
N->hasOneUse() &&
N->getOperand(0).hasOneUse() &&
10376 AddToWorklist(Trunc00.
getNode());
10377 AddToWorklist(Trunc01.
getNode());
10385SDValue DAGCombiner::visitRotate(SDNode *
N) {
10389 EVT VT =
N->getValueType(0);
10404 bool OutOfRange =
false;
10405 auto MatchOutOfRange = [Bitsize, &OutOfRange](ConstantSDNode *
C) {
10406 OutOfRange |=
C->getAPIntValue().uge(Bitsize);
10414 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, Amt);
10419 if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
10430 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10431 return DAG.
getNode(
N->getOpcode(), dl, VT, N0, NewOp1);
10443 bool SameSide = (
N->getOpcode() == NextOp);
10450 if (Norm1 && Norm2)
10452 CombineOp, dl, ShiftVT, {Norm1, Norm2})) {
10454 {CombinedShift, BitsizeC});
10456 ISD::UREM, dl, ShiftVT, {CombinedShift, BitsizeC});
10458 CombinedShiftNorm);
10465SDValue DAGCombiner::visitSHL(SDNode *
N) {
10482 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10505 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10515 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
10521 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
10522 ConstantSDNode *
RHS) {
10523 APInt c1 =
LHS->getAPIntValue();
10524 APInt c2 =
RHS->getAPIntValue();
10526 return (c1 + c2).uge(OpSizeInBits);
10531 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
10532 ConstantSDNode *
RHS) {
10533 APInt c1 =
LHS->getAPIntValue();
10534 APInt c2 =
RHS->getAPIntValue();
10536 return (c1 + c2).ult(OpSizeInBits);
10558 auto MatchOutOfRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10559 ConstantSDNode *
RHS) {
10560 APInt c1 =
LHS->getAPIntValue();
10561 APInt c2 =
RHS->getAPIntValue();
10563 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10564 (c1 + c2).uge(OpSizeInBits);
10571 auto MatchInRange = [OpSizeInBits, InnerBitwidth](ConstantSDNode *
LHS,
10572 ConstantSDNode *
RHS) {
10573 APInt c1 =
LHS->getAPIntValue();
10574 APInt c2 =
RHS->getAPIntValue();
10576 return c2.
uge(OpSizeInBits - InnerBitwidth) &&
10577 (c1 + c2).ult(OpSizeInBits);
10597 auto MatchEqual = [VT](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
10598 APInt c1 =
LHS->getAPIntValue();
10599 APInt c2 =
RHS->getAPIntValue();
10609 AddToWorklist(NewSHL.
getNode());
10615 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
10616 ConstantSDNode *
RHS) {
10617 const APInt &LHSC =
LHS->getAPIntValue();
10618 const APInt &RHSC =
RHS->getAPIntValue();
10619 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
10691 AddToWorklist(Shl0.
getNode());
10710 {Add.getOperand(1)})) {
10730 if (
SDValue NewSHL = visitShiftByConstant(
N))
10752 if (N0.
getOpcode() == ISD::VSCALE && N1C) {
10764 Flags.setNoUnsignedWrap(
N->getFlags().hasNoUnsignedWrap() &&
10777 APInt NewStep = C0 << ShlVal;
10792 "SRL or SRA node is required here!");
10801 SDValue ShiftOperand =
N->getOperand(0);
10812 if (!IsSignExt && !IsZeroExt)
10819 auto UserOfLowerBits = [NarrowVTSize](
SDNode *U) {
10824 if (!UShiftAmtSrc) {
10828 return UShiftAmt < NarrowVTSize;
10842 unsigned ActiveBits = IsSignExt
10843 ?
Constant->getAPIntValue().getSignificantBits()
10844 :
Constant->getAPIntValue().getActiveBits();
10845 if (ActiveBits > NarrowVTSize)
10862 "Cannot have a multiply node with two different operand types.");
10873 if (ShiftAmt != NarrowVTSize)
10895 bool IsSigned =
N->getOpcode() ==
ISD::SRA;
10902 unsigned Opcode =
N->getOpcode();
10907 EVT VT =
N->getValueType(0);
10926SDValue DAGCombiner::visitSRA(SDNode *
N) {
10948 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
10951 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
10963 auto SumOfShifts = [&](ConstantSDNode *
LHS, ConstantSDNode *
RHS) {
10964 APInt c1 =
LHS->getAPIntValue();
10965 APInt c2 =
RHS->getAPIntValue();
10967 APInt Sum = c1 + c2;
10968 unsigned ShiftSum =
10969 Sum.
uge(OpSizeInBits) ? (OpSizeInBits - 1) : Sum.getZExtValue();
10979 "Expected matchBinaryPredicate to return one element for "
10983 ShiftValue = ShiftValues[0];
11011 if ((ShiftAmt > 0) &&
11021 N->getValueType(0), Trunc);
11038 if (ConstantSDNode *AddC =
11056 DAG.
getConstant(AddC->getAPIntValue().lshr(ShiftAmt).trunc(
11073 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11090 if (LargeShift->getAPIntValue() == TruncBits) {
11111 if (
SDValue NewSRA = visitShiftByConstant(
N))
11120 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11129SDValue DAGCombiner::visitSRL(SDNode *
N) {
11146 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
11149 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
11160 auto MatchOutOfRange = [OpSizeInBits](ConstantSDNode *
LHS,
11161 ConstantSDNode *
RHS) {
11162 APInt c1 =
LHS->getAPIntValue();
11163 APInt c2 =
RHS->getAPIntValue();
11165 return (c1 + c2).uge(OpSizeInBits);
11170 auto MatchInRange = [OpSizeInBits](ConstantSDNode *
LHS,
11171 ConstantSDNode *
RHS) {
11172 APInt c1 =
LHS->getAPIntValue();
11173 APInt c2 =
RHS->getAPIntValue();
11175 return (c1 + c2).ult(OpSizeInBits);
11195 if (c1 + OpSizeInBits == InnerShiftSize) {
11196 if (c1 + c2 >= InnerShiftSize)
11206 c1 + c2 < InnerShiftSize) {
11211 OpSizeInBits - c2),
11228 auto MatchShiftAmount = [OpSizeInBits](ConstantSDNode *
LHS,
11229 ConstantSDNode *
RHS) {
11230 const APInt &LHSC =
LHS->getAPIntValue();
11231 const APInt &RHSC =
RHS->getAPIntValue();
11232 return LHSC.
ult(OpSizeInBits) && RHSC.
ult(OpSizeInBits) &&
11274 AddToWorklist(SmallShift.
getNode());
11302 APInt UnknownBits = ~Known.Zero;
11303 if (UnknownBits == 0)
return DAG.
getConstant(1, SDLoc(N0), VT);
11318 AddToWorklist(
Op.getNode());
11327 if (
SDValue NewOp1 = distributeTruncateThroughAnd(N1.
getNode()))
11353 if (
SDValue NewSRL = visitShiftByConstant(
N))
11357 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
11384 if (
N->hasOneUse()) {
11385 SDNode *
User = *
N->user_begin();
11393 AddToWorklist(User);
11407SDValue DAGCombiner::visitFunnelShift(SDNode *
N) {
11408 EVT VT =
N->getValueType(0);
11426 return IsFSHL ? N0 : N1;
11428 auto IsUndefOrZero = [](
SDValue V) {
11437 if (Cst->getAPIntValue().uge(
BitWidth)) {
11438 uint64_t RotAmt = Cst->getAPIntValue().urem(
BitWidth);
11439 return DAG.
getNode(
N->getOpcode(),
DL, VT, N0, N1,
11443 unsigned ShAmt = Cst->getZExtValue();
11445 return IsFSHL ? N0 : N1;
11451 if (IsUndefOrZero(N0))
11455 if (IsUndefOrZero(N1))
11469 if (
LHS &&
RHS &&
LHS->isSimple() &&
RHS->isSimple() &&
11470 LHS->getAddressSpace() ==
RHS->getAddressSpace() &&
11471 (
LHS->hasNUsesOfValue(1, 0) ||
RHS->hasNUsesOfValue(1, 0)) &&
11480 RHS->getAddressSpace(), NewAlign,
11481 RHS->getMemOperand()->getFlags(), &
Fast) &&
11485 AddToWorklist(NewPtr.
getNode());
11487 VT,
DL,
RHS->getChain(), NewPtr,
11488 RHS->getPointerInfo().getWithOffset(PtrOff), NewAlign,
11489 RHS->getMemOperand()->getFlags(),
RHS->getAAInfo());
11517 if (N0 == N1 && hasOperation(RotOpc, VT))
11518 return DAG.
getNode(RotOpc,
DL, VT, N0, N2);
11527SDValue DAGCombiner::visitSHLSAT(SDNode *
N) {
11562SDValue DAGCombiner::foldABSToABD(SDNode *
N,
const SDLoc &
DL) {
11563 EVT SrcVT =
N->getValueType(0);
11566 N =
N->getOperand(0).getNode();
11568 EVT VT =
N->getValueType(0);
11574 SDValue AbsOp0 =
N->getOperand(0);
11611 EVT MaxVT = VT0.
bitsGT(VT1) ? VT0 : VT1;
11612 if ((VT0 == MaxVT || Op0->
hasOneUse()) &&
11614 (!LegalTypes || hasOperation(ABDOpcode, MaxVT))) {
11624 if (!LegalOperations || hasOperation(ABDOpcode, VT)) {
11632SDValue DAGCombiner::visitABS(SDNode *
N) {
11634 EVT VT =
N->getValueType(0);
11667SDValue DAGCombiner::visitBSWAP(SDNode *
N) {
11669 EVT VT =
N->getValueType(0);
11694 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11695 ShAmt->getZExtValue() >= (BW / 2) &&
11696 (ShAmt->getZExtValue() % 16) == 0 && TLI.
isTypeLegal(HalfVT) &&
11698 (!LegalOperations || hasOperation(
ISD::BSWAP, HalfVT))) {
11700 if (uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2)))
11716 if (ShAmt && ShAmt->getAPIntValue().ult(BW) &&
11717 ShAmt->getZExtValue() % 8 == 0) {
11730SDValue DAGCombiner::visitBITREVERSE(SDNode *
N) {
11732 EVT VT =
N->getValueType(0);
11758SDValue DAGCombiner::visitCTLZ(SDNode *
N) {
11760 EVT VT =
N->getValueType(0);
11775SDValue DAGCombiner::visitCTLZ_ZERO_UNDEF(SDNode *
N) {
11777 EVT VT =
N->getValueType(0);
11787SDValue DAGCombiner::visitCTTZ(SDNode *
N) {
11789 EVT VT =
N->getValueType(0);
11804SDValue DAGCombiner::visitCTTZ_ZERO_UNDEF(SDNode *
N) {
11806 EVT VT =
N->getValueType(0);
11816SDValue DAGCombiner::visitCTPOP(SDNode *
N) {
11818 EVT VT =
N->getValueType(0);
11830 const APInt &Amt = AmtC->getAPIntValue();
11831 if (Amt.
ult(NumBits)) {
11865 EVT VT =
LHS.getValueType();
11869 return Flags.hasNoSignedZeros() &&
11871 (Flags.hasNoNaNs() ||
11891 unsigned IEEEOpcode = (
LHS == True) ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
11895 unsigned Opcode = (
LHS == True) ? ISD::FMINNUM : ISD::FMAXNUM;
11906 unsigned IEEEOpcode = (
LHS == True) ? ISD::FMAXNUM_IEEE : ISD::FMINNUM_IEEE;
11910 unsigned Opcode = (
LHS == True) ? ISD::FMAXNUM : ISD::FMINNUM;
11921SDValue DAGCombiner::foldShiftToAvg(SDNode *
N,
const SDLoc &
DL) {
11922 const unsigned Opcode =
N->getOpcode();
11926 EVT VT =
N->getValueType(0);
11927 bool IsUnsigned = Opcode ==
ISD::SRL;
11938 if (!hasOperation(FloorISD, VT))
11942 if ((IsUnsigned && !
Add->getFlags().hasNoUnsignedWrap()) ||
11943 (!IsUnsigned && !
Add->getFlags().hasNoSignedWrap()))
11946 return DAG.
getNode(FloorISD,
DL,
N->getValueType(0), {A, B});
11952SDValue DAGCombiner::foldBitwiseOpWithNeg(SDNode *
N,
const SDLoc &
DL, EVT VT) {
11953 unsigned Opc =
N->getOpcode();
11972 if ((
LHS == True &&
RHS == False) || (
LHS == False &&
RHS == True))
11978 True, DAG, LegalOperations, ForCodeSize);
11982 HandleSDNode NegTrueHandle(NegTrue);
11990 if (
LHS == NegTrue) {
11994 RHS, DAG, LegalOperations, ForCodeSize);
11996 HandleSDNode NegRHSHandle(NegRHS);
11997 if (NegRHS == False) {
11999 False, CC, TLI, DAG);
12001 return DAG.
getNode(ISD::FNEG,
DL, VT, Combined);
12019 EVT VT =
N->getValueType(0);
12021 VT !=
Cond.getOperand(0).getValueType())
12064SDValue DAGCombiner::foldSelectOfConstants(SDNode *
N) {
12068 EVT VT =
N->getValueType(0);
12069 EVT CondVT =
Cond.getValueType();
12080 if (CondVT != MVT::i1 || LegalOperations) {
12095 C1->
isZero() && C2->isOne()) {
12110 assert(CondVT == MVT::i1 && !LegalOperations);
12113 if (C1->
isOne() && C2->isZero())
12121 if (C1->
isZero() && C2->isOne()) {
12128 if (C1->
isZero() && C2->isAllOnes()) {
12141 const APInt &C1Val = C1->getAPIntValue();
12142 const APInt &C2Val = C2->getAPIntValue();
12145 if (C1Val - 1 == C2Val) {
12151 if (C1Val + 1 == C2Val) {
12171 if (C2->isAllOnes()) {
12183template <
class MatchContextClass>
12187 N->getOpcode() == ISD::VP_SELECT) &&
12188 "Expected a (v)(vp.)select");
12190 SDValue T =
N->getOperand(1),
F =
N->getOperand(2);
12191 EVT VT =
N->getValueType(0);
12193 MatchContextClass matcher(DAG, TLI,
N);
12229 EVT VT =
N->getValueType(0);
12293 EVT VT =
LHS.getValueType();
12295 if (LegalOperations && !hasOperation(ABDOpc, VT))
12308 hasOperation(ABDOpc, VT))
12320 hasOperation(ABDOpc, VT))
12354SDValue DAGCombiner::visitSELECT(SDNode *
N) {
12358 EVT VT =
N->getValueType(0);
12361 SDNodeFlags
Flags =
N->getFlags();
12373 if (
SDValue V = foldSelectOfConstants(
N))
12377 if (SimplifySelectOps(
N, N1, N2))
12380 if (VT0 == MVT::i1) {
12389 bool normalizeToSequence =
12398 if (normalizeToSequence || !InnerSelect.
use_empty())
12400 InnerSelect, N2, Flags);
12403 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
12410 Cond1, N1, N2, Flags);
12411 if (normalizeToSequence || !InnerSelect.
use_empty())
12413 InnerSelect, Flags);
12416 recursivelyDeleteUnusedNodes(InnerSelect.
getNode());
12426 if (!normalizeToSequence) {
12432 if (
SDValue Combined = visitANDLike(N0, N1_0,
N)) {
12445 if (!normalizeToSequence) {
12451 if (
SDValue Combined = visitORLike(N0, N2_0,
DL))
12487 combineMinNumMaxNum(
DL, VT, Cond0, Cond1, N1, N2, CC))
12500 if (
C && NotC &&
C->getAPIntValue() == ~NotC->getAPIntValue()) {
12520 (!LegalOperations &&
12528 if (
SDValue ABD = foldSelectToABD(Cond0, Cond1, N1, N2, CC,
DL))
12531 if (
SDValue NewSel = SimplifySelect(
DL, N0, N1, N2))
12536 if (
SDValue UMin = foldSelectToUMin(Cond0, Cond1, N1, N2, CC,
DL))
12541 if (
SDValue BinOp = foldSelectOfBinops(
N))
12557 EVT VT =
N->getValueType(0);
12565 if (
LHS->getNumOperands() != 2 ||
RHS->getNumOperands() != 2)
12574 for (
int i = 0; i < NumElems / 2; ++i) {
12575 if (
Cond->getOperand(i)->isUndef())
12578 if (BottomHalf ==
nullptr)
12580 else if (
Cond->getOperand(i).getNode() != BottomHalf)
12586 for (
int i = NumElems / 2; i < NumElems; ++i) {
12587 if (
Cond->getOperand(i)->isUndef())
12590 if (TopHalf ==
nullptr)
12592 else if (
Cond->getOperand(i).getNode() != TopHalf)
12596 assert(TopHalf && BottomHalf &&
12597 "One half of the selector was all UNDEFs and the other was all the "
12598 "same value. This should have been addressed before this function.");
12601 BottomHalf->
isZero() ?
RHS->getOperand(0) :
LHS->getOperand(0),
12602 TopHalf->
isZero() ?
RHS->getOperand(1) :
LHS->getOperand(1));
12615 EVT VT = BasePtr.getValueType();
12619 SplatVal.getValueType() == VT) {
12625 if (Index.getOpcode() !=
ISD::ADD)
12652 Index = Index.getOperand(0);
12665 Index = Index.getOperand(0);
12672SDValue DAGCombiner::visitVPSCATTER(SDNode *
N) {
12703SDValue DAGCombiner::visitMSCATTER(SDNode *
N) {
12735SDValue DAGCombiner::visitMSTORE(SDNode *
N) {
12749 MST1->isSimple() && MST1->getBasePtr() ==
Ptr &&
12752 MST1->getMemoryVT().getStoreSize()) ||
12756 CombineTo(MST1, MST1->getChain());
12773 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12777 Value.getValueType().isInteger() &&
12780 APInt TruncDemandedBits =
12806 Value.getOperand(0).getValueType());
12816SDValue DAGCombiner::visitVP_STRIDED_STORE(SDNode *
N) {
12818 EVT EltVT = SST->getValue().getValueType().getVectorElementType();
12821 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
12822 return DAG.
getStoreVP(SST->getChain(), SDLoc(
N), SST->getValue(),
12823 SST->getBasePtr(), SST->getOffset(), SST->getMask(),
12824 SST->getVectorLength(), SST->getMemoryVT(),
12825 SST->getMemOperand(), SST->getAddressingMode(),
12826 SST->isTruncatingStore(), SST->isCompressingStore());
12831SDValue DAGCombiner::visitVECTOR_COMPRESS(SDNode *
N) {
12835 SDValue Passthru =
N->getOperand(2);
12838 bool HasPassthru = !Passthru.
isUndef();
12851 unsigned NumSelected = 0;
12853 for (
unsigned I = 0;
I < NumElmts; ++
I) {
12862 Ops.push_back(VecI);
12866 for (
unsigned Rest = NumSelected; Rest < NumElmts; ++Rest) {
12872 Ops.push_back(Val);
12880SDValue DAGCombiner::visitVPGATHER(SDNode *
N) {
12908SDValue DAGCombiner::visitMGATHER(SDNode *
N) {
12921 return CombineTo(
N, PassThru, MGT->
getChain());
12940SDValue DAGCombiner::visitMLOAD(SDNode *
N) {
12956 return CombineTo(
N, NewLd, NewLd.
getValue(1));
12960 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
12966SDValue DAGCombiner::visitMHISTOGRAM(SDNode *
N) {
12976 EVT DataVT =
Index.getValueType();
12994SDValue DAGCombiner::visitPARTIAL_REDUCE_MLA(SDNode *
N) {
12995 if (
SDValue Res = foldPartialReduceMLAMulOp(
N))
12997 if (
SDValue Res = foldPartialReduceAdd(
N))
13007SDValue DAGCombiner::foldPartialReduceMLAMulOp(SDNode *
N) {
13030 RHS.getValueType().getScalarType()));
13039 unsigned LHSOpcode =
LHS->getOpcode();
13051 unsigned LHSBits =
LHS.getValueType().getScalarSizeInBits();
13057 ? ISD::PARTIAL_REDUCE_SMLA
13058 : ISD::PARTIAL_REDUCE_UMLA;
13067 return DAG.
getNode(NewOpcode,
DL,
N->getValueType(0), Acc, LHSExtOp,
13071 unsigned RHSOpcode =
RHS->getOpcode();
13081 NewOpc = ISD::PARTIAL_REDUCE_SMLA;
13083 NewOpc = ISD::PARTIAL_REDUCE_UMLA;
13085 NewOpc = ISD::PARTIAL_REDUCE_SUMLA;
13087 NewOpc = ISD::PARTIAL_REDUCE_SUMLA;
13097 NewOpc !=
N->getOpcode())
13107 return DAG.
getNode(NewOpc,
DL,
N->getValueType(0), Acc, LHSExtOp, RHSExtOp);
13116SDValue DAGCombiner::foldPartialReduceAdd(SDNode *
N) {
13124 !ConstantOne.
isOne())
13132 bool NodeIsSigned =
N->getOpcode() != ISD::PARTIAL_REDUCE_UMLA;
13134 if (Op1IsSigned != NodeIsSigned &&
13138 unsigned NewOpcode =
13139 Op1IsSigned ? ISD::PARTIAL_REDUCE_SMLA : ISD::PARTIAL_REDUCE_UMLA;
13149 return DAG.
getNode(NewOpcode,
DL,
N->getValueType(0), Acc, UnextOp1,
13153SDValue DAGCombiner::visitVP_STRIDED_LOAD(SDNode *
N) {
13158 CStride && CStride->getZExtValue() == EltVT.
getStoreSize()) {
13160 SLD->getAddressingMode(), SLD->getExtensionType(), SLD->getValueType(0),
13161 SDLoc(
N), SLD->getChain(), SLD->getBasePtr(), SLD->getOffset(),
13162 SLD->getMask(), SLD->getVectorLength(), SLD->getMemoryVT(),
13163 SLD->getMemOperand(), SLD->isExpandingLoad());
13164 return CombineTo(
N, NewLd, NewLd.
getValue(1));
13171SDValue DAGCombiner::foldVSelectOfConstants(SDNode *
N) {
13175 EVT VT =
N->getValueType(0);
13176 if (!
Cond.hasOneUse() ||
Cond.getScalarValueSizeInBits() != 1 ||
13185 bool AllAddOne =
true;
13186 bool AllSubOne =
true;
13188 for (
unsigned i = 0; i != Elts; ++i) {
13211 if (AllAddOne || AllSubOne) {
13238SDValue DAGCombiner::visitVP_SELECT(SDNode *
N) {
13262 EVT CondVT =
Cond.getValueType();
13263 assert(CondVT.
isVector() &&
"Vector select expects a vector selector!");
13271 if (!IsTAllZero && !IsTAllOne && !IsFAllZero && !IsFAllOne)
13275 if (IsTAllZero && IsFAllZero) {
13284 Cond.getOperand(0).getValueType() == VT && VT.
isSimple() &&
13286 TValAPInt.
isOne() &&
13305 if (!IsTAllOne && !IsFAllZero &&
Cond.hasOneUse() &&
13309 if (IsTAllZero || IsFAllOne) {
13322 "Select condition no longer all-sign bits");
13325 if (IsTAllOne && IsFAllZero)
13354SDValue DAGCombiner::visitVSELECT(SDNode *
N) {
13358 EVT VT =
N->getValueType(0);
13391 bool isAbs =
false;
13410 AddToWorklist(Shift.
getNode());
13411 AddToWorklist(
Add.getNode());
13423 if (
SDValue FMinMax = combineMinNumMaxNum(
DL, VT,
LHS,
RHS, N1, N2, CC))
13438 EVT NarrowVT =
LHS.getValueType();
13446 SetCCWidth != 1 && SetCCWidth < WideWidth &&
13492 (OpLHS == CondLHS || OpRHS == CondLHS))
13495 if (OpRHS.getOpcode() == CondRHS.getOpcode() &&
13498 CondLHS == OpLHS) {
13502 auto MatchUADDSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
13503 return Cond->getAPIntValue() == ~Op->getAPIntValue();
13544 if (OpLHS ==
LHS) {
13559 auto MatchUSUBSAT = [](ConstantSDNode *
Op, ConstantSDNode *
Cond) {
13560 return (!
Op && !
Cond) ||
13562 Cond->getAPIntValue() == (-
Op->getAPIntValue() - 1));
13598 if (SimplifySelectOps(
N, N1, N2))
13618 if (
SDValue V = foldVSelectOfConstants(
N))
13634SDValue DAGCombiner::visitSELECT_CC(SDNode *
N) {
13655 AddToWorklist(
SCC.getNode());
13660 return SCCC->isZero() ? N3 : N2;
13664 if (
SCC->isUndef())
13670 SCC.getOperand(0),
SCC.getOperand(1), N2, N3,
13671 SCC.getOperand(2),
SCC->getFlags());
13676 if (SimplifySelectOps(
N, N2, N3))
13680 return SimplifySelectCC(
DL, N0, N1, N2, N3, CC);
13683SDValue DAGCombiner::visitSETCC(SDNode *
N) {
13688 N->hasOneUse() &&
N->user_begin()->getOpcode() == ISD::BRCOND;
13691 EVT VT =
N->getValueType(0);
13698 if (PreferSetCC && Combined.getOpcode() !=
ISD::SETCC) {
13699 SDValue NewSetCC = rebuildSetCC(Combined);
13727 A.getOperand(0) ==
B.getOperand(0);
13731 B.getOperand(0) ==
A;
13734 bool IsRotate =
false;
13737 if (IsAndWithShift(N0, N1)) {
13739 ShiftOrRotate = N1;
13740 }
else if (IsAndWithShift(N1, N0)) {
13742 ShiftOrRotate = N0;
13743 }
else if (IsRotateWithOp(N0, N1)) {
13746 ShiftOrRotate = N1;
13747 }
else if (IsRotateWithOp(N1, N0)) {
13750 ShiftOrRotate = N0;
13753 if (AndOrOp && ShiftOrRotate && ShiftOrRotate.hasOneUse() &&
13758 auto GetAPIntValue = [](
SDValue Op) -> std::optional<APInt> {
13761 if (CNode ==
nullptr)
13762 return std::nullopt;
13765 std::optional<APInt> AndCMask =
13766 IsRotate ? std::nullopt : GetAPIntValue(AndOrOp.
getOperand(1));
13767 std::optional<APInt> ShiftCAmt =
13768 GetAPIntValue(ShiftOrRotate.getOperand(1));
13772 if (ShiftCAmt && (IsRotate || AndCMask) && ShiftCAmt->ult(NumBits)) {
13773 unsigned ShiftOpc = ShiftOrRotate.getOpcode();
13775 bool CanTransform = IsRotate;
13776 if (!CanTransform) {
13778 CanTransform = *ShiftCAmt == (~*AndCMask).
popcount();
13780 CanTransform &= (*ShiftCAmt + AndCMask->popcount()) == NumBits;
13788 OpVT, ShiftOpc, ShiftCAmt->isPowerOf2(), *ShiftCAmt, AndCMask);
13790 if (CanTransform && NewShiftOpc != ShiftOpc) {
13792 DAG.
getNode(NewShiftOpc,
DL, OpVT, ShiftOrRotate.getOperand(0),
13793 ShiftOrRotate.getOperand(1));
13800 NumBits - ShiftCAmt->getZExtValue())
13801 : APInt::getLowBitsSet(NumBits,
13802 NumBits - ShiftCAmt->getZExtValue());
13810 return DAG.
getSetCC(
DL, VT, NewAndOrOp, NewShiftOrRotate,
Cond);
13818SDValue DAGCombiner::visitSETCCCARRY(SDNode *
N) {
13839 if (!
N.hasOneUse())
13868 unsigned Opcode =
N->getOpcode();
13870 EVT VT =
N->getValueType(0);
13873 "Expected EXTEND dag node in input!");
13913 unsigned Opcode =
N->getOpcode();
13915 EVT VT =
N->getValueType(0);
13918 "Expected EXTEND dag node in input!");
13924 return DAG.
getNode(Opcode,
DL, VT, N0);
13943 unsigned FoldOpc = Opcode;
13966 for (
unsigned i = 0; i != NumElts; ++i) {
13968 if (
Op.isUndef()) {
13979 APInt C =
Op->getAsAPIntVal().zextOrTrunc(EVTBits);
13997 bool HasCopyToRegUses =
false;
14012 for (
unsigned i = 0; i != 2; ++i) {
14030 HasCopyToRegUses =
true;
14033 if (HasCopyToRegUses) {
14034 bool BothLiveOut =
false;
14037 BothLiveOut =
true;
14044 return !ExtendNodes.
empty();
14049void DAGCombiner::ExtendSetCCUses(
const SmallVectorImpl<SDNode *> &SetCCs,
14054 for (SDNode *SetCC : SetCCs) {
14057 for (
unsigned j = 0;
j != 2; ++
j) {
14058 SDValue SOp = SetCC->getOperand(j);
14059 if (SOp == OrigLoad)
14060 Ops.push_back(ExtLoad);
14065 Ops.push_back(SetCC->getOperand(2));
14071SDValue DAGCombiner::CombineExtLoad(SDNode *
N) {
14073 EVT DstVT =
N->getValueType(0);
14078 "Unexpected node type (not an extend)!");
14116 EVT SplitSrcVT = SrcVT;
14117 EVT SplitDstVT = DstVT;
14130 const unsigned NumSplits =
14137 for (
unsigned Idx = 0; Idx < NumSplits; Idx++) {
14138 const unsigned Offset = Idx * Stride;
14156 AddToWorklist(NewChain.
getNode());
14158 CombineTo(
N, NewValue);
14164 ExtendSetCCUses(SetCCs, N0, NewValue, (
ISD::NodeType)
N->getOpcode());
14165 CombineTo(N0.
getNode(), Trunc, NewChain);
14171SDValue DAGCombiner::CombineZExtLogicopShiftLoad(SDNode *
N) {
14173 EVT VT =
N->getValueType(0);
14174 EVT OrigVT =
N->getOperand(0).getValueType();
14196 EVT MemVT =
Load->getMemoryVT();
14217 Load->getChain(),
Load->getBasePtr(),
14218 Load->getMemoryVT(),
Load->getMemOperand());
14231 if (
SDValue(Load, 0).hasOneUse()) {
14235 Load->getValueType(0), ExtLoad);
14236 CombineTo(Load, Trunc, ExtLoad.
getValue(1));
14240 recursivelyDeleteUnusedNodes(N0.
getNode());
14249SDValue DAGCombiner::matchVSelectOpSizesWithSetCC(SDNode *Cast) {
14250 unsigned CastOpcode = Cast->
getOpcode();
14252 CastOpcode ==
ISD::TRUNCATE || CastOpcode == ISD::FP_EXTEND ||
14254 "Unexpected opcode for vector select narrowing/widening");
14294 bool LegalOperations,
SDNode *
N,
14305 if ((LegalOperations || !LN0->
isSimple() ||
14316 Combiner.recursivelyDeleteUnusedNodes(LN0);
14329 bool NonNegZExt =
false) {
14336 "Unexpected load type or opcode");
14357 bool DoXform =
true;
14370 Combiner.ExtendSetCCUses(SetCCs, N0, ExtLoad, ExtOpc);
14372 bool NoReplaceTrunc =
SDValue(LN0, 0).hasOneUse();
14374 if (NoReplaceTrunc) {
14376 Combiner.recursivelyDeleteUnusedNodes(LN0);
14419 if (!ALoad || ALoad->getOpcode() != ISD::ATOMIC_LOAD)
14421 EVT MemoryVT = ALoad->getMemoryVT();
14430 EVT OrigVT = ALoad->getValueType(0);
14433 ExtLoadType,
SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(),
14434 ALoad->getBasePtr(), ALoad->getMemOperand()));
14444 bool LegalOperations) {
14456 EVT VT =
N->getValueType(0);
14457 EVT XVT =
X.getValueType();
14473 return DAG.
getNode(ShiftOpcode,
DL, VT, NotX, ShiftAmount);
14479SDValue DAGCombiner::foldSextSetcc(SDNode *
N) {
14487 EVT VT =
N->getValueType(0);
14492 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
14497 if (VT.
isVector() && !LegalOperations &&
14516 if (SVT == MatchingVecType) {
14532 auto IsFreeToExtend = [&](
SDValue V) {
14546 for (SDUse &Use :
V->uses()) {
14548 SDNode *
User =
Use.getUser();
14549 if (
Use.getResNo() != 0 || User == N0.
getNode())
14554 if (
User->getOpcode() != ExtOpcode ||
User->getValueType(0) != VT)
14560 if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) {
14563 return DAG.
getSetCC(
DL, VT, Ext0, Ext1, CC);
14580 SDValue ExtTrueVal = (SetCCWidth == 1)
14584 if (
SDValue SCC = SimplifySelectCC(
DL, N00, N01, ExtTrueVal, Zero, CC,
true))
14596 return DAG.
getSelect(
DL, VT, SetCC, ExtTrueVal, Zero);
14603SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *
N) {
14605 EVT VT =
N->getValueType(0);
14609 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14655 if (NarrowLoad.getNode() != N0.
getNode()) {
14656 CombineTo(N0.
getNode(), NarrowLoad);
14658 AddToWorklist(oye);
14666 unsigned OpBits =
Op.getScalarValueSizeInBits();
14672 if (OpBits == DestBits) {
14678 if (OpBits < DestBits) {
14687 Flags.setNoSignedWrap(
true);
14695 if (OpBits < DestBits)
14697 else if (OpBits > DestBits)
14717 if (
SDValue ExtLoad = CombineExtLoad(
N))
14752 bool NoReplaceTruncAnd = !N0.
hasOneUse();
14753 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
14756 if (NoReplaceTruncAnd) {
14759 CombineTo(N0.
getNode(), TruncAnd);
14761 if (NoReplaceTrunc) {
14766 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
14785 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
14816 if (NewXor.getNode() == N0.
getNode()) {
14842 "Expected extend op");
14886SDValue DAGCombiner::visitZERO_EXTEND(SDNode *
N) {
14888 EVT VT =
N->getValueType(0);
14892 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
14923 APInt TruncatedBits =
14925 APInt(
Op.getScalarValueSizeInBits(), 0) :
14926 APInt::getBitsSet(
Op.getScalarValueSizeInBits(),
14927 N0.getScalarValueSizeInBits(),
14928 std::min(
Op.getScalarValueSizeInBits(),
14931 SDValue ZExtOrTrunc = DAG.getZExtOrTrunc(Op, DL, VT);
14932 DAG.salvageDebugInfo(*N0.getNode());
14934 return ZExtOrTrunc;
14944 if (NarrowLoad.getNode() != N0.
getNode()) {
14945 CombineTo(N0.
getNode(), NarrowLoad);
14947 AddToWorklist(oye);
14955 if (
N->getFlags().hasNonNeg()) {
14963 if (OpBits == DestBits) {
14969 if (OpBits < DestBits) {
14979 Flags.setNoSignedWrap(
true);
14980 Flags.setNoUnsignedWrap(
true);
14992 AddToWorklist(
Op.getNode());
14996 return ZExtOrTrunc;
15002 AddToWorklist(
Op.getNode());
15038 if (
SDValue ExtLoad = CombineExtLoad(
N))
15058 bool DoXform =
true;
15065 if (isAndLoadExtLoad(AndC, LN00, LoadResultTy, ExtVT))
15081 bool NoReplaceTruncAnd = !N0.
hasOneUse();
15082 bool NoReplaceTrunc =
SDValue(LN00, 0).hasOneUse();
15085 if (NoReplaceTruncAnd) {
15088 CombineTo(N0.
getNode(), TruncAnd);
15090 if (NoReplaceTrunc) {
15095 CombineTo(LN00, Trunc, ExtLoad.
getValue(1));
15104 if (
SDValue ZExtLoad = CombineZExtLogicopShiftLoad(
N))
15117 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
15120 if (!LegalOperations && VT.
isVector() &&
15152 if (
SDValue SCC = SimplifySelectCC(
15172 if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) {
15193 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
15215SDValue DAGCombiner::visitANY_EXTEND(SDNode *
N) {
15217 EVT VT =
N->getValueType(0);
15251 if (NarrowLoad.getNode() != N0.
getNode()) {
15252 CombineTo(N0.
getNode(), NarrowLoad);
15254 AddToWorklist(oye);
15288 bool DoXform =
true;
15301 CombineTo(
N, ExtLoad);
15302 if (NoReplaceTrunc) {
15304 recursivelyDeleteUnusedNodes(LN0);
15308 CombineTo(LN0, Trunc, ExtLoad.
getValue(1));
15322 if (!LegalOperations || TLI.
isLoadExtLegal(ExtType, VT, MemVT)) {
15326 CombineTo(
N, ExtLoad);
15328 recursivelyDeleteUnusedNodes(LN0);
15335 SelectionDAG::FlagInserter FlagsInserter(DAG, N0->
getFlags());
15342 if (VT.
isVector() && !LegalOperations) {
15367 if (
SDValue SCC = SimplifySelectCC(
15383SDValue DAGCombiner::visitAssertExt(SDNode *
N) {
15384 unsigned Opcode =
N->getOpcode();
15404 EVT MinAssertVT = AssertVT.
bitsLT(BigA_AssertVT) ? AssertVT : BigA_AssertVT;
15419 if (AssertVT.
bitsLT(BigA_AssertVT)) {
15437 if (AssertVT.
bitsLT(BigA_AssertVT) &&
15457SDValue DAGCombiner::visitAssertAlign(SDNode *
N) {
15467 std::max(AL, AAN->getAlign()));
15478 unsigned AlignShift =
Log2(AL);
15483 if (LHSAlignShift >= AlignShift || RHSAlignShift >= AlignShift) {
15484 if (LHSAlignShift < AlignShift)
15486 if (RHSAlignShift < AlignShift)
15500SDValue DAGCombiner::reduceLoadWidth(SDNode *
N) {
15501 unsigned Opc =
N->getOpcode();
15505 EVT VT =
N->getValueType(0);
15515 unsigned ShAmt = 0;
15520 unsigned ShiftedOffset = 0;
15540 uint64_t MemoryWidth = LN->getMemoryVT().getScalarSizeInBits();
15541 if (MemoryWidth <= ShAmt)
15552 LN->getExtensionType() != ExtType)
15561 unsigned ActiveBits = 0;
15562 if (
Mask.isMask()) {
15563 ActiveBits =
Mask.countr_one();
15564 }
else if (
Mask.isShiftedMask(ShAmt, ActiveBits)) {
15565 ShiftedOffset = ShAmt;
15586 if (!
SRL.hasOneUse())
15599 ShAmt = SRL1C->getZExtValue();
15600 uint64_t MemoryWidth = LN->getMemoryVT().getSizeInBits();
15601 if (ShAmt >= MemoryWidth)
15626 SDNode *
Mask = *(
SRL->user_begin());
15629 unsigned Offset, ActiveBits;
15630 const APInt& ShiftMask =
Mask->getConstantOperandAPInt(1);
15631 if (ShiftMask.
isMask()) {
15653 N0 =
SRL.getOperand(0);
15661 unsigned ShLeftAmt = 0;
15665 ShLeftAmt = N01->getZExtValue();
15678 !isLegalNarrowLdSt(LN0, ExtType, ExtVT, ShAmt))
15681 auto AdjustBigEndianShift = [&](
unsigned ShAmt) {
15682 unsigned LVTStoreBits =
15685 return LVTStoreBits - EVTStoreBits - ShAmt;
15690 unsigned PtrAdjustmentInBits =
15693 uint64_t PtrOff = PtrAdjustmentInBits / 8;
15699 AddToWorklist(NewPtr.
getNode());
15703 const MDNode *OldRanges = LN0->
getRanges();
15704 const MDNode *NewRanges =
nullptr;
15708 if (ShAmt == 0 && OldRanges) {
15716 ConstantRange TruncatedCR = CR.
truncate(BitSize);
15726 NewRanges = OldRanges;
15739 WorklistRemover DeadNodes(*
this);
15744 if (ShLeftAmt != 0) {
15756 if (ShiftedOffset != 0) {
15770SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *
N) {
15773 EVT VT =
N->getValueType(0);
15804 if ((N00Bits <= ExtVTBits ||
15817 if ((N00Bits == ExtVTBits ||
15818 (!IsZext && (N00Bits < ExtVTBits ||
15820 (!LegalOperations ||
15845 if (
SDValue NarrowLoad = reduceLoadWidth(
N))
15853 if (ShAmt->getAPIntValue().ule(VTBits - ExtVTBits)) {
15857 if (((VTBits - ExtVTBits) - ShAmt->getZExtValue()) < InSignBits)
15876 CombineTo(
N, ExtLoad);
15878 AddToWorklist(ExtLoad.
getNode());
15891 CombineTo(
N, ExtLoad);
15899 if (ExtVT == Ld->getMemoryVT() && N0.
hasOneUse() &&
15903 VT,
DL, Ld->getChain(), Ld->getBasePtr(), Ld->getOffset(),
15904 Ld->getMask(), Ld->getPassThru(), ExtVT, Ld->getMemOperand(),
15905 Ld->getAddressingMode(),
ISD::SEXTLOAD, Ld->isExpandingLoad());
15906 CombineTo(
N, ExtMaskedLoad);
15914 if (
SDValue(GN0, 0).hasOneUse() && ExtVT == GN0->getMemoryVT() &&
15916 SDValue Ops[] = {GN0->getChain(), GN0->getPassThru(), GN0->getMask(),
15917 GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()};
15920 DAG.
getVTList(VT, MVT::Other), ExtVT,
DL,
Ops, GN0->getMemOperand(),
15923 CombineTo(
N, ExtLoad);
15925 AddToWorklist(ExtLoad.
getNode());
15948 (!LegalOperations ||
15962 bool LegalOperations) {
15963 unsigned InregOpcode =
N->getOpcode();
15967 EVT VT =
N->getValueType(0);
15969 Src.getValueType().getVectorElementType(),
15973 "Expected EXTEND_VECTOR_INREG dag node in input!");
15982 Src = Src.getOperand(0);
15983 if (Src.getValueType() != SrcVT)
15989 return DAG.
getNode(Opcode,
DL, VT, Src);
15992SDValue DAGCombiner::visitEXTEND_VECTOR_INREG(SDNode *
N) {
15994 EVT VT =
N->getValueType(0);
16018SDValue DAGCombiner::visitTRUNCATE_USAT_U(SDNode *
N) {
16019 EVT VT =
N->getValueType(0);
16040 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16042 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16063 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16065 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16086 unsigned NumSrcBits = In.getScalarValueSizeInBits();
16088 assert(NumSrcBits > NumDstBits &&
"Unexpected types for truncate operation");
16111 auto AllowedTruncateSat = [&](
unsigned Opc,
EVT SrcVT,
EVT VT) ->
bool {
16123 }
else if (Src.getOpcode() ==
ISD::UMIN) {
16135SDValue DAGCombiner::visitTRUNCATE(SDNode *
N) {
16137 EVT VT =
N->getValueType(0);
16152 return SaturatedTR;
16204 if (LegalTypes && !LegalOperations && VT.
isScalarInteger() && VT != MVT::i1 &&
16206 EVT TrTy =
N->getValueType(0);
16211 if (Src.getOpcode() ==
ISD::SRL && Src.getOperand(0)->hasOneUse()) {
16214 Src = Src.getOperand(0);
16221 EVT VecTy = Src.getOperand(0).getValueType();
16222 EVT ExTy = Src.getValueType();
16226 auto NewEltCnt = EltCnt * SizeRatio;
16231 SDValue EltNo = Src->getOperand(1);
16234 int Index = isLE ? (Elt * SizeRatio + EltOffset)
16235 : (Elt * SizeRatio + (SizeRatio - 1) - EltOffset);
16246 if (!LegalOperations ||
16269 AddToWorklist(Amt.
getNode());
16318 if (BuildVectEltTy == TruncVecEltTy) {
16322 unsigned TruncEltOffset = BuildVecNumElts / TruncVecNumElts;
16323 unsigned FirstElt = isLE ? 0 : (TruncEltOffset - 1);
16325 assert((BuildVecNumElts % TruncVecNumElts) == 0 &&
16326 "Invalid number of elements");
16329 for (
unsigned i = FirstElt, e = BuildVecNumElts; i <
e;
16330 i += TruncEltOffset)
16340 if (
SDValue Reduced = reduceLoadWidth(
N))
16363 unsigned NumDefs = 0;
16367 if (!
X.isUndef()) {
16384 if (NumDefs == 1) {
16385 assert(
V.getNode() &&
"The single defined operand is empty!");
16387 for (
unsigned i = 0, e = VTs.
size(); i != e; ++i) {
16393 AddToWorklist(
NV.getNode());
16408 (!LegalOperations ||
16436 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
16450 if (!LegalOperations && N0.
hasOneUse() &&
16467 Flags.setNoUnsignedWrap(
true);
16492 if (!LegalOperations && N0.
hasOneUse() &&
16533 if (!LegalOperations && N0.
hasOneUse() &&
16541 bool CanFold =
false;
16549 unsigned NeededBits = SrcBits - TruncBits;
16575SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *
N, EVT VT) {
16588 !LD1->hasOneUse() || !LD2->hasOneUse() ||
16589 LD1->getAddressSpace() != LD2->getAddressSpace())
16592 unsigned LD1Fast = 0;
16593 EVT LD1VT = LD1->getValueType(0);
16598 *LD1->getMemOperand(), &LD1Fast) && LD1Fast)
16599 return DAG.
getLoad(VT, SDLoc(
N), LD1->getChain(), LD1->getBasePtr(),
16600 LD1->getPointerInfo(), LD1->getAlign());
16611SDValue DAGCombiner::foldBitcastedFPLogic(SDNode *
N, SelectionDAG &DAG,
16615 EVT VT =
N->getValueType(0);
16631 FPOpcode = ISD::FABS;
16635 FPOpcode = ISD::FNEG;
16639 FPOpcode = ISD::FABS;
16652 auto IsBitCastOrFree = [&TLI, FPOpcode](
SDValue Op, EVT VT) {
16666 IsBitCastOrFree(LogicOp0, VT)) {
16669 NumFPLogicOpsConv++;
16671 return DAG.
getNode(ISD::FNEG, SDLoc(
N), VT, FPOp);
16678SDValue DAGCombiner::visitBITCAST(SDNode *
N) {
16680 EVT VT =
N->getValueType(0);
16705 if (!LegalOperations ||
16711 if (
C.getNode() !=
N)
16724 auto IsFreeBitcast = [VT](
SDValue V) {
16725 return (
V.getOpcode() == ISD::BITCAST &&
16726 V.getOperand(0).getValueType() == VT) ||
16755 if (
const MDNode *MD = LN0->
getRanges()) {
16770 if (
SDValue V = foldBitcastedFPLogic(
N, DAG, TLI))
16790 AddToWorklist(NewConv.
getNode());
16793 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
16800 AddToWorklist(FlipBit.
getNode());
16807 AddToWorklist(
Hi.getNode());
16809 AddToWorklist(FlipBit.
getNode());
16813 AddToWorklist(FlipBits.
getNode());
16843 AddToWorklist(
X.getNode());
16847 if (OrigXWidth < VTWidth) {
16849 AddToWorklist(
X.getNode());
16850 }
else if (OrigXWidth > VTWidth) {
16855 X.getValueType(),
X,
16857 X.getValueType()));
16858 AddToWorklist(
X.getNode());
16860 AddToWorklist(
X.getNode());
16863 if (N0.
getValueType() == MVT::ppcf128 && !LegalTypes) {
16866 AddToWorklist(Cst.
getNode());
16868 AddToWorklist(
X.getNode());
16870 AddToWorklist(XorResult.
getNode());
16874 SDLoc(XorResult)));
16875 AddToWorklist(XorResult64.
getNode());
16878 DAG.
getConstant(SignBit, SDLoc(XorResult64), MVT::i64));
16879 AddToWorklist(FlipBit.
getNode());
16882 AddToWorklist(FlipBits.
getNode());
16888 AddToWorklist(
X.getNode());
16893 AddToWorklist(Cst.
getNode());
16901 if (
SDValue CombineLD = CombineConsecutiveLoads(N0.
getNode(), VT))
16924 auto PeekThroughBitcast = [&](
SDValue Op) {
16925 if (
Op.getOpcode() == ISD::BITCAST &&
16926 Op.getOperand(0).getValueType() == VT)
16943 SmallVector<int, 8> NewMask;
16945 for (
int i = 0; i != MaskScale; ++i)
16946 NewMask.
push_back(M < 0 ? -1 : M * MaskScale + i);
16951 return LegalShuffle;
16957SDValue DAGCombiner::visitBUILD_PAIR(SDNode *
N) {
16958 EVT VT =
N->getValueType(0);
16959 return CombineConsecutiveLoads(
N, VT);
16962SDValue DAGCombiner::visitFREEZE(SDNode *
N) {
16976 assert(
N->getOperand(0) == FrozenN0 &&
"Expected cycle in DAG");
17004 bool AllowMultipleMaybePoisonOperands =
17032 SmallSet<SDValue, 8> MaybePoisonOperands;
17033 SmallVector<unsigned, 8> MaybePoisonOperandNumbers;
17037 bool HadMaybePoisonOperands = !MaybePoisonOperands.
empty();
17038 bool IsNewMaybePoisonOperand = MaybePoisonOperands.
insert(
Op).second;
17039 if (IsNewMaybePoisonOperand)
17040 MaybePoisonOperandNumbers.
push_back(OpNo);
17041 if (!HadMaybePoisonOperands)
17043 if (IsNewMaybePoisonOperand && !AllowMultipleMaybePoisonOperands) {
17052 for (
unsigned OpNo : MaybePoisonOperandNumbers) {
17063 SDValue MaybePoisonOperand =
N->getOperand(0).getOperand(OpNo);
17065 if (MaybePoisonOperand.
isUndef())
17072 FrozenMaybePoisonOperand.
getOperand(0) == FrozenMaybePoisonOperand) {
17076 MaybePoisonOperand);
17112 SDNodeFlags SrcFlags = N0->
getFlags();
17113 SDNodeFlags SafeFlags;
17127 N->getFlags().hasAllowContract();
17131template <
class MatchContextClass>
17132SDValue DAGCombiner::visitFADDForFMACombine(SDNode *
N) {
17135 EVT VT =
N->getValueType(0);
17137 MatchContextClass matcher(DAG, TLI,
N);
17140 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
17145 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
17149 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
17153 if (!HasFMAD && !HasFMA)
17156 bool AllowFusionGlobally =
17159 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
17185 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
17196 return matcher.getNode(PreferredFusedOpcode, SL, VT, N0.
getOperand(0),
17203 return matcher.getNode(PreferredFusedOpcode, SL, VT, N1.
getOperand(0),
17215 bool CanReassociate =
N->getFlags().hasAllowReassociation();
17216 if (CanReassociate) {
17221 }
else if (isFusedOp(N1) && N1.
hasOneUse()) {
17227 while (
E && isFusedOp(TmpFMA) && TmpFMA.
hasOneUse()) {
17232 SDValue CDE = matcher.getNode(PreferredFusedOpcode, SL, VT,
C,
D,
E);
17246 if (matcher.match(N0, ISD::FP_EXTEND)) {
17251 return matcher.getNode(
17252 PreferredFusedOpcode, SL, VT,
17253 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(0)),
17254 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(1)), N1);
17260 if (matcher.match(N1, ISD::FP_EXTEND)) {
17265 return matcher.getNode(
17266 PreferredFusedOpcode, SL, VT,
17267 matcher.getNode(ISD::FP_EXTEND, SL, VT, N10.
getOperand(0)),
17268 matcher.getNode(ISD::FP_EXTEND, SL, VT, N10.
getOperand(1)), N0);
17278 return matcher.getNode(
17279 PreferredFusedOpcode, SL, VT,
X,
Y,
17280 matcher.getNode(PreferredFusedOpcode, SL, VT,
17281 matcher.getNode(ISD::FP_EXTEND, SL, VT, U),
17282 matcher.getNode(ISD::FP_EXTEND, SL, VT, V), Z));
17284 if (isFusedOp(N0)) {
17286 if (matcher.match(N02, ISD::FP_EXTEND)) {
17305 return matcher.getNode(
17306 PreferredFusedOpcode, SL, VT,
17307 matcher.getNode(ISD::FP_EXTEND, SL, VT,
X),
17308 matcher.getNode(ISD::FP_EXTEND, SL, VT,
Y),
17309 matcher.getNode(PreferredFusedOpcode, SL, VT,
17310 matcher.getNode(ISD::FP_EXTEND, SL, VT, U),
17311 matcher.getNode(ISD::FP_EXTEND, SL, VT, V), Z));
17313 if (N0.
getOpcode() == ISD::FP_EXTEND) {
17315 if (isFusedOp(N00)) {
17329 if (isFusedOp(N1)) {
17331 if (N12.
getOpcode() == ISD::FP_EXTEND) {
17348 if (N1.
getOpcode() == ISD::FP_EXTEND) {
17350 if (isFusedOp(N10)) {
17367template <
class MatchContextClass>
17368SDValue DAGCombiner::visitFSUBForFMACombine(SDNode *
N) {
17371 EVT VT =
N->getValueType(0);
17373 MatchContextClass matcher(DAG, TLI,
N);
17376 bool UseVP = std::is_same_v<MatchContextClass, VPMatchContext>;
17381 bool HasFMAD = !UseVP && (LegalOperations && TLI.
isFMADLegal(DAG,
N));
17385 (!LegalOperations || matcher.isOperationLegalOrCustom(
ISD::FMA, VT)) &&
17389 if (!HasFMAD && !HasFMA)
17392 const SDNodeFlags
Flags =
N->getFlags();
17393 bool AllowFusionGlobally =
17397 if (!AllowFusionGlobally && !
N->getFlags().hasAllowContract())
17406 bool NoSignedZero =
Flags.hasNoSignedZeros();
17413 return AllowFusionGlobally ||
N->getFlags().hasAllowContract();
17419 return matcher.getNode(PreferredFusedOpcode, SL, VT, XY.
getOperand(0),
17421 matcher.
getNode(ISD::FNEG, SL, VT, Z));
17430 return matcher.getNode(
17431 PreferredFusedOpcode, SL, VT,
17432 matcher.getNode(ISD::FNEG, SL, VT, YZ.getOperand(0)),
17433 YZ.getOperand(1),
X);
17443 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
17446 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
17450 if (
SDValue V = tryToFoldXYSubZ(N0, N1))
17453 if (
SDValue V = tryToFoldXSubYZ(N0, N1))
17462 return matcher.
getNode(PreferredFusedOpcode, SL, VT,
17463 matcher.getNode(ISD::FNEG, SL, VT, N00), N01,
17464 matcher.getNode(ISD::FNEG, SL, VT, N1));
17471 if (matcher.match(N0, ISD::FP_EXTEND)) {
17476 return matcher.getNode(
17477 PreferredFusedOpcode, SL, VT,
17478 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(0)),
17479 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(1)),
17480 matcher.getNode(ISD::FNEG, SL, VT, N1));
17487 if (matcher.match(N1, ISD::FP_EXTEND)) {
17492 return matcher.getNode(
17493 PreferredFusedOpcode, SL, VT,
17496 matcher.getNode(ISD::FP_EXTEND, SL, VT, N10.
getOperand(0))),
17497 matcher.getNode(ISD::FP_EXTEND, SL, VT, N10.
getOperand(1)), N0);
17507 if (matcher.match(N0, ISD::FP_EXTEND)) {
17509 if (matcher.match(N00, ISD::FNEG)) {
17514 return matcher.getNode(
17517 PreferredFusedOpcode, SL, VT,
17518 matcher.getNode(ISD::FP_EXTEND, SL, VT, N000.
getOperand(0)),
17519 matcher.getNode(ISD::FP_EXTEND, SL, VT, N000.
getOperand(1)),
17531 if (matcher.match(N0, ISD::FNEG)) {
17533 if (matcher.match(N00, ISD::FP_EXTEND)) {
17538 return matcher.getNode(
17541 PreferredFusedOpcode, SL, VT,
17542 matcher.getNode(ISD::FP_EXTEND, SL, VT, N000.
getOperand(0)),
17543 matcher.getNode(ISD::FP_EXTEND, SL, VT, N000.
getOperand(1)),
17558 if (
Aggressive &&
N->getFlags().hasAllowReassociation()) {
17559 bool CanFuse =
N->getFlags().hasAllowContract();
17562 if (CanFuse && isFusedOp(N0) &&
17563 isContractableAndReassociableFMUL(N0.
getOperand(2)) &&
17565 return matcher.getNode(
17567 matcher.
getNode(PreferredFusedOpcode, SL, VT,
17570 matcher.
getNode(ISD::FNEG, SL, VT, N1)));
17575 if (CanFuse && isFusedOp(N1) &&
17576 isContractableAndReassociableFMUL(N1.
getOperand(2)) &&
17581 PreferredFusedOpcode, SL, VT,
17582 matcher.getNode(ISD::FNEG, SL, VT, N1.
getOperand(0)),
17584 matcher.
getNode(PreferredFusedOpcode, SL, VT,
17585 matcher.getNode(ISD::FNEG, SL, VT, N20), N21, N0));
17590 if (isFusedOp(N0) && N0->
hasOneUse()) {
17592 if (matcher.match(N02, ISD::FP_EXTEND)) {
17594 if (isContractableAndReassociableFMUL(N020) &&
17597 return matcher.getNode(
17600 PreferredFusedOpcode, SL, VT,
17601 matcher.getNode(ISD::FP_EXTEND, SL, VT, N020.
getOperand(0)),
17602 matcher.getNode(ISD::FP_EXTEND, SL, VT, N020.
getOperand(1)),
17603 matcher.getNode(ISD::FNEG, SL, VT, N1)));
17614 if (matcher.match(N0, ISD::FP_EXTEND)) {
17616 if (isFusedOp(N00)) {
17618 if (isContractableAndReassociableFMUL(N002) &&
17621 return matcher.getNode(
17622 PreferredFusedOpcode, SL, VT,
17623 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(0)),
17624 matcher.getNode(ISD::FP_EXTEND, SL, VT, N00.
getOperand(1)),
17626 PreferredFusedOpcode, SL, VT,
17627 matcher.getNode(ISD::FP_EXTEND, SL, VT, N002.
getOperand(0)),
17628 matcher.getNode(ISD::FP_EXTEND, SL, VT, N002.
getOperand(1)),
17629 matcher.getNode(ISD::FNEG, SL, VT, N1)));
17636 if (isFusedOp(N1) && matcher.match(N1.
getOperand(2), ISD::FP_EXTEND) &&
17639 if (isContractableAndReassociableFMUL(N120) &&
17645 PreferredFusedOpcode, SL, VT,
17646 matcher.getNode(ISD::FNEG, SL, VT, N1.
getOperand(0)),
17649 PreferredFusedOpcode, SL, VT,
17650 matcher.getNode(ISD::FNEG, SL, VT,
17651 matcher.getNode(ISD::FP_EXTEND, SL, VT, N1200)),
17652 matcher.getNode(ISD::FP_EXTEND, SL, VT, N1201), N0));
17662 if (matcher.match(N1, ISD::FP_EXTEND) && isFusedOp(N1.
getOperand(0))) {
17667 if (isContractableAndReassociableFMUL(N102) &&
17673 PreferredFusedOpcode, SL, VT,
17674 matcher.getNode(ISD::FNEG, SL, VT,
17675 matcher.getNode(ISD::FP_EXTEND, SL, VT, N100)),
17676 matcher.getNode(ISD::FP_EXTEND, SL, VT, N101),
17678 PreferredFusedOpcode, SL, VT,
17679 matcher.getNode(ISD::FNEG, SL, VT,
17680 matcher.getNode(ISD::FP_EXTEND, SL, VT, N1020)),
17681 matcher.getNode(ISD::FP_EXTEND, SL, VT, N1021), N0));
17692SDValue DAGCombiner::visitFMULForFMADistributiveCombine(SDNode *
N) {
17695 EVT VT =
N->getValueType(0);
17705 if (!
FAdd->getFlags().hasNoInfs())
17716 bool HasFMAD = LegalOperations && TLI.
isFMADLegal(DAG,
N);
17719 if (!HasFMAD && !HasFMA)
17731 if (
C->isExactlyValue(+1.0))
17732 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17734 if (
C->isExactlyValue(-1.0))
17735 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17736 DAG.
getNode(ISD::FNEG, SL, VT,
Y));
17742 if (
SDValue FMA = FuseFADD(N0, N1))
17744 if (
SDValue FMA = FuseFADD(N1, N0))
17754 if (C0->isExactlyValue(+1.0))
17755 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
17756 DAG.
getNode(ISD::FNEG, SL, VT,
X.getOperand(1)),
Y,
17758 if (C0->isExactlyValue(-1.0))
17759 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
17760 DAG.
getNode(ISD::FNEG, SL, VT,
X.getOperand(1)),
Y,
17761 DAG.
getNode(ISD::FNEG, SL, VT,
Y));
17764 if (C1->isExactlyValue(+1.0))
17765 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17766 DAG.
getNode(ISD::FNEG, SL, VT,
Y));
17767 if (C1->isExactlyValue(-1.0))
17768 return DAG.
getNode(PreferredFusedOpcode, SL, VT,
X.getOperand(0),
Y,
17775 if (
SDValue FMA = FuseFSUB(N0, N1))
17777 if (
SDValue FMA = FuseFSUB(N1, N0))
17783SDValue DAGCombiner::visitVP_FADD(SDNode *
N) {
17784 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
17787 if (
SDValue Fused = visitFADDForFMACombine<VPMatchContext>(
N)) {
17789 AddToWorklist(Fused.getNode());
17795SDValue DAGCombiner::visitFADD(SDNode *
N) {
17800 EVT VT =
N->getValueType(0);
17802 SDNodeFlags
Flags =
N->getFlags();
17803 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
17813 if (N0CFP && !N1CFP)
17818 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
17823 if (N1C && N1C->
isZero())
17827 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
17833 N1, DAG, LegalOperations, ForCodeSize))
17839 N0, DAG, LegalOperations, ForCodeSize))
17846 return C &&
C->isExactlyValue(-2.0);
17850 if (isFMulNegTwo(N0)) {
17856 if (isFMulNegTwo(N1)) {
17867 if (
Flags.hasNoNaNs() && AllowNewConst) {
17880 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
17898 if (CFP01 && !CFP00 && N0.
getOperand(0) == N1) {
17919 if (CFP11 && !CFP10 && N1.
getOperand(0) == N0) {
17966 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros()) {
17969 VT, N0, N1, Flags))
17974 if (
SDValue Fused = visitFADDForFMACombine<EmptyMatchContext>(
N)) {
17976 AddToWorklist(Fused.getNode());
17982SDValue DAGCombiner::visitSTRICT_FADD(SDNode *
N) {
17986 EVT VT =
N->getValueType(0);
17987 EVT ChainVT =
N->getValueType(1);
17989 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
17994 N1, DAG, LegalOperations, ForCodeSize)) {
17996 {Chain, N0, NegN1});
18002 N0, DAG, LegalOperations, ForCodeSize)) {
18004 {Chain, N1, NegN0});
18009SDValue DAGCombiner::visitFSUB(SDNode *
N) {
18014 EVT VT =
N->getValueType(0);
18016 const SDNodeFlags
Flags =
N->getFlags();
18017 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18028 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18031 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18035 if (N1CFP && N1CFP->
isZero()) {
18043 if (
Flags.hasNoNaNs())
18048 if (N0CFP && N0CFP->
isZero()) {
18060 return DAG.
getNode(ISD::FNEG,
DL, VT, N1);
18065 if (
Flags.hasAllowReassociation() &&
Flags.hasNoSignedZeros() &&
18081 if (
SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(
N)) {
18082 AddToWorklist(Fused.getNode());
18104SDValue DAGCombiner::combineFMulOrFDivWithIntPow2(SDNode *
N) {
18105 EVT VT =
N->getValueType(0);
18111 std::optional<int> Mantissa;
18112 auto GetConstAndPow2Ops = [&](
unsigned ConstOpIdx) {
18113 if (ConstOpIdx == 1 &&
N->getOpcode() ==
ISD::FDIV)
18129 auto IsFPConstValid = [
N, MaxExpChange, &Mantissa](ConstantFPSDNode *CFP) {
18130 if (CFP ==
nullptr)
18133 const APFloat &APF = CFP->getValueAPF();
18141 int CurExp =
ilogb(APF);
18144 N->getOpcode() ==
ISD::FMUL ? CurExp : (CurExp - MaxExpChange);
18147 N->getOpcode() ==
ISD::FDIV ? CurExp : (CurExp + MaxExpChange);
18155 Mantissa = ThisMantissa;
18157 return *Mantissa == ThisMantissa && ThisMantissa > 0;
18164 if (!GetConstAndPow2Ops(0) && !GetConstAndPow2Ops(1))
18193 NewIntVT, DAG.
getBitcast(NewIntVT, ConstOp), Shift);
18198SDValue DAGCombiner::visitFMUL(SDNode *
N) {
18202 EVT VT =
N->getValueType(0);
18204 const SDNodeFlags
Flags =
N->getFlags();
18205 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18221 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18224 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18227 if (
Flags.hasAllowReassociation()) {
18253 VT, N0, N1, Flags))
18277 HandleSDNode NegN0Handle(NegN0);
18287 if (
Flags.hasNoNaNs() &&
Flags.hasNoSignedZeros() &&
18298 if (TrueOpnd && FalseOpnd &&
18319 if (TrueOpnd->isExactlyValue(-1.0) && FalseOpnd->isExactlyValue(1.0) &&
18323 if (TrueOpnd->isExactlyValue(1.0) && FalseOpnd->isExactlyValue(-1.0))
18332 if (
SDValue Fused = visitFMULForFMADistributiveCombine(
N)) {
18333 AddToWorklist(Fused.getNode());
18339 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
18345template <
class MatchContextClass>
SDValue DAGCombiner::visitFMA(SDNode *
N) {
18352 EVT VT =
N->getValueType(0);
18355 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18356 MatchContextClass matcher(DAG, TLI,
N);
18371 HandleSDNode NegN0Handle(NegN0);
18379 if (
N->getFlags().hasNoNaNs() &&
N->getFlags().hasNoInfs()) {
18380 if (
N->getFlags().hasNoSignedZeros() ||
18382 if (N0CFP && N0CFP->
isZero())
18384 if (N1CFP && N1CFP->
isZero())
18393 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
18398 return matcher.getNode(
ISD::FMA,
DL, VT, N1, N0, N2);
18400 bool CanReassociate =
N->getFlags().hasAllowReassociation();
18401 if (CanReassociate) {
18406 return matcher.getNode(
18415 return matcher.getNode(
18425 return matcher.getNode(
ISD::FADD,
DL, VT, N0, N2);
18429 SDValue RHSNeg = matcher.getNode(ISD::FNEG,
DL, VT, N0);
18430 AddToWorklist(RHSNeg.
getNode());
18431 return matcher.getNode(
ISD::FADD,
DL, VT, N2, RHSNeg);
18435 if (matcher.match(N0, ISD::FNEG) &&
18440 matcher.
getNode(ISD::FNEG,
DL, VT, N1), N2);
18445 if (CanReassociate) {
18447 if (N1CFP && N0 == N2) {
18454 if (N1CFP && matcher.match(N2, ISD::FNEG) && N2.
getOperand(0) == N0) {
18465 SDValue(
N, 0), DAG, LegalOperations, ForCodeSize))
18466 return matcher.getNode(ISD::FNEG,
DL, VT, Neg);
18470SDValue DAGCombiner::visitFMAD(SDNode *
N) {
18474 EVT VT =
N->getValueType(0);
18484SDValue DAGCombiner::visitFMULADD(SDNode *
N) {
18488 EVT VT =
N->getValueType(0);
18506SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *
N) {
18510 const SDNodeFlags
Flags =
N->getFlags();
18511 if (LegalDAG || !
Flags.hasAllowReciprocal())
18526 unsigned NumElts = 1;
18527 EVT VT =
N->getValueType(0);
18531 if (!MinUses || (N1->
use_size() * NumElts) < MinUses)
18536 SetVector<SDNode *>
Users;
18537 for (
auto *U : N1->
users()) {
18538 if (
U->getOpcode() ==
ISD::FDIV &&
U->getOperand(1) == N1) {
18540 if (
U->getOperand(1).getOpcode() == ISD::FSQRT &&
18541 U->getOperand(0) ==
U->getOperand(1).getOperand(0) &&
18542 U->getFlags().hasAllowReassociation() &&
18543 U->getFlags().hasNoSignedZeros())
18548 if (
U->getFlags().hasAllowReciprocal())
18555 if ((
Users.size() * NumElts) < MinUses)
18563 for (
auto *U :
Users) {
18564 SDValue Dividend =
U->getOperand(0);
18565 if (Dividend != FPOne) {
18567 Reciprocal, Flags);
18568 CombineTo(U, NewNode);
18569 }
else if (U != Reciprocal.
getNode()) {
18572 CombineTo(U, Reciprocal);
18578SDValue DAGCombiner::visitFDIV(SDNode *
N) {
18581 EVT VT =
N->getValueType(0);
18583 SDNodeFlags
Flags =
N->getFlags();
18584 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18595 if (
SDValue FoldedVOp = SimplifyVBinOp(
N,
DL))
18598 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18615 (!LegalOperations ||
18625 if (
Flags.hasAllowReciprocal()) {
18631 }
else if (N1.
getOpcode() == ISD::FP_EXTEND &&
18634 RV = DAG.
getNode(ISD::FP_EXTEND, SDLoc(N1), VT, RV);
18662 if (
Y.getOpcode() == ISD::FABS &&
Y.hasOneUse())
18663 A =
Y.getOperand(0);
18672 if (
SDValue Rsqrt = buildRsqrtEstimate(AAZ))
18676 recursivelyDeleteUnusedNodes(AAZ.
getNode());
18684 AddToWorklist(Div.
getNode());
18691 if (
Flags.hasNoInfs())
18692 if (
SDValue RV = BuildDivEstimate(N0, N1, Flags))
18697 if (
Flags.hasNoSignedZeros() &&
Flags.hasAllowReassociation())
18709 HandleSDNode NegN0Handle(NegN0);
18717 if (
SDValue R = combineFMulOrFDivWithIntPow2(
N))
18723SDValue DAGCombiner::visitFREM(SDNode *
N) {
18726 EVT VT =
N->getValueType(0);
18727 SDNodeFlags
Flags =
N->getFlags();
18728 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18738 if (
SDValue NewSel = foldBinOpIntoSelect(
N))
18748 bool NeedsCopySign =
18766SDValue DAGCombiner::visitFSQRT(SDNode *
N) {
18767 SDNodeFlags
Flags =
N->getFlags();
18771 if (!
Flags.hasApproximateFuncs() || !
Flags.hasNoInfs())
18779 SelectionDAG::FlagInserter FlagInserter(DAG, Flags);
18784 return buildSqrtEstimate(N0);
18799 if (YTy == MVT::f128)
18808 if (N1.
getOpcode() != ISD::FP_EXTEND &&
18816SDValue DAGCombiner::visitFCOPYSIGN(SDNode *
N) {
18819 EVT VT =
N->getValueType(0);
18837SDValue DAGCombiner::visitFPOW(SDNode *
N) {
18841 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
18847 EVT VT =
N->getValueType(0);
18856 SDNodeFlags
Flags =
N->getFlags();
18857 if (!
Flags.hasNoSignedZeros() || !
Flags.hasNoInfs() || !
Flags.hasNoNaNs() ||
18858 !
Flags.hasApproximateFuncs())
18868 return DAG.
getNode(ISD::FCBRT, SDLoc(
N), VT,
N->getOperand(0));
18877 if (ExponentIs025 || ExponentIs075) {
18885 SDNodeFlags
Flags =
N->getFlags();
18888 if ((!
Flags.hasNoSignedZeros() && ExponentIs025) || !
Flags.hasNoInfs() ||
18889 !
Flags.hasApproximateFuncs())
18924 EVT VT =
N->getValueType(0);
18945 return DAG.
getNode(ISD::FTRUNC,
DL, VT, Abs);
18952SDValue DAGCombiner::visitSINT_TO_FP(SDNode *
N) {
18954 EVT VT =
N->getValueType(0);
19006SDValue DAGCombiner::visitUINT_TO_FP(SDNode *
N) {
19008 EVT VT =
N->getValueType(0);
19052 EVT VT =
N->getValueType(0);
19058 EVT SrcVT = Src.getValueType();
19073 unsigned ActualSize = std::min(InputSize, OutputSize);
19082 return DAG.
getNode(ExtOp,
DL, VT, Src);
19091SDValue DAGCombiner::visitFP_TO_SINT(SDNode *
N) {
19093 EVT VT =
N->getValueType(0);
19107SDValue DAGCombiner::visitFP_TO_UINT(SDNode *
N) {
19109 EVT VT =
N->getValueType(0);
19123SDValue DAGCombiner::visitXROUND(SDNode *
N) {
19125 EVT VT =
N->getValueType(0);
19141SDValue DAGCombiner::visitFP_ROUND(SDNode *
N) {
19144 EVT VT =
N->getValueType(0);
19157 const bool NIsTrunc =
N->getConstantOperandVal(1) == 1;
19179 if ((
N->getFlags().hasAllowContract() &&
19197 AddToWorklist(Tmp.
getNode());
19201 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
19211 EVT VT =
N->getValueType(0);
19213 unsigned NarrowingOp;
19214 switch (
N->getOpcode()) {
19215 case ISD::FP16_TO_FP:
19216 NarrowingOp = ISD::FP_TO_FP16;
19218 case ISD::BF16_TO_FP:
19219 NarrowingOp = ISD::FP_TO_BF16;
19221 case ISD::FP_EXTEND:
19244SDValue DAGCombiner::visitFP_EXTEND(SDNode *
N) {
19245 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19247 EVT VT =
N->getValueType(0);
19251 if (
SDValue FoldedVOp = SimplifyVCastOp(
N,
DL))
19263 if (N0.
getOpcode() == ISD::FP16_TO_FP &&
19271 if (
In.getValueType() == VT)
return In;
19274 return DAG.
getNode(ISD::FP_EXTEND,
DL, VT, In);
19285 CombineTo(
N, ExtLoad);
19294 if (
SDValue NewVSel = matchVSelectOpSizesWithSetCC(
N))
19298 return CastEliminated;
19303SDValue DAGCombiner::visitFCEIL(SDNode *
N) {
19305 EVT VT =
N->getValueType(0);
19314SDValue DAGCombiner::visitFTRUNC(SDNode *
N) {
19316 EVT VT =
N->getValueType(0);
19329 case ISD::FNEARBYINT:
19330 case ISD::FROUNDEVEN:
19339SDValue DAGCombiner::visitFFREXP(SDNode *
N) {
19344 return DAG.
getNode(ISD::FFREXP, SDLoc(
N),
N->getVTList(), N0);
19348SDValue DAGCombiner::visitFFLOOR(SDNode *
N) {
19350 EVT VT =
N->getValueType(0);
19359SDValue DAGCombiner::visitFNEG(SDNode *
N) {
19361 EVT VT =
N->getValueType(0);
19362 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19385 if (
SDValue Cast = foldSignChangeInBitcast(
N))
19391SDValue DAGCombiner::visitFMinMax(SDNode *
N) {
19394 EVT VT =
N->getValueType(0);
19395 const SDNodeFlags
Flags =
N->getFlags();
19396 unsigned Opc =
N->getOpcode();
19397 bool PropAllNaNsToQNaNs =
Opc == ISD::FMINIMUM ||
Opc == ISD::FMAXIMUM;
19398 bool PropOnlySNaNsToQNaNs =
Opc == ISD::FMINNUM ||
Opc == ISD::FMAXNUM;
19400 Opc == ISD::FMINNUM ||
Opc == ISD::FMINIMUM ||
Opc == ISD::FMINIMUMNUM;
19401 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
19410 return DAG.
getNode(
N->getOpcode(), SDLoc(
N), VT, N1, N0);
19424 if (PropAllNaNsToQNaNs || (AF.
isSignaling() && PropOnlySNaNsToQNaNs)) {
19429 return N->getOperand(0);
19442 (!PropAllNaNsToQNaNs ||
Flags.hasNoNaNs()))
19443 return N->getOperand(1);
19451 if (IsMin != AF.
isNegative() && (PropAllNaNsToQNaNs ||
Flags.hasNoNaNs()))
19452 return N->getOperand(0);
19457 if (
Opc == ISD::FMINIMUMNUM ||
Opc == ISD::FMAXIMUMNUM)
19460 if (
SDValue SD = reassociateReduction(
19462 ? (IsMin ? ISD::VECREDUCE_FMINIMUM : ISD::VECREDUCE_FMAXIMUM)
19463 : (IsMin ? ISD::VECREDUCE_FMIN : ISD::VECREDUCE_FMAX),
19464 Opc, SDLoc(
N), VT, N0, N1, Flags))
19470SDValue DAGCombiner::visitFABS(SDNode *
N) {
19472 EVT VT =
N->getValueType(0);
19482 if (
SDValue Cast = foldSignChangeInBitcast(
N))
19488SDValue DAGCombiner::visitBRCOND(SDNode *
N) {
19496 return DAG.
getNode(ISD::BRCOND, SDLoc(
N), MVT::Other, Chain,
19515 bool Updated =
false;
19527 return True || False;
19531 if (!IsAlwaysTrueOrFalse(
Cond, S1C)) {
19538 S1 =
S1->getOperand(0);
19545 ISD::BRCOND, SDLoc(
N), MVT::Other, Chain,
19561 return DAG.
getNode(ISD::BR_CC, SDLoc(
N), MVT::Other, Chain,
19569 HandleSDNode ChainHandle(Chain);
19570 if (
SDValue NewN1 = rebuildSetCC(N1))
19571 return DAG.
getNode(ISD::BRCOND, SDLoc(
N), MVT::Other,
19572 ChainHandle.getValue(), NewN1, N2,
N->getFlags());
19581 (
N.getOperand(0).hasOneUse() &&
19582 N.getOperand(0).getOpcode() ==
ISD::SRL))) {
19585 N =
N.getOperand(0);
19632 HandleSDNode XORHandle(
N);
19634 SDValue Tmp = visitXOR(
N.getNode());
19641 N = XORHandle.getValue();
19653 bool Equal =
false;
19663 EVT SetCCVT =
N.getValueType();
19672 return DAG.
getSetCC(SDLoc(
N), SetCCVT, Op0, Op1, CC);
19681SDValue DAGCombiner::visitBR_CC(SDNode *
N) {
19693 CondLHS, CondRHS, CC->
get(), SDLoc(
N),
19699 return DAG.
getNode(ISD::BR_CC, SDLoc(
N), MVT::Other,
19711 if (LD->isIndexed())
19713 EVT VT = LD->getMemoryVT();
19716 Ptr = LD->getBasePtr();
19718 if (ST->isIndexed())
19720 EVT VT = ST->getMemoryVT();
19723 Ptr = ST->getBasePtr();
19726 if (LD->isIndexed())
19728 EVT VT = LD->getMemoryVT();
19732 Ptr = LD->getBasePtr();
19735 if (ST->isIndexed())
19737 EVT VT = ST->getMemoryVT();
19741 Ptr = ST->getBasePtr();
19755bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *
N) {
19759 bool IsLoad =
true;
19760 bool IsMasked =
false;
19782 bool Swapped =
false;
19811 if (Val == BasePtr)
19820 SmallPtrSet<const SDNode *, 32> Visited;
19830 for (SDUse &Use :
BasePtr->uses()) {
19833 if (
Use.getUser() ==
Ptr.getNode() || Use != BasePtr)
19846 SDValue Op1 =
Use.getUser()->getOperand((
Use.getOperandNo() + 1) & 1);
19865 bool RealUse =
false;
19867 for (SDNode *User :
Ptr->users()) {
19901 WorklistRemover DeadNodes(*
this);
19910 deleteAndRecombine(
N);
19916 for (SDNode *OtherUse : OtherUses) {
19917 unsigned OffsetIdx = 1;
19918 if (OtherUse->getOperand(OffsetIdx).getNode() ==
BasePtr.getNode())
19920 assert(OtherUse->getOperand(!OffsetIdx).getNode() ==
BasePtr.getNode() &&
19921 "Expected BasePtr operand");
19935 const APInt &Offset0 = CN->getAPIntValue();
19936 const APInt &Offset1 =
Offset->getAsAPIntVal();
19937 int X0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 1) ? -1 : 1;
19938 int Y0 = (OtherUse->getOpcode() ==
ISD::SUB && OffsetIdx == 0) ? -1 : 1;
19942 unsigned Opcode = (Y0 * Y1 < 0) ?
ISD::SUB : ISD::
ADD;
19944 APInt CNV = Offset0;
19945 if (X0 < 0) CNV = -CNV;
19946 if (X1 * Y0 * Y1 < 0) CNV = CNV + Offset1;
19947 else CNV = CNV - Offset1;
19949 SDLoc
DL(OtherUse);
19956 DAG.
getNode(Opcode,
DL, OtherUse->getValueType(0), NewOp1, NewOp2);
19958 deleteAndRecombine(OtherUse);
19963 deleteAndRecombine(
Ptr.getNode());
19964 AddToWorklist(
Result.getNode());
19996 bool IsLoad =
true;
19997 bool IsMasked =
false;
20000 IsMasked, OtherPtr, TLI)) {
20026 IsMasked,
Ptr, TLI) ||
20038 if (U.getResNo() !=
Ptr.getResNo())
20064bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *
N) {
20068 bool IsLoad =
true;
20069 bool IsMasked =
false;
20090 ++PostIndexedNodes;
20094 WorklistRemover DeadNodes(*
this);
20103 deleteAndRecombine(
N);
20107 Result.getValue(IsLoad ? 1 : 0));
20108 deleteAndRecombine(
Op);
20113SDValue DAGCombiner::SplitIndexingFromLoad(LoadSDNode *LD) {
20124 "Cannot split out indexing using opaque target constants");
20140bool DAGCombiner::getTruncatedStoreValue(StoreSDNode *ST,
SDValue &Val) {
20142 EVT STMemType =
ST->getMemoryVT();
20143 if (STType == STMemType)
20149 Val = DAG.
getNode(ISD::FTRUNC, SDLoc(ST), STMemType, Val);
20164bool DAGCombiner::extendLoadedValueToExtension(LoadSDNode *LD,
SDValue &Val) {
20165 EVT LDMemType =
LD->getMemoryVT();
20166 EVT LDType =
LD->getValueType(0);
20168 "Attempting to extend value of non-matching type");
20169 if (LDType == LDMemType)
20172 switch (
LD->getExtensionType()) {
20190StoreSDNode *DAGCombiner::getUniqueStoreFeeding(LoadSDNode *LD,
20195 if (Chain.
getOpcode() == ISD::CALLSEQ_START)
20198 StoreSDNode *
ST =
nullptr;
20208 if (!BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
20211 GatherAllAliases(Store, Chain, Aliases);
20212 if (Aliases.
empty() ||
20213 (Aliases.
size() == 1 && Aliases.
front().getNode() == Store))
20222 if (BasePtrST.equalBaseIndex(BasePtrLD, DAG,
Offset))
20230SDValue DAGCombiner::ForwardStoreValueToDirectLoad(LoadSDNode *LD) {
20236 StoreSDNode *
ST = getUniqueStoreFeeding(LD,
Offset);
20238 if (!ST || !
ST->isSimple() ||
ST->getAddressSpace() !=
LD->getAddressSpace())
20241 EVT LDType =
LD->getValueType(0);
20242 EVT LDMemType =
LD->getMemoryVT();
20243 EVT STMemType =
ST->getMemoryVT();
20244 EVT STType =
ST->getValue().getValueType();
20268 int64_t OrigOffset =
Offset;
20281 STCoversLD = (
Offset == 0) && LdMemSize == StMemSize;
20287 if (
LD->isIndexed()) {
20292 SDValue Idx = SplitIndexingFromLoad(LD);
20294 return CombineTo(LD,
Ops, 3);
20296 return CombineTo(LD, Val, Chain);
20303 if (
Offset == 0 && LDType == STType && STMemType == LDMemType) {
20306 return ReplaceLd(LD,
ST->getValue(), Chain);
20314 SDLoc(ST), STType);
20316 return ReplaceLd(LD, Val, Chain);
20334 if (
LD->getBasePtr().isUndef() ||
Offset != 0)
20339 if (!getTruncatedStoreValue(ST, Val))
20343 if (STMemType != LDMemType) {
20351 if (!extendLoadedValueToExtension(LD, Val))
20353 return ReplaceLd(LD, Val, Chain);
20358 deleteAndRecombine(Val.
getNode());
20362SDValue DAGCombiner::visitLOAD(SDNode *
N) {
20371 if (
LD->isSimple()) {
20372 if (
N->getValueType(1) == MVT::Other) {
20374 if (!
N->hasAnyUseOfValue(0)) {
20382 dbgs() <<
"\nWith chain: "; Chain.
dump(&DAG);
20384 WorklistRemover DeadNodes(*
this);
20386 AddUsersToWorklist(Chain.
getNode());
20387 if (
N->use_empty())
20388 deleteAndRecombine(
N);
20394 assert(
N->getValueType(2) == MVT::Other &&
"Malformed indexed loads?");
20402 if (!
N->hasAnyUseOfValue(0) && (CanSplitIdx || !
N->hasAnyUseOfValue(1))) {
20405 if (
N->hasAnyUseOfValue(1) && CanSplitIdx) {
20406 Index = SplitIndexingFromLoad(LD);
20409 AddUsersToWorklist(
N);
20413 dbgs() <<
"\nWith: ";
Undef.dump(&DAG);
20414 dbgs() <<
" and 2 other values\n");
20415 WorklistRemover DeadNodes(*
this);
20419 deleteAndRecombine(
N);
20427 if (
auto V = ForwardStoreValueToDirectLoad(LD))
20434 if (*Alignment >
LD->getAlign() &&
20435 isAligned(*Alignment,
LD->getSrcValueOffset())) {
20437 LD->getExtensionType(), SDLoc(
N),
LD->getValueType(0), Chain,
Ptr,
20438 LD->getPointerInfo(),
LD->getMemoryVT(), *Alignment,
20439 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
20447 if (
LD->isUnindexed()) {
20449 SDValue BetterChain = FindBetterChain(LD, Chain);
20452 if (Chain != BetterChain) {
20457 ReplLoad = DAG.
getLoad(
N->getValueType(0), SDLoc(LD),
20458 BetterChain,
Ptr,
LD->getMemOperand());
20460 ReplLoad = DAG.
getExtLoad(
LD->getExtensionType(), SDLoc(LD),
20461 LD->getValueType(0),
20462 BetterChain,
Ptr,
LD->getMemoryVT(),
20463 LD->getMemOperand());
20468 MVT::Other, Chain, ReplLoad.
getValue(1));
20471 return CombineTo(
N, ReplLoad.
getValue(0), Token);
20476 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
20481 if (SliceUpLoad(
N))
20501struct LoadedSlice {
20505 bool ForCodeSize =
false;
20508 unsigned Loads = 0;
20509 unsigned Truncates = 0;
20510 unsigned CrossRegisterBanksCopies = 0;
20511 unsigned ZExts = 0;
20512 unsigned Shift = 0;
20514 explicit Cost(
bool ForCodeSize) : ForCodeSize(ForCodeSize) {}
20517 Cost(
const LoadedSlice &LS,
bool ForCodeSize)
20518 : ForCodeSize(ForCodeSize), Loads(1) {
20519 EVT TruncType =
LS.Inst->getValueType(0);
20520 EVT LoadedType =
LS.getLoadedType();
20521 if (TruncType != LoadedType &&
20522 !
LS.DAG->getTargetLoweringInfo().isZExtFree(LoadedType, TruncType))
20530 void addSliceGain(
const LoadedSlice &LS) {
20532 const TargetLowering &TLI =
LS.DAG->getTargetLoweringInfo();
20539 if (
LS.canMergeExpensiveCrossRegisterBankCopy())
20540 ++CrossRegisterBanksCopies;
20544 Loads +=
RHS.Loads;
20545 Truncates +=
RHS.Truncates;
20546 CrossRegisterBanksCopies +=
RHS.CrossRegisterBanksCopies;
20547 ZExts +=
RHS.ZExts;
20548 Shift +=
RHS.Shift;
20553 return Loads ==
RHS.Loads && Truncates ==
RHS.Truncates &&
20554 CrossRegisterBanksCopies ==
RHS.CrossRegisterBanksCopies &&
20555 ZExts ==
RHS.ZExts && Shift ==
RHS.Shift;
20563 unsigned ExpensiveOpsLHS = Loads + CrossRegisterBanksCopies;
20564 unsigned ExpensiveOpsRHS =
RHS.Loads +
RHS.CrossRegisterBanksCopies;
20567 if (!ForCodeSize && ExpensiveOpsLHS != ExpensiveOpsRHS)
20568 return ExpensiveOpsLHS < ExpensiveOpsRHS;
20569 return (Truncates + ZExts + Shift + ExpensiveOpsLHS) <
20570 (
RHS.Truncates +
RHS.ZExts +
RHS.Shift + ExpensiveOpsRHS);
20585 LoadSDNode *Origin;
20594 LoadedSlice(SDNode *Inst =
nullptr, LoadSDNode *Origin =
nullptr,
20595 unsigned Shift = 0, SelectionDAG *DAG =
nullptr)
20596 : Inst(Inst), Origin(Origin), Shift(Shift), DAG(DAG) {}
20601 APInt getUsedBits()
const {
20606 assert(Origin &&
"No original load to compare against.");
20608 assert(Inst &&
"This slice is not bound to an instruction");
20610 "Extracted slice is bigger than the whole type!");
20612 UsedBits.setAllBits();
20613 UsedBits = UsedBits.zext(
BitWidth);
20614 UsedBits <<= Shift;
20619 unsigned getLoadedSize()
const {
20620 unsigned SliceSize = getUsedBits().popcount();
20621 assert(!(SliceSize & 0x7) &&
"Size is not a multiple of a byte.");
20622 return SliceSize / 8;
20627 EVT getLoadedType()
const {
20628 assert(DAG &&
"Missing context");
20636 uint64_t
Offset = getOffsetFromBase();
20643 bool isLegal()
const {
20645 if (!Origin || !Inst || !DAG)
20655 EVT SliceType = getLoadedType();
20666 if (PtrType == MVT::Untyped || PtrType.
isExtended())
20679 if (TruncateType != SliceType &&
20689 uint64_t getOffsetFromBase()
const {
20690 assert(DAG &&
"Missing context.");
20692 assert(!(Shift & 0x7) &&
"Shifts not aligned on Bytes are not supported.");
20693 uint64_t
Offset = Shift / 8;
20696 "The size of the original loaded type is not a multiple of a"
20701 "Invalid shift amount for given loaded size");
20714 assert(Inst && Origin &&
"Unable to replace a non-existing slice.");
20718 int64_t
Offset =
static_cast<int64_t
>(getOffsetFromBase());
20719 assert(
Offset >= 0 &&
"Offset too big to fit in int64_t!");
20722 EVT ArithType =
BaseAddr.getValueType();
20729 EVT SliceType = getLoadedType();
20739 if (SliceType != FinalType)
20749 bool canMergeExpensiveCrossRegisterBankCopy()
const {
20753 if (
User->getOpcode() != ISD::BITCAST)
20755 assert(DAG &&
"Missing context");
20757 EVT ResVT =
User->getValueType(0);
20758 const TargetRegisterClass *ResRC =
20760 const TargetRegisterClass *ArgRC =
20762 User->getOperand(0)->isDivergent());
20771 if (!
TRI ||
TRI->getCommonSubClass(ArgRC, ResRC))
20776 unsigned IsFast = 0;
20817 const LoadedSlice &Second) {
20819 "Unable to match different memory origins.");
20821 assert((UsedBits & Second.getUsedBits()) == 0 &&
20822 "Slices are not supposed to overlap.");
20823 UsedBits |= Second.getUsedBits();
20832 LoadedSlice::Cost &GlobalLSCost) {
20833 unsigned NumberOfSlices = LoadedSlices.
size();
20835 if (NumberOfSlices < 2)
20840 llvm::sort(LoadedSlices, [](
const LoadedSlice &
LHS,
const LoadedSlice &
RHS) {
20841 assert(
LHS.Origin ==
RHS.Origin &&
"Different bases not implemented.");
20842 return LHS.getOffsetFromBase() <
RHS.getOffsetFromBase();
20844 const TargetLowering &TLI = LoadedSlices[0].DAG->getTargetLoweringInfo();
20847 const LoadedSlice *
First =
nullptr;
20848 const LoadedSlice *Second =
nullptr;
20849 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice,
20852 Second = &LoadedSlices[CurrSlice];
20859 EVT LoadedType =
First->getLoadedType();
20862 if (LoadedType != Second->getLoadedType())
20866 Align RequiredAlignment;
20867 if (!TLI.hasPairedLoad(LoadedType, RequiredAlignment)) {
20873 if (
First->getAlign() < RequiredAlignment)
20880 assert(GlobalLSCost.Loads > 0 &&
"We save more loads than we created!");
20881 --GlobalLSCost.Loads;
20898 const APInt &UsedBits,
bool ForCodeSize) {
20899 unsigned NumberOfSlices = LoadedSlices.
size();
20901 return NumberOfSlices > 1;
20904 if (NumberOfSlices != 2)
20912 LoadedSlice::Cost OrigCost(ForCodeSize), GlobalSlicingCost(ForCodeSize);
20914 OrigCost.Loads = 1;
20915 for (
unsigned CurrSlice = 0; CurrSlice < NumberOfSlices; ++CurrSlice) {
20916 const LoadedSlice &LS = LoadedSlices[CurrSlice];
20918 LoadedSlice::Cost SliceCost(LS, ForCodeSize);
20919 GlobalSlicingCost += SliceCost;
20923 OrigCost.addSliceGain(LS);
20928 return OrigCost > GlobalSlicingCost;
20937bool DAGCombiner::SliceUpLoad(SDNode *
N) {
20943 !
LD->getValueType(0).isInteger())
20949 if (
LD->getValueType(0).isScalableVector())
20954 APInt UsedBits(
LD->getValueSizeInBits(0), 0);
20961 for (SDUse &U :
LD->uses()) {
20963 if (
U.getResNo() != 0)
20966 SDNode *
User =
U.getUser();
20967 unsigned Shift = 0;
20972 Shift =
User->getConstantOperandVal(1);
20985 unsigned Width =
User->getValueSizeInBits(0);
20990 LoadedSlice
LS(User, LD, Shift, &DAG);
20991 APInt CurrentUsedBits =
LS.getUsedBits();
20994 if ((CurrentUsedBits & UsedBits) != 0)
20997 UsedBits |= CurrentUsedBits;
21018 for (
const LoadedSlice &LS : LoadedSlices) {
21020 CombineTo(
LS.Inst, SliceInst,
true);
21021 if (SliceInst.
getOpcode() != ISD::LOAD)
21024 "It takes more than a zext to get to the loaded slice!!");
21031 AddToWorklist(Chain.
getNode());
21038static std::pair<unsigned, unsigned>
21040 std::pair<unsigned, unsigned> Result(0, 0);
21050 if (LD->getBasePtr() !=
Ptr)
return Result;
21053 if (V.getValueType() != MVT::i16 &&
21054 V.getValueType() != MVT::i32 &&
21055 V.getValueType() != MVT::i64)
21063 if (NotMaskLZ & 7)
return Result;
21065 if (NotMaskTZ & 7)
return Result;
21066 if (NotMaskLZ == 64)
return Result;
21073 if (V.getValueType() != MVT::i64 && NotMaskLZ)
21074 NotMaskLZ -= 64-V.getValueSizeInBits();
21076 unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8;
21077 switch (MaskedBytes) {
21081 default:
return Result;
21086 if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes)
return Result;
21093 SDValue(LD, 1).hasOneUse()) {
21095 if (!LD->isOperandOf(Chain.
getNode()))
21100 Result.first = MaskedBytes;
21101 Result.second = NotMaskTZ/8;
21112 unsigned NumBytes = MaskInfo.first;
21113 unsigned ByteShift = MaskInfo.second;
21119 ByteShift*8, (ByteShift+NumBytes)*8);
21128 bool UseTruncStore;
21129 if (DC->isTypeLegal(VT))
21130 UseTruncStore =
false;
21133 UseTruncStore =
true;
21159 StOffset = ByteShift;
21187SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *
N) {
21189 if (!
ST->isSimple())
21195 EVT VT =
Value.getValueType();
21197 if (
ST->isTruncatingStore() || VT.
isVector())
21203 !
Value.hasOneUse())
21212 std::pair<unsigned, unsigned> MaskedLoad;
21214 if (MaskedLoad.first)
21216 Value.getOperand(1), ST,
this))
21221 if (MaskedLoad.first)
21223 Value.getOperand(0), ST,
this))
21237 if (
LD->getBasePtr() !=
Ptr ||
21238 LD->getPointerInfo().getAddrSpace() !=
21239 ST->getPointerInfo().getAddrSpace())
21248 if (Imm == 0 ||
Imm.isAllOnes())
21253 unsigned BitsPerByteMask = 7u;
21254 unsigned LSB =
Imm.countr_zero() & ~BitsPerByteMask;
21255 unsigned MSB = (
Imm.getActiveBits() - 1) | BitsPerByteMask;
21283 unsigned ShAmt = 0;
21284 uint64_t PtrOff = 0;
21285 for (; ShAmt + NewBW <= VTStoreSize; ShAmt += 8) {
21289 if (ShAmt + NewBW < MSB)
21294 ? VTStoreSize - NewBW - ShAmt
21296 PtrOff = PtrAdjustmentInBits / 8;
21299 unsigned IsFast = 0;
21302 LD->getAddressSpace(), NewAlign,
21303 LD->getMemOperand()->getFlags(), &IsFast) &&
21308 if (ShAmt + NewBW > VTStoreSize)
21311 APInt NewImm =
Imm.lshr(ShAmt).trunc(NewBW);
21318 DAG.
getLoad(NewVT, SDLoc(N0),
LD->getChain(), NewPtr,
21319 LD->getPointerInfo().getWithOffset(PtrOff), NewAlign,
21320 LD->getMemOperand()->getFlags(),
LD->getAAInfo());
21324 DAG.
getStore(Chain, SDLoc(
N), NewVal, NewPtr,
21325 ST->getPointerInfo().getWithOffset(PtrOff), NewAlign);
21327 AddToWorklist(NewPtr.
getNode());
21328 AddToWorklist(NewLD.
getNode());
21329 AddToWorklist(NewVal.
getNode());
21330 WorklistRemover DeadNodes(*
this);
21342SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *
N) {
21346 Value.hasOneUse()) {
21348 EVT VT =
LD->getMemoryVT();
21350 LD->isNonTemporal() ||
ST->isNonTemporal() ||
21351 LD->getPointerInfo().getAddrSpace() != 0 ||
21352 ST->getPointerInfo().getAddrSpace() != 0)
21362 unsigned FastLD = 0, FastST = 0;
21369 *
LD->getMemOperand(), &FastLD) ||
21371 *
ST->getMemOperand(), &FastST) ||
21372 !FastLD || !FastST)
21376 LD->getBasePtr(),
LD->getMemOperand());
21379 ST->getBasePtr(),
ST->getMemOperand());
21381 AddToWorklist(NewLD.
getNode());
21382 AddToWorklist(NewST.
getNode());
21383 WorklistRemover DeadNodes(*
this);
21405bool DAGCombiner::isMulAddWithConstProfitable(SDNode *MulNode,
SDValue AddNode,
21414 for (SDNode *User : ConstNode->
users()) {
21415 if (User == MulNode)
21423 if (
User->getOperand(0) == ConstNode)
21424 OtherOp =
User->getOperand(1).getNode();
21426 OtherOp =
User->getOperand(0).getNode();
21438 if (OtherOp == MulVar)
21465SDValue DAGCombiner::getMergeStoreChains(SmallVectorImpl<MemOpLink> &StoreNodes,
21466 unsigned NumStores) {
21468 SmallPtrSet<const SDNode *, 8> Visited;
21469 SDLoc StoreDL(StoreNodes[0].MemNode);
21471 for (
unsigned i = 0; i < NumStores; ++i) {
21472 Visited.
insert(StoreNodes[i].MemNode);
21476 for (
unsigned i = 0; i < NumStores; ++i) {
21477 if (Visited.
insert(StoreNodes[i].MemNode->getChain().getNode()).second)
21478 Chains.
push_back(StoreNodes[i].MemNode->getChain());
21481 assert(!Chains.
empty() &&
"Chain should have generated a chain");
21486 const Value *UnderlyingObj =
nullptr;
21487 for (
const auto &MemOp : StoreNodes) {
21488 const MachineMemOperand *MMO = MemOp.MemNode->getMemOperand();
21499 if (UnderlyingObj && UnderlyingObj != Obj)
21502 if (!UnderlyingObj)
21503 UnderlyingObj = Obj;
21509bool DAGCombiner::mergeStoresOfConstantsOrVecElts(
21510 SmallVectorImpl<MemOpLink> &StoreNodes, EVT MemVT,
unsigned NumStores,
21511 bool IsConstantSrc,
bool UseVector,
bool UseTrunc) {
21516 assert((!UseTrunc || !UseVector) &&
21517 "This optimization cannot emit a vector truncating store");
21520 SDLoc
DL(StoreNodes[0].MemNode);
21523 unsigned SizeInBits = NumStores * ElementSizeBits;
21526 std::optional<MachineMemOperand::Flags>
Flags;
21528 for (
unsigned I = 0;
I != NumStores; ++
I) {
21544 unsigned Elts = NumStores * NumMemElts;
21552 if (IsConstantSrc) {
21554 for (
unsigned I = 0;
I != NumStores; ++
I) {
21573 .zextOrTrunc(ElementSizeBits),
21574 SDLoc(
C), IntMemVT);
21583 DL, StoreTy, BuildVector);
21586 for (
unsigned i = 0; i < NumStores; ++i) {
21610 Val = DAG.
getNode(OpC, SDLoc(Val), MemVT, Vec, Idx);
21613 Ops.push_back(Val);
21624 assert(IsConstantSrc &&
"Merged vector elements should use vector store");
21626 APInt StoreInt(SizeInBits, 0);
21631 for (
unsigned i = 0; i < NumStores; ++i) {
21632 unsigned Idx = IsLE ? (NumStores - 1 - i) : i;
21637 StoreInt <<= ElementSizeBits;
21639 StoreInt |=
C->getAPIntValue()
21640 .zextOrTrunc(ElementSizeBits)
21641 .zextOrTrunc(SizeInBits);
21643 StoreInt |=
C->getValueAPF()
21645 .zextOrTrunc(ElementSizeBits)
21646 .zextOrTrunc(SizeInBits);
21663 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
21664 SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
21665 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
21679 FirstInChain->
getAlign(), *Flags, AAInfo);
21681 EVT LegalizedStoredValTy =
21683 unsigned LegalizedStoreSize = LegalizedStoredValTy.
getSizeInBits();
21686 DAG.
getConstant(
C->getAPIntValue().zextOrTrunc(LegalizedStoreSize),
DL,
21687 LegalizedStoredValTy);
21689 NewChain,
DL, ExtendedStoreVal, FirstInChain->
getBasePtr(),
21698 for (
unsigned i = 0; i < NumStores; ++i)
21699 CombineTo(StoreNodes[i].MemNode, NewStore);
21701 AddToWorklist(NewChain.
getNode());
21706DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
21707 SmallVectorImpl<MemOpLink> &StoreNodes) {
21712 if (!
BasePtr.getBase().getNode() ||
BasePtr.getBase().isUndef())
21716 StoreSource StoreSrc = getStoreSource(Val);
21717 assert(StoreSrc != StoreSource::Unknown &&
"Expected known source for store");
21721 BaseIndexOffset LBasePtr;
21723 if (StoreSrc == StoreSource::Load) {
21726 LoadVT = Ld->getMemoryVT();
21728 if (MemVT != LoadVT)
21731 if (!Ld->hasNUsesOfValue(1, 0))
21735 if (!Ld->isSimple() || Ld->isIndexed())
21738 auto CandidateMatch = [&](StoreSDNode *
Other, BaseIndexOffset &
Ptr,
21739 int64_t &
Offset) ->
bool {
21742 if (!
Other->isSimple() ||
Other->isIndexed())
21752 :
Other->getMemoryVT() != MemVT;
21753 switch (StoreSrc) {
21754 case StoreSource::Load: {
21762 if (LoadVT != OtherLd->getMemoryVT())
21765 if (!OtherLd->hasNUsesOfValue(1, 0))
21769 if (!OtherLd->isSimple() || OtherLd->isIndexed())
21777 if (!(LBasePtr.equalBaseIndex(LPtr, DAG)))
21781 case StoreSource::Constant:
21784 if (getStoreSource(OtherBC) != StoreSource::Constant)
21787 case StoreSource::Extract:
21789 if (
Other->isTruncatingStore())
21822 if (ChainsWithoutMergeableStores.
contains(RootNode))
21827 auto OverLimitInDependenceCheck = [&](SDNode *StoreNode,
21828 SDNode *RootNode) ->
bool {
21829 auto RootCount = StoreRootCountMap.
find(StoreNode);
21830 return RootCount != StoreRootCountMap.
end() &&
21831 RootCount->second.first == RootNode &&
21835 auto TryToAddCandidate = [&](SDUse &
Use) {
21837 if (
Use.getOperandNo() != 0)
21840 BaseIndexOffset
Ptr;
21842 if (CandidateMatch(OtherStore,
Ptr, PtrDiff) &&
21843 !OverLimitInDependenceCheck(OtherStore, RootNode))
21844 StoreNodes.
push_back(MemOpLink(OtherStore, PtrDiff));
21848 unsigned NumNodesExplored = 0;
21849 const unsigned MaxSearchNodes = 1024;
21851 RootNode = Ldn->getChain().getNode();
21853 if (ChainsWithoutMergeableStores.
contains(RootNode))
21856 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored) {
21857 SDNode *
User =
I->getUser();
21859 for (SDUse &U2 :
User->uses())
21860 TryToAddCandidate(U2);
21864 TryToAddCandidate(*
I);
21869 I !=
E && NumNodesExplored < MaxSearchNodes; ++
I, ++NumNodesExplored)
21870 TryToAddCandidate(*
I);
21879bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
21880 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumStores,
21881 SDNode *RootNode) {
21887 SmallPtrSet<const SDNode *, 32> Visited;
21895 while (!Worklist.
empty()) {
21897 if (!Visited.
insert(
N).second)
21906 unsigned int Max = 1024 + Visited.
size();
21908 for (
unsigned i = 0; i < NumStores; ++i) {
21909 SDNode *
N = StoreNodes[i].MemNode;
21930 for (
unsigned i = 0; i < NumStores; ++i)
21936 if (Visited.
size() >= Max) {
21937 auto &RootCount = StoreRootCountMap[StoreNodes[i].MemNode];
21938 if (RootCount.first == RootNode)
21939 RootCount.second++;
21941 RootCount = {RootNode, 1};
21948bool DAGCombiner::hasCallInLdStChain(StoreSDNode *St, LoadSDNode *Ld) {
21949 SmallPtrSet<const SDNode *, 32> Visited;
21953 while (!Worklist.
empty()) {
21955 if (!Visited.
insert(Node).second ||
Node->getNumOperands() == 0)
21958 switch (
Node->getOpcode()) {
21959 case ISD::CALLSEQ_END:
21971 assert(
Node->getOperand(0).getValueType() == MVT::Other &&
21972 "Invalid chain type");
21981DAGCombiner::getConsecutiveStores(SmallVectorImpl<MemOpLink> &StoreNodes,
21982 int64_t ElementSizeBytes)
const {
21985 size_t StartIdx = 0;
21986 while ((StartIdx + 1 < StoreNodes.
size()) &&
21987 StoreNodes[StartIdx].OffsetFromBase + ElementSizeBytes !=
21988 StoreNodes[StartIdx + 1].OffsetFromBase)
21992 if (StartIdx + 1 >= StoreNodes.
size())
22001 unsigned NumConsecutiveStores = 1;
22002 int64_t StartAddress = StoreNodes[0].OffsetFromBase;
22005 for (
unsigned i = 1, e = StoreNodes.
size(); i < e; ++i) {
22006 int64_t CurrAddress = StoreNodes[i].OffsetFromBase;
22007 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
22009 NumConsecutiveStores = i + 1;
22011 if (NumConsecutiveStores > 1)
22012 return NumConsecutiveStores;
22020bool DAGCombiner::tryStoreMergeOfConstants(
22021 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
22022 EVT MemVT, SDNode *RootNode,
bool AllowVectors) {
22027 bool MadeChange =
false;
22030 while (NumConsecutiveStores >= 2) {
22031 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22034 unsigned LastLegalType = 1;
22035 unsigned LastLegalVectorType = 1;
22036 bool LastIntegerTrunc =
false;
22037 bool NonZero =
false;
22038 unsigned FirstZeroAfterNonZero = NumConsecutiveStores;
22039 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22042 bool IsElementZero =
false;
22044 IsElementZero =
C->isZero();
22046 IsElementZero =
C->getConstantFPValue()->isNullValue();
22048 IsElementZero =
true;
22049 if (IsElementZero) {
22050 if (NonZero && FirstZeroAfterNonZero == NumConsecutiveStores)
22051 FirstZeroAfterNonZero = i;
22053 NonZero |= !IsElementZero;
22056 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
22058 unsigned IsFast = 0;
22070 LastIntegerTrunc =
false;
22071 LastLegalType = i + 1;
22075 EVT LegalizedStoredValTy =
22083 LastIntegerTrunc =
true;
22084 LastLegalType = i + 1;
22093 unsigned Elts = (i + 1) * NumMemElts;
22100 LastLegalVectorType = i + 1;
22104 bool UseVector = (LastLegalVectorType > LastLegalType) && AllowVectors;
22105 unsigned NumElem = (UseVector) ? LastLegalVectorType : LastLegalType;
22106 bool UseTrunc = LastIntegerTrunc && !UseVector;
22118 unsigned NumSkip = 1;
22119 while ((NumSkip < NumConsecutiveStores) &&
22120 (NumSkip < FirstZeroAfterNonZero) &&
22121 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22125 NumConsecutiveStores -= NumSkip;
22130 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
22133 NumConsecutiveStores -= NumElem;
22137 MadeChange |= mergeStoresOfConstantsOrVecElts(StoreNodes, MemVT, NumElem,
22139 UseVector, UseTrunc);
22143 NumConsecutiveStores -= NumElem;
22148bool DAGCombiner::tryStoreMergeOfExtracts(
22149 SmallVectorImpl<MemOpLink> &StoreNodes,
unsigned NumConsecutiveStores,
22150 EVT MemVT, SDNode *RootNode) {
22154 bool MadeChange =
false;
22157 while (NumConsecutiveStores >= 2) {
22158 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22161 unsigned NumStoresToMerge = 1;
22162 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22164 unsigned Elts = (i + 1) * NumMemElts;
22166 unsigned IsFast = 0;
22177 NumStoresToMerge = i + 1;
22182 if (NumStoresToMerge < 2) {
22189 unsigned NumSkip = 1;
22190 while ((NumSkip < NumConsecutiveStores) &&
22191 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22195 NumConsecutiveStores -= NumSkip;
22200 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumStoresToMerge,
22203 StoreNodes.
begin() + NumStoresToMerge);
22204 NumConsecutiveStores -= NumStoresToMerge;
22208 MadeChange |= mergeStoresOfConstantsOrVecElts(
22209 StoreNodes, MemVT, NumStoresToMerge,
false,
22212 StoreNodes.
erase(StoreNodes.
begin(), StoreNodes.
begin() + NumStoresToMerge);
22213 NumConsecutiveStores -= NumStoresToMerge;
22218bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl<MemOpLink> &StoreNodes,
22219 unsigned NumConsecutiveStores, EVT MemVT,
22220 SDNode *RootNode,
bool AllowVectors,
22221 bool IsNonTemporalStore,
22222 bool IsNonTemporalLoad) {
22227 bool MadeChange =
false;
22234 BaseIndexOffset LdBasePtr;
22236 for (
unsigned i = 0; i < NumConsecutiveStores; ++i) {
22243 int64_t LdOffset = 0;
22244 if (LdBasePtr.
getBase().getNode()) {
22246 if (!LdBasePtr.equalBaseIndex(LdPtr, DAG, LdOffset))
22254 LoadNodes.
push_back(MemOpLink(Ld, LdOffset));
22257 while (NumConsecutiveStores >= 2 && LoadNodes.
size() >= 2) {
22258 Align RequiredAlignment;
22259 bool NeedRotate =
false;
22260 if (LoadNodes.
size() == 2) {
22264 StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
22270 int64_t Offset0 = LoadNodes[0].OffsetFromBase;
22271 int64_t Offset1 = LoadNodes[1].OffsetFromBase;
22273 if (Offset0 - Offset1 == ElementSizeBytes &&
22280 LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
22289 unsigned LastConsecutiveLoad = 1;
22292 unsigned LastLegalVectorType = 1;
22293 unsigned LastLegalIntegerType = 1;
22294 bool isDereferenceable =
true;
22295 bool DoIntegerTruncate =
false;
22296 int64_t StartAddress = LoadNodes[0].OffsetFromBase;
22298 for (
unsigned i = 1; i < LoadNodes.
size(); ++i) {
22300 if (LoadNodes[i].MemNode->getChain() != LoadChain)
22303 int64_t CurrAddress = LoadNodes[i].OffsetFromBase;
22304 if (CurrAddress - StartAddress != (ElementSizeBytes * i))
22306 LastConsecutiveLoad = i;
22308 if (isDereferenceable && !LoadNodes[i].MemNode->isDereferenceable())
22309 isDereferenceable =
false;
22312 unsigned Elts = (i + 1) * NumMemElts;
22319 unsigned IsFastSt = 0;
22320 unsigned IsFastLd = 0;
22334 LastLegalVectorType = i + 1;
22338 unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
22349 LastLegalIntegerType = i + 1;
22350 DoIntegerTruncate =
false;
22367 LastLegalIntegerType = i + 1;
22368 DoIntegerTruncate =
true;
22376 LastLegalVectorType > LastLegalIntegerType && AllowVectors;
22377 unsigned LastLegalType =
22378 std::max(LastLegalVectorType, LastLegalIntegerType);
22382 unsigned NumElem = std::min(NumConsecutiveStores, LastConsecutiveLoad + 1);
22383 NumElem = std::min(LastLegalType, NumElem);
22394 unsigned NumSkip = 1;
22395 while ((NumSkip < LoadNodes.
size()) &&
22396 (LoadNodes[NumSkip].MemNode->getAlign() <= FirstLoadAlign) &&
22397 (StoreNodes[NumSkip].MemNode->getAlign() <= FirstStoreAlign))
22401 NumConsecutiveStores -= NumSkip;
22406 if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
22410 NumConsecutiveStores -= NumElem;
22419 unsigned Elts = NumElem * NumMemElts;
22422 unsigned SizeInBits = NumElem * ElementSizeBytes * 8;
22432 NumConsecutiveStores -= NumElem;
22436 SDLoc LoadDL(LoadNodes[0].MemNode);
22437 SDLoc StoreDL(StoreNodes[0].MemNode);
22442 SDValue NewStoreChain = getMergeStoreChains(StoreNodes, NumElem);
22443 bool CanReusePtrInfo = hasSameUnderlyingObj(StoreNodes);
22444 AddToWorklist(NewStoreChain.
getNode());
22449 if (IsNonTemporalLoad)
22461 if (UseVectorTy || !DoIntegerTruncate) {
22467 unsigned LoadWidth = ElementSizeBytes * 8 * 2;
22469 "Unexpected type for rotate-able load pair");
22476 NewStoreChain, StoreDL, StoreOp, FirstInChain->
getBasePtr(),
22478 : MachinePointerInfo(FirstStoreAS),
22479 FirstStoreAlign, StMMOFlags);
22486 FirstLoadAlign, LdMMOFlags);
22488 NewStoreChain, StoreDL, NewLoad, FirstInChain->
getBasePtr(),
22490 : MachinePointerInfo(FirstStoreAS),
22491 JointMemOpVT, FirstInChain->
getAlign(),
22496 for (
unsigned i = 0; i < NumElem; ++i) {
22504 for (
unsigned i = 0; i < NumElem; ++i) {
22505 SDValue Val = StoreNodes[i].MemNode->getOperand(1);
22506 CombineTo(StoreNodes[i].MemNode, NewStore);
22508 recursivelyDeleteUnusedNodes(Val.
getNode());
22514 NumConsecutiveStores -= NumElem;
22519bool DAGCombiner::mergeConsecutiveStores(StoreSDNode *St) {
22535 if (ElementSizeBytes * 8 != (int64_t)MemVT.
getSizeInBits())
22541 const StoreSource StoreSrc = getStoreSource(StoredVal);
22542 if (StoreSrc == StoreSource::Unknown)
22547 SDNode *RootNode = getStoreMergeCandidates(St, StoreNodes);
22550 if (StoreNodes.
size() < 2)
22556 return LHS.OffsetFromBase <
RHS.OffsetFromBase;
22560 Attribute::NoImplicitFloat);
22562 bool IsNonTemporalLoad = StoreSrc == StoreSource::Load &&
22572 bool MadeChange =
false;
22573 while (StoreNodes.
size() > 1) {
22574 unsigned NumConsecutiveStores =
22575 getConsecutiveStores(StoreNodes, ElementSizeBytes);
22577 if (NumConsecutiveStores == 0)
22581 assert(NumConsecutiveStores >= 2 &&
"Expected at least 2 stores");
22582 switch (StoreSrc) {
22583 case StoreSource::Constant:
22584 MadeChange |= tryStoreMergeOfConstants(StoreNodes, NumConsecutiveStores,
22585 MemVT, RootNode, AllowVectors);
22588 case StoreSource::Extract:
22589 MadeChange |= tryStoreMergeOfExtracts(StoreNodes, NumConsecutiveStores,
22593 case StoreSource::Load:
22594 MadeChange |= tryStoreMergeOfLoads(StoreNodes, NumConsecutiveStores,
22595 MemVT, RootNode, AllowVectors,
22596 IsNonTemporalStore, IsNonTemporalLoad);
22606 ChainsWithoutMergeableStores.
insert(RootNode);
22611SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST,
SDValue BetterChain) {
22616 if (
ST->isTruncatingStore()) {
22618 ST->getBasePtr(),
ST->getMemoryVT(),
22619 ST->getMemOperand());
22621 ReplStore = DAG.
getStore(BetterChain, SL,
ST->getValue(),
ST->getBasePtr(),
22622 ST->getMemOperand());
22627 MVT::Other,
ST->getChain(), ReplStore);
22630 AddToWorklist(Token.
getNode());
22633 return CombineTo(ST, Token,
false);
22636SDValue DAGCombiner::replaceStoreOfFPConstant(StoreSDNode *ST) {
22667 if ((
isTypeLegal(MVT::i32) && !LegalOperations &&
ST->isSimple()) ||
22670 bitcastToAPInt().getZExtValue(), SDLoc(CFP),
22677 if ((TLI.
isTypeLegal(MVT::i64) && !LegalOperations &&
22681 getZExtValue(), SDLoc(CFP), MVT::i64);
22683 Ptr,
ST->getMemOperand());
22698 AAMDNodes AAInfo =
ST->getAAInfo();
22701 ST->getBaseAlign(), MMOFlags, AAInfo);
22704 ST->getPointerInfo().getWithOffset(4),
22705 ST->getBaseAlign(), MMOFlags, AAInfo);
22719SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
22734 EltVT !=
Value.getOperand(0).getValueType().getVectorElementType())
22748 ST->getAlign(),
ST->getMemOperand()->getFlags(),
22753 MachinePointerInfo PointerInfo(
ST->getAddressSpace());
22759 unsigned COffset = CIdx->getSExtValue() * EltVT.
getSizeInBits() / 8;
22761 PointerInfo =
ST->getPointerInfo().getWithOffset(COffset);
22769 return DAG.
getStore(Chain,
DL, Elt, NewPtr, PointerInfo,
ST->getAlign(),
22770 ST->getMemOperand()->getFlags());
22773SDValue DAGCombiner::visitATOMIC_STORE(SDNode *
N) {
22777 EVT MemVT =
ST->getMemoryVT();
22796 SDValue StoredVal = Store->getValue();
22797 SDValue StorePtr = Store->getBasePtr();
22798 SDValue StoreOffset = Store->getOffset();
22799 EVT VT = Store->getMemoryVT();
22806 unsigned AddrSpace = Store->getAddressSpace();
22807 Align Alignment = Store->getAlign();
22814 SDValue Mask, OtherVec, LoadCh;
22833 Load->getAddressSpace() != AddrSpace)
22836 if (!Store->getChain().reachesChainWithoutSideEffects(LoadCh))
22840 Mask = DAG.
getNOT(Dl, Mask, Mask.getValueType());
22842 return DAG.
getMaskedStore(Store->getChain(), Dl, OtherVec, StorePtr,
22843 StoreOffset, Mask, VT, Store->getMemOperand(),
22844 Store->getAddressingMode());
22847SDValue DAGCombiner::visitSTORE(SDNode *
N) {
22855 if (
Value.getOpcode() == ISD::BITCAST && !
ST->isTruncatingStore() &&
22856 ST->isUnindexed()) {
22857 EVT SVT =
Value.getOperand(0).getValueType();
22864 if (((!LegalOperations &&
ST->isSimple()) ||
22867 DAG, *
ST->getMemOperand())) {
22869 ST->getMemOperand());
22874 if (
Value.isUndef() &&
ST->isUnindexed() && !
ST->isVolatile())
22881 if (*Alignment >
ST->getAlign() &&
22882 isAligned(*Alignment,
ST->getSrcValueOffset())) {
22885 ST->getMemoryVT(), *Alignment,
22886 ST->getMemOperand()->getFlags(),
ST->getAAInfo());
22896 if (
SDValue NewST = TransformFPLoadStorePair(
N))
22900 if (
SDValue Store = mergeTruncStores(ST))
22903 if (
ST->isUnindexed()) {
22906 if (findBetterNeighborChains(ST)) {
22911 Chain =
ST->getChain();
22915 if (
ST->isTruncatingStore() &&
ST->isUnindexed() &&
22916 Value.getValueType().isInteger() &&
22923 Value.getOperand(0).getValueType() ==
ST->getMemoryVT() &&
22926 ST->getMemOperand());
22928 APInt TruncDemandedBits =
22930 ST->getMemoryVT().getScalarSizeInBits());
22934 AddToWorklist(
Value.getNode());
22951 ST->getMemOperand());
22956 if (!Cst->isOpaque()) {
22957 const APInt &CValue = Cst->getAPIntValue();
22958 APInt NewVal = CValue & TruncDemandedBits;
22959 if (NewVal != CValue) {
22963 ST->getMemoryVT(),
ST->getMemOperand());
22977 ST->isUnindexed() &&
ST->isSimple() &&
22988 if (
SDValue NewST = replaceStoreOfInsertLoad(ST))
22993 if (
ST->isUnindexed() &&
ST->isSimple() &&
22994 ST1->isUnindexed() && ST1->isSimple()) {
22996 ST1->getValue() ==
Value &&
ST->getMemoryVT() == ST1->getMemoryVT() &&
22997 ST->getAddressSpace() == ST1->getAddressSpace()) {
23004 !ST1->getBasePtr().isUndef() &&
23005 ST->getAddressSpace() == ST1->getAddressSpace()) {
23010 if (
ST->getMemoryVT().isScalableVector() ||
23011 ST1->getMemoryVT().isScalableVector()) {
23012 if (ST1->getBasePtr() ==
Ptr &&
23014 ST->getMemoryVT().getStoreSize())) {
23015 CombineTo(ST1, ST1->getChain());
23025 if (STBase.contains(DAG,
ST->getMemoryVT().getFixedSizeInBits(),
23027 ST1->getMemoryVT().getFixedSizeInBits())) {
23028 CombineTo(ST1, ST1->getChain());
23040 Value->hasOneUse() &&
ST->isUnindexed() &&
23042 ST->getMemoryVT(), LegalOperations)) {
23044 Ptr,
ST->getMemoryVT(),
ST->getMemOperand());
23055 bool Changed = mergeConsecutiveStores(ST);
23065 if (CombineToPreIndexedLoadStore(
N) || CombineToPostIndexedLoadStore(
N))
23074 if (
SDValue NewSt = replaceStoreOfFPConstant(ST))
23082 return MaskedStore;
23084 return ReduceLoadOpStoreWidth(
N);
23087SDValue DAGCombiner::visitLIFETIME_END(SDNode *
N) {
23089 const BaseIndexOffset LifetimeEndBase(
N->getOperand(1),
SDValue(), 0,
false);
23093 while (!Chains.
empty()) {
23102 case ISD::LIFETIME_START:
23103 case ISD::LIFETIME_END:
23112 if (!
ST->isSimple() ||
ST->isIndexed())
23114 const TypeSize StoreSize =
ST->getMemoryVT().getStoreSize();
23123 if (LifetimeEndBase.contains(
23127 dbgs() <<
"\nwithin LIFETIME_END of : ";
23128 LifetimeEndBase.dump();
dbgs() <<
"\n");
23129 CombineTo(ST,
ST->getChain());
23166SDValue DAGCombiner::splitMergedValStore(StoreSDNode *ST) {
23172 if (!
ST->isSimple())
23205 !
Lo.getOperand(0).getValueType().isScalarInteger() ||
23206 Lo.getOperand(0).getValueSizeInBits() > HalfValBitSize ||
23208 !
Hi.getOperand(0).getValueType().isScalarInteger() ||
23209 Hi.getOperand(0).getValueSizeInBits() > HalfValBitSize)
23214 EVT LowTy = (
Lo.getOperand(0).
getOpcode() == ISD::BITCAST)
23215 ?
Lo.getOperand(0).getValueType()
23216 :
Lo.getValueType();
23217 EVT HighTy = (
Hi.getOperand(0).
getOpcode() == ISD::BITCAST)
23218 ?
Hi.getOperand(0).getValueType()
23219 :
Hi.getValueType();
23225 AAMDNodes AAInfo =
ST->getAAInfo();
23236 ST->getBaseAlign(), MMOFlags, AAInfo);
23241 St0,
DL,
Hi,
Ptr,
ST->getPointerInfo().getWithOffset(HalfValBitSize / 8),
23242 ST->getBaseAlign(), MMOFlags, AAInfo);
23253 unsigned InsIndex) {
23262 int ElementOffset = -1;
23271 while (!ArgWorkList.
empty()) {
23274 std::tie(ArgOffset, ArgVal) = ArgWorkList.
pop_back_val();
23276 if (ArgVal == InsertVal0) {
23277 ElementOffset = ArgOffset;
23283 int CurrentArgOffset =
23287 CurrentArgOffset -= Step;
23293 assert(CurrentArgOffset == ArgOffset);
23299 if (ElementOffset == -1) {
23300 if (!
Y.isUndef() || InsertVal0.
getValueType() !=
Y.getValueType())
23302 ElementOffset = Mask.size();
23306 NewMask.
assign(Mask.begin(), Mask.end());
23308 assert(NewMask[InsIndex] < (
int)(2 * Mask.size()) && NewMask[InsIndex] >= 0 &&
23309 "NewMask[InsIndex] is out of bound");
23318SDValue DAGCombiner::mergeInsertEltWithShuffle(SDNode *
N,
unsigned InsIndex) {
23320 "Expected extract_vector_elt");
23321 SDValue InsertVal =
N->getOperand(1);
23332 SmallVector<int, 16> NewMask(Mask);
23337 return LegalShuffle;
23348SDValue DAGCombiner::combineInsertEltToShuffle(SDNode *
N,
unsigned InsIndex) {
23350 "Expected extract_vector_elt");
23364 if (NumSrcElts == 1)
23367 unsigned NumMaskVals = ExtendRatio * NumSrcElts;
23374 SmallVector<int, 16>
Mask(NumMaskVals);
23375 for (
unsigned i = 0; i != NumMaskVals; ++i) {
23376 if (i / NumSrcElts == InsIndex)
23377 Mask[i] = (i % NumSrcElts) + NumMaskVals;
23392 ConcatOps[0] = SubVec;
23398 AddToWorklist(PaddedSubV.
getNode());
23399 AddToWorklist(DestVecBC.
getNode());
23400 AddToWorklist(Shuf.
getNode());
23407SDValue DAGCombiner::combineInsertEltToLoad(SDNode *
N,
unsigned InsIndex) {
23408 EVT VT =
N->getValueType(0);
23420 return InsIndex == P.index() || P.value() < 0 ||
23421 (InsIndex == 0 && P.value() == (int)P.index() - 1) ||
23422 (InsIndex == VT.getVectorNumElements() - 1 &&
23423 P.value() == (int)P.index() + 1);
23429 unsigned Extend = 0;
23433 Extend =
Scalar.getOpcode();
23451 int EltSize = ScalarLoad->getValueType(0).getScalarSizeInBits();
23452 if (EltSize == 0 || EltSize % 8 != 0 || !ScalarLoad->isSimple() ||
23455 ScalarLoad->getAddressSpace() !=
VecLoad->getAddressSpace())
23460 if (InsIndex == 0) {
23471 unsigned IsFast = 0;
23475 NewAlign,
VecLoad->getMemOperand()->getFlags(),
23486 MachinePointerInfo PtrInfo =
23487 InsIndex == 0 ? ScalarLoad->getPointerInfo()
23488 :
VecLoad->getPointerInfo().getWithOffset(EltSize / 8);
23491 ScalarLoad->getChain(),
Ptr, PtrInfo, NewAlign);
23497SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *
N) {
23534 if (!IsByteSized) {
23541 auto IsTypeDefaultHandled = [
this](EVT VT) {
23549 if (IsTypeDefaultHandled(OldVT) && IsTypeDefaultHandled(VT)) {
23558 unsigned NumDynamic = 1;
23570 if (NumDynamic > 1) {
23586 PtrInfo, SmallestAlign);
23610 DAG.
getLoad(VT,
DL, Store, StackPtr, PtrInfo, SmallestAlign);
23625 unsigned Elt = IndexC->getZExtValue();
23628 if (NumElts == 1) {
23646 if (Elt < OtherElt) {
23650 AddToWorklist(NewOp.
getNode());
23656 if (
SDValue Shuf = mergeInsertEltWithShuffle(
N, Elt))
23659 if (
SDValue Shuf = combineInsertEltToShuffle(
N, Elt))
23662 if (
SDValue Shuf = combineInsertEltToLoad(
N, Elt))
23673 auto AddBuildVectorOp = [&](SmallVectorImpl<SDValue> &
Ops,
SDValue Elt,
23678 EVT EltVT = Elt.getValueType();
23679 MaxEltVT = MaxEltVT.
bitsGE(EltVT) ? MaxEltVT : EltVT;
23686 auto CanonicalizeBuildVector = [&](SmallVectorImpl<SDValue> &
Ops,
23687 bool FreezeUndef =
false) {
23688 assert(
Ops.size() == NumElts &&
"Unexpected vector size");
23704 for (
SDValue CurVec = InVec; CurVec;) {
23706 if (CurVec.isUndef())
23707 return CanonicalizeBuildVector(
Ops);
23711 return CanonicalizeBuildVector(
Ops,
true);
23715 for (
unsigned I = 0;
I != NumElts; ++
I)
23716 AddBuildVectorOp(
Ops, CurVec.getOperand(
I),
I);
23717 return CanonicalizeBuildVector(
Ops);
23722 AddBuildVectorOp(
Ops, CurVec.getOperand(0), 0);
23723 return CanonicalizeBuildVector(
Ops);
23729 if (CurIdx->getAPIntValue().ult(NumElts)) {
23730 unsigned Idx = CurIdx->getZExtValue();
23731 AddBuildVectorOp(
Ops, CurVec.getOperand(1), Idx);
23735 return CanonicalizeBuildVector(
Ops);
23737 CurVec = CurVec->getOperand(0);
23749 bool Merged =
true;
23753 SmallVector<int, 16> NewMask;
23758 Mask = std::move(NewMask);
23767 if (!LegalOperations) {
23780 unsigned MaskOpcode) {
23781 for (
unsigned I = 0;
I != NumElts; ++
I)
23783 return DAG.
getNode(MaskOpcode,
DL, VT, CurVec,
23803 for (
unsigned I = 0;
I != NumElts; ++
I)
23810 for (
unsigned I = 0;
I != NumElts; ++
I)
23814 return CanonicalizeBuildVector(
Ops);
23824 const SDLoc &
DL,
bool LegalTypes) {
23866 if (ResVT != MVT::i1 &&
23891bool DAGCombiner::refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
23913 "Original ISD::EXTRACT_VECTOR_ELT is undefinend?");
23917 EVT ScalarVT =
N->getValueType(0);
23933 Entry(Entry &&) =
default;
23934 Entry(SDNode *Producer_,
unsigned BitPos_,
int NumBits_)
23935 :
Producer(Producer_), BitPos(BitPos_), NumBits(NumBits_) {}
23938 Entry(
const Entry &) =
delete;
23939 Entry &operator=(
const Entry &) =
delete;
23940 Entry &operator=(Entry &&) =
delete;
23946 Worklist.
emplace_back(
N, VecEltBitWidth * IndexC->getZExtValue(),
23949 while (!Worklist.
empty()) {
23956 bool ProducerIsLeaf =
false;
23958 for (SDNode *User :
E.Producer->users()) {
23959 switch (
User->getOpcode()) {
23967 User->getValueSizeInBits(0));
23974 User->getOperand(0).getNode() ==
E.Producer && ShAmtC) {
23977 unsigned ShAmt = ShAmtC->getZExtValue();
23978 Worklist.
emplace_back(User,
E.BitPos + ShAmt,
E.NumBits - ShAmt);
23985 ProducerIsLeaf =
true;
23993 if (ProducerIsLeaf)
23997 unsigned NewVecEltBitWidth = Leafs.
front().NumBits;
24000 if (NewVecEltBitWidth == VecEltBitWidth)
24010 if (!
all_of(Leafs, [NewVecEltBitWidth](
const Entry &
E) {
24011 return (
unsigned)
E.NumBits == NewVecEltBitWidth &&
24012 E.Producer->getValueSizeInBits(0) == NewVecEltBitWidth &&
24013 E.BitPos % NewVecEltBitWidth == 0;
24025 if (LegalOperations &&
24031 for (
const Entry &
E : Leafs) {
24032 SDLoc
DL(
E.Producer);
24033 unsigned NewIndex =
E.BitPos / NewVecEltBitWidth;
24035 "Creating out-of-bounds ISD::EXTRACT_VECTOR_ELT?");
24038 CombineTo(
E.Producer, V);
24044SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *
N) {
24047 EVT ScalarVT =
N->getValueType(0);
24060 AddUsersToWorklist(VecOp.
getNode());
24095 "BUILD_VECTOR used for scalable vectors");
24096 unsigned IndexVal =
24104 if (ScalarVT == InEltVT)
24144 unsigned ExtractIndex = IndexC->getZExtValue();
24146 unsigned BCTruncElt = IsLE ? 0 : NumElts - 1;
24159 EVT XVT =
X.getValueType();
24161 "Extract element and scalar to vector can't change element type "
24162 "from FP to integer.");
24163 unsigned XBitWidth =
X.getValueSizeInBits();
24164 unsigned Scale = XBitWidth / VecEltBitWidth;
24165 BCTruncElt = IsLE ? 0 : Scale - 1;
24170 if (ExtractIndex < Scale && XBitWidth > VecEltBitWidth) {
24171 assert(XBitWidth % VecEltBitWidth == 0 &&
24172 "Scalar bitwidth must be a multiple of vector element bitwidth");
24174 if (ExtractIndex != BCTruncElt) {
24175 unsigned ShiftIndex =
24176 IsLE ? ExtractIndex : (Scale - 1) - ExtractIndex;
24196 int OrigElt = Shuf->getMaskElt(IndexC->getZExtValue());
24204 if (OrigElt < (
int)NumElts) {
24208 OrigElt -= NumElts;
24229 if (!LegalOperations ||
24241 return Use->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
24242 Use->getOperand(0) == VecOp &&
24243 isa<ConstantSDNode>(Use->getOperand(1));
24246 for (SDNode *User : VecOp->
users()) {
24248 if (CstElt->getAPIntValue().ult(NumElts))
24249 DemandedElts.
setBit(CstElt->getZExtValue());
24268 if (refineExtractVectorEltIntoMultipleNarrowExtractVectorElts(
N))
24274 bool BCNumEltsChanged =
false;
24280 if (VecOp.
getOpcode() == ISD::BITCAST) {
24289 BCNumEltsChanged =
true;
24295 if (!LegalOperations && !IndexC && VecOp.
hasOneUse() &&
24299 if (VecLoad &&
VecLoad->isSimple()) {
24301 ScalarVT, SDLoc(
N), VecVT, Index, VecLoad, DAG)) {
24310 if (!LegalOperations || !IndexC)
24316 int Elt = IndexC->getZExtValue();
24317 LoadSDNode *LN0 =
nullptr;
24340 if (BCNumEltsChanged)
24344 int Idx = (Elt > (int)NumElts) ? -1 : Shuf->getMaskElt(Elt);
24349 if (!VecOp.hasOneUse())
24352 VecOp = VecOp.getOperand(0);
24355 LN0 = cast<LoadSDNode>(VecOp);
24356 Elt = (Idx < (int)NumElts) ? Idx : Idx - (int)NumElts;
24357 Index = DAG.getConstant(Elt, DL, Index.getValueType());
24375 Index.getValueType());
24381 return DAG.
getNode(ISD::BITCAST,
DL, ScalarVT, Elt);
24403SDValue DAGCombiner::reduceBuildVecExtToExtBuildVec(SDNode *
N) {
24413 unsigned NumInScalars =
N->getNumOperands();
24415 EVT VT =
N->getValueType(0);
24422 EVT SourceType = MVT::Other;
24423 bool AllAnyExt =
true;
24425 for (
unsigned i = 0; i != NumInScalars; ++i) {
24428 if (
In.isUndef())
continue;
24434 if (!ZeroExt && !AnyExt) {
24435 SourceType = MVT::Other;
24440 EVT InTy =
In.getOperand(0).getValueType();
24443 if (SourceType == MVT::Other)
24446 else if (InTy != SourceType) {
24448 SourceType = MVT::Other;
24453 AllAnyExt &= AnyExt;
24461 SourceType != MVT::Other &&
24477 assert(ElemRatio > 1 &&
"Invalid element size ratio");
24485 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
24489 Cast.
isUndef()) &&
"Invalid cast opcode");
24495 unsigned Index = isLE ? (i * ElemRatio) :
24496 (i * ElemRatio + (ElemRatio - 1));
24498 assert(Index <
Ops.size() &&
"Invalid index");
24505 "Invalid vector size");
24525SDValue DAGCombiner::reduceBuildVecTruncToBitCast(SDNode *
N) {
24528 EVT VT =
N->getValueType(0);
24546 unsigned NumInScalars =
N->getNumOperands();
24549 auto PeekThroughBitcast = [](
SDValue Op) {
24550 if (
Op.getOpcode() == ISD::BITCAST)
24551 return Op.getOperand(0);
24557 for (
unsigned i = 0; i != NumInScalars; ++i) {
24558 SDValue In = PeekThroughBitcast(
N->getOperand(i));
24560 if (
In.isUndef())
continue;
24565 In = PeekThroughBitcast(
In.getOperand(0));
24576 SDValue part = PeekThroughBitcast(
In.getOperand(0));
24580 }
else if (Src != part) {
24585 SDValue ShiftAmtVal =
In.getOperand(1);
24589 uint64_t ShiftAmt =
In.getConstantOperandVal(1);
24592 if (ShiftAmt != i * ScalarTypeBitsize)
24598 if (!Src || Src.getValueType().getSizeInBits() != VT.
getSizeInBits())
24604SDValue DAGCombiner::createBuildVecShuffle(
const SDLoc &
DL, SDNode *
N,
24605 ArrayRef<int> VectorMask,
24607 unsigned LeftIdx,
bool DidSplitVec) {
24608 EVT VT =
N->getValueType(0);
24613 unsigned ShuffleNumElems = NumElems;
24623 assert(InVT2Size <= InVT1Size &&
24624 "Inputs must be sorted to be in non-increasing vector size order.");
24628 if (InVT1 != VT || InVT2 != VT) {
24629 if ((VTSize % InVT1Size == 0) && InVT1 == InVT2) {
24632 unsigned NumConcats = VTSize / InVT1Size;
24633 assert(NumConcats >= 2 &&
"Concat needs at least two inputs!");
24635 ConcatOps[0] = VecIn1;
24636 ConcatOps[1] = VecIn2 ? VecIn2 : DAG.
getUNDEF(InVT1);
24639 }
else if (InVT1Size == VTSize * 2) {
24651 Vec2Offset = NumElems;
24653 assert(InVT2Size <= InVT1Size &&
24654 "Second input is not going to be larger than the first one.");
24660 if (LegalOperations &&
24667 if (InVT1 != InVT2) {
24672 ShuffleNumElems = NumElems * 2;
24674 }
else if (InVT2Size * 2 == VTSize && InVT1Size == VTSize) {
24676 ConcatOps[0] = VecIn2;
24678 }
else if (InVT1Size / VTSize > 1 && InVT1Size % VTSize == 0) {
24686 assert(InVT2Size <= InVT1Size &&
24687 "Second input is not going to be larger than the first one.");
24696 if (InVT1 != InVT2) {
24699 ShuffleNumElems = InVT1Size / VTSize * NumElems;
24710 SmallVector<int, 8>
Mask(ShuffleNumElems, -1);
24715 for (
unsigned i = 0; i != NumElems; ++i) {
24716 if (VectorMask[i] <= 0)
24719 unsigned ExtIndex =
N->getOperand(i).getConstantOperandVal(1);
24720 if (VectorMask[i] == (
int)LeftIdx) {
24721 Mask[i] = ExtIndex;
24722 }
else if (VectorMask[i] == (
int)LeftIdx + 1) {
24723 Mask[i] = Vec2Offset + ExtIndex;
24736 if (ShuffleNumElems > NumElems)
24749 for (
int i = 0; i != NumBVOps; ++i) {
24781 if (DestSize % SrcSize != 0 ||
24787 int ZextRatio = DestSize / SrcSize;
24788 int NumMaskElts = NumBVOps * ZextRatio;
24790 for (
int i = 0; i != NumMaskElts; ++i) {
24791 if (i / ZextRatio == ZextElt) {
24812 ZeroVec, ShufMask, DAG);
24819template <
typename R,
typename T>
24823 return static_cast<decltype(std::distance(
Range.begin(),
I))
>(-1);
24824 return std::distance(
Range.begin(),
I);
24830SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *
N) {
24832 EVT VT =
N->getValueType(0);
24845 bool UsesZeroVector =
false;
24846 unsigned NumElems =
N->getNumOperands();
24854 SmallVector<int, 8> VectorMask(NumElems, -1);
24860 unsigned OneConstExtractIndex = ~0
u;
24863 unsigned NumExtracts = 0;
24865 for (
unsigned i = 0; i != NumElems; ++i) {
24875 UsesZeroVector =
true;
24885 SDValue ExtractedFromVec =
Op.getOperand(0);
24892 if (ExtractIdx->getAsAPIntVal().uge(
24901 OneConstExtractIndex = ExtractIdx->getZExtValue();
24909 Idx = VecIn.
size();
24913 VectorMask[i] = Idx;
24917 if (VecIn.
size() < 2)
24924 bool DidSplitVec =
false;
24925 if (VecIn.
size() == 2) {
24934 if (NumExtracts == 1 &&
24940 unsigned MaxIndex = 0;
24941 unsigned NearestPow2 = 0;
24944 SmallVector<unsigned, 8> IndexVec(NumElems, 0);
24946 for (
unsigned i = 0; i < NumElems; i++) {
24947 if (VectorMask[i] <= 0)
24949 unsigned Index =
N->getOperand(i).getConstantOperandVal(1);
24950 IndexVec[i] =
Index;
24951 MaxIndex = std::max(MaxIndex, Index);
24955 if (InVT.
isSimple() && NearestPow2 > 2 && MaxIndex < NearestPow2 &&
24956 NumElems * 2 < NearestPow2) {
24957 unsigned SplitSize = NearestPow2 / 2;
24970 DidSplitVec =
true;
24972 for (
unsigned i = 0; i < NumElems; i++) {
24973 if (VectorMask[i] <= 0)
24975 VectorMask[i] = (IndexVec[i] < SplitSize) ? 1 : 2;
24988 b.getValueType().getVectorNumElements();
24993 for (
int &SourceVectorIndex : VectorMask) {
24994 if (SourceVectorIndex <= 0)
24996 unsigned Idx =
getFirstIndexOf(SortedVecIn, VecIn[SourceVectorIndex]);
24997 assert(Idx > 0 && Idx < SortedVecIn.size() &&
24998 VecIn[SourceVectorIndex] == SortedVecIn[Idx] &&
"Remapping failure");
24999 SourceVectorIndex = Idx;
25002 VecIn = std::move(SortedVecIn);
25020 for (
unsigned In = 0, Len = (VecIn.
size() / 2); In < Len; ++In) {
25021 unsigned LeftIdx = 2 *
In + 1;
25022 SDValue VecLeft = VecIn[LeftIdx];
25024 (LeftIdx + 1) < VecIn.
size() ? VecIn[LeftIdx + 1] :
SDValue();
25026 if (
SDValue Shuffle = createBuildVecShuffle(
DL,
N, VectorMask, VecLeft,
25027 VecRight, LeftIdx, DidSplitVec))
25035 if (UsesZeroVector)
25040 if (Shuffles.
size() == 1)
25041 return Shuffles[0];
25044 for (
int &Vec : VectorMask)
25046 Vec = Shuffles.
size() - 1;
25048 Vec = (Vec - 1) / 2;
25062 if (Shuffles.
size() % 2)
25065 for (
unsigned CurSize = Shuffles.
size(); CurSize > 1; CurSize /= 2) {
25067 Shuffles[CurSize] = DAG.
getUNDEF(VT);
25070 for (
unsigned In = 0, Len = CurSize / 2;
In <
Len; ++
In) {
25073 SmallVector<int, 8>
Mask(NumElems, -1);
25075 ArrayRef<int> LMask;
25077 L.use_empty() &&
L.getOperand(1).isUndef() &&
25078 L.getOperand(0).getValueType() ==
L.getValueType();
25079 if (IsLeftShuffle) {
25081 L =
L.getOperand(0);
25084 ArrayRef<int> RMask;
25086 R.use_empty() &&
R.getOperand(1).isUndef() &&
25087 R.getOperand(0).getValueType() ==
R.getValueType();
25088 if (IsRightShuffle) {
25090 R =
R.getOperand(0);
25092 for (
unsigned I = 0;
I != NumElems; ++
I) {
25093 if (VectorMask[
I] ==
Left) {
25097 VectorMask[
I] =
In;
25098 }
else if (VectorMask[
I] ==
Right) {
25100 if (IsRightShuffle)
25101 Mask[
I] = RMask[
I] + NumElems;
25102 VectorMask[
I] =
In;
25109 return Shuffles[0];
25116SDValue DAGCombiner::convertBuildVecZextToZext(SDNode *
N) {
25117 if (LegalOperations)
25120 EVT VT =
N->getValueType(0);
25122 bool FoundZeroExtend =
false;
25124 auto checkElem = [&](
SDValue Op) -> int64_t {
25125 unsigned Opc =
Op.getOpcode();
25131 return C->getZExtValue();
25139 int64_t
Offset = checkElem(Op0);
25143 unsigned NumElems =
N->getNumOperands();
25145 EVT InSVT =
In.getValueType().getScalarType();
25153 for (
unsigned i = 1; i != NumElems; ++i) {
25154 if ((
Offset + i) != checkElem(
N->getOperand(i)))
25172SDValue DAGCombiner::convertBuildVecZextToBuildVecWithZeros(SDNode *
N) {
25181 EVT VT =
N->getValueType(0);
25182 EVT OpVT =
N->getOperand(0).getValueType();
25196 unsigned ActiveBits = 0;
25202 unsigned OpActiveBits =
25203 Cst->getAPIntValue().trunc(EltBitwidth).getActiveBits();
25204 if (OpActiveBits == 0) {
25205 KnownZeroOps.setBit(
I.index());
25213 if (
I.index() != 0)
25219 unsigned CurrActiveBits =
25220 Op.getOperand(0).getValueSizeInBits().getFixedValue();
25221 assert(!ActiveBits &&
"Already encountered non-constant-zero operand?");
25222 ActiveBits = CurrActiveBits;
25224 if (2 * ActiveBits > EltBitwidth)
25229 if (ActiveBits == 0)
25234 EVT NewScalarIntVT, NewIntVT;
25235 std::optional<unsigned> Factor;
25240 assert(2 * ActiveBits <= EltBitwidth &&
25241 "We know that half or less bits of the element are active.");
25242 for (
unsigned Scale = EltBitwidth / ActiveBits; Scale >= 2; --Scale) {
25243 if (EltBitwidth % Scale != 0)
25245 unsigned ChunkBitwidth = EltBitwidth / Scale;
25246 assert(ChunkBitwidth >= ActiveBits &&
"As per starting point.");
25249 Scale *
N->getNumOperands());
25251 (LegalOperations &&
25269 assert(!
Op.isUndef() &&
"FIXME: after allowing UNDEF's, handle them here.");
25270 unsigned SrcOpIdx =
I.index();
25271 if (KnownZeroOps[SrcOpIdx]) {
25272 NewOps.
append(*Factor, ZeroOp);
25278 NewOps.
append(*Factor - 1, ZeroOp);
25286SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *
N) {
25287 EVT VT =
N->getValueType(0);
25301 if (!LegalOperations) {
25307 EVT SrcVT =
Splat.getValueType();
25323 if (!LegalTypes && (
N->getNumOperands() > 1)) {
25325 auto checkElem = [&](
SDValue Op) -> uint64_t {
25333 int Offset = checkElem(Op0);
25334 for (
unsigned i = 0; i <
N->getNumOperands(); ++i) {
25335 if (
Offset + i != checkElem(
N->getOperand(i))) {
25345 ((
Offset %
N->getValueType(0).getVectorNumElements()) ==
25351 if (
SDValue V = convertBuildVecZextToZext(
N))
25354 if (
SDValue V = convertBuildVecZextToBuildVecWithZeros(
N))
25357 if (
SDValue V = reduceBuildVecExtToExtBuildVec(
N))
25360 if (
SDValue V = reduceBuildVecTruncToBitCast(
N))
25363 if (
SDValue V = reduceBuildVecToShuffle(
N))
25370 assert(!
V.isUndef() &&
"Splat of undef should have been handled earlier");
25379 EVT OpVT =
N->getOperand(0).getValueType();
25386 EVT VT =
N->getValueType(0);
25394 if (ISD::BITCAST ==
Op.getOpcode() &&
25395 !
Op.getOperand(0).getValueType().isVector())
25396 Ops.push_back(
Op.getOperand(0));
25397 else if (
Op.isUndef())
25404 EVT LastOpVT =
Ops.back().getValueType();
25406 AnyFPVT = LastOpVT;
25414 if (AnyFPVT !=
EVT()) {
25417 if (
Op.getValueType() == SVT)
25436 EVT VT =
N->getValueType(0);
25446 if (!FirstConcat) {
25447 SubVT =
Op.getOperand(0).getValueType();
25453 if (SubVT !=
Op.getOperand(0).getValueType())
25456 assert(FirstConcat &&
"Concat of all-undefs found");
25460 if (
Op.isUndef()) {
25464 ConcatOps.
append(
Op->op_begin(),
Op->op_end());
25474 EVT VT =
N->getValueType(0);
25475 EVT OpVT =
N->getOperand(0).getValueType();
25491 if (
Op.isUndef()) {
25492 Mask.append((
unsigned)NumOpElts, -1);
25501 int ExtIdx =
Op.getConstantOperandVal(1);
25510 Mask.append((
unsigned)NumOpElts, -1);
25521 if (0 == (NumExtElts % NumElts))
25522 ExtIdx /= (NumExtElts / NumElts);
25523 else if (0 == (NumElts % NumExtElts))
25524 ExtIdx *= (NumElts / NumExtElts);
25529 if (SV0.
isUndef() || SV0 == ExtVec) {
25531 for (
int i = 0; i != NumOpElts; ++i)
25532 Mask.push_back(i + ExtIdx);
25533 }
else if (SV1.
isUndef() || SV1 == ExtVec) {
25535 for (
int i = 0; i != NumOpElts; ++i)
25536 Mask.push_back(i + ExtIdx + NumElts);
25548 unsigned CastOpcode =
N->getOperand(0).getOpcode();
25549 switch (CastOpcode) {
25565 EVT SrcVT =
N->getOperand(0).getOperand(0).getValueType();
25573 if (
Op.getOpcode() != CastOpcode || !
Op.hasOneUse() ||
25574 Op.getOperand(0).getValueType() != SrcVT)
25582 EVT VT =
N->getValueType(0);
25587 switch (CastOpcode) {
25607 return DAG.
getNode(CastOpcode,
DL, VT, NewConcat);
25615 bool LegalOperations) {
25616 EVT VT =
N->getValueType(0);
25617 EVT OpVT =
N->getOperand(0).getValueType();
25622 if (
N->getNumOperands() != 2)
25627 (LegalOperations &&
25639 CurSVN && CurSVN->getOperand(1).
isUndef() &&
N->isOnlyUserOf(CurSVN) &&
25642 return !Op.isUndef() &&
25643 (Op.getNode() == CurSVN || is_contained(CurSVN->ops(), Op));
25664 std::iota(FirstShufOpIdentityMask.
begin(), FirstShufOpIdentityMask.
end(), 0);
25665 std::iota(SecondShufOpIdentityMask.
begin(), SecondShufOpIdentityMask.
end(),
25672 assert(!
Op.isUndef() &&
"Not expecting to concatenate UNDEF.");
25673 if (
Op.getNode() == SVN) {
25694 std::array<SDValue, 2> ShufOps;
25695 for (
auto I :
zip(SVN->
ops(), ShufOps)) {
25697 SDValue &NewShufOp = std::get<1>(
I);
25703 ShufOpParts[0] = ShufOp;
25714 bool LegalOperations) {
25715 EVT VT =
N->getValueType(0);
25733SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *
N) {
25735 if (
N->getNumOperands() == 1)
25739 EVT VT =
N->getValueType(0);
25745 [](
const SDValue &
Op) { return Op.isUndef(); })) {
25747 assert(
In.getValueType().isVector() &&
"Must concat vectors");
25757 !(LegalDAG &&
In.getValueType().isScalableVector())) {
25758 unsigned NumOps =
N->getNumOperands() *
In.getNumOperands();
25770 EVT SVT =
Scalar.getValueType().getVectorElementType();
25771 if (SVT ==
Scalar.getOperand(0).getValueType())
25776 if (!
Scalar.getValueType().isVector() &&
In.hasOneUse()) {
25785 EVT SclTy =
Scalar.getValueType();
25795 if (VNTNumElms < 2)
25811 auto IsBuildVectorOrUndef = [](
const SDValue &
Op) {
25822 bool FoundMinVT =
false;
25825 EVT OpSVT =
Op.getOperand(0).getValueType();
25826 MinVT = (!FoundMinVT || OpSVT.
bitsLE(MinVT)) ? OpSVT : MinVT;
25829 assert(FoundMinVT &&
"Concat vector type mismatch");
25833 EVT OpVT =
Op.getValueType();
25842 Opnds.
append(
Op->op_begin(),
Op->op_begin() + NumElts);
25844 for (
unsigned i = 0; i != NumElts; ++i)
25852 "Concat vector type mismatch");
25879 N, DAG, TLI, LegalTypes, LegalOperations))
25889 unsigned PartNumElem =
25890 N->getOperand(0).getValueType().getVectorMinNumElements();
25892 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
25903 if (SingleSource.
getNode()) {
25904 if (
Op.getOperand(0) != SingleSource)
25907 SingleSource =
Op.getOperand(0);
25917 unsigned IdentityIndex = i * PartNumElem;
25918 if (
Op.getConstantOperandAPInt(1) != IdentityIndex)
25923 return SingleSource;
25928SDValue DAGCombiner::visitVECTOR_INTERLEAVE(SDNode *
N) {
25939 Ops.append(
N->op_values().begin(),
N->op_values().end());
25940 return CombineTo(
N, &
Ops);
25947 V.getOperand(1).getValueType() == SubVT &&
25948 V.getConstantOperandAPInt(2) == Index) {
25949 return V.getOperand(1);
25952 V.getOperand(0).getValueType() == SubVT &&
25955 return V.getOperand(SubIdx);
25961 unsigned Index,
const SDLoc &
DL,
25963 bool LegalOperations) {
25965 unsigned BinOpcode = BinOp.
getOpcode();
25971 if (VecVT != Bop0.
getValueType() || VecVT != Bop1.getValueType())
25982 if (!Sub0 || !Sub1)
25995 bool LegalOperations) {
26016 if (
C &&
C->getValueAPF().isNegZero())
26029 "Extract index is not a multiple of the vector length.");
26034 if (WideWidth % NarrowWidth != 0)
26039 unsigned NarrowingRatio = WideWidth / NarrowWidth;
26041 if (WideNumElts % NarrowingRatio != 0)
26046 WideNumElts / NarrowingRatio);
26058 BinOp.
hasOneUse() && Src->hasOneUse()) {
26072 if (NarrowingRatio != 2)
26087 return V.getOperand(ConcatOpNum);
26093 if (SubVecL || SubVecR) {
26144 assert(Index % NumElts == 0 &&
"The extract subvector index is not a "
26145 "multiple of the result's element count");
26149 std::optional<unsigned> ByteOffset;
26151 ByteOffset =
Offset.getFixedValue();
26163 if (
Offset.isScalable()) {
26187 bool LegalOperations) {
26189 EVT WideVT = Src.getValueType();
26195 if (!WideShuffleVector)
26199 if (!WideShuffleVector->hasOneUse())
26204 if (LegalOperations &&
26209 assert((Index % NumEltsExtracted) == 0 &&
26210 "Extract index is not a multiple of the output vector length.");
26215 NewMask.
reserve(NumEltsExtracted);
26217 DemandedSubvectors;
26220 for (
int M : WideShuffleVector->getMask().slice(Index, NumEltsExtracted)) {
26221 assert((M >= -1) && (M < (2 * WideNumElts)) &&
26222 "Out-of-bounds shuffle mask?");
26231 int WideShufOpIdx = M / WideNumElts;
26233 int OpEltIdx = M % WideNumElts;
26235 assert((OpEltIdx + WideShufOpIdx * WideNumElts) == M &&
26236 "Shuffle mask vector decomposition failure.");
26239 int OpSubvecIdx = OpEltIdx / NumEltsExtracted;
26241 int OpEltIdxInSubvec = OpEltIdx % NumEltsExtracted;
26243 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted) == OpEltIdx &&
26244 "Shuffle mask subvector decomposition failure.");
26246 assert((OpEltIdxInSubvec + OpSubvecIdx * NumEltsExtracted +
26247 WideShufOpIdx * WideNumElts) == M &&
26248 "Shuffle mask full decomposition failure.");
26250 SDValue Op = WideShuffleVector->getOperand(WideShufOpIdx);
26252 if (
Op.isUndef()) {
26258 const std::pair<SDValue, int> DemandedSubvector =
26259 std::make_pair(
Op, OpSubvecIdx);
26261 if (DemandedSubvectors.insert(DemandedSubvector)) {
26262 if (DemandedSubvectors.size() > 2)
26265 int Index = NumEltsExtracted * OpSubvecIdx;
26273 getFirstIndexOf(DemandedSubvectors.getArrayRef(), DemandedSubvector);
26274 assert((NewOpIdx == 0 || NewOpIdx == 1) &&
"Unexpected operand index.");
26276 int AdjM = OpEltIdxInSubvec + NewOpIdx * NumEltsExtracted;
26279 assert(NewMask.
size() == (
unsigned)NumEltsExtracted &&
"Produced bad mask.");
26280 assert(DemandedSubvectors.size() <= 2 &&
26281 "Should have ended up demanding at most two subvectors.");
26284 if (DemandedSubvectors.empty())
26290 any_of(NewMask, [](
int M) {
return M < 0; }))
26291 for (
auto &DemandedSubvector : DemandedSubvectors)
26292 if (DemandedSubvector.second != 0)
26304 for (
const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
26305 &DemandedSubvector : DemandedSubvectors) {
26307 int Index = NumEltsExtracted * DemandedSubvector.second;
26310 DemandedSubvector.first, IndexC));
26313 "Should end up with either one or two ops");
26316 if (NewOps.
size() == 1)
26322SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *
N) {
26323 EVT NVT =
N->getValueType(0);
26325 uint64_t ExtIdx =
N->getConstantOperandVal(1);
26342 V.getConstantOperandVal(1)) &&
26362 unsigned InsIdx =
V.getConstantOperandVal(2);
26364 if (InsIdx <= ExtIdx && (ExtIdx + NumSubElts) <= (InsIdx + NumInsElts) &&
26367 V.getValueType().isFixedLengthVector())
26374 if (
V.getOpcode() == ISD::BITCAST &&
26375 V.getOperand(0).getValueType().isVector() &&
26380 unsigned DestNumElts =
V.getValueType().getVectorMinNumElements();
26381 if ((SrcNumElts % DestNumElts) == 0) {
26382 unsigned SrcDestRatio = SrcNumElts / DestNumElts;
26389 V.getOperand(0), NewIndex);
26393 if ((DestNumElts % SrcNumElts) == 0) {
26394 unsigned DestSrcRatio = DestNumElts / SrcNumElts;
26396 ElementCount NewExtEC =
26399 if ((ExtIdx % DestSrcRatio) == 0) {
26400 unsigned IndexValScaled = ExtIdx / DestSrcRatio;
26407 V.getOperand(0), NewIndex);
26415 V.getOperand(0), NewIndex);
26425 EVT ConcatSrcVT =
V.getOperand(0).getValueType();
26427 "Concat and extract subvector do not change element type");
26430 unsigned ConcatOpIdx = ExtIdx / ConcatSrcNumElts;
26436 return V.getOperand(ConcatOpIdx);
26444 ConcatSrcNumElts % ExtNumElts == 0) {
26445 unsigned NewExtIdx = ExtIdx - ConcatOpIdx * ConcatSrcNumElts;
26446 assert(NewExtIdx + ExtNumElts <= ConcatSrcNumElts &&
26447 "Trying to extract from >1 concat operand?");
26448 assert(NewExtIdx % ExtNumElts == 0 &&
26449 "Extract index is not a multiple of the input vector length.");
26452 V.getOperand(ConcatOpIdx), NewIndexC);
26457 NVT, V, ExtIdx,
DL, DAG, LegalOperations))
26468 EVT InVT =
V.getValueType();
26472 if (ExtractSize % EltSize == 0) {
26473 unsigned NumElems = ExtractSize / EltSize;
26476 NumElems == 1 ? EltVT
26484 if (NumElems == 1) {
26485 SDValue Src =
V->getOperand(IdxVal);
26486 if (EltVT != Src.getValueType())
26502 EVT SmallVT =
V.getOperand(1).getValueType();
26503 if (NVT.
bitsEq(SmallVT)) {
26509 uint64_t InsIdx =
V.getConstantOperandVal(2);
26517 DAG.
getBitcast(
N->getOperand(0).getValueType(),
V.getOperand(0)),
26525 if (!
V.getValueType().isScalableVector() &&
26527 return Use->getOpcode() == ISD::EXTRACT_SUBVECTOR &&
26528 Use->getOperand(0) == V;
26530 unsigned NumElts =
V.getValueType().getVectorNumElements();
26532 for (SDNode *User :
V->users()) {
26533 unsigned ExtIdx =
User->getConstantOperandVal(1);
26534 unsigned NumSubElts =
User->getValueType(0).getVectorNumElements();
26535 DemandedElts.
setBits(ExtIdx, ExtIdx + NumSubElts);
26569 unsigned HalfNumElts = NumElts / 2;
26572 for (
unsigned i = 0; i != NumElts; ++i) {
26576 if ((Mask[i] % NumElts) >= HalfNumElts)
26578 int M = Mask[i] < (int)NumElts ? Mask[i] : Mask[i] - (int)HalfNumElts;
26579 if (i < HalfNumElts)
26582 Mask1[i - HalfNumElts] = M;
26605 EVT VT =
N->getValueType(0);
26616 unsigned NumConcats = NumElts / NumElemsPerConcat;
26618 auto IsUndefMaskElt = [](
int i) {
return i == -1; };
26623 if (NumElemsPerConcat * 2 == NumElts && N1.
isUndef() &&
26624 llvm::all_of(Mask.slice(NumElemsPerConcat, NumElemsPerConcat),
26628 Mask.slice(0, NumElemsPerConcat));
26635 for (
unsigned I = 0;
I != NumConcats; ++
I) {
26636 unsigned Begin =
I * NumElemsPerConcat;
26637 ArrayRef<int> SubMask = Mask.slice(Begin, NumElemsPerConcat);
26646 for (
int i = 0; i != (int)NumElemsPerConcat; ++i) {
26647 if (IsUndefMaskElt(SubMask[i]))
26649 if ((SubMask[i] % (
int)NumElemsPerConcat) != i)
26651 int EltOpIdx = SubMask[i] / NumElemsPerConcat;
26656 assert(0 <=
OpIdx &&
"Unknown concat_vectors op");
26710 bool IsSplat =
false;
26714 if (
SDValue Splat0 = BV0->getSplatValue())
26715 IsSplat = (Splat0 == BV1->getSplatValue());
26719 for (
int M : SVN->
getMask()) {
26722 int Idx = M < (int)NumElts ? M : M - NumElts;
26723 SDValue &S = (M < (int)NumElts ? N0 : N1);
26740 if (!IsSplat && !DuplicateOps.
insert(
Op).second)
26751 SVT = (SVT.
bitsLT(
Op.getValueType()) ?
Op.getValueType() : SVT);
26767 unsigned Opcode,
EVT VT, std::function<
bool(
unsigned)> Match,
26769 bool LegalOperations) {
26774 return std::nullopt;
26782 for (
unsigned Scale = 2; Scale < NumElts; Scale *= 2) {
26784 if (NumElts % Scale != 0)
26798 return std::nullopt;
26807 bool LegalOperations) {
26817 Mask = SVN->
getMask()](
unsigned Scale) {
26818 for (
unsigned i = 0; i != NumElts; ++i) {
26821 if ((i % Scale) == 0 && Mask[i] == (
int)(i / Scale))
26833 Opcode, VT, isAnyExtend, DAG, TLI,
true, LegalOperations);
26845 bool LegalOperations) {
26846 bool LegalTypes =
true;
26858 auto ForEachDecomposedIndice = [NumElts, &Mask](
auto Fn) {
26859 for (
int &Indice : Mask) {
26863 int OpEltIdx = (
unsigned)Indice < NumElts ? Indice : Indice - NumElts;
26864 Fn(Indice,
OpIdx, OpEltIdx);
26869 std::array<APInt, 2> OpsDemandedElts;
26870 for (
APInt &OpDemandedElts : OpsDemandedElts)
26872 ForEachDecomposedIndice(
26873 [&OpsDemandedElts](
int &Indice,
int OpIdx,
int OpEltIdx) {
26874 OpsDemandedElts[
OpIdx].setBit(OpEltIdx);
26878 std::array<APInt, 2> OpsKnownZeroElts;
26879 for (
auto I :
zip(SVN->
ops(), OpsDemandedElts, OpsKnownZeroElts))
26887 bool HadZeroableElts =
false;
26888 ForEachDecomposedIndice([&OpsKnownZeroElts, &HadZeroableElts](
26889 int &Indice,
int OpIdx,
int OpEltIdx) {
26890 if (OpsKnownZeroElts[
OpIdx][OpEltIdx]) {
26892 HadZeroableElts =
true;
26900 if (!HadZeroableElts)
26908 Mask.size() % ScaledMask.
size() == 0 &&
"Unexpected mask widening.");
26909 int Prescale = Mask.size() / ScaledMask.
size();
26911 NumElts = ScaledMask.
size();
26912 EltSizeInBits *= Prescale;
26924 auto isZeroExtend = [NumElts, &ScaledMask](
unsigned Scale) {
26925 assert(Scale >= 2 && Scale <= NumElts && NumElts % Scale == 0 &&
26926 "Unexpected mask scaling factor.");
26928 for (
unsigned SrcElt = 0, NumSrcElts = NumElts / Scale;
26929 SrcElt != NumSrcElts; ++SrcElt) {
26932 assert(MaskChunk.
size() == Scale &&
"Unexpected mask size.");
26933 Mask = Mask.drop_front(MaskChunk.
size());
26936 if (
int FirstIndice = MaskChunk[0]; (
unsigned)FirstIndice != SrcElt)
26941 [](
int Indice) { return Indice == -2; }))
26944 assert(Mask.empty() &&
"Did not process the whole mask?");
26949 for (
bool Commuted : {
false,
true}) {
26954 Opcode, PrescaledVT, isZeroExtend, DAG, TLI, LegalTypes,
26990 if (ExtDstSizeInBits % ExtSrcSizeInBits != 0)
26992 unsigned ExtScale = ExtDstSizeInBits / ExtSrcSizeInBits;
26997 auto isTruncate = [&Mask, &NumElts](
unsigned Scale) {
26998 for (
unsigned i = 0; i != NumElts; ++i) {
27001 if ((i * Scale) < NumElts && Mask[i] == (
int)(i * Scale))
27011 if (EltSizeInBits != ExtSrcSizeInBits)
27018 if (isTruncate(ExtScale))
27041 APInt DemandedElts(NumElts, 0);
27042 for (
int Idx : Shuf->
getMask()) {
27045 assert((
unsigned)Idx < NumElts &&
"Out-of-bounds shuffle indice?");
27046 DemandedElts.
setBit(Idx);
27048 assert(DemandedElts.
popcount() > 1 &&
"Is a splat shuffle already?");
27053 std::optional<unsigned> MinNonUndefIdx;
27054 for (
int Idx : Shuf->
getMask()) {
27055 if (Idx < 0 || UndefElts[Idx])
27057 MinNonUndefIdx = std::min<unsigned>(Idx, MinNonUndefIdx.value_or(~0U));
27059 if (!MinNonUndefIdx)
27061 assert(*MinNonUndefIdx < NumElts &&
"Expected valid element index.");
27063 for (
int &Idx : SplatMask) {
27068 Idx = UndefElts[Idx] ? -1 : *MinNonUndefIdx;
27070 assert(SplatMask != Shuf->
getMask() &&
"Expected mask to change!");
27088 assert(ShufMask.
size() == SplatMask.
size() &&
"Mask length mismatch");
27106 auto CanSimplifyToExistingSplat = [](
ArrayRef<int> UserMask,
27108 for (
unsigned i = 0, e = UserMask.
size(); i != e; ++i)
27109 if (UserMask[i] != -1 && SplatMask[i] == -1 &&
27110 SplatMask[UserMask[i]] != -1)
27114 if (CanSimplifyToExistingSplat(ShufMask, SplatMask))
27120 for (
int Idx : ShufMask)
27121 NewMask.
push_back(Idx == -1 ? -1 : SplatMask[Idx]);
27133 bool LegalOperations) {
27150 if (VTLanes <= InLanes || VTLanes % InLanes != 0 ||
27151 (LegalOperations &&
27154 int Factor = VTLanes / InLanes;
27182 if (!InnerShuf || !InnerShuf->getOperand(1).isUndef())
27187 unsigned NumElts = OuterMask.
size();
27188 assert(NumElts == InnerMask.
size() &&
"Mask length mismatch");
27190 int SplatIndex = -1;
27191 for (
unsigned i = 0; i != NumElts; ++i) {
27193 int OuterMaskElt = OuterMask[i];
27194 if (OuterMaskElt == -1)
27198 int InnerMaskElt = InnerMask[OuterMaskElt];
27199 if (InnerMaskElt == -1)
27203 if (SplatIndex == -1)
27204 SplatIndex = InnerMaskElt;
27207 if (SplatIndex != InnerMaskElt)
27210 CombinedMask[i] = InnerMaskElt;
27212 assert((
all_of(CombinedMask, [](
int M) {
return M == -1; }) ||
27214 "Expected a splat mask");
27218 assert(VT == InnerShuf->getValueType(0) &&
"Expected matching shuffle types");
27223 InnerShuf->getOperand(1), CombinedMask);
27231 int MaskSize = Mask.size();
27232 int EltFromOp0 = -1;
27237 for (
int i = 0; i != MaskSize; ++i) {
27238 if (Mask[i] >= 0 && Mask[i] < MaskSize) {
27240 if (EltFromOp0 != -1)
27243 }
else if (Mask[i] != i + MaskSize) {
27254SDValue DAGCombiner::replaceShuffleOfInsert(ShuffleVectorSDNode *Shuf) {
27258 SmallVector<int, 16> CommutedMask(Mask);
27262 if (ShufOp0Index == -1) {
27266 if (ShufOp0Index == -1)
27270 Mask = CommutedMask;
27278 assert(Mask[ShufOp0Index] >= 0 && Mask[ShufOp0Index] < (
int)
Mask.size() &&
27279 "Shuffle mask value must be from operand 0");
27297 Op1, Elt, NewInsIndex);
27304 Mask[ShufOp0Index] == 0) {
27307 Op1, Elt, NewInsIndex);
27325 for (
int i = 0, e = (
int)Mask.size(); i != e; ++i) {
27329 assert(Mask[i] >= 0 && Mask[i] < e &&
"Unexpected shuffle mask value");
27333 if (Mask0[Mask[i]] != Mask0[i])
27341SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *
N) {
27342 EVT VT =
N->getValueType(0);
27368 SmallVector<int, 8> NewMask;
27369 for (
unsigned i = 0; i != NumElts; ++i) {
27371 if (Idx >= (
int)NumElts) {
27381 if (
SDValue InsElt = replaceShuffleOfInsert(SVN))
27421 if (Idx->getAPIntValue() == SplatIndex)
27446 if (
V->getOpcode() == ISD::BITCAST) {
27447 SDValue ConvInput =
V->getOperand(0);
27454 assert(
V->getNumOperands() == NumElts &&
27455 "BUILD_VECTOR has wrong number of operands");
27457 bool AllSame =
true;
27458 for (
unsigned i = 0; i != NumElts; ++i) {
27459 if (!
V->getOperand(i).isUndef()) {
27460 Base =
V->getOperand(i);
27465 if (!
Base.getNode())
27467 for (
unsigned i = 0; i != NumElts; ++i) {
27468 if (
V->getOperand(i) !=
Base) {
27479 SDValue Splatted =
V->getOperand(SplatIndex);
27483 for (
unsigned i = 0; i != NumElts; ++i) {
27492 if (
V->getValueType(0) != VT)
27531 int HalfNumElts = (int)NumElts / 2;
27532 SmallVector<int, 8> NewMask;
27533 for (
unsigned i = 0; i != NumElts; ++i) {
27535 if (Idx >= HalfNumElts) {
27536 assert(Idx < (
int)NumElts &&
"Shuffle mask chooses undef op");
27537 Idx -= HalfNumElts;
27558 EVT SubVT =
RHS.getOperand(0).getValueType();
27559 int NumSubVecs =
RHS.getNumOperands();
27561 assert((NumElts % NumSubElts) == 0 &&
"Subvector mismatch");
27566 if (
all_of(Mask, [NumElts](
int M) {
return M < (int)NumElts; }))
27571 SmallVector<int> InsertionMask(NumElts);
27572 for (
int SubVec = 0; SubVec != NumSubVecs; ++SubVec) {
27573 for (
int SubIdx = 0; SubIdx != (int)NumElts; SubIdx += NumSubElts) {
27575 std::iota(InsertionMask.begin(), InsertionMask.end(), 0);
27578 std::iota(InsertionMask.begin() + SubIdx,
27579 InsertionMask.begin() + SubIdx + NumSubElts,
27580 NumElts + (SubVec * NumSubElts));
27583 bool MatchingShuffle =
true;
27584 for (
int i = 0; i != (int)NumElts; ++i) {
27585 int ExpectIdx = InsertionMask[i];
27586 int ActualIdx =
Mask[i];
27587 if (0 <= ActualIdx && ExpectIdx != ActualIdx) {
27588 MatchingShuffle =
false;
27593 if (MatchingShuffle)
27602 if (
SDValue InsertN1 = ShuffleToInsert(N0, N1, Mask))
27605 SmallVector<int> CommuteMask(Mask);
27607 if (
SDValue InsertN0 = ShuffleToInsert(N1, N0, CommuteMask))
27615 bool IsInLaneMask =
true;
27617 SmallVector<int, 16> ClearMask(NumElts, -1);
27620 for (
int I = 0;
I != (int)NumElts; ++
I) {
27624 ClearMask[
I] =
M ==
I ?
I : (
I + NumElts);
27625 IsInLaneMask &= (
M ==
I) || (M == (
int)(
I + NumElts));
27627 APInt &Demanded =
M < (int)NumElts ? DemandedLHS : DemandedRHS;
27628 Demanded.
setBit(M % NumElts);
27632 if (!IsInLaneMask && (!DemandedLHS.
isZero() || !DemandedRHS.
isZero()) &&
27647 for (
int I = 0;
I != (int)NumElts; ++
I)
27649 AndMask[
I] =
Mask[
I] ==
I ? AllOnesElt : ZeroElt;
27686 EVT ScaleVT = SVT.
bitsLT(InnerSVT) ? VT : InnerVT;
27697 SmallVector<int, 8> InnerMask;
27698 SmallVector<int, 8> OuterMask;
27703 SmallVector<int, 8> NewMask;
27704 for (
int M : OuterMask)
27705 NewMask.
push_back(M < 0 ? -1 : InnerMask[M]);
27736 auto MergeInnerShuffle =
27737 [NumElts, &VT](
bool Commute, ShuffleVectorSDNode *SVN,
27738 ShuffleVectorSDNode *OtherSVN,
SDValue N1,
27740 SmallVectorImpl<int> &
Mask) ->
bool {
27743 if (OtherSVN->isSplat())
27749 for (
unsigned i = 0; i != NumElts; ++i) {
27750 int Idx = SVN->getMaskElt(i);
27753 Mask.push_back(Idx);
27758 Idx = (Idx < (int)NumElts) ? (Idx + NumElts) : (Idx - NumElts);
27761 if (Idx < (
int)NumElts) {
27764 Idx = OtherSVN->getMaskElt(Idx);
27767 Mask.push_back(Idx);
27770 CurrentVec = (Idx < (int)NumElts) ? OtherSVN->
getOperand(0)
27779 Mask.push_back(-1);
27785 Idx = Idx % NumElts;
27786 if (!SV0.getNode() || SV0 == CurrentVec) {
27790 Mask.push_back(Idx);
27793 if (!SV1.getNode() || SV1 == CurrentVec) {
27797 Mask.push_back(Idx + NumElts);
27804 int InnerIdx = CurrentSVN->getMaskElt(Idx);
27805 if (InnerIdx < 0) {
27806 Mask.push_back(-1);
27809 SDValue InnerVec = (InnerIdx < (int)NumElts)
27810 ? CurrentSVN->getOperand(0)
27811 : CurrentSVN->getOperand(1);
27813 Mask.push_back(-1);
27816 InnerIdx %= NumElts;
27817 if (InnerVec == SV0) {
27818 Mask.push_back(InnerIdx);
27821 if (InnerVec == SV1) {
27822 Mask.push_back(InnerIdx + NumElts);
27841 if (TLI.isShuffleMaskLegal(Mask, VT))
27846 return TLI.isShuffleMaskLegal(Mask, VT);
27858 assert(N1->getOperand(0).getValueType() == VT &&
27859 "Shuffle types don't match");
27861 SDValue SV0 = N1->getOperand(0);
27862 SDValue SV1 = N1->getOperand(1);
27863 bool HasSameOp0 = N0 == SV0;
27864 bool IsSV1Undef = SV1.
isUndef();
27865 if (HasSameOp0 || IsSV1Undef || N0 == SV1)
27886 for (
int i = 0; i != 2; ++i) {
27888 N->isOnlyUserOf(
N->getOperand(i).getNode())) {
27892 assert(OtherSV->getOperand(0).getValueType() == VT &&
27893 "Shuffle types don't match");
27896 SmallVector<int, 4>
Mask;
27897 if (MergeInnerShuffle(i != 0, SVN, OtherSV,
N->getOperand(1 - i), TLI,
27905 SV1 ? SV1 : DAG.
getUNDEF(VT), Mask);
27915 if (TLI.isBinOp(SrcOpcode) &&
N->isOnlyUserOf(N0.
getNode()) &&
27917 (SrcOpcode == N1.getOpcode() &&
N->isOnlyUserOf(N1.getNode())))) {
27922 SDValue Op11 = N1.isUndef() ? N1 : N1.getOperand(1);
27933 SmallVectorImpl<int> &
Mask,
bool LeftOp,
27935 SDValue InnerN = Commute ? N1 : N0;
27936 SDValue Op0 = LeftOp ? Op00 : Op01;
27937 SDValue Op1 = LeftOp ? Op10 : Op11;
27944 MergeInnerShuffle(Commute, SVN, SVN0, Op1, TLI, SV0, SV1,
27946 (
llvm::any_of(SVN0->getMask(), [](
int M) { return M < 0; }) ||
27952 bool MergedLeft =
false;
27954 SmallVector<int, 4> LeftMask;
27955 if (CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
false) ||
27956 CanMergeInnerShuffle(LeftSV0, LeftSV1, LeftMask,
true,
true)) {
27959 LeftMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
27960 LeftSV0 = Op00, LeftSV1 = Op10;
27963 bool MergedRight =
false;
27965 SmallVector<int, 4> RightMask;
27966 if (CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
false) ||
27967 CanMergeInnerShuffle(RightSV0, RightSV1, RightMask,
false,
true)) {
27968 MergedRight =
true;
27970 RightMask.
assign(SVN->getMask().begin(), SVN->getMask().end());
27971 RightSV0 = Op01, RightSV1 = Op11;
27974 if (MergedLeft || MergedRight) {
27977 VT,
DL, LeftSV0 ? LeftSV0 : DAG.
getUNDEF(VT),
27978 LeftSV1 ? LeftSV1 : DAG.
getUNDEF(VT), LeftMask);
27980 VT,
DL, RightSV0 ? RightSV0 : DAG.
getUNDEF(VT),
27981 RightSV1 ? RightSV1 : DAG.
getUNDEF(VT), RightMask);
28002SDValue DAGCombiner::visitSCALAR_TO_VECTOR(SDNode *
N) {
28003 EVT VT =
N->getValueType(0);
28013 unsigned Opcode =
Scalar.getOpcode();
28015 if (
Scalar.hasOneUse() &&
Scalar->getNumValues() == 1 &&
28016 TLI.isBinOp(Opcode) &&
Scalar.getValueType() == VecEltVT &&
28017 Scalar.getOperand(0).getValueType() == VecEltVT &&
28018 Scalar.getOperand(1).getValueType() == VecEltVT &&
28019 Scalar->isOnlyUserOf(
Scalar.getOperand(0).getNode()) &&
28020 Scalar->isOnlyUserOf(
Scalar.getOperand(1).getNode()) &&
28025 for (
int i : {0, 1}) {
28036 if (TLI.isShuffleMaskLegal(ShufMask, VT)) {
28051 !
Scalar.getOperand(0).getValueType().isFixedLengthVector())
28055 if (VecEltVT !=
Scalar.getValueType() &&
28069 if (VecEltVT == SrcVT.
getScalarType() && VTNumElts <= SrcNumElts) {
28071 SmallVector<int, 8>
Mask(SrcNumElts, -1);
28072 Mask[0] = ExtIndexC->getZExtValue();
28073 SDValue LegalShuffle = TLI.buildLegalVectorShuffle(
28074 SrcVT, SDLoc(
N), SrcVec, DAG.
getUNDEF(SrcVT), Mask, DAG);
28080 return LegalShuffle;
28083 if (VTNumElts != SrcNumElts) {
28095SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *
N) {
28096 EVT VT =
N->getValueType(0);
28100 uint64_t InsIdx =
N->getConstantOperandVal(2);
28124 InsIdx + SubVecNumElts);
28221 if ((N0.
isUndef() || N0SrcSVT == N1SrcSVT) &&
28233 }
else if ((N1SrcSVT.
getSizeInBits() % EltSizeInBits) == 0) {
28256 if (InsIdx < OtherIdx) {
28260 AddToWorklist(NewOp.
getNode());
28274 Ops[InsIdx / Factor] = N1;
28285SDValue DAGCombiner::visitFP_TO_FP16(SDNode *
N) {
28289 if (N0->
getOpcode() == ISD::FP16_TO_FP)
28295SDValue DAGCombiner::visitFP16_TO_FP(SDNode *
N) {
28296 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
28297 auto Op =
N->getOpcode();
28298 assert((
Op == ISD::FP16_TO_FP ||
Op == ISD::BF16_TO_FP) &&
28299 "opcode should be FP16_TO_FP or BF16_TO_FP.");
28312 return CastEliminated;
28318 N->getValueType(0), {N0});
28322SDValue DAGCombiner::visitFP_TO_BF16(SDNode *
N) {
28326 if (N0->
getOpcode() == ISD::BF16_TO_FP)
28332SDValue DAGCombiner::visitBF16_TO_FP(SDNode *
N) {
28334 return visitFP16_TO_FP(
N);
28337SDValue DAGCombiner::visitVECREDUCE(SDNode *
N) {
28340 unsigned Opcode =
N->getOpcode();
28355 if (Opcode == ISD::VECREDUCE_AND || Opcode == ISD::VECREDUCE_OR) {
28356 unsigned NewOpcode = Opcode == ISD::VECREDUCE_AND
28357 ? ISD::VECREDUCE_UMIN : ISD::VECREDUCE_UMAX;
28358 if (!TLI.isOperationLegalOrCustom(Opcode, VT) &&
28359 TLI.isOperationLegalOrCustom(NewOpcode, VT) &&
28361 return DAG.
getNode(NewOpcode, SDLoc(
N),
N->getValueType(0), N0);
28370 if ((Opcode == ISD::VECREDUCE_OR &&
28372 (Opcode == ISD::VECREDUCE_AND &&
28374 return DAG.
getNode(Opcode, SDLoc(
N),
N->getValueType(0), Subvec);
28379 if ((Opcode == ISD::VECREDUCE_OR || Opcode == ISD::VECREDUCE_AND ||
28380 Opcode == ISD::VECREDUCE_XOR) &&
28393SDValue DAGCombiner::visitVP_FSUB(SDNode *
N) {
28394 SelectionDAG::FlagInserter FlagsInserter(DAG,
N);
28397 if (
SDValue Fused = visitFSUBForFMACombine<VPMatchContext>(
N)) {
28398 AddToWorklist(Fused.getNode());
28404SDValue DAGCombiner::visitVPOp(SDNode *
N) {
28406 if (
N->getOpcode() == ISD::VP_GATHER)
28407 if (
SDValue SD = visitVPGATHER(
N))
28410 if (
N->getOpcode() == ISD::VP_SCATTER)
28411 if (
SDValue SD = visitVPSCATTER(
N))
28414 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD)
28415 if (
SDValue SD = visitVP_STRIDED_LOAD(
N))
28418 if (
N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE)
28419 if (
SDValue SD = visitVP_STRIDED_STORE(
N))
28425 bool AreAllEltsDisabled =
false;
28429 AreAllEltsDisabled |=
28433 if (!AreAllEltsDisabled) {
28434 switch (
N->getOpcode()) {
28436 return visitVP_FADD(
N);
28438 return visitVP_FSUB(
N);
28440 return visitFMA<VPMatchContext>(
N);
28441 case ISD::VP_SELECT:
28442 return visitVP_SELECT(
N);
28444 return visitMUL<VPMatchContext>(
N);
28455 return DAG.
getUNDEF(
N->getValueType(0));
28460 if (MemSD->writeMem())
28461 return MemSD->getChain();
28462 return CombineTo(
N, DAG.
getUNDEF(
N->getValueType(0)), MemSD->getChain());
28472SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *
N) {
28479 LoadSDNode *LdNode =
nullptr;
28480 for (
auto *U :
Ptr->users()) {
28484 if (LdNode && LdNode != Ld)
28497 StoreSDNode *StNode =
nullptr;
28498 for (SDUse &U : LdNode->
uses()) {
28499 if (
U.getResNo() == 0) {
28518 CombineTo(StNode, Res,
false);
28522SDValue DAGCombiner::visitSET_FPENV_MEM(SDNode *
N) {
28528 StoreSDNode *StNode =
nullptr;
28529 for (
auto *U :
Ptr->users()) {
28533 if (StNode && StNode != St)
28566SDValue DAGCombiner::XformToShuffleWithZero(SDNode *
N) {
28569 EVT VT =
N->getValueType(0);
28576 if (LegalOperations)
28582 EVT RVT =
RHS.getValueType();
28583 unsigned NumElts =
RHS.getNumOperands();
28588 auto BuildClearMask = [&](
int Split) {
28589 int NumSubElts = NumElts *
Split;
28592 SmallVector<int, 8> Indices;
28593 for (
int i = 0; i != NumSubElts; ++i) {
28594 int EltIdx = i /
Split;
28595 int SubIdx = i %
Split;
28611 Bits->extractBits(NumSubBits, (Split - SubIdx - 1) * NumSubBits);
28613 *
Bits =
Bits->extractBits(NumSubBits, SubIdx * NumSubBits);
28615 if (
Bits->isAllOnes())
28617 else if (*Bits == 0)
28626 if (!TLI.isVectorClearMaskLegal(Indices, ClearVT))
28640 for (
int Split = 1;
Split <= MaxSplit; ++
Split)
28642 if (
SDValue S = BuildClearMask(Split))
28651 const SDLoc &
DL,
bool LegalTypes) {
28654 unsigned Opcode =
N->getOpcode();
28655 EVT VT =
N->getValueType(0);
28662 int Index0, Index1;
28669 if (!Src0 || !Src1 || Index0 != Index1 ||
28696 for (
auto [
X,
Y] :
zip(EltsX, EltsY))
28711SDValue DAGCombiner::SimplifyVCastOp(SDNode *
N,
const SDLoc &
DL) {
28712 EVT VT =
N->getValueType(0);
28713 assert(VT.
isVector() &&
"SimplifyVCastOp only works on vectors!");
28715 unsigned Opcode =
N->getOpcode();
28746SDValue DAGCombiner::SimplifyVBinOp(SDNode *
N,
const SDLoc &
DL) {
28747 EVT VT =
N->getValueType(0);
28748 assert(VT.
isVector() &&
"SimplifyVBinOp only works on vectors!");
28752 unsigned Opcode =
N->getOpcode();
28753 SDNodeFlags
Flags =
N->getFlags();
28765 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
28766 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
28769 RHS.getOperand(0), Flags);
28781 Shuf0->hasOneUse() && Shuf0->getOperand(1).isUndef() &&
28790 Shuf1->hasOneUse() && Shuf1->getOperand(1).isUndef() &&
28806 LHS.getOperand(2) ==
RHS.getOperand(2) &&
28811 EVT NarrowVT =
X.getValueType();
28812 if (NarrowVT ==
Y.getValueType() &&
28814 LegalOperations)) {
28827 return Op.isUndef() ||
28828 ISD::isBuildVectorOfConstantSDNodes(Op.getNode());
28837 if (ConcatWithConstantOrUndef(
LHS) && ConcatWithConstantOrUndef(
RHS) &&
28839 EVT NarrowVT =
LHS.getOperand(0).getValueType();
28840 if (NarrowVT ==
RHS.getOperand(0).getValueType() &&
28842 unsigned NumOperands =
LHS.getNumOperands();
28844 for (
unsigned i = 0; i != NumOperands; ++i) {
28847 RHS.getOperand(i)));
28863 "First argument must be a SetCC node!");
28871 if (
SCC.getNode()) {
28878 SCC.getOperand(0),
SCC.getOperand(1),
28879 SCC.getOperand(4), Flags);
28880 AddToWorklist(
SETCC.getNode());
28881 return DAG.
getSelect(SDLoc(SCC),
SCC.getValueType(), SETCC,
28882 SCC.getOperand(2),
SCC.getOperand(3), Flags);
28895bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect,
SDValue LHS,
28900 if (NaN->isNaN() &&
RHS.getOpcode() == ISD::FSQRT) {
28905 const ConstantFPSDNode *
Zero =
nullptr;
28916 CmpLHS =
Cmp.getOperand(0);
28920 if (Zero &&
Zero->isZero() &&
28924 CombineTo(TheSelect, Sqrt);
28934 if (
LHS.getOpcode() !=
RHS.getOpcode() ||
28942 if (
LHS.getOpcode() == ISD::LOAD) {
28947 if (
LHS.getOperand(0) !=
RHS.getOperand(0) ||
28985 SmallPtrSet<const SDNode *, 32> Visited;
28991 Visited.
insert(TheSelect);
29052 MMOFlags &= ~MachineMemOperand::MOInvariant;
29054 MMOFlags &= ~MachineMemOperand::MODereferenceable;
29058 LLD->
getChain(), Addr, MachinePointerInfo(), Alignment,
29066 MachinePointerInfo(), LLD->
getMemoryVT(), Alignment, MMOFlags);
29070 CombineTo(TheSelect, Load);
29074 CombineTo(
LHS.getNode(),
Load.getValue(0),
Load.getValue(1));
29075 CombineTo(
RHS.getNode(),
Load.getValue(0),
Load.getValue(1));
29116 if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue() - 1)) == 0)) {
29117 unsigned ShCt = XType.
getSizeInBits() - N2C->getAPIntValue().logBase2() - 1;
29121 AddToWorklist(Shift.
getNode());
29123 if (XType.
bitsGT(AType)) {
29125 AddToWorklist(Shift.
getNode());
29129 Shift = DAG.
getNOT(
DL, Shift, AType);
29141 AddToWorklist(Shift.
getNode());
29143 if (XType.
bitsGT(AType)) {
29145 AddToWorklist(Shift.
getNode());
29149 Shift = DAG.
getNOT(
DL, Shift, AType);
29155SDValue DAGCombiner::foldSelectOfBinops(SDNode *
N) {
29209SDValue DAGCombiner::foldSignChangeInBitcast(SDNode *
N) {
29211 EVT VT =
N->getValueType(0);
29212 bool IsFabs =
N->getOpcode() == ISD::FABS;
29219 EVT IntVT =
Int.getValueType();
29233 SignMask = ~SignMask;
29239 SignMask = ~SignMask;
29244 AddToWorklist(
Int.getNode());
29252SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
29268 TLI.
isFPImmLegal(TV->getValueAPF(), TV->getValueType(0), ForCodeSize) ||
29269 TLI.
isFPImmLegal(FV->getValueAPF(), FV->getValueType(0), ForCodeSize))
29274 if (!TV->hasOneUse() && !FV->hasOneUse())
29278 const_cast<ConstantFP*
>(TV->getConstantFPValue()) };
29295 AddToWorklist(
Cond.getNode());
29297 AddToWorklist(CstOffset.
getNode());
29299 AddToWorklist(CPIdx.
getNode());
29309 bool NotExtCompare) {
29311 if (N2 == N3)
return N2;
29322 AddToWorklist(
SCC.getNode());
29326 return !(SCCC->isZero()) ? N2 : N3;
29331 convertSelectOfFPConstantsToLoadOffset(
DL, N0, N1, N2, N3, CC))
29334 if (
SDValue V = foldSelectCCToShiftAnd(
DL, N0, N1, N2, N3, CC))
29347 if (ConstAndRHS && ConstAndRHS->getAPIntValue().popcount() == 1) {
29349 const APInt &AndMask = ConstAndRHS->getAPIntValue();
29367 bool Fold = N2C &&
isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2();
29368 bool Swap = N3C &&
isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2();
29370 if ((Fold || Swap) &&
29383 if (NotExtCompare && N2C->isOne())
29392 SCC = DAG.
getSetCC(SDLoc(N0), MVT::i1, N0, N1, CC);
29396 AddToWorklist(
SCC.getNode());
29397 AddToWorklist(Temp.
getNode());
29402 unsigned ShCt = N2C->getAPIntValue().logBase2();
29433 N0 ==
Count.getOperand(0) &&
29440 N0 ==
Count.getOperand(0) &&
29449 if (!NotExtCompare && N1C && N2C && N3C &&
29450 N2C->getAPIntValue() == ~N3C->getAPIntValue() &&
29463 if (CC ==
ISD::SETGT && N1C && N2C && N3C && N1C->isAllOnes() &&
29464 N2C->isOne() && N3C->isAllOnes() &&
29479 if (
SDValue ABD = foldSelectToABD(N0, N1, N2, N3, CC,
DL))
29508 const auto IsSrc = [&](
SDValue V) {
29519 while (!Worklist.
empty()) {
29521 if (!V.hasOneUse() && (Src && Src != V))
29524 if (V.getOpcode() ==
ISD::OR) {
29541 PartsMask |= (RootMask << ShiftAmtVal);
29546 PartsMask |= RootMask;
29564 bool foldBooleans) {
29565 TargetLowering::DAGCombinerInfo
29566 DagCombineInfo(DAG, Level,
false,
this);
29585SDValue DAGCombiner::BuildSDIV(SDNode *
N) {
29593 for (SDNode *
N : Built)
29603SDValue DAGCombiner::BuildSDIVPow2(SDNode *
N) {
29614 for (SDNode *
N : Built)
29626SDValue DAGCombiner::BuildUDIV(SDNode *
N) {
29634 for (SDNode *
N : Built)
29644SDValue DAGCombiner::BuildSREMPow2(SDNode *
N) {
29655 for (SDNode *
N : Built)
29675 bool AssumeNonZero) {
29678 auto PeekThroughCastsAndTrunc = [](
SDValue V) {
29680 switch (V.getOpcode()) {
29683 V = V.getOperand(0);
29694 Op = PeekThroughCastsAndTrunc(
Op);
29700 if (
C->isZero() ||
C->isOpaque())
29703 if (
C->getAPIntValue().isPowerOf2()) {
29719 for (
const APInt &Pow2 : Pow2Constants)
29728 auto CastToVT = [&](
EVT NewVT,
SDValue ToCast) {
29733 ToCast = ToCast.getOperand(0);
29734 EVT CurVT = ToCast.getValueType();
29735 if (NewVT == CurVT)
29747 if (AssumeNonZero ||
Op->getFlags().hasNoUnsignedWrap() ||
29750 Depth + 1, AssumeNonZero))
29752 CastToVT(VT,
Op.getOperand(1)));
29778 return DAG.
getNode(
Op.getOpcode(),
DL, VT, LogX, LogY);
29787 bool KnownNonZero,
bool InexpensiveOnly,
29788 std::optional<EVT> OutVT) {
29789 EVT VT = OutVT ? *OutVT :
V.getValueType();
29790 SDValue InexpensiveLogBase2 =
29793 return InexpensiveLogBase2;
29810 SDNodeFlags Flags) {
29815 EVT VT =
Op.getValueType();
29823 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
29830 AddToWorklist(Est.getNode());
29838 for (
int i = 0; i < Iterations; ++i) {
29841 if (i == Iterations - 1) {
29843 AddToWorklist(MulEst.
getNode());
29847 AddToWorklist(NewEst.
getNode());
29850 (i == Iterations - 1 ?
N : FPOne), NewEst, Flags);
29851 AddToWorklist(NewEst.
getNode());
29854 AddToWorklist(NewEst.
getNode());
29857 AddToWorklist(Est.getNode());
29862 AddToWorklist(Est.getNode());
29878 unsigned Iterations,
bool Reciprocal) {
29889 for (
unsigned i = 0; i < Iterations; ++i) {
29909 unsigned Iterations,
bool Reciprocal) {
29921 for (
unsigned i = 0; i < Iterations; ++i) {
29930 if (Reciprocal || (i + 1) < Iterations) {
29952 EVT VT =
Op.getValueType();
29960 if (
Enabled == TLI.ReciprocalEstimate::Disabled)
29967 bool UseOneConstNR =
false;
29971 AddToWorklist(Est.
getNode());
29973 if (Iterations > 0)
29974 Est = UseOneConstNR
29975 ? buildSqrtNROneConst(
Op, Est, Iterations, Reciprocal)
29976 : buildSqrtNRTwoConst(
Op, Est, Iterations, Reciprocal);
29995 return buildSqrtEstimateImpl(
Op,
true);
29999 return buildSqrtEstimateImpl(
Op,
false);
30003bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1)
const {
30005 struct MemUseCharacteristics {
30010 LocationSize NumBytes;
30011 MachineMemOperand *MMO;
30014 auto getCharacteristics = [
this](SDNode *
N) -> MemUseCharacteristics {
30020 ? -1 *
C->getSExtValue()
30022 TypeSize
Size = LSN->getMemoryVT().getStoreSize();
30023 return {LSN->isVolatile(), LSN->isAtomic(),
30024 LSN->getBasePtr(),
Offset ,
30034 (MachineMemOperand *)
nullptr};
30042 (MachineMemOperand *)
nullptr};
30045 MemUseCharacteristics MUC0 = getCharacteristics(Op0),
30046 MUC1 = getCharacteristics(Op1);
30049 if (MUC0.BasePtr.getNode() && MUC0.BasePtr == MUC1.BasePtr &&
30050 MUC0.Offset == MUC1.Offset)
30054 if (MUC0.IsVolatile && MUC1.IsVolatile)
30059 if (MUC0.IsAtomic && MUC1.IsAtomic)
30062 if (MUC0.MMO && MUC1.MMO) {
30063 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
30064 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
30070 if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() &&
30071 MUC0.Offset != 0) ||
30072 (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() &&
30084 if (!MUC0.MMO || !MUC1.MMO)
30090 if ((MUC0.MMO->isInvariant() && MUC1.MMO->isStore()) ||
30091 (MUC1.MMO->isInvariant() && MUC0.MMO->isStore()))
30099 int64_t SrcValOffset0 = MUC0.MMO->getOffset();
30100 int64_t SrcValOffset1 = MUC1.MMO->getOffset();
30101 Align OrigAlignment0 = MUC0.MMO->getBaseAlign();
30102 Align OrigAlignment1 = MUC1.MMO->getBaseAlign();
30103 LocationSize Size0 = MUC0.NumBytes;
30104 LocationSize Size1 = MUC1.NumBytes;
30106 if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 &&
30112 int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.
value();
30113 int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.
value();
30117 if ((OffAlign0 +
static_cast<int64_t
>(
30119 (OffAlign1 +
static_cast<int64_t
>(
30133 if (
UseAA && BatchAA && MUC0.MMO->getValue() && MUC1.MMO->getValue() &&
30136 (!Size0.
isScalable() || SrcValOffset0 == 0) &&
30137 (!Size1.
isScalable() || SrcValOffset1 == 0)) {
30139 int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1);
30144 LocationSize Loc0 =
30146 LocationSize Loc1 =
30149 MemoryLocation(MUC0.MMO->getValue(), Loc0,
30150 UseTBAA ? MUC0.MMO->getAAInfo() : AAMDNodes()),
30151 MemoryLocation(MUC1.MMO->getValue(), Loc1,
30152 UseTBAA ? MUC1.MMO->getAAInfo() : AAMDNodes())))
30162void DAGCombiner::GatherAllAliases(SDNode *
N,
SDValue OriginalChain,
30163 SmallVectorImpl<SDValue> &Aliases) {
30165 SmallPtrSet<SDNode *, 16> Visited;
30173 unsigned Depth = 0;
30176 auto ImproveChain = [&](
SDValue &
C) ->
bool {
30177 switch (
C.getOpcode()) {
30188 if ((IsLoad && IsOpLoad) || !
mayAlias(
N,
C.getNode())) {
30190 C =
C.getOperand(0);
30199 C =
C.getOperand(0);
30202 case ISD::LIFETIME_START:
30203 case ISD::LIFETIME_END: {
30208 C =
C.getOperand(0);
30221 while (!Chains.
empty()) {
30255 if (ImproveChain(Chain)) {
30277 GatherAllAliases(
N, OldChain, Aliases);
30280 if (Aliases.
empty())
30284 if (Aliases.
size() == 1)
30304bool DAGCombiner::parallelizeChainedStores(StoreSDNode *St) {
30306 StoreSDNode *STChain = St;
30311 using IMap = llvm::IntervalMap<int64_t, std::monostate, 8,
30312 IntervalMapHalfOpenInfo<int64_t>>;
30321 if (!
BasePtr.getBase().getNode())
30325 if (
BasePtr.getBase().isUndef())
30343 if (Chain->getMemoryVT().isScalableVector())
30347 if (!
SDValue(Chain, 0)->hasOneUse())
30350 if (!Chain->isSimple() || Chain->isIndexed())
30359 int64_t
Length = (Chain->getMemoryVT().getSizeInBits() + 7) / 8;
30367 if (
I != Intervals.begin() && (--
I).stop() <=
Offset)
30376 if (ChainedStores.
empty())
30383 for (
unsigned I = ChainedStores.
size();
I;) {
30384 StoreSDNode *S = ChainedStores[--
I];
30385 SDValue BetterChain = FindBetterChain(S, NewChain);
30389 ChainedStores[
I] = S;
30393 SDValue BetterChain = FindBetterChain(St, NewChain);
30408 auto hasImprovedChain = [&](
SDValue ST) ->
bool {
30409 return ST->getOperand(0) != NewChain;
30411 bool AddNewChain =
llvm::all_of(TFOps, hasImprovedChain);
30421 AddToWorklist(
Op.getNode());
30422 AddToWorklist(STChain);
30426bool DAGCombiner::findBetterNeighborChains(StoreSDNode *St) {
30433 if (!
BasePtr.getBase().getNode())
30437 if (
BasePtr.getBase().isUndef())
30441 if (parallelizeChainedStores(St))
30446 if (St->
getChain() != BetterChain) {
30447 replaceStoreChain(St, BetterChain);
30457 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...
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 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 bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned, const TargetLowering &TLI)
Return true if divmod libcall is available.
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 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 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 unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2, ISD::CondCode CC, unsigned OrAndOpcode, SelectionDAG &DAG, bool isFMAXNUMFMINNUM_IEEE, bool isFMAXNUMFMINNUM)
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 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< 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 int 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)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> 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")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file describes how to lower LLVM code to machine code.
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static constexpr int Concat[]
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.
static APFloat getOne(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative One.
APInt bitcastToAPInt() 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
LLVM_ABI APInt uadd_ov(const APInt &RHS, bool &Overflow) const
unsigned countr_zero() const
Count the number of trailing zero bits.
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 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 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.
ArrayRef - 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
size - 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 bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
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.
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.
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(unsigned CounterName)
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().
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.
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)
static auto all_valuetypes()
SimpleValueType Iteration.
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 a 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.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
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.
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)
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 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 FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl)
Constant fold a setcc to true or false.
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 getVScale(const SDLoc &DL, EVT VT, APInt MulImm, bool ConstantFold=true)
Return a node that represents the runtime scaling 'MulImm * RuntimeVL'.
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.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
bool isSafeToSpeculativelyExecute(unsigned Opcode) const
Some opcodes may create immediate undefined behavior when used with some values (integer division-by-...
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,...
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,...
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 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.
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
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 bool isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly=false, unsigned Depth=0) const
Return true if this function can prove that Op is never poison and, if PoisonOnly is false,...
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
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 bool isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth=0) const
Test if the given value is known to have exactly one bit set.
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()
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)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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)
const TargetLibraryInfo & getLibInfo() const
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 bool canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts, bool PoisonOnly=false, bool ConsiderFlags=true, unsigned Depth=0) const
Return true if Op can create undef or poison from non-undef & non-poison operands.
LLVM_ABI OverflowKind computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const
Determine if the result of the unsigned addition of 2 nodes can overflow.
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 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.
bool has(LibFunc F) const
Tests whether a library function is available.
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 canCombineTruncStore(EVT ValVT, EVT MemVT, bool LegalOnly) const
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.
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...
bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const
Return true if the specified store with truncation is legal on this target.
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...
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 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...
bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension is legal or custom on this target.
bool isAtomicLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified atomic load with extension is legal on this target.
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 isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const
Return true if the specified load with extension 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.
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.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const
virtual bool shouldRemoveExtendFromGSIndex(SDValue Extend, EVT DataVT) const
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...
virtual SDValue getSqrtInputTest(SDValue Operand, SelectionDAG &DAG, const DenormalMode &Mode) const
Return a target-dependent comparison result if the input operand is suitable for use with a square ro...
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 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 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.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ POISON
POISON - A poison node.
@ 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...
@ 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.
@ 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 ...
@ FADD
Simple binary floating point operators.
@ 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.
@ FMULADD
FMULADD - Performs a * b + c, with, or without, intermediate rounding.
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
@ 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...
@ CTTZ_ZERO_UNDEF
Bit counting operators with an undefined result for zero inputs.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ 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.
@ SSUBSAT
RESULT = [US]SUBSAT(LHS, RHS) - Perform saturation subtraction on 2 integers with the same bit width ...
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ 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.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ 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.
@ 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) ...
@ 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.
@ 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.
@ 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.
@ 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.
@ 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 ...
@ 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.
@ 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)...
@ 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 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)
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
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.
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().
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)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
deferredval_ty< 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()...
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)
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)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
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)
@ Undef
Value of the register doesn't matter.
Opcode_match m_Opc(unsigned Opcode)
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.
BinaryOpc_match< LHS, RHS > m_Sra(const LHS &L, const RHS &R)
auto m_UMinLike(const LHS &L, const RHS &R)
auto m_SelectLike(const T0_P &Cond, const T1_P &T, const T2_P &F)
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)
UnaryOpc_match< Opnd > m_AnyExt(const Opnd &Op)
auto m_SMaxLike(const LHS &L, const RHS &R)
UnaryOpc_match< Opnd > m_Ctlz(const Opnd &Op)
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.
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.
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.
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)
bool operator>=(int64_t V1, const APSInt &V2)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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...
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)
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.
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 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 const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V, unsigned OperandNo)
Returns true if V is a neutral element of Opc with Flags.
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.
EVT changeElementType(EVT EltVT) const
Return a VT for a type whose attributes match ourselves with the exception of the element type that i...
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.
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.
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).
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.
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 isAllOnes() const
Returns true if value is all one bits.
const APInt & getConstant() const
Returns the value when all bits have a known value.
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
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...